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
18 * The exception table consists of pairs of addresses: the first is the
19 * address of an instruction that is allowed to fault, and the second is
20 * the address at which the program should continue. No registers are
21 * modified, so it is entirely up to the continuation code to figure out
24 * All the routines below use bits of fixup code that are out of line
25 * with the main instruction path. This means when everything is well,
26 * we don't even have to jump over them. Further, they do not intrude
27 * on our cache or tlb entries.
30 struct exception_table_entry
32 unsigned long insn
, fixup
;
37 * These are the main single-value transfer routines. They automatically
38 * use the right size if we just have the right pointer type.
41 #define put_user(x, ptr) \
44 typeof(*(ptr)) __pu_val = (x); \
45 switch (sizeof (*(ptr))) { \
47 __put_user_asm(__pu_err, __pu_val, ptr, b); \
50 __put_user_asm(__pu_err, __pu_val, ptr, w); \
53 __put_user_asm(__pu_err, __pu_val, ptr, l); \
56 __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8); \
59 __pu_err = __put_user_bad(); \
64 #define __put_user(x, ptr) put_user(x, ptr)
66 extern int __put_user_bad(void);
69 * Tell gcc we read from memory instead of writing: this is because
70 * we do not write to any memory gcc knows about, so there are no
73 #define __put_user_asm(err,x,ptr,bwl) \
74 __asm__ __volatile__ \
75 ("21:moves" #bwl " %2,%1\n" \
77 ".section .fixup,\"ax\"\n" \
82 ".section __ex_table,\"a\"\n" \
88 : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
90 #define get_user(x, ptr) \
93 typeof(*(ptr)) __gu_val; \
94 switch (sizeof(*(ptr))) { \
96 __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
99 __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \
102 __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \
105 __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \
109 __gu_err = __get_user_bad(); \
115 #define __get_user(x, ptr) get_user(x, ptr)
117 extern int __get_user_bad(void);
119 #define __get_user_asm(err,x,ptr,bwl,reg) \
120 __asm__ __volatile__ \
121 ("1: moves" #bwl " %2,%1\n" \
123 ".section .fixup,\"ax\"\n" \
126 " sub" #bwl " %1,%1\n" \
129 ".section __ex_table,\"a\"\n" \
133 : "=d"(err), reg(x) \
134 : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
136 static inline unsigned long
137 __generic_copy_from_user(void *to
, const void *from
, unsigned long n
)
143 "1: movesl (%1)+,%3\n"
150 "3: movesw (%1)+,%3\n"
154 "5: movesb (%1)+,%3\n"
157 ".section .fixup,\"ax\"\n"
179 ".section __ex_table,\"a\"\n"
185 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
186 : "d"(n
& 3), "0"(to
), "1"(from
), "2"(n
/4)
191 static inline unsigned long
192 __generic_copy_to_user(void *to
, const void *from
, unsigned long n
)
198 "1: movel (%1)+,%3\n"
199 "22:movesl %3,(%0)+\n"
206 "24:movesw %3,(%0)+\n"
210 "25:movesb %3,(%0)+\n"
212 ".section .fixup,\"ax\"\n"
223 ".section __ex_table,\"a\"\n"
234 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
235 : "r"(n
& 3), "0"(to
), "1"(from
), "2"(n
/ 4)
240 #define __copy_from_user_big(to, from, n, fixup, copy) \
241 __asm__ __volatile__ \
242 ("10: movesl (%1)+,%%d0\n" \
243 " movel %%d0,(%0)+\n" \
246 ".section .fixup,\"ax\"\n" \
248 "11: movel %2,%%d0\n" \
256 ".section __ex_table,\"a\"\n" \
262 : "=a"(to), "=a"(from), "=d"(n) \
263 : "0"(to), "1"(from), "2"(n/4) \
266 static inline unsigned long
267 __constant_copy_from_user(void *to
, const void *from
, unsigned long n
)
274 ("1: movesb (%1)+,%%d0\n"
275 " moveb %%d0,(%0)+\n"
277 ".section .fixup,\"ax\"\n"
283 ".section __ex_table,\"a\"\n"
287 : "=a"(to
), "=a"(from
), "=d"(n
)
288 : "0"(to
), "1"(from
), "2"(0)
293 ("1: movesw (%1)+,%%d0\n"
294 " movew %%d0,(%0)+\n"
296 ".section .fixup,\"ax\"\n"
302 ".section __ex_table,\"a\"\n"
306 : "=a"(to
), "=a"(from
), "=d"(n
)
307 : "0"(to
), "1"(from
), "2"(0)
312 ("1: movesw (%1)+,%%d0\n"
313 " movew %%d0,(%0)+\n"
314 "2: movesb (%1)+,%%d0\n"
315 " moveb %%d0,(%0)+\n"
317 ".section .fixup,\"ax\"\n"
325 ".section __ex_table,\"a\"\n"
330 : "=a"(to
), "=a"(from
), "=d"(n
)
331 : "0"(to
), "1"(from
), "2"(0)
336 ("1: movesl (%1)+,%%d0\n"
337 " movel %%d0,(%0)+\n"
339 ".section .fixup,\"ax\"\n"
345 ".section __ex_table,\"a\"\n"
349 : "=a"(to
), "=a"(from
), "=d"(n
)
350 : "0"(to
), "1"(from
), "2"(0)
355 ("1: movesl (%1)+,%%d0\n"
356 " movel %%d0,(%0)+\n"
357 "2: movesl (%1)+,%%d0\n"
358 " movel %%d0,(%0)+\n"
360 ".section .fixup,\"ax\"\n"
368 ".section __ex_table,\"a\"\n"
373 : "=a"(to
), "=a"(from
), "=d"(n
)
374 : "0"(to
), "1"(from
), "2"(0)
379 ("1: movesl (%1)+,%%d0\n"
380 " movel %%d0,(%0)+\n"
381 "2: movesl (%1)+,%%d0\n"
382 " movel %%d0,(%0)+\n"
383 "3: movesl (%1)+,%%d0\n"
384 " movel %%d0,(%0)+\n"
386 ".section .fixup,\"ax\"\n"
396 ".section __ex_table,\"a\"\n"
402 : "=a"(to
), "=a"(from
), "=d"(n
)
403 : "0"(to
), "1"(from
), "2"(0)
408 ("1: movesl (%1)+,%%d0\n"
409 " movel %%d0,(%0)+\n"
410 "2: movesl (%1)+,%%d0\n"
411 " movel %%d0,(%0)+\n"
412 "3: movesl (%1)+,%%d0\n"
413 " movel %%d0,(%0)+\n"
414 "4: movesl (%1)+,%%d0\n"
415 " movel %%d0,(%0)+\n"
417 ".section .fixup,\"ax\"\n"
429 ".section __ex_table,\"a\"\n"
436 : "=a"(to
), "=a"(from
), "=d"(n
)
437 : "0"(to
), "1"(from
), "2"(0)
443 __copy_from_user_big(to
, from
, n
, "", "");
446 __copy_from_user_big(to
, from
, n
,
451 "2: movesb (%1)+,%%d0\n"
452 " moveb %%d0,(%0)+\n"
453 ".section __ex_table,\"a\"\n"
458 __copy_from_user_big(to
, from
, n
,
463 "2: movesw (%1)+,%%d0\n"
464 " movew %%d0,(%0)+\n"
465 ".section __ex_table,\"a\"\n"
470 __copy_from_user_big(to
, from
, n
,
477 "3: movesw (%1)+,%%d0\n"
478 " movew %%d0,(%0)+\n"
479 "4: movesb (%1)+,%%d0\n"
480 " moveb %%d0,(%0)+\n"
481 ".section __ex_table,\"a\"\n"
492 #define __copy_to_user_big(to, from, n, fixup, copy) \
493 __asm__ __volatile__ \
494 ("10: movel (%1)+,%%d0\n" \
495 "31: movesl %%d0,(%0)+\n" \
496 "11: subql #1,%2\n" \
499 ".section .fixup,\"ax\"\n" \
501 "22: addql #1,%2\n" \
506 ".section __ex_table,\"a\"\n" \
515 : "=a"(to), "=a"(from), "=d"(n) \
516 : "0"(to), "1"(from), "2"(n/4) \
519 #define __copy_to_user_inatomic __copy_to_user
520 #define __copy_from_user_inatomic __copy_from_user
522 static inline unsigned long
523 __constant_copy_to_user(void *to
, const void *from
, unsigned long n
)
530 (" moveb (%1)+,%%d0\n"
531 "21:movesb %%d0,(%0)+\n"
533 ".section .fixup,\"ax\"\n"
538 ".section __ex_table,\"a\"\n"
543 : "=a"(to
), "=a"(from
), "=d"(n
)
544 : "0"(to
), "1"(from
), "2"(0)
549 (" movew (%1)+,%%d0\n"
550 "21:movesw %%d0,(%0)+\n"
552 ".section .fixup,\"ax\"\n"
557 ".section __ex_table,\"a\"\n"
562 : "=a"(to
), "=a"(from
), "=d"(n
)
563 : "0"(to
), "1"(from
), "2"(0)
568 (" movew (%1)+,%%d0\n"
569 "21:movesw %%d0,(%0)+\n"
570 "1: moveb (%1)+,%%d0\n"
571 "22:movesb %%d0,(%0)+\n"
573 ".section .fixup,\"ax\"\n"
579 ".section __ex_table,\"a\"\n"
586 : "=a"(to
), "=a"(from
), "=d"(n
)
587 : "0"(to
), "1"(from
), "2"(0)
592 (" movel (%1)+,%%d0\n"
593 "21:movesl %%d0,(%0)+\n"
595 ".section .fixup,\"ax\"\n"
600 ".section __ex_table,\"a\"\n"
605 : "=a"(to
), "=a"(from
), "=d"(n
)
606 : "0"(to
), "1"(from
), "2"(0)
611 (" movel (%1)+,%%d0\n"
612 "21:movesl %%d0,(%0)+\n"
613 "1: movel (%1)+,%%d0\n"
614 "22:movesl %%d0,(%0)+\n"
616 ".section .fixup,\"ax\"\n"
622 ".section __ex_table,\"a\"\n"
629 : "=a"(to
), "=a"(from
), "=d"(n
)
630 : "0"(to
), "1"(from
), "2"(0)
635 (" movel (%1)+,%%d0\n"
636 "21:movesl %%d0,(%0)+\n"
637 "1: movel (%1)+,%%d0\n"
638 "22:movesl %%d0,(%0)+\n"
639 "2: movel (%1)+,%%d0\n"
640 "23:movesl %%d0,(%0)+\n"
642 ".section .fixup,\"ax\"\n"
649 ".section __ex_table,\"a\"\n"
658 : "=a"(to
), "=a"(from
), "=d"(n
)
659 : "0"(to
), "1"(from
), "2"(0)
664 (" movel (%1)+,%%d0\n"
665 "21:movesl %%d0,(%0)+\n"
666 "1: movel (%1)+,%%d0\n"
667 "22:movesl %%d0,(%0)+\n"
668 "2: movel (%1)+,%%d0\n"
669 "23:movesl %%d0,(%0)+\n"
670 "3: movel (%1)+,%%d0\n"
671 "24:movesl %%d0,(%0)+\n"
673 ".section .fixup,\"ax\"\n"
681 ".section __ex_table,\"a\"\n"
692 : "=a"(to
), "=a"(from
), "=d"(n
)
693 : "0"(to
), "1"(from
), "2"(0)
699 __copy_to_user_big(to
, from
, n
, "", "");
702 __copy_to_user_big(to
, from
, n
,
706 " moveb (%1)+,%%d0\n"
707 "22:movesb %%d0,(%0)+\n"
709 ".section __ex_table,\"a\"\n"
715 __copy_to_user_big(to
, from
, n
,
719 " movew (%1)+,%%d0\n"
720 "22:movesw %%d0,(%0)+\n"
722 ".section __ex_table,\"a\"\n"
728 __copy_to_user_big(to
, from
, n
,
733 " movew (%1)+,%%d0\n"
734 "23:movesw %%d0,(%0)+\n"
735 "3: moveb (%1)+,%%d0\n"
736 "24:movesb %%d0,(%0)+\n"
738 ".section __ex_table,\"a\"\n"
751 #define copy_from_user(to, from, n) \
752 (__builtin_constant_p(n) ? \
753 __constant_copy_from_user(to, from, n) : \
754 __generic_copy_from_user(to, from, n))
756 #define copy_to_user(to, from, n) \
757 (__builtin_constant_p(n) ? \
758 __constant_copy_to_user(to, from, n) : \
759 __generic_copy_to_user(to, from, n))
761 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
762 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
765 * Copy a null terminated string from userspace.
769 strncpy_from_user(char *dst
, const char *src
, long count
)
772 if (count
== 0) return count
;
774 ("1: movesb (%2)+,%%d0\n"
775 "12:moveb %%d0,(%1)+\n"
781 ".section .fixup,\"ax\"\n"
786 ".section __ex_table,\"a\"\n"
791 : "=d"(res
), "=a"(dst
), "=a"(src
), "=d"(count
)
792 : "i"(-EFAULT
), "0"(count
), "1"(dst
), "2"(src
), "3"(count
)
798 * Return the size of a string (including the ending 0)
800 * Return 0 on exception, a value greater than N if too long
802 static inline long strnlen_user(const char *src
, long n
)
811 "2: movesb (%1)+,%%d0\n"
822 ".section .fixup,\"ax\"\n"
827 ".section __ex_table,\"a\"\n"
832 : "=d"(res
), "=a"(src
), "=d"(n
)
833 : "i"(0), "0"(res
), "1"(src
), "2"(n
)
838 #define strlen_user(str) strnlen_user(str, 32767)
844 static inline unsigned long
845 clear_user(void *to
, unsigned long n
)
850 "1: movesl %3,(%0)+\n"
856 "24:movesw %3,(%0)+\n"
859 "25:movesb %3,(%0)+\n"
861 ".section .fixup,\"ax\"\n"
872 ".section __ex_table,\"a\"\n"
883 : "r"(n
& 3), "r"(0), "0"(to
), "1"(n
/4));
887 #endif /* _M68K_UACCESS_H */