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