aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips/uaccess.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-mips/uaccess.h')
-rw-r--r--include/asm-mips/uaccess.h156
1 files changed, 70 insertions, 86 deletions
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 5c2c98329012..b41901db69b8 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -196,63 +196,56 @@
196 __get_user_nocheck((x),(ptr),sizeof(*(ptr))) 196 __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
197 197
198struct __large_struct { unsigned long buf[100]; }; 198struct __large_struct { unsigned long buf[100]; };
199#define __m(x) (*(struct __large_struct *)(x)) 199#define __m(x) (*(struct __large_struct __user *)(x))
200 200
201/* 201/*
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 __mips64
206#define __GET_USER_DW(__gu_err) __get_user_asm("ld", __gu_err) 206#define __GET_USER_DW(ptr) __get_user_asm("ld", ptr)
207#else 207#else
208#define __GET_USER_DW(__gu_err) __get_user_asm_ll32(__gu_err) 208#define __GET_USER_DW(ptr) __get_user_asm_ll32(ptr)
209#endif 209#endif
210 210
211#define __get_user_nocheck(x,ptr,size) \ 211#define __get_user_nocheck(x,ptr,size) \
212({ \ 212({ \
213 __typeof(*(ptr)) __gu_val = 0; \ 213 __typeof(*(ptr)) __gu_val = (__typeof(*(ptr))) 0; \
214 long __gu_addr; \
215 long __gu_err = 0; \ 214 long __gu_err = 0; \
216 \ 215 \
217 might_sleep(); \ 216 might_sleep(); \
218 __gu_addr = (long) (ptr); \
219 switch (size) { \ 217 switch (size) { \
220 case 1: __get_user_asm("lb", __gu_err); break; \ 218 case 1: __get_user_asm("lb", ptr); break; \
221 case 2: __get_user_asm("lh", __gu_err); break; \ 219 case 2: __get_user_asm("lh", ptr); break; \
222 case 4: __get_user_asm("lw", __gu_err); break; \ 220 case 4: __get_user_asm("lw", ptr); break; \
223 case 8: __GET_USER_DW(__gu_err); break; \ 221 case 8: __GET_USER_DW(ptr); break; \
224 default: __get_user_unknown(); break; \ 222 default: __get_user_unknown(); break; \
225 } \ 223 } \
226 x = (__typeof__(*(ptr))) __gu_val; \ 224 (x) = (__typeof__(*(ptr))) __gu_val; \
227 __gu_err; \ 225 __gu_err; \
228}) 226})
229 227
230#define __get_user_check(x,ptr,size) \ 228#define __get_user_check(x,ptr,size) \
231({ \ 229({ \
230 const __typeof__(*(ptr)) __user * __gu_addr = (ptr); \
232 __typeof__(*(ptr)) __gu_val = 0; \ 231 __typeof__(*(ptr)) __gu_val = 0; \
233 long __gu_addr; \ 232 long __gu_err = -EFAULT; \
234 long __gu_err; \
235 \ 233 \
236 might_sleep(); \ 234 if (likely(access_ok(VERIFY_READ, __gu_addr, size))) { \
237 __gu_addr = (long) (ptr); \
238 __gu_err = access_ok(VERIFY_READ, (void *) __gu_addr, size) \
239 ? 0 : -EFAULT; \
240 \
241 if (likely(!__gu_err)) { \
242 switch (size) { \ 235 switch (size) { \
243 case 1: __get_user_asm("lb", __gu_err); break; \ 236 case 1: __get_user_asm("lb", __gu_addr); break; \
244 case 2: __get_user_asm("lh", __gu_err); break; \ 237 case 2: __get_user_asm("lh", __gu_addr); break; \
245 case 4: __get_user_asm("lw", __gu_err); break; \ 238 case 4: __get_user_asm("lw", __gu_addr); break; \
246 case 8: __GET_USER_DW(__gu_err); break; \ 239 case 8: __GET_USER_DW(__gu_addr); break; \
247 default: __get_user_unknown(); break; \ 240 default: __get_user_unknown(); break; \
248 } \ 241 } \
249 } \ 242 } \
250 x = (__typeof__(*(ptr))) __gu_val; \ 243 (x) = (__typeof__(*(ptr))) __gu_val; \
251 __gu_err; \ 244 __gu_err; \
252}) 245})
253 246
254#define __get_user_asm(insn,__gu_err) \ 247#define __get_user_asm(insn, addr) \
255({ \ 248{ \
256 __asm__ __volatile__( \ 249 __asm__ __volatile__( \
257 "1: " insn " %1, %3 \n" \ 250 "1: " insn " %1, %3 \n" \
258 "2: \n" \ 251 "2: \n" \
@@ -264,20 +257,20 @@ struct __large_struct { unsigned long buf[100]; };
264 " "__UA_ADDR "\t1b, 3b \n" \ 257 " "__UA_ADDR "\t1b, 3b \n" \
265 " .previous \n" \ 258 " .previous \n" \
266 : "=r" (__gu_err), "=r" (__gu_val) \ 259 : "=r" (__gu_err), "=r" (__gu_val) \
267 : "0" (__gu_err), "o" (__m(__gu_addr)), "i" (-EFAULT)); \ 260 : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \
268}) 261}
269 262
270/* 263/*
271 * Get a long long 64 using 32 bit registers. 264 * Get a long long 64 using 32 bit registers.
272 */ 265 */
273#define __get_user_asm_ll32(__gu_err) \ 266#define __get_user_asm_ll32(addr) \
274({ \ 267{ \
275 __asm__ __volatile__( \ 268 __asm__ __volatile__( \
276 "1: lw %1, %3 \n" \ 269 "1: lw %1, (%3) \n" \
277 "2: lw %D1, %4 \n" \ 270 "2: lw %D1, 4(%3) \n" \
278 " move %0, $0 \n" \ 271 " move %0, $0 \n" \
279 "3: .section .fixup,\"ax\" \n" \ 272 "3: .section .fixup,\"ax\" \n" \
280 "4: li %0, %5 \n" \ 273 "4: li %0, %4 \n" \
281 " move %1, $0 \n" \ 274 " move %1, $0 \n" \
282 " move %D1, $0 \n" \ 275 " move %D1, $0 \n" \
283 " j 3b \n" \ 276 " j 3b \n" \
@@ -287,9 +280,8 @@ struct __large_struct { unsigned long buf[100]; };
287 " " __UA_ADDR " 2b, 4b \n" \ 280 " " __UA_ADDR " 2b, 4b \n" \
288 " .previous \n" \ 281 " .previous \n" \
289 : "=r" (__gu_err), "=&r" (__gu_val) \ 282 : "=r" (__gu_err), "=&r" (__gu_val) \
290 : "0" (__gu_err), "o" (__m(__gu_addr)), \ 283 : "0" (0), "r" (addr), "i" (-EFAULT)); \
291 "o" (__m(__gu_addr + 4)), "i" (-EFAULT)); \ 284}
292})
293 285
294extern void __get_user_unknown(void); 286extern void __get_user_unknown(void);
295 287
@@ -298,25 +290,23 @@ extern void __get_user_unknown(void);
298 * for 32 bit mode and old iron. 290 * for 32 bit mode and old iron.
299 */ 291 */
300#ifdef __mips64 292#ifdef __mips64
301#define __PUT_USER_DW(__pu_val) __put_user_asm("sd", __pu_val) 293#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
302#else 294#else
303#define __PUT_USER_DW(__pu_val) __put_user_asm_ll32(__pu_val) 295#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr)
304#endif 296#endif
305 297
306#define __put_user_nocheck(x,ptr,size) \ 298#define __put_user_nocheck(x,ptr,size) \
307({ \ 299({ \
308 __typeof__(*(ptr)) __pu_val; \ 300 __typeof__(*(ptr)) __pu_val; \
309 long __pu_addr; \
310 long __pu_err = 0; \ 301 long __pu_err = 0; \
311 \ 302 \
312 might_sleep(); \ 303 might_sleep(); \
313 __pu_val = (x); \ 304 __pu_val = (x); \
314 __pu_addr = (long) (ptr); \
315 switch (size) { \ 305 switch (size) { \
316 case 1: __put_user_asm("sb", __pu_val); break; \ 306 case 1: __put_user_asm("sb", ptr); break; \
317 case 2: __put_user_asm("sh", __pu_val); break; \ 307 case 2: __put_user_asm("sh", ptr); break; \
318 case 4: __put_user_asm("sw", __pu_val); break; \ 308 case 4: __put_user_asm("sw", ptr); break; \
319 case 8: __PUT_USER_DW(__pu_val); break; \ 309 case 8: __PUT_USER_DW(ptr); break; \
320 default: __put_user_unknown(); break; \ 310 default: __put_user_unknown(); break; \
321 } \ 311 } \
322 __pu_err; \ 312 __pu_err; \
@@ -324,30 +314,24 @@ extern void __get_user_unknown(void);
324 314
325#define __put_user_check(x,ptr,size) \ 315#define __put_user_check(x,ptr,size) \
326({ \ 316({ \
327 __typeof__(*(ptr)) __pu_val; \ 317 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
328 long __pu_addr; \ 318 __typeof__(*(ptr)) __pu_val = (x); \
329 long __pu_err; \ 319 long __pu_err = -EFAULT; \
330 \ 320 \
331 might_sleep(); \ 321 if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \
332 __pu_val = (x); \
333 __pu_addr = (long) (ptr); \
334 __pu_err = access_ok(VERIFY_WRITE, (void *) __pu_addr, size) \
335 ? 0 : -EFAULT; \
336 \
337 if (likely(!__pu_err)) { \
338 switch (size) { \ 322 switch (size) { \
339 case 1: __put_user_asm("sb", __pu_val); break; \ 323 case 1: __put_user_asm("sb", __pu_addr); break; \
340 case 2: __put_user_asm("sh", __pu_val); break; \ 324 case 2: __put_user_asm("sh", __pu_addr); break; \
341 case 4: __put_user_asm("sw", __pu_val); break; \ 325 case 4: __put_user_asm("sw", __pu_addr); break; \
342 case 8: __PUT_USER_DW(__pu_val); break; \ 326 case 8: __PUT_USER_DW(__pu_addr); break; \
343 default: __put_user_unknown(); break; \ 327 default: __put_user_unknown(); break; \
344 } \ 328 } \
345 } \ 329 } \
346 __pu_err; \ 330 __pu_err; \
347}) 331})
348 332
349#define __put_user_asm(insn, __pu_val) \ 333#define __put_user_asm(insn, ptr) \
350({ \ 334{ \
351 __asm__ __volatile__( \ 335 __asm__ __volatile__( \
352 "1: " insn " %z2, %3 # __put_user_asm\n" \ 336 "1: " insn " %z2, %3 # __put_user_asm\n" \
353 "2: \n" \ 337 "2: \n" \
@@ -359,18 +343,18 @@ extern void __get_user_unknown(void);
359 " " __UA_ADDR " 1b, 3b \n" \ 343 " " __UA_ADDR " 1b, 3b \n" \
360 " .previous \n" \ 344 " .previous \n" \
361 : "=r" (__pu_err) \ 345 : "=r" (__pu_err) \
362 : "0" (__pu_err), "Jr" (__pu_val), "o" (__m(__pu_addr)), \ 346 : "0" (0), "Jr" (__pu_val), "o" (__m(ptr)), \
363 "i" (-EFAULT)); \ 347 "i" (-EFAULT)); \
364}) 348}
365 349
366#define __put_user_asm_ll32(__pu_val) \ 350#define __put_user_asm_ll32(ptr) \
367({ \ 351{ \
368 __asm__ __volatile__( \ 352 __asm__ __volatile__( \
369 "1: sw %2, %3 # __put_user_asm_ll32 \n" \ 353 "1: sw %2, (%3) # __put_user_asm_ll32 \n" \
370 "2: sw %D2, %4 \n" \ 354 "2: sw %D2, 4(%3) \n" \
371 "3: \n" \ 355 "3: \n" \
372 " .section .fixup,\"ax\" \n" \ 356 " .section .fixup,\"ax\" \n" \
373 "4: li %0, %5 \n" \ 357 "4: li %0, %4 \n" \
374 " j 3b \n" \ 358 " j 3b \n" \
375 " .previous \n" \ 359 " .previous \n" \
376 " .section __ex_table,\"a\" \n" \ 360 " .section __ex_table,\"a\" \n" \
@@ -378,9 +362,9 @@ extern void __get_user_unknown(void);
378 " " __UA_ADDR " 2b, 4b \n" \ 362 " " __UA_ADDR " 2b, 4b \n" \
379 " .previous" \ 363 " .previous" \
380 : "=r" (__pu_err) \ 364 : "=r" (__pu_err) \
381 : "0" (__pu_err), "r" (__pu_val), "o" (__m(__pu_addr)), \ 365 : "0" (0), "r" (__pu_val), "r" (ptr), \
382 "o" (__m(__pu_addr + 4)), "i" (-EFAULT)); \ 366 "i" (-EFAULT)); \
383}) 367}
384 368
385extern void __put_user_unknown(void); 369extern void __put_user_unknown(void);
386 370
@@ -403,7 +387,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
403 387
404#define __invoke_copy_to_user(to,from,n) \ 388#define __invoke_copy_to_user(to,from,n) \
405({ \ 389({ \
406 register void *__cu_to_r __asm__ ("$4"); \ 390 register void __user *__cu_to_r __asm__ ("$4"); \
407 register const void *__cu_from_r __asm__ ("$5"); \ 391 register const void *__cu_from_r __asm__ ("$5"); \
408 register long __cu_len_r __asm__ ("$6"); \ 392 register long __cu_len_r __asm__ ("$6"); \
409 \ 393 \
@@ -435,7 +419,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
435 */ 419 */
436#define __copy_to_user(to,from,n) \ 420#define __copy_to_user(to,from,n) \
437({ \ 421({ \
438 void *__cu_to; \ 422 void __user *__cu_to; \
439 const void *__cu_from; \ 423 const void *__cu_from; \
440 long __cu_len; \ 424 long __cu_len; \
441 \ 425 \
@@ -465,7 +449,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
465 */ 449 */
466#define copy_to_user(to,from,n) \ 450#define copy_to_user(to,from,n) \
467({ \ 451({ \
468 void *__cu_to; \ 452 void __user *__cu_to; \
469 const void *__cu_from; \ 453 const void *__cu_from; \
470 long __cu_len; \ 454 long __cu_len; \
471 \ 455 \
@@ -482,7 +466,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
482#define __invoke_copy_from_user(to,from,n) \ 466#define __invoke_copy_from_user(to,from,n) \
483({ \ 467({ \
484 register void *__cu_to_r __asm__ ("$4"); \ 468 register void *__cu_to_r __asm__ ("$4"); \
485 register const void *__cu_from_r __asm__ ("$5"); \ 469 register const void __user *__cu_from_r __asm__ ("$5"); \
486 register long __cu_len_r __asm__ ("$6"); \ 470 register long __cu_len_r __asm__ ("$6"); \
487 \ 471 \
488 __cu_to_r = (to); \ 472 __cu_to_r = (to); \
@@ -521,7 +505,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
521#define __copy_from_user(to,from,n) \ 505#define __copy_from_user(to,from,n) \
522({ \ 506({ \
523 void *__cu_to; \ 507 void *__cu_to; \
524 const void *__cu_from; \ 508 const void __user *__cu_from; \
525 long __cu_len; \ 509 long __cu_len; \
526 \ 510 \
527 might_sleep(); \ 511 might_sleep(); \
@@ -552,7 +536,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
552#define copy_from_user(to,from,n) \ 536#define copy_from_user(to,from,n) \
553({ \ 537({ \
554 void *__cu_to; \ 538 void *__cu_to; \
555 const void *__cu_from; \ 539 const void __user *__cu_from; \
556 long __cu_len; \ 540 long __cu_len; \
557 \ 541 \
558 might_sleep(); \ 542 might_sleep(); \
@@ -569,8 +553,8 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
569 553
570#define copy_in_user(to,from,n) \ 554#define copy_in_user(to,from,n) \
571({ \ 555({ \
572 void *__cu_to; \ 556 void __user *__cu_to; \
573 const void *__cu_from; \ 557 const void __user *__cu_from; \
574 long __cu_len; \ 558 long __cu_len; \
575 \ 559 \
576 might_sleep(); \ 560 might_sleep(); \
@@ -596,7 +580,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
596 * On success, this will be zero. 580 * On success, this will be zero.
597 */ 581 */
598static inline __kernel_size_t 582static inline __kernel_size_t
599__clear_user(void *addr, __kernel_size_t size) 583__clear_user(void __user *addr, __kernel_size_t size)
600{ 584{
601 __kernel_size_t res; 585 __kernel_size_t res;
602 586
@@ -616,7 +600,7 @@ __clear_user(void *addr, __kernel_size_t size)
616 600
617#define clear_user(addr,n) \ 601#define clear_user(addr,n) \
618({ \ 602({ \
619 void * __cl_addr = (addr); \ 603 void __user * __cl_addr = (addr); \
620 unsigned long __cl_size = (n); \ 604 unsigned long __cl_size = (n); \
621 if (__cl_size && access_ok(VERIFY_WRITE, \ 605 if (__cl_size && access_ok(VERIFY_WRITE, \
622 ((unsigned long)(__cl_addr)), __cl_size)) \ 606 ((unsigned long)(__cl_addr)), __cl_size)) \
@@ -645,7 +629,7 @@ __clear_user(void *addr, __kernel_size_t size)
645 * and returns @count. 629 * and returns @count.
646 */ 630 */
647static inline long 631static inline long
648__strncpy_from_user(char *__to, const char *__from, long __len) 632__strncpy_from_user(char *__to, const char __user *__from, long __len)
649{ 633{
650 long res; 634 long res;
651 635
@@ -682,7 +666,7 @@ __strncpy_from_user(char *__to, const char *__from, long __len)
682 * and returns @count. 666 * and returns @count.
683 */ 667 */
684static inline long 668static inline long
685strncpy_from_user(char *__to, const char *__from, long __len) 669strncpy_from_user(char *__to, const char __user *__from, long __len)
686{ 670{
687 long res; 671 long res;
688 672
@@ -701,7 +685,7 @@ strncpy_from_user(char *__to, const char *__from, long __len)
701} 685}
702 686
703/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ 687/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
704static inline long __strlen_user(const char *s) 688static inline long __strlen_user(const char __user *s)
705{ 689{
706 long res; 690 long res;
707 691
@@ -731,7 +715,7 @@ static inline long __strlen_user(const char *s)
731 * If there is a limit on the length of a valid string, you may wish to 715 * If there is a limit on the length of a valid string, you may wish to
732 * consider using strnlen_user() instead. 716 * consider using strnlen_user() instead.
733 */ 717 */
734static inline long strlen_user(const char *s) 718static inline long strlen_user(const char __user *s)
735{ 719{
736 long res; 720 long res;
737 721
@@ -748,7 +732,7 @@ static inline long strlen_user(const char *s)
748} 732}
749 733
750/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ 734/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
751static inline long __strnlen_user(const char *s, long n) 735static inline long __strnlen_user(const char __user *s, long n)
752{ 736{
753 long res; 737 long res;
754 738
@@ -779,7 +763,7 @@ static inline long __strnlen_user(const char *s, long n)
779 * If there is a limit on the length of a valid string, you may wish to 763 * If there is a limit on the length of a valid string, you may wish to
780 * consider using strnlen_user() instead. 764 * consider using strnlen_user() instead.
781 */ 765 */
782static inline long strnlen_user(const char *s, long n) 766static inline long strnlen_user(const char __user *s, long n)
783{ 767{
784 long res; 768 long res;
785 769