aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-01-23 11:15:30 -0500
committerRalf Baechle <ralf@linux-mips.org>2006-02-07 08:30:23 -0500
commit4feb8f8f4589d1cb1594e344c9672ec40f627ab4 (patch)
tree21f603c3537c2533b68ce1e7f3adfa7b950dbdbc /include/asm-mips
parentc03bc121212ecb36120b118a94c1b91a2e07b7b2 (diff)
[MIPS] Bullet proof uaccess.h against 4.0.1 miss-compilation.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'include/asm-mips')
-rw-r--r--include/asm-mips/uaccess.h71
1 files changed, 36 insertions, 35 deletions
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 41bb96bb2120..91d813a37823 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -202,49 +202,49 @@ struct __large_struct { unsigned long buf[100]; };
202 * Yuck. We need two variants, one for 64bit operation and one 202 * Yuck. We need two variants, one for 64bit operation and one
203 * for 32 bit mode and old iron. 203 * for 32 bit mode and old iron.
204 */ 204 */
205#ifdef __mips64 205#ifdef CONFIG_32BIT
206#define __GET_USER_DW(ptr) __get_user_asm("ld", ptr) 206#define __GET_USER_DW(val, ptr) __get_user_asm_ll32(val, ptr)
207#else 207#endif
208#define __GET_USER_DW(ptr) __get_user_asm_ll32(ptr) 208#ifdef CONFIG_64BIT
209#define __GET_USER_DW(val, ptr) __get_user_asm(val, "ld", ptr)
209#endif 210#endif
210 211
211#define __get_user_nocheck(x,ptr,size) \ 212extern void __get_user_unknown(void);
212({ \ 213
213 __typeof(*(ptr)) __gu_val = (__typeof(*(ptr))) 0; \ 214#define __get_user_common(val, size, ptr) \
214 long __gu_err = 0; \ 215do { \
215 \
216 switch (size) { \ 216 switch (size) { \
217 case 1: __get_user_asm("lb", ptr); break; \ 217 case 1: __get_user_asm(val, "lb", ptr); break; \
218 case 2: __get_user_asm("lh", ptr); break; \ 218 case 2: __get_user_asm(val, "lh", ptr); break; \
219 case 4: __get_user_asm("lw", ptr); break; \ 219 case 4: __get_user_asm(val, "lw", ptr); break; \
220 case 8: __GET_USER_DW(ptr); break; \ 220 case 8: __GET_USER_DW(val, ptr); break; \
221 default: __get_user_unknown(); break; \ 221 default: __get_user_unknown(); break; \
222 } \ 222 } \
223 (x) = (__typeof__(*(ptr))) __gu_val; \ 223} while (0)
224
225#define __get_user_nocheck(x,ptr,size) \
226({ \
227 long __gu_err; \
228 \
229 __get_user_common((x), size, ptr); \
224 __gu_err; \ 230 __gu_err; \
225}) 231})
226 232
227#define __get_user_check(x,ptr,size) \ 233#define __get_user_check(x,ptr,size) \
228({ \ 234({ \
229 const __typeof__(*(ptr)) __user * __gu_addr = (ptr); \
230 __typeof__(*(ptr)) __gu_val = 0; \
231 long __gu_err = -EFAULT; \ 235 long __gu_err = -EFAULT; \
236 const void __user * __gu_ptr = (ptr); \
237 \
238 if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \
239 __get_user_common((x), size, __gu_ptr); \
232 \ 240 \
233 if (likely(access_ok(VERIFY_READ, __gu_addr, size))) { \
234 switch (size) { \
235 case 1: __get_user_asm("lb", __gu_addr); break; \
236 case 2: __get_user_asm("lh", __gu_addr); break; \
237 case 4: __get_user_asm("lw", __gu_addr); break; \
238 case 8: __GET_USER_DW(__gu_addr); break; \
239 default: __get_user_unknown(); break; \
240 } \
241 } \
242 (x) = (__typeof__(*(ptr))) __gu_val; \
243 __gu_err; \ 241 __gu_err; \
244}) 242})
245 243
246#define __get_user_asm(insn, addr) \ 244#define __get_user_asm(val, insn, addr) \
247{ \ 245{ \
246 long __gu_tmp; \
247 \
248 __asm__ __volatile__( \ 248 __asm__ __volatile__( \
249 "1: " insn " %1, %3 \n" \ 249 "1: " insn " %1, %3 \n" \
250 "2: \n" \ 250 "2: \n" \
@@ -255,14 +255,16 @@ struct __large_struct { unsigned long buf[100]; };
255 " .section __ex_table,\"a\" \n" \ 255 " .section __ex_table,\"a\" \n" \
256 " "__UA_ADDR "\t1b, 3b \n" \ 256 " "__UA_ADDR "\t1b, 3b \n" \
257 " .previous \n" \ 257 " .previous \n" \
258 : "=r" (__gu_err), "=r" (__gu_val) \ 258 : "=r" (__gu_err), "=r" (__gu_tmp) \
259 : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \ 259 : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \
260 \
261 (val) = (__typeof__(val)) __gu_tmp; \
260} 262}
261 263
262/* 264/*
263 * Get a long long 64 using 32 bit registers. 265 * Get a long long 64 using 32 bit registers.
264 */ 266 */
265#define __get_user_asm_ll32(addr) \ 267#define __get_user_asm_ll32(val, addr) \
266{ \ 268{ \
267 __asm__ __volatile__( \ 269 __asm__ __volatile__( \
268 "1: lw %1, (%3) \n" \ 270 "1: lw %1, (%3) \n" \
@@ -278,21 +280,20 @@ struct __large_struct { unsigned long buf[100]; };
278 " " __UA_ADDR " 1b, 4b \n" \ 280 " " __UA_ADDR " 1b, 4b \n" \
279 " " __UA_ADDR " 2b, 4b \n" \ 281 " " __UA_ADDR " 2b, 4b \n" \
280 " .previous \n" \ 282 " .previous \n" \
281 : "=r" (__gu_err), "=&r" (__gu_val) \ 283 : "=r" (__gu_err), "=&r" (val) \
282 : "0" (0), "r" (addr), "i" (-EFAULT)); \ 284 : "0" (0), "r" (addr), "i" (-EFAULT)); \
283} 285}
284 286
285extern void __get_user_unknown(void);
286
287/* 287/*
288 * Yuck. We need two variants, one for 64bit operation and one 288 * Yuck. We need two variants, one for 64bit operation and one
289 * for 32 bit mode and old iron. 289 * for 32 bit mode and old iron.
290 */ 290 */
291#ifdef __mips64 291#ifdef CONFIG_32BIT
292#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
293#else
294#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr) 292#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr)
295#endif 293#endif
294#ifdef CONFIG_64BIT
295#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
296#endif
296 297
297#define __put_user_nocheck(x,ptr,size) \ 298#define __put_user_nocheck(x,ptr,size) \
298({ \ 299({ \