1 #ifndef __M68K_UACCESS_H
2 #define __M68K_UACCESS_H
5 * User space memory access functions
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <asm/segment.h>
12 #define VERIFY_WRITE 1
14 /* We let the MMU do all checking */
15 #define access_ok(type,addr,size) 1
17 /* this function will go away soon - use access_ok() instead */
18 static inline int __deprecated
verify_area(int type
, const void *addr
, unsigned long size
)
20 return access_ok(type
,addr
,size
) ? 0 : -EFAULT
;
24 * The exception table consists of pairs of addresses: the first is the
25 * address of an instruction that is allowed to fault, and the second is
26 * the address at which the program should continue. No registers are
27 * modified, so it is entirely up to the continuation code to figure out
30 * All the routines below use bits of fixup code that are out of line
31 * with the main instruction path. This means when everything is well,
32 * we don't even have to jump over them. Further, they do not intrude
33 * on our cache or tlb entries.
36 struct exception_table_entry
38 unsigned long insn
, fixup
;
43 * These are the main single-value transfer routines. They automatically
44 * use the right size if we just have the right pointer type.
47 #define put_user(x, ptr) \
50 typeof(*(ptr)) __pu_val = (x); \
51 switch (sizeof (*(ptr))) { \
53 __put_user_asm(__pu_err, __pu_val, ptr, b); \
56 __put_user_asm(__pu_err, __pu_val, ptr, w); \
59 __put_user_asm(__pu_err, __pu_val, ptr, l); \
62 __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8); \
65 __pu_err = __put_user_bad(); \
70 #define __put_user(x, ptr) put_user(x, ptr)
72 extern int __put_user_bad(void);
75 * Tell gcc we read from memory instead of writing: this is because
76 * we do not write to any memory gcc knows about, so there are no
79 #define __put_user_asm(err,x,ptr,bwl) \
80 __asm__ __volatile__ \
81 ("21:moves" #bwl " %2,%1\n" \
83 ".section .fixup,\"ax\"\n" \
88 ".section __ex_table,\"a\"\n" \
94 : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
96 #define get_user(x, ptr) \
99 typeof(*(ptr)) __gu_val; \
100 switch (sizeof(*(ptr))) { \
102 __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
105 __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \
108 __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \
111 __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \
115 __gu_err = __get_user_bad(); \
121 #define __get_user(x, ptr) get_user(x, ptr)
123 extern int __get_user_bad(void);
125 #define __get_user_asm(err,x,ptr,bwl,reg) \
126 __asm__ __volatile__ \
127 ("1: moves" #bwl " %2,%1\n" \
129 ".section .fixup,\"ax\"\n" \
132 " sub" #bwl " %1,%1\n" \
135 ".section __ex_table,\"a\"\n" \
139 : "=d"(err), reg(x) \
140 : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
142 static inline unsigned long
143 __generic_copy_from_user(void *to
, const void *from
, unsigned long n
)
149 "1: movesl (%1)+,%3\n"
156 "3: movesw (%1)+,%3\n"
160 "5: movesb (%1)+,%3\n"
163 ".section .fixup,\"ax\"\n"
185 ".section __ex_table,\"a\"\n"
191 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
192 : "d"(n
& 3), "0"(to
), "1"(from
), "2"(n
/4)
197 static inline unsigned long
198 __generic_copy_to_user(void *to
, const void *from
, unsigned long n
)
204 "1: movel (%1)+,%3\n"
205 "22:movesl %3,(%0)+\n"
212 "24:movesw %3,(%0)+\n"
216 "25:movesb %3,(%0)+\n"
218 ".section .fixup,\"ax\"\n"
229 ".section __ex_table,\"a\"\n"
240 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
241 : "r"(n
& 3), "0"(to
), "1"(from
), "2"(n
/ 4)
246 #define __copy_from_user_big(to, from, n, fixup, copy) \
247 __asm__ __volatile__ \
248 ("10: movesl (%1)+,%%d0\n" \
249 " movel %%d0,(%0)+\n" \
252 ".section .fixup,\"ax\"\n" \
254 "11: movel %2,%%d0\n" \
262 ".section __ex_table,\"a\"\n" \
268 : "=a"(to), "=a"(from), "=d"(n) \
269 : "0"(to), "1"(from), "2"(n/4) \
272 static inline unsigned long
273 __constant_copy_from_user(void *to
, const void *from
, unsigned long n
)
280 ("1: movesb (%1)+,%%d0\n"
281 " moveb %%d0,(%0)+\n"
283 ".section .fixup,\"ax\"\n"
289 ".section __ex_table,\"a\"\n"
293 : "=a"(to
), "=a"(from
), "=d"(n
)
294 : "0"(to
), "1"(from
), "2"(0)
299 ("1: movesw (%1)+,%%d0\n"
300 " movew %%d0,(%0)+\n"
302 ".section .fixup,\"ax\"\n"
308 ".section __ex_table,\"a\"\n"
312 : "=a"(to
), "=a"(from
), "=d"(n
)
313 : "0"(to
), "1"(from
), "2"(0)
318 ("1: movesw (%1)+,%%d0\n"
319 " movew %%d0,(%0)+\n"
320 "2: movesb (%1)+,%%d0\n"
321 " moveb %%d0,(%0)+\n"
323 ".section .fixup,\"ax\"\n"
331 ".section __ex_table,\"a\"\n"
336 : "=a"(to
), "=a"(from
), "=d"(n
)
337 : "0"(to
), "1"(from
), "2"(0)
342 ("1: movesl (%1)+,%%d0\n"
343 " movel %%d0,(%0)+\n"
345 ".section .fixup,\"ax\"\n"
351 ".section __ex_table,\"a\"\n"
355 : "=a"(to
), "=a"(from
), "=d"(n
)
356 : "0"(to
), "1"(from
), "2"(0)
361 ("1: movesl (%1)+,%%d0\n"
362 " movel %%d0,(%0)+\n"
363 "2: movesl (%1)+,%%d0\n"
364 " movel %%d0,(%0)+\n"
366 ".section .fixup,\"ax\"\n"
374 ".section __ex_table,\"a\"\n"
379 : "=a"(to
), "=a"(from
), "=d"(n
)
380 : "0"(to
), "1"(from
), "2"(0)
385 ("1: movesl (%1)+,%%d0\n"
386 " movel %%d0,(%0)+\n"
387 "2: movesl (%1)+,%%d0\n"
388 " movel %%d0,(%0)+\n"
389 "3: movesl (%1)+,%%d0\n"
390 " movel %%d0,(%0)+\n"
392 ".section .fixup,\"ax\"\n"
402 ".section __ex_table,\"a\"\n"
408 : "=a"(to
), "=a"(from
), "=d"(n
)
409 : "0"(to
), "1"(from
), "2"(0)
414 ("1: movesl (%1)+,%%d0\n"
415 " movel %%d0,(%0)+\n"
416 "2: movesl (%1)+,%%d0\n"
417 " movel %%d0,(%0)+\n"
418 "3: movesl (%1)+,%%d0\n"
419 " movel %%d0,(%0)+\n"
420 "4: movesl (%1)+,%%d0\n"
421 " movel %%d0,(%0)+\n"
423 ".section .fixup,\"ax\"\n"
435 ".section __ex_table,\"a\"\n"
442 : "=a"(to
), "=a"(from
), "=d"(n
)
443 : "0"(to
), "1"(from
), "2"(0)
449 __copy_from_user_big(to
, from
, n
, "", "");
452 __copy_from_user_big(to
, from
, n
,
457 "2: movesb (%1)+,%%d0\n"
458 " moveb %%d0,(%0)+\n"
459 ".section __ex_table,\"a\"\n"
464 __copy_from_user_big(to
, from
, n
,
469 "2: movesw (%1)+,%%d0\n"
470 " movew %%d0,(%0)+\n"
471 ".section __ex_table,\"a\"\n"
476 __copy_from_user_big(to
, from
, n
,
483 "3: movesw (%1)+,%%d0\n"
484 " movew %%d0,(%0)+\n"
485 "4: movesb (%1)+,%%d0\n"
486 " moveb %%d0,(%0)+\n"
487 ".section __ex_table,\"a\"\n"
498 #define __copy_to_user_big(to, from, n, fixup, copy) \
499 __asm__ __volatile__ \
500 ("10: movel (%1)+,%%d0\n" \
501 "31: movesl %%d0,(%0)+\n" \
502 "11: subql #1,%2\n" \
505 ".section .fixup,\"ax\"\n" \
507 "22: addql #1,%2\n" \
512 ".section __ex_table,\"a\"\n" \
521 : "=a"(to), "=a"(from), "=d"(n) \
522 : "0"(to), "1"(from), "2"(n/4) \
525 #define __copy_to_user_inatomic __copy_to_user
526 #define __copy_from_user_inatomic __copy_from_user
528 static inline unsigned long
529 __constant_copy_to_user(void *to
, const void *from
, unsigned long n
)
536 (" moveb (%1)+,%%d0\n"
537 "21:movesb %%d0,(%0)+\n"
539 ".section .fixup,\"ax\"\n"
544 ".section __ex_table,\"a\"\n"
549 : "=a"(to
), "=a"(from
), "=d"(n
)
550 : "0"(to
), "1"(from
), "2"(0)
555 (" movew (%1)+,%%d0\n"
556 "21:movesw %%d0,(%0)+\n"
558 ".section .fixup,\"ax\"\n"
563 ".section __ex_table,\"a\"\n"
568 : "=a"(to
), "=a"(from
), "=d"(n
)
569 : "0"(to
), "1"(from
), "2"(0)
574 (" movew (%1)+,%%d0\n"
575 "21:movesw %%d0,(%0)+\n"
576 "1: moveb (%1)+,%%d0\n"
577 "22:movesb %%d0,(%0)+\n"
579 ".section .fixup,\"ax\"\n"
585 ".section __ex_table,\"a\"\n"
592 : "=a"(to
), "=a"(from
), "=d"(n
)
593 : "0"(to
), "1"(from
), "2"(0)
598 (" movel (%1)+,%%d0\n"
599 "21:movesl %%d0,(%0)+\n"
601 ".section .fixup,\"ax\"\n"
606 ".section __ex_table,\"a\"\n"
611 : "=a"(to
), "=a"(from
), "=d"(n
)
612 : "0"(to
), "1"(from
), "2"(0)
617 (" movel (%1)+,%%d0\n"
618 "21:movesl %%d0,(%0)+\n"
619 "1: movel (%1)+,%%d0\n"
620 "22:movesl %%d0,(%0)+\n"
622 ".section .fixup,\"ax\"\n"
628 ".section __ex_table,\"a\"\n"
635 : "=a"(to
), "=a"(from
), "=d"(n
)
636 : "0"(to
), "1"(from
), "2"(0)
641 (" movel (%1)+,%%d0\n"
642 "21:movesl %%d0,(%0)+\n"
643 "1: movel (%1)+,%%d0\n"
644 "22:movesl %%d0,(%0)+\n"
645 "2: movel (%1)+,%%d0\n"
646 "23:movesl %%d0,(%0)+\n"
648 ".section .fixup,\"ax\"\n"
655 ".section __ex_table,\"a\"\n"
664 : "=a"(to
), "=a"(from
), "=d"(n
)
665 : "0"(to
), "1"(from
), "2"(0)
670 (" movel (%1)+,%%d0\n"
671 "21:movesl %%d0,(%0)+\n"
672 "1: movel (%1)+,%%d0\n"
673 "22:movesl %%d0,(%0)+\n"
674 "2: movel (%1)+,%%d0\n"
675 "23:movesl %%d0,(%0)+\n"
676 "3: movel (%1)+,%%d0\n"
677 "24:movesl %%d0,(%0)+\n"
679 ".section .fixup,\"ax\"\n"
687 ".section __ex_table,\"a\"\n"
698 : "=a"(to
), "=a"(from
), "=d"(n
)
699 : "0"(to
), "1"(from
), "2"(0)
705 __copy_to_user_big(to
, from
, n
, "", "");
708 __copy_to_user_big(to
, from
, n
,
712 " moveb (%1)+,%%d0\n"
713 "22:movesb %%d0,(%0)+\n"
715 ".section __ex_table,\"a\"\n"
721 __copy_to_user_big(to
, from
, n
,
725 " movew (%1)+,%%d0\n"
726 "22:movesw %%d0,(%0)+\n"
728 ".section __ex_table,\"a\"\n"
734 __copy_to_user_big(to
, from
, n
,
739 " movew (%1)+,%%d0\n"
740 "23:movesw %%d0,(%0)+\n"
741 "3: moveb (%1)+,%%d0\n"
742 "24:movesb %%d0,(%0)+\n"
744 ".section __ex_table,\"a\"\n"
757 #define copy_from_user(to, from, n) \
758 (__builtin_constant_p(n) ? \
759 __constant_copy_from_user(to, from, n) : \
760 __generic_copy_from_user(to, from, n))
762 #define copy_to_user(to, from, n) \
763 (__builtin_constant_p(n) ? \
764 __constant_copy_to_user(to, from, n) : \
765 __generic_copy_to_user(to, from, n))
767 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
768 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
771 * Copy a null terminated string from userspace.
775 strncpy_from_user(char *dst
, const char *src
, long count
)
778 if (count
== 0) return count
;
780 ("1: movesb (%2)+,%%d0\n"
781 "12:moveb %%d0,(%1)+\n"
787 ".section .fixup,\"ax\"\n"
792 ".section __ex_table,\"a\"\n"
797 : "=d"(res
), "=a"(dst
), "=a"(src
), "=d"(count
)
798 : "i"(-EFAULT
), "0"(count
), "1"(dst
), "2"(src
), "3"(count
)
804 * Return the size of a string (including the ending 0)
806 * Return 0 on exception, a value greater than N if too long
808 static inline long strnlen_user(const char *src
, long n
)
817 "2: movesb (%1)+,%%d0\n"
828 ".section .fixup,\"ax\"\n"
833 ".section __ex_table,\"a\"\n"
838 : "=d"(res
), "=a"(src
), "=d"(n
)
839 : "i"(0), "0"(res
), "1"(src
), "2"(n
)
844 #define strlen_user(str) strnlen_user(str, 32767)
850 static inline unsigned long
851 clear_user(void *to
, unsigned long n
)
856 "1: movesl %3,(%0)+\n"
862 "24:movesw %3,(%0)+\n"
865 "25:movesb %3,(%0)+\n"
867 ".section .fixup,\"ax\"\n"
878 ".section __ex_table,\"a\"\n"
889 : "r"(n
& 3), "r"(0), "0"(to
), "1"(n
/4));
893 #endif /* _M68K_UACCESS_H */