root/arch/mips/include/asm/futex.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. arch_futex_atomic_op_inuser
  2. futex_atomic_cmpxchg_inatomic

   1 /*
   2  * This file is subject to the terms and conditions of the GNU General Public
   3  * License.  See the file "COPYING" in the main directory of this archive
   4  * for more details.
   5  *
   6  * Copyright (c) 2006  Ralf Baechle (ralf@linux-mips.org)
   7  */
   8 #ifndef _ASM_FUTEX_H
   9 #define _ASM_FUTEX_H
  10 
  11 #ifdef __KERNEL__
  12 
  13 #include <linux/futex.h>
  14 #include <linux/uaccess.h>
  15 #include <asm/asm-eva.h>
  16 #include <asm/barrier.h>
  17 #include <asm/compiler.h>
  18 #include <asm/errno.h>
  19 #include <asm/war.h>
  20 
  21 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)              \
  22 {                                                                       \
  23         if (cpu_has_llsc && R10000_LLSC_WAR) {                          \
  24                 __asm__ __volatile__(                                   \
  25                 "       .set    push                            \n"     \
  26                 "       .set    noat                            \n"     \
  27                 "       .set    push                            \n"     \
  28                 "       .set    arch=r4000                      \n"     \
  29                 "1:     ll      %1, %4  # __futex_atomic_op     \n"     \
  30                 "       .set    pop                             \n"     \
  31                 "       " insn  "                               \n"     \
  32                 "       .set    arch=r4000                      \n"     \
  33                 "2:     sc      $1, %2                          \n"     \
  34                 "       beqzl   $1, 1b                          \n"     \
  35                 __WEAK_LLSC_MB                                          \
  36                 "3:                                             \n"     \
  37                 "       .insn                                   \n"     \
  38                 "       .set    pop                             \n"     \
  39                 "       .section .fixup,\"ax\"                  \n"     \
  40                 "4:     li      %0, %6                          \n"     \
  41                 "       j       3b                              \n"     \
  42                 "       .previous                               \n"     \
  43                 "       .section __ex_table,\"a\"               \n"     \
  44                 "       "__UA_ADDR "\t1b, 4b                    \n"     \
  45                 "       "__UA_ADDR "\t2b, 4b                    \n"     \
  46                 "       .previous                               \n"     \
  47                 : "=r" (ret), "=&r" (oldval),                           \
  48                   "=" GCC_OFF_SMALL_ASM() (*uaddr)                              \
  49                 : "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),  \
  50                   "i" (-EFAULT)                                         \
  51                 : "memory");                                            \
  52         } else if (cpu_has_llsc) {                                      \
  53                 loongson_llsc_mb();                                     \
  54                 __asm__ __volatile__(                                   \
  55                 "       .set    push                            \n"     \
  56                 "       .set    noat                            \n"     \
  57                 "       .set    push                            \n"     \
  58                 "       .set    "MIPS_ISA_ARCH_LEVEL"           \n"     \
  59                 "1:     "user_ll("%1", "%4")" # __futex_atomic_op\n"    \
  60                 "       .set    pop                             \n"     \
  61                 "       " insn  "                               \n"     \
  62                 "       .set    "MIPS_ISA_ARCH_LEVEL"           \n"     \
  63                 "2:     "user_sc("$1", "%2")"                   \n"     \
  64                 "       beqz    $1, 1b                          \n"     \
  65                 __WEAK_LLSC_MB                                          \
  66                 "3:                                             \n"     \
  67                 "       .insn                                   \n"     \
  68                 "       .set    pop                             \n"     \
  69                 "       .section .fixup,\"ax\"                  \n"     \
  70                 "4:     li      %0, %6                          \n"     \
  71                 "       j       3b                              \n"     \
  72                 "       .previous                               \n"     \
  73                 "       .section __ex_table,\"a\"               \n"     \
  74                 "       "__UA_ADDR "\t1b, 4b                    \n"     \
  75                 "       "__UA_ADDR "\t2b, 4b                    \n"     \
  76                 "       .previous                               \n"     \
  77                 : "=r" (ret), "=&r" (oldval),                           \
  78                   "=" GCC_OFF_SMALL_ASM() (*uaddr)                              \
  79                 : "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg),  \
  80                   "i" (-EFAULT)                                         \
  81                 : "memory");                                            \
  82         } else                                                          \
  83                 ret = -ENOSYS;                                          \
  84 }
  85 
  86 static inline int
  87 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
  88 {
  89         int oldval = 0, ret;
  90 
  91         pagefault_disable();
  92 
  93         switch (op) {
  94         case FUTEX_OP_SET:
  95                 __futex_atomic_op("move $1, %z5", ret, oldval, uaddr, oparg);
  96                 break;
  97 
  98         case FUTEX_OP_ADD:
  99                 __futex_atomic_op("addu $1, %1, %z5",
 100                                   ret, oldval, uaddr, oparg);
 101                 break;
 102         case FUTEX_OP_OR:
 103                 __futex_atomic_op("or   $1, %1, %z5",
 104                                   ret, oldval, uaddr, oparg);
 105                 break;
 106         case FUTEX_OP_ANDN:
 107                 __futex_atomic_op("and  $1, %1, %z5",
 108                                   ret, oldval, uaddr, ~oparg);
 109                 break;
 110         case FUTEX_OP_XOR:
 111                 __futex_atomic_op("xor  $1, %1, %z5",
 112                                   ret, oldval, uaddr, oparg);
 113                 break;
 114         default:
 115                 ret = -ENOSYS;
 116         }
 117 
 118         pagefault_enable();
 119 
 120         if (!ret)
 121                 *oval = oldval;
 122 
 123         return ret;
 124 }
 125 
 126 static inline int
 127 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 128                               u32 oldval, u32 newval)
 129 {
 130         int ret = 0;
 131         u32 val;
 132 
 133         if (!access_ok(uaddr, sizeof(u32)))
 134                 return -EFAULT;
 135 
 136         if (cpu_has_llsc && R10000_LLSC_WAR) {
 137                 __asm__ __volatile__(
 138                 "# futex_atomic_cmpxchg_inatomic                        \n"
 139                 "       .set    push                                    \n"
 140                 "       .set    noat                                    \n"
 141                 "       .set    push                                    \n"
 142                 "       .set    arch=r4000                              \n"
 143                 "1:     ll      %1, %3                                  \n"
 144                 "       bne     %1, %z4, 3f                             \n"
 145                 "       .set    pop                                     \n"
 146                 "       move    $1, %z5                                 \n"
 147                 "       .set    arch=r4000                              \n"
 148                 "2:     sc      $1, %2                                  \n"
 149                 "       beqzl   $1, 1b                                  \n"
 150                 __WEAK_LLSC_MB
 151                 "3:                                                     \n"
 152                 "       .insn                                           \n"
 153                 "       .set    pop                                     \n"
 154                 "       .section .fixup,\"ax\"                          \n"
 155                 "4:     li      %0, %6                                  \n"
 156                 "       j       3b                                      \n"
 157                 "       .previous                                       \n"
 158                 "       .section __ex_table,\"a\"                       \n"
 159                 "       "__UA_ADDR "\t1b, 4b                            \n"
 160                 "       "__UA_ADDR "\t2b, 4b                            \n"
 161                 "       .previous                                       \n"
 162                 : "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
 163                 : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
 164                   "i" (-EFAULT)
 165                 : "memory");
 166         } else if (cpu_has_llsc) {
 167                 loongson_llsc_mb();
 168                 __asm__ __volatile__(
 169                 "# futex_atomic_cmpxchg_inatomic                        \n"
 170                 "       .set    push                                    \n"
 171                 "       .set    noat                                    \n"
 172                 "       .set    push                                    \n"
 173                 "       .set    "MIPS_ISA_ARCH_LEVEL"                   \n"
 174                 "1:     "user_ll("%1", "%3")"                           \n"
 175                 "       bne     %1, %z4, 3f                             \n"
 176                 "       .set    pop                                     \n"
 177                 "       move    $1, %z5                                 \n"
 178                 "       .set    "MIPS_ISA_ARCH_LEVEL"                   \n"
 179                 "2:     "user_sc("$1", "%2")"                           \n"
 180                 "       beqz    $1, 1b                                  \n"
 181                 __WEAK_LLSC_MB
 182                 "3:                                                     \n"
 183                 "       .insn                                           \n"
 184                 "       .set    pop                                     \n"
 185                 "       .section .fixup,\"ax\"                          \n"
 186                 "4:     li      %0, %6                                  \n"
 187                 "       j       3b                                      \n"
 188                 "       .previous                                       \n"
 189                 "       .section __ex_table,\"a\"                       \n"
 190                 "       "__UA_ADDR "\t1b, 4b                            \n"
 191                 "       "__UA_ADDR "\t2b, 4b                            \n"
 192                 "       .previous                                       \n"
 193                 : "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
 194                 : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
 195                   "i" (-EFAULT)
 196                 : "memory");
 197                 loongson_llsc_mb();
 198         } else
 199                 return -ENOSYS;
 200 
 201         *uval = val;
 202         return ret;
 203 }
 204 
 205 #endif
 206 #endif /* _ASM_FUTEX_H */

/* [<][>][^][v][top][bottom][index][help] */