Commit 47d632f9f8f3ed62b21f725e98b726d65769b6d7

Authored by Chris Metcalf
1 parent 1efea40d41

arch/tile: optimize get_user/put_user and friends

Use direct load/store for the get_user/put_user.

Previously, we would call out to a helper routine that would do the
appropriate thing and then return, handling the possible exception
internally.  Now we inline the load or store, along with a "we succeeded"
indication in a register; if the load or store faults, we write a
"we failed" indication into the same register and then return to the
following instruction.  This is more efficient and gives us more compact
code, as well as being more in line with what other architectures do.

The special futex assembly source file for TILE-Gx also disappears in
this change; we just use the same inlining idiom there as well, putting
the appropriate atomic operations directly into futex_atomic_op_inuser()
(and thus into the FUTEX_WAIT function).

The underlying atomic copy_from_user, copy_to_user functions were
renamed using the (cryptic) x86 convention as copy_from_user_ll and
copy_to_user_ll.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>

Showing 8 changed files with 241 additions and 315 deletions Side-by-side Diff

arch/tile/include/asm/atomic_32.h
... ... @@ -303,7 +303,14 @@
303 303 void __atomic_fault_unlock(int *lock_ptr);
304 304 #endif
305 305  
  306 +/* Return a pointer to the lock for the given address. */
  307 +int *__atomic_hashed_lock(volatile void *v);
  308 +
306 309 /* Private helper routines in lib/atomic_asm_32.S */
  310 +struct __get_user {
  311 + unsigned long val;
  312 + int err;
  313 +};
307 314 extern struct __get_user __atomic_cmpxchg(volatile int *p,
308 315 int *lock, int o, int n);
309 316 extern struct __get_user __atomic_xchg(volatile int *p, int *lock, int n);
... ... @@ -318,6 +325,9 @@
318 325 extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n);
319 326 extern u64 __atomic64_xchg_add_unless(volatile u64 *p,
320 327 int *lock, u64 o, u64 n);
  328 +
  329 +/* Return failure from the atomic wrappers. */
  330 +struct __get_user __atomic_bad_address(int __user *addr);
321 331  
322 332 #endif /* !__ASSEMBLY__ */
323 333  
arch/tile/include/asm/futex.h
... ... @@ -28,29 +28,81 @@
28 28 #include <linux/futex.h>
29 29 #include <linux/uaccess.h>
30 30 #include <linux/errno.h>
  31 +#include <asm/atomic.h>
31 32  
32   -extern struct __get_user futex_set(u32 __user *v, int i);
33   -extern struct __get_user futex_add(u32 __user *v, int n);
34   -extern struct __get_user futex_or(u32 __user *v, int n);
35   -extern struct __get_user futex_andn(u32 __user *v, int n);
36   -extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
  33 +/*
  34 + * Support macros for futex operations. Do not use these macros directly.
  35 + * They assume "ret", "val", "oparg", and "uaddr" in the lexical context.
  36 + * __futex_cmpxchg() additionally assumes "oldval".
  37 + */
37 38  
38   -#ifndef __tilegx__
39   -extern struct __get_user futex_xor(u32 __user *v, int n);
  39 +#ifdef __tilegx__
  40 +
  41 +#define __futex_asm(OP) \
  42 + asm("1: {" #OP " %1, %3, %4; movei %0, 0 }\n" \
  43 + ".pushsection .fixup,\"ax\"\n" \
  44 + "0: { movei %0, %5; j 9f }\n" \
  45 + ".section __ex_table,\"a\"\n" \
  46 + ".quad 1b, 0b\n" \
  47 + ".popsection\n" \
  48 + "9:" \
  49 + : "=r" (ret), "=r" (val), "+m" (*(uaddr)) \
  50 + : "r" (uaddr), "r" (oparg), "i" (-EFAULT))
  51 +
  52 +#define __futex_set() __futex_asm(exch4)
  53 +#define __futex_add() __futex_asm(fetchadd4)
  54 +#define __futex_or() __futex_asm(fetchor4)
  55 +#define __futex_andn() ({ oparg = ~oparg; __futex_asm(fetchand4); })
  56 +#define __futex_cmpxchg() \
  57 + ({ __insn_mtspr(SPR_CMPEXCH_VALUE, oldval); __futex_asm(cmpexch4); })
  58 +
  59 +#define __futex_xor() \
  60 + ({ \
  61 + u32 oldval, n = oparg; \
  62 + if ((ret = __get_user(oldval, uaddr)) == 0) { \
  63 + do { \
  64 + oparg = oldval ^ n; \
  65 + __futex_cmpxchg(); \
  66 + } while (ret == 0 && oldval != val); \
  67 + } \
  68 + })
  69 +
  70 +/* No need to prefetch, since the atomic ops go to the home cache anyway. */
  71 +#define __futex_prolog()
  72 +
40 73 #else
41   -static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
42   -{
43   - struct __get_user asm_ret = __get_user_4(uaddr);
44   - if (!asm_ret.err) {
45   - int oldval, newval;
46   - do {
47   - oldval = asm_ret.val;
48   - newval = oldval ^ n;
49   - asm_ret = futex_cmpxchg(uaddr, oldval, newval);
50   - } while (asm_ret.err == 0 && oldval != asm_ret.val);
  74 +
  75 +#define __futex_call(FN) \
  76 + { \
  77 + struct __get_user gu = FN((u32 __force *)uaddr, lock, oparg); \
  78 + val = gu.val; \
  79 + ret = gu.err; \
51 80 }
52   - return asm_ret;
53   -}
  81 +
  82 +#define __futex_set() __futex_call(__atomic_xchg)
  83 +#define __futex_add() __futex_call(__atomic_xchg_add)
  84 +#define __futex_or() __futex_call(__atomic_or)
  85 +#define __futex_andn() __futex_call(__atomic_andn)
  86 +#define __futex_xor() __futex_call(__atomic_xor)
  87 +
  88 +#define __futex_cmpxchg() \
  89 + { \
  90 + struct __get_user gu = __atomic_cmpxchg((u32 __force *)uaddr, \
  91 + lock, oldval, oparg); \
  92 + val = gu.val; \
  93 + ret = gu.err; \
  94 + }
  95 +
  96 +/*
  97 + * Find the lock pointer for the atomic calls to use, and issue a
  98 + * prefetch to the user address to bring it into cache. Similar to
  99 + * __atomic_setup(), but we can't do a read into the L1 since it might
  100 + * fault; instead we do a prefetch into the L2.
  101 + */
  102 +#define __futex_prolog() \
  103 + int *lock; \
  104 + __insn_prefetch(uaddr); \
  105 + lock = __atomic_hashed_lock((int __force *)uaddr)
54 106 #endif
55 107  
56 108 static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
57 109  
... ... @@ -59,9 +111,13 @@
59 111 int cmp = (encoded_op >> 24) & 15;
60 112 int oparg = (encoded_op << 8) >> 20;
61 113 int cmparg = (encoded_op << 20) >> 20;
62   - int ret;
63   - struct __get_user asm_ret;
  114 + int uninitialized_var(val), ret;
64 115  
  116 + __futex_prolog();
  117 +
  118 + /* The 32-bit futex code makes this assumption, so validate it here. */
  119 + BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
  120 +
65 121 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
66 122 oparg = 1 << oparg;
67 123  
68 124  
69 125  
70 126  
71 127  
72 128  
73 129  
74 130  
75 131  
76 132  
77 133  
78 134  
79 135  
... ... @@ -71,46 +127,45 @@
71 127 pagefault_disable();
72 128 switch (op) {
73 129 case FUTEX_OP_SET:
74   - asm_ret = futex_set(uaddr, oparg);
  130 + __futex_set();
75 131 break;
76 132 case FUTEX_OP_ADD:
77   - asm_ret = futex_add(uaddr, oparg);
  133 + __futex_add();
78 134 break;
79 135 case FUTEX_OP_OR:
80   - asm_ret = futex_or(uaddr, oparg);
  136 + __futex_or();
81 137 break;
82 138 case FUTEX_OP_ANDN:
83   - asm_ret = futex_andn(uaddr, oparg);
  139 + __futex_andn();
84 140 break;
85 141 case FUTEX_OP_XOR:
86   - asm_ret = futex_xor(uaddr, oparg);
  142 + __futex_xor();
87 143 break;
88 144 default:
89   - asm_ret.err = -ENOSYS;
  145 + ret = -ENOSYS;
  146 + break;
90 147 }
91 148 pagefault_enable();
92 149  
93   - ret = asm_ret.err;
94   -
95 150 if (!ret) {
96 151 switch (cmp) {
97 152 case FUTEX_OP_CMP_EQ:
98   - ret = (asm_ret.val == cmparg);
  153 + ret = (val == cmparg);
99 154 break;
100 155 case FUTEX_OP_CMP_NE:
101   - ret = (asm_ret.val != cmparg);
  156 + ret = (val != cmparg);
102 157 break;
103 158 case FUTEX_OP_CMP_LT:
104   - ret = (asm_ret.val < cmparg);
  159 + ret = (val < cmparg);
105 160 break;
106 161 case FUTEX_OP_CMP_GE:
107   - ret = (asm_ret.val >= cmparg);
  162 + ret = (val >= cmparg);
108 163 break;
109 164 case FUTEX_OP_CMP_LE:
110   - ret = (asm_ret.val <= cmparg);
  165 + ret = (val <= cmparg);
111 166 break;
112 167 case FUTEX_OP_CMP_GT:
113   - ret = (asm_ret.val > cmparg);
  168 + ret = (val > cmparg);
114 169 break;
115 170 default:
116 171 ret = -ENOSYS;
117 172  
118 173  
119 174  
120 175  
... ... @@ -120,22 +175,20 @@
120 175 }
121 176  
122 177 static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
123   - u32 oldval, u32 newval)
  178 + u32 oldval, u32 oparg)
124 179 {
125   - struct __get_user asm_ret;
  180 + int ret, val;
126 181  
  182 + __futex_prolog();
  183 +
127 184 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
128 185 return -EFAULT;
129 186  
130   - asm_ret = futex_cmpxchg(uaddr, oldval, newval);
131   - *uval = asm_ret.val;
132   - return asm_ret.err;
133   -}
  187 + __futex_cmpxchg();
134 188  
135   -#ifndef __tilegx__
136   -/* Return failure from the atomic wrappers. */
137   -struct __get_user __atomic_bad_address(int __user *addr);
138   -#endif
  189 + *uval = val;
  190 + return ret;
  191 +}
139 192  
140 193 #endif /* !__ASSEMBLY__ */
141 194  
arch/tile/include/asm/uaccess.h
... ... @@ -114,45 +114,75 @@
114 114 extern int fixup_exception(struct pt_regs *regs);
115 115  
116 116 /*
117   - * We return the __get_user_N function results in a structure,
118   - * thus in r0 and r1. If "err" is zero, "val" is the result
119   - * of the read; otherwise, "err" is -EFAULT.
  117 + * Support macros for __get_user().
120 118 *
121   - * We rarely need 8-byte values on a 32-bit architecture, but
122   - * we size the structure to accommodate. In practice, for the
123   - * the smaller reads, we can zero the high word for free, and
124   - * the caller will ignore it by virtue of casting anyway.
  119 + * Implementation note: The "case 8" logic of casting to the type of
  120 + * the result of subtracting the value from itself is basically a way
  121 + * of keeping all integer types the same, but casting any pointers to
  122 + * ptrdiff_t, i.e. also an integer type. This way there are no
  123 + * questionable casts seen by the compiler on an ILP32 platform.
  124 + *
  125 + * Note that __get_user() and __put_user() assume proper alignment.
125 126 */
126   -struct __get_user {
127   - unsigned long long val;
128   - int err;
129   -};
130 127  
131   -/*
132   - * FIXME: we should express these as inline extended assembler, since
133   - * they're fundamentally just a variable dereference and some
134   - * supporting exception_table gunk. Note that (a la i386) we can
135   - * extend the copy_to_user and copy_from_user routines to call into
136   - * such extended assembler routines, though we will have to use a
137   - * different return code in that case (1, 2, or 4, rather than -EFAULT).
138   - */
139   -extern struct __get_user __get_user_1(const void __user *);
140   -extern struct __get_user __get_user_2(const void __user *);
141   -extern struct __get_user __get_user_4(const void __user *);
142   -extern struct __get_user __get_user_8(const void __user *);
143   -extern int __put_user_1(long, void __user *);
144   -extern int __put_user_2(long, void __user *);
145   -extern int __put_user_4(long, void __user *);
146   -extern int __put_user_8(long long, void __user *);
  128 +#ifdef __LP64__
  129 +#define _ASM_PTR ".quad"
  130 +#else
  131 +#define _ASM_PTR ".long"
  132 +#endif
147 133  
148   -/* Unimplemented routines to cause linker failures */
149   -extern struct __get_user __get_user_bad(void);
150   -extern int __put_user_bad(void);
  134 +#define __get_user_asm(OP, x, ptr, ret) \
  135 + asm volatile("1: {" #OP " %1, %2; movei %0, 0 }\n" \
  136 + ".pushsection .fixup,\"ax\"\n" \
  137 + "0: { movei %1, 0; movei %0, %3 }\n" \
  138 + "j 9f\n" \
  139 + ".section __ex_table,\"a\"\n" \
  140 + _ASM_PTR " 1b, 0b\n" \
  141 + ".popsection\n" \
  142 + "9:" \
  143 + : "=r" (ret), "=r" (x) \
  144 + : "r" (ptr), "i" (-EFAULT))
151 145  
152   -/*
153   - * Careful: we have to cast the result to the type of the pointer
154   - * for sign reasons.
155   - */
  146 +#ifdef __tilegx__
  147 +#define __get_user_1(x, ptr, ret) __get_user_asm(ld1u, x, ptr, ret)
  148 +#define __get_user_2(x, ptr, ret) __get_user_asm(ld2u, x, ptr, ret)
  149 +#define __get_user_4(x, ptr, ret) __get_user_asm(ld4u, x, ptr, ret)
  150 +#define __get_user_8(x, ptr, ret) __get_user_asm(ld, x, ptr, ret)
  151 +#else
  152 +#define __get_user_1(x, ptr, ret) __get_user_asm(lb_u, x, ptr, ret)
  153 +#define __get_user_2(x, ptr, ret) __get_user_asm(lh_u, x, ptr, ret)
  154 +#define __get_user_4(x, ptr, ret) __get_user_asm(lw, x, ptr, ret)
  155 +#ifdef __LITTLE_ENDIAN
  156 +#define __lo32(a, b) a
  157 +#define __hi32(a, b) b
  158 +#else
  159 +#define __lo32(a, b) b
  160 +#define __hi32(a, b) a
  161 +#endif
  162 +#define __get_user_8(x, ptr, ret) \
  163 + ({ \
  164 + unsigned int __a, __b; \
  165 + asm volatile("1: { lw %1, %3; addi %2, %3, 4 }\n" \
  166 + "2: { lw %2, %2; movei %0, 0 }\n" \
  167 + ".pushsection .fixup,\"ax\"\n" \
  168 + "0: { movei %1, 0; movei %2, 0 }\n" \
  169 + "{ movei %0, %4; j 9f }\n" \
  170 + ".section __ex_table,\"a\"\n" \
  171 + ".word 1b, 0b\n" \
  172 + ".word 2b, 0b\n" \
  173 + ".popsection\n" \
  174 + "9:" \
  175 + : "=r" (ret), "=r" (__a), "=&r" (__b) \
  176 + : "r" (ptr), "i" (-EFAULT)); \
  177 + (x) = (__typeof(x))(__typeof((x)-(x))) \
  178 + (((u64)__hi32(__a, __b) << 32) | \
  179 + __lo32(__a, __b)); \
  180 + })
  181 +#endif
  182 +
  183 +extern int __get_user_bad(void)
  184 + __attribute__((warning("sizeof __get_user argument not 1, 2, 4 or 8")));
  185 +
156 186 /**
157 187 * __get_user: - Get a simple variable from user space, with less checking.
158 188 * @x: Variable to store result.
159 189  
... ... @@ -174,31 +204,63 @@
174 204 * function.
175 205 */
176 206 #define __get_user(x, ptr) \
177   -({ struct __get_user __ret; \
178   - __typeof__(*(ptr)) const __user *__gu_addr = (ptr); \
179   - __chk_user_ptr(__gu_addr); \
180   - switch (sizeof(*(__gu_addr))) { \
181   - case 1: \
182   - __ret = __get_user_1(__gu_addr); \
183   - break; \
184   - case 2: \
185   - __ret = __get_user_2(__gu_addr); \
186   - break; \
187   - case 4: \
188   - __ret = __get_user_4(__gu_addr); \
189   - break; \
190   - case 8: \
191   - __ret = __get_user_8(__gu_addr); \
192   - break; \
193   - default: \
194   - __ret = __get_user_bad(); \
195   - break; \
196   - } \
197   - (x) = (__typeof__(*__gu_addr)) (__typeof__(*__gu_addr - *__gu_addr)) \
198   - __ret.val; \
199   - __ret.err; \
200   -})
  207 + ({ \
  208 + int __ret; \
  209 + __chk_user_ptr(ptr); \
  210 + switch (sizeof(*(ptr))) { \
  211 + case 1: __get_user_1(x, ptr, __ret); break; \
  212 + case 2: __get_user_2(x, ptr, __ret); break; \
  213 + case 4: __get_user_4(x, ptr, __ret); break; \
  214 + case 8: __get_user_8(x, ptr, __ret); break; \
  215 + default: __ret = __get_user_bad(); break; \
  216 + } \
  217 + __ret; \
  218 + })
201 219  
  220 +/* Support macros for __put_user(). */
  221 +
  222 +#define __put_user_asm(OP, x, ptr, ret) \
  223 + asm volatile("1: {" #OP " %1, %2; movei %0, 0 }\n" \
  224 + ".pushsection .fixup,\"ax\"\n" \
  225 + "0: { movei %0, %3; j 9f }\n" \
  226 + ".section __ex_table,\"a\"\n" \
  227 + _ASM_PTR " 1b, 0b\n" \
  228 + ".popsection\n" \
  229 + "9:" \
  230 + : "=r" (ret) \
  231 + : "r" (ptr), "r" (x), "i" (-EFAULT))
  232 +
  233 +#ifdef __tilegx__
  234 +#define __put_user_1(x, ptr, ret) __put_user_asm(st1, x, ptr, ret)
  235 +#define __put_user_2(x, ptr, ret) __put_user_asm(st2, x, ptr, ret)
  236 +#define __put_user_4(x, ptr, ret) __put_user_asm(st4, x, ptr, ret)
  237 +#define __put_user_8(x, ptr, ret) __put_user_asm(st, x, ptr, ret)
  238 +#else
  239 +#define __put_user_1(x, ptr, ret) __put_user_asm(sb, x, ptr, ret)
  240 +#define __put_user_2(x, ptr, ret) __put_user_asm(sh, x, ptr, ret)
  241 +#define __put_user_4(x, ptr, ret) __put_user_asm(sw, x, ptr, ret)
  242 +#define __put_user_8(x, ptr, ret) \
  243 + ({ \
  244 + u64 __x = (__typeof((x)-(x)))(x); \
  245 + int __lo = (int) __x, __hi = (int) (__x >> 32); \
  246 + asm volatile("1: { sw %1, %2; addi %0, %1, 4 }\n" \
  247 + "2: { sw %0, %3; movei %0, 0 }\n" \
  248 + ".pushsection .fixup,\"ax\"\n" \
  249 + "0: { movei %0, %4; j 9f }\n" \
  250 + ".section __ex_table,\"a\"\n" \
  251 + ".word 1b, 0b\n" \
  252 + ".word 2b, 0b\n" \
  253 + ".popsection\n" \
  254 + "9:" \
  255 + : "=&r" (ret) \
  256 + : "r" (ptr), "r" (__lo32(__lo, __hi)), \
  257 + "r" (__hi32(__lo, __hi)), "i" (-EFAULT)); \
  258 + })
  259 +#endif
  260 +
  261 +extern int __put_user_bad(void)
  262 + __attribute__((warning("sizeof __put_user argument not 1, 2, 4 or 8")));
  263 +
202 264 /**
203 265 * __put_user: - Write a simple value into user space, with less checking.
204 266 * @x: Value to copy to user space.
205 267  
206 268  
... ... @@ -217,39 +279,19 @@
217 279 * function.
218 280 *
219 281 * Returns zero on success, or -EFAULT on error.
220   - *
221   - * Implementation note: The "case 8" logic of casting to the type of
222   - * the result of subtracting the value from itself is basically a way
223   - * of keeping all integer types the same, but casting any pointers to
224   - * ptrdiff_t, i.e. also an integer type. This way there are no
225   - * questionable casts seen by the compiler on an ILP32 platform.
226 282 */
227 283 #define __put_user(x, ptr) \
228 284 ({ \
229   - int __pu_err = 0; \
230   - __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
231   - typeof(*__pu_addr) __pu_val = (x); \
232   - __chk_user_ptr(__pu_addr); \
233   - switch (sizeof(__pu_val)) { \
234   - case 1: \
235   - __pu_err = __put_user_1((long)__pu_val, __pu_addr); \
236   - break; \
237   - case 2: \
238   - __pu_err = __put_user_2((long)__pu_val, __pu_addr); \
239   - break; \
240   - case 4: \
241   - __pu_err = __put_user_4((long)__pu_val, __pu_addr); \
242   - break; \
243   - case 8: \
244   - __pu_err = \
245   - __put_user_8((__typeof__(__pu_val - __pu_val))__pu_val,\
246   - __pu_addr); \
247   - break; \
248   - default: \
249   - __pu_err = __put_user_bad(); \
250   - break; \
  285 + int __ret; \
  286 + __chk_user_ptr(ptr); \
  287 + switch (sizeof(*(ptr))) { \
  288 + case 1: __put_user_1(x, ptr, __ret); break; \
  289 + case 2: __put_user_2(x, ptr, __ret); break; \
  290 + case 4: __put_user_4(x, ptr, __ret); break; \
  291 + case 8: __put_user_8(x, ptr, __ret); break; \
  292 + default: __ret = __put_user_bad(); break; \
251 293 } \
252   - __pu_err; \
  294 + __ret; \
253 295 })
254 296  
255 297 /*
... ... @@ -378,7 +420,7 @@
378 420 /**
379 421 * __copy_in_user() - copy data within user space, with less checking.
380 422 * @to: Destination address, in user space.
381   - * @from: Source address, in kernel space.
  423 + * @from: Source address, in user space.
382 424 * @n: Number of bytes to copy.
383 425 *
384 426 * Context: User context only. This function may sleep.
arch/tile/kernel/Makefile
... ... @@ -9,7 +9,6 @@
9 9 intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o
10 10  
11 11 obj-$(CONFIG_HARDWALL) += hardwall.o
12   -obj-$(CONFIG_TILEGX) += futex_64.o
13 12 obj-$(CONFIG_COMPAT) += compat.o compat_signal.o
14 13 obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o
15 14 obj-$(CONFIG_MODULES) += module.o
arch/tile/lib/atomic_32.c
... ... @@ -18,7 +18,6 @@
18 18 #include <linux/module.h>
19 19 #include <linux/mm.h>
20 20 #include <linux/atomic.h>
21   -#include <asm/futex.h>
22 21 #include <arch/chip.h>
23 22  
24 23 /* See <asm/atomic_32.h> */
... ... @@ -50,7 +49,7 @@
50 49  
51 50 #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
52 51  
53   -static inline int *__atomic_hashed_lock(volatile void *v)
  52 +int *__atomic_hashed_lock(volatile void *v)
54 53 {
55 54 /* NOTE: this code must match "sys_cmpxchg" in kernel/intvec_32.S */
56 55 #if ATOMIC_LOCKS_FOUND_VIA_TABLE()
... ... @@ -191,47 +190,6 @@
191 190 EXPORT_SYMBOL(_atomic64_cmpxchg);
192 191  
193 192  
194   -static inline int *__futex_setup(int __user *v)
195   -{
196   - /*
197   - * Issue a prefetch to the counter to bring it into cache.
198   - * As for __atomic_setup, but we can't do a read into the L1
199   - * since it might fault; instead we do a prefetch into the L2.
200   - */
201   - __insn_prefetch(v);
202   - return __atomic_hashed_lock((int __force *)v);
203   -}
204   -
205   -struct __get_user futex_set(u32 __user *v, int i)
206   -{
207   - return __atomic_xchg((int __force *)v, __futex_setup(v), i);
208   -}
209   -
210   -struct __get_user futex_add(u32 __user *v, int n)
211   -{
212   - return __atomic_xchg_add((int __force *)v, __futex_setup(v), n);
213   -}
214   -
215   -struct __get_user futex_or(u32 __user *v, int n)
216   -{
217   - return __atomic_or((int __force *)v, __futex_setup(v), n);
218   -}
219   -
220   -struct __get_user futex_andn(u32 __user *v, int n)
221   -{
222   - return __atomic_andn((int __force *)v, __futex_setup(v), n);
223   -}
224   -
225   -struct __get_user futex_xor(u32 __user *v, int n)
226   -{
227   - return __atomic_xor((int __force *)v, __futex_setup(v), n);
228   -}
229   -
230   -struct __get_user futex_cmpxchg(u32 __user *v, int o, int n)
231   -{
232   - return __atomic_cmpxchg((int __force *)v, __futex_setup(v), o, n);
233   -}
234   -
235 193 /*
236 194 * If any of the atomic or futex routines hit a bad address (not in
237 195 * the page tables at kernel PL) this routine is called. The futex
... ... @@ -323,8 +281,5 @@
323 281 BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
324 282  
325 283 #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
326   -
327   - /* The futex code makes this assumption, so we validate it here. */
328   - BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
329 284 }
arch/tile/lib/exports.c
... ... @@ -18,14 +18,6 @@
18 18  
19 19 /* arch/tile/lib/usercopy.S */
20 20 #include <linux/uaccess.h>
21   -EXPORT_SYMBOL(__get_user_1);
22   -EXPORT_SYMBOL(__get_user_2);
23   -EXPORT_SYMBOL(__get_user_4);
24   -EXPORT_SYMBOL(__get_user_8);
25   -EXPORT_SYMBOL(__put_user_1);
26   -EXPORT_SYMBOL(__put_user_2);
27   -EXPORT_SYMBOL(__put_user_4);
28   -EXPORT_SYMBOL(__put_user_8);
29 21 EXPORT_SYMBOL(strnlen_user_asm);
30 22 EXPORT_SYMBOL(strncpy_from_user_asm);
31 23 EXPORT_SYMBOL(clear_user_asm);
arch/tile/lib/usercopy_32.S
... ... @@ -19,82 +19,6 @@
19 19  
20 20 /* Access user memory, but use MMU to avoid propagating kernel exceptions. */
21 21  
22   - .pushsection .fixup,"ax"
23   -
24   -get_user_fault:
25   - { move r0, zero; move r1, zero }
26   - { movei r2, -EFAULT; jrp lr }
27   - ENDPROC(get_user_fault)
28   -
29   -put_user_fault:
30   - { movei r0, -EFAULT; jrp lr }
31   - ENDPROC(put_user_fault)
32   -
33   - .popsection
34   -
35   -/*
36   - * __get_user_N functions take a pointer in r0, and return 0 in r2
37   - * on success, with the value in r0; or else -EFAULT in r2.
38   - */
39   -#define __get_user_N(bytes, LOAD) \
40   - STD_ENTRY(__get_user_##bytes); \
41   -1: { LOAD r0, r0; move r1, zero; move r2, zero }; \
42   - jrp lr; \
43   - STD_ENDPROC(__get_user_##bytes); \
44   - .pushsection __ex_table,"a"; \
45   - .word 1b, get_user_fault; \
46   - .popsection
47   -
48   -__get_user_N(1, lb_u)
49   -__get_user_N(2, lh_u)
50   -__get_user_N(4, lw)
51   -
52   -/*
53   - * __get_user_8 takes a pointer in r0, and returns 0 in r2
54   - * on success, with the value in r0/r1; or else -EFAULT in r2.
55   - */
56   - STD_ENTRY(__get_user_8);
57   -1: { lw r0, r0; addi r1, r0, 4 };
58   -2: { lw r1, r1; move r2, zero };
59   - jrp lr;
60   - STD_ENDPROC(__get_user_8);
61   - .pushsection __ex_table,"a";
62   - .word 1b, get_user_fault;
63   - .word 2b, get_user_fault;
64   - .popsection
65   -
66   -/*
67   - * __put_user_N functions take a value in r0 and a pointer in r1,
68   - * and return 0 in r0 on success or -EFAULT on failure.
69   - */
70   -#define __put_user_N(bytes, STORE) \
71   - STD_ENTRY(__put_user_##bytes); \
72   -1: { STORE r1, r0; move r0, zero }; \
73   - jrp lr; \
74   - STD_ENDPROC(__put_user_##bytes); \
75   - .pushsection __ex_table,"a"; \
76   - .word 1b, put_user_fault; \
77   - .popsection
78   -
79   -__put_user_N(1, sb)
80   -__put_user_N(2, sh)
81   -__put_user_N(4, sw)
82   -
83   -/*
84   - * __put_user_8 takes a value in r0/r1 and a pointer in r2,
85   - * and returns 0 in r0 on success or -EFAULT on failure.
86   - */
87   -STD_ENTRY(__put_user_8)
88   -1: { sw r2, r0; addi r2, r2, 4 }
89   -2: { sw r2, r1; move r0, zero }
90   - jrp lr
91   - STD_ENDPROC(__put_user_8)
92   - .pushsection __ex_table,"a"
93   - .word 1b, put_user_fault
94   - .word 2b, put_user_fault
95   - .popsection
96   -
97   -
98 22 /*
99 23 * strnlen_user_asm takes the pointer in r0, and the length bound in r1.
100 24 * It returns the length, including the terminating NUL, or zero on exception.
arch/tile/lib/usercopy_64.S
... ... @@ -19,55 +19,6 @@
19 19  
20 20 /* Access user memory, but use MMU to avoid propagating kernel exceptions. */
21 21  
22   - .pushsection .fixup,"ax"
23   -
24   -get_user_fault:
25   - { movei r1, -EFAULT; move r0, zero }
26   - jrp lr
27   - ENDPROC(get_user_fault)
28   -
29   -put_user_fault:
30   - { movei r0, -EFAULT; jrp lr }
31   - ENDPROC(put_user_fault)
32   -
33   - .popsection
34   -
35   -/*
36   - * __get_user_N functions take a pointer in r0, and return 0 in r1
37   - * on success, with the value in r0; or else -EFAULT in r1.
38   - */
39   -#define __get_user_N(bytes, LOAD) \
40   - STD_ENTRY(__get_user_##bytes); \
41   -1: { LOAD r0, r0; move r1, zero }; \
42   - jrp lr; \
43   - STD_ENDPROC(__get_user_##bytes); \
44   - .pushsection __ex_table,"a"; \
45   - .quad 1b, get_user_fault; \
46   - .popsection
47   -
48   -__get_user_N(1, ld1u)
49   -__get_user_N(2, ld2u)
50   -__get_user_N(4, ld4u)
51   -__get_user_N(8, ld)
52   -
53   -/*
54   - * __put_user_N functions take a value in r0 and a pointer in r1,
55   - * and return 0 in r0 on success or -EFAULT on failure.
56   - */
57   -#define __put_user_N(bytes, STORE) \
58   - STD_ENTRY(__put_user_##bytes); \
59   -1: { STORE r1, r0; move r0, zero }; \
60   - jrp lr; \
61   - STD_ENDPROC(__put_user_##bytes); \
62   - .pushsection __ex_table,"a"; \
63   - .quad 1b, put_user_fault; \
64   - .popsection
65   -
66   -__put_user_N(1, st1)
67   -__put_user_N(2, st2)
68   -__put_user_N(4, st4)
69   -__put_user_N(8, st)
70   -
71 22 /*
72 23 * strnlen_user_asm takes the pointer in r0, and the length bound in r1.
73 24 * It returns the length, including the terminating NUL, or zero on exception.