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 __chk_user_ptr(ptr); \
46 switch (sizeof (*(ptr))) { \
48 __put_user_asm(__pu_err, __pu_val, ptr, b); \
51 __put_user_asm(__pu_err, __pu_val, ptr, w); \
54 __put_user_asm(__pu_err, __pu_val, ptr, l); \
57 __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8); \
60 __pu_err = __put_user_bad(); \
65 #define __put_user(x, ptr) put_user(x, ptr)
67 extern int __put_user_bad(void);
70 * Tell gcc we read from memory instead of writing: this is because
71 * we do not write to any memory gcc knows about, so there are no
74 #define __put_user_asm(err,x,ptr,bwl) \
75 __asm__ __volatile__ \
76 ("21:moves" #bwl " %2,%1\n" \
78 ".section .fixup,\"ax\"\n" \
83 ".section __ex_table,\"a\"\n" \
89 : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
91 #define get_user(x, ptr) \
94 typeof(*(ptr)) __gu_val; \
95 __chk_user_ptr(ptr); \
96 switch (sizeof(*(ptr))) { \
98 __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
101 __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \
104 __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \
107 __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \
110 __gu_val = (typeof(*(ptr)))0; \
111 __gu_err = __get_user_bad(); \
117 #define __get_user(x, ptr) get_user(x, ptr)
119 extern int __get_user_bad(void);
121 #define __get_user_asm(err,x,ptr,bwl,reg) \
122 __asm__ __volatile__ \
123 ("1: moves" #bwl " %2,%1\n" \
125 ".section .fixup,\"ax\"\n" \
128 " sub" #bwl " %1,%1\n" \
131 ".section __ex_table,\"a\"\n" \
135 : "=d"(err), reg(x) \
136 : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
138 static inline unsigned long
139 __generic_copy_from_user(void *to
, const void __user
*from
, unsigned long n
)
145 "1: movesl (%1)+,%3\n"
152 "3: movesw (%1)+,%3\n"
156 "5: movesb (%1)+,%3\n"
159 ".section .fixup,\"ax\"\n"
181 ".section __ex_table,\"a\"\n"
187 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
188 : "d"(n
& 3), "0"(to
), "1"(from
), "2"(n
/4)
193 static inline unsigned long
194 __generic_copy_to_user(void __user
*to
, const void *from
, unsigned long n
)
200 "1: movel (%1)+,%3\n"
201 "22:movesl %3,(%0)+\n"
208 "24:movesw %3,(%0)+\n"
212 "25:movesb %3,(%0)+\n"
214 ".section .fixup,\"ax\"\n"
225 ".section __ex_table,\"a\"\n"
236 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
237 : "r"(n
& 3), "0"(to
), "1"(from
), "2"(n
/ 4)
242 #define __copy_from_user_big(to, from, n, fixup, copy) \
243 __asm__ __volatile__ \
244 ("10: movesl (%1)+,%%d0\n" \
245 " movel %%d0,(%0)+\n" \
248 ".section .fixup,\"ax\"\n" \
250 "11: movel %2,%%d0\n" \
258 ".section __ex_table,\"a\"\n" \
264 : "=a"(to), "=a"(from), "=d"(n) \
265 : "0"(to), "1"(from), "2"(n/4) \
268 static inline unsigned long
269 __constant_copy_from_user(void *to
, const void __user
*from
, unsigned long n
)
276 ("1: movesb (%1)+,%%d0\n"
277 " moveb %%d0,(%0)+\n"
279 ".section .fixup,\"ax\"\n"
285 ".section __ex_table,\"a\"\n"
289 : "=a"(to
), "=a"(from
), "=d"(n
)
290 : "0"(to
), "1"(from
), "2"(0)
295 ("1: movesw (%1)+,%%d0\n"
296 " movew %%d0,(%0)+\n"
298 ".section .fixup,\"ax\"\n"
304 ".section __ex_table,\"a\"\n"
308 : "=a"(to
), "=a"(from
), "=d"(n
)
309 : "0"(to
), "1"(from
), "2"(0)
314 ("1: movesw (%1)+,%%d0\n"
315 " movew %%d0,(%0)+\n"
316 "2: movesb (%1)+,%%d0\n"
317 " moveb %%d0,(%0)+\n"
319 ".section .fixup,\"ax\"\n"
327 ".section __ex_table,\"a\"\n"
332 : "=a"(to
), "=a"(from
), "=d"(n
)
333 : "0"(to
), "1"(from
), "2"(0)
338 ("1: movesl (%1)+,%%d0\n"
339 " movel %%d0,(%0)+\n"
341 ".section .fixup,\"ax\"\n"
347 ".section __ex_table,\"a\"\n"
351 : "=a"(to
), "=a"(from
), "=d"(n
)
352 : "0"(to
), "1"(from
), "2"(0)
357 ("1: movesl (%1)+,%%d0\n"
358 " movel %%d0,(%0)+\n"
359 "2: movesl (%1)+,%%d0\n"
360 " movel %%d0,(%0)+\n"
362 ".section .fixup,\"ax\"\n"
370 ".section __ex_table,\"a\"\n"
375 : "=a"(to
), "=a"(from
), "=d"(n
)
376 : "0"(to
), "1"(from
), "2"(0)
381 ("1: movesl (%1)+,%%d0\n"
382 " movel %%d0,(%0)+\n"
383 "2: movesl (%1)+,%%d0\n"
384 " movel %%d0,(%0)+\n"
385 "3: movesl (%1)+,%%d0\n"
386 " movel %%d0,(%0)+\n"
388 ".section .fixup,\"ax\"\n"
398 ".section __ex_table,\"a\"\n"
404 : "=a"(to
), "=a"(from
), "=d"(n
)
405 : "0"(to
), "1"(from
), "2"(0)
410 ("1: movesl (%1)+,%%d0\n"
411 " movel %%d0,(%0)+\n"
412 "2: movesl (%1)+,%%d0\n"
413 " movel %%d0,(%0)+\n"
414 "3: movesl (%1)+,%%d0\n"
415 " movel %%d0,(%0)+\n"
416 "4: movesl (%1)+,%%d0\n"
417 " movel %%d0,(%0)+\n"
419 ".section .fixup,\"ax\"\n"
431 ".section __ex_table,\"a\"\n"
438 : "=a"(to
), "=a"(from
), "=d"(n
)
439 : "0"(to
), "1"(from
), "2"(0)
445 __copy_from_user_big(to
, from
, n
, "", "");
448 __copy_from_user_big(to
, from
, n
,
453 "2: movesb (%1)+,%%d0\n"
454 " moveb %%d0,(%0)+\n"
455 ".section __ex_table,\"a\"\n"
460 __copy_from_user_big(to
, from
, n
,
465 "2: movesw (%1)+,%%d0\n"
466 " movew %%d0,(%0)+\n"
467 ".section __ex_table,\"a\"\n"
472 __copy_from_user_big(to
, from
, n
,
479 "3: movesw (%1)+,%%d0\n"
480 " movew %%d0,(%0)+\n"
481 "4: movesb (%1)+,%%d0\n"
482 " moveb %%d0,(%0)+\n"
483 ".section __ex_table,\"a\"\n"
494 #define __copy_to_user_big(to, from, n, fixup, copy) \
495 __asm__ __volatile__ \
496 ("10: movel (%1)+,%%d0\n" \
497 "31: movesl %%d0,(%0)+\n" \
498 "11: subql #1,%2\n" \
501 ".section .fixup,\"ax\"\n" \
503 "22: addql #1,%2\n" \
508 ".section __ex_table,\"a\"\n" \
517 : "=a"(to), "=a"(from), "=d"(n) \
518 : "0"(to), "1"(from), "2"(n/4) \
521 #define __copy_to_user_inatomic __copy_to_user
522 #define __copy_from_user_inatomic __copy_from_user
524 static inline unsigned long
525 __constant_copy_to_user(void __user
*to
, const void *from
, unsigned long n
)
532 (" moveb (%1)+,%%d0\n"
533 "21:movesb %%d0,(%0)+\n"
535 ".section .fixup,\"ax\"\n"
540 ".section __ex_table,\"a\"\n"
545 : "=a"(to
), "=a"(from
), "=d"(n
)
546 : "0"(to
), "1"(from
), "2"(0)
551 (" movew (%1)+,%%d0\n"
552 "21:movesw %%d0,(%0)+\n"
554 ".section .fixup,\"ax\"\n"
559 ".section __ex_table,\"a\"\n"
564 : "=a"(to
), "=a"(from
), "=d"(n
)
565 : "0"(to
), "1"(from
), "2"(0)
570 (" movew (%1)+,%%d0\n"
571 "21:movesw %%d0,(%0)+\n"
572 "1: moveb (%1)+,%%d0\n"
573 "22:movesb %%d0,(%0)+\n"
575 ".section .fixup,\"ax\"\n"
581 ".section __ex_table,\"a\"\n"
588 : "=a"(to
), "=a"(from
), "=d"(n
)
589 : "0"(to
), "1"(from
), "2"(0)
594 (" movel (%1)+,%%d0\n"
595 "21:movesl %%d0,(%0)+\n"
597 ".section .fixup,\"ax\"\n"
602 ".section __ex_table,\"a\"\n"
607 : "=a"(to
), "=a"(from
), "=d"(n
)
608 : "0"(to
), "1"(from
), "2"(0)
613 (" movel (%1)+,%%d0\n"
614 "21:movesl %%d0,(%0)+\n"
615 "1: movel (%1)+,%%d0\n"
616 "22:movesl %%d0,(%0)+\n"
618 ".section .fixup,\"ax\"\n"
624 ".section __ex_table,\"a\"\n"
631 : "=a"(to
), "=a"(from
), "=d"(n
)
632 : "0"(to
), "1"(from
), "2"(0)
637 (" movel (%1)+,%%d0\n"
638 "21:movesl %%d0,(%0)+\n"
639 "1: movel (%1)+,%%d0\n"
640 "22:movesl %%d0,(%0)+\n"
641 "2: movel (%1)+,%%d0\n"
642 "23:movesl %%d0,(%0)+\n"
644 ".section .fixup,\"ax\"\n"
651 ".section __ex_table,\"a\"\n"
660 : "=a"(to
), "=a"(from
), "=d"(n
)
661 : "0"(to
), "1"(from
), "2"(0)
666 (" movel (%1)+,%%d0\n"
667 "21:movesl %%d0,(%0)+\n"
668 "1: movel (%1)+,%%d0\n"
669 "22:movesl %%d0,(%0)+\n"
670 "2: movel (%1)+,%%d0\n"
671 "23:movesl %%d0,(%0)+\n"
672 "3: movel (%1)+,%%d0\n"
673 "24:movesl %%d0,(%0)+\n"
675 ".section .fixup,\"ax\"\n"
683 ".section __ex_table,\"a\"\n"
694 : "=a"(to
), "=a"(from
), "=d"(n
)
695 : "0"(to
), "1"(from
), "2"(0)
701 __copy_to_user_big(to
, from
, n
, "", "");
704 __copy_to_user_big(to
, from
, n
,
708 " moveb (%1)+,%%d0\n"
709 "22:movesb %%d0,(%0)+\n"
711 ".section __ex_table,\"a\"\n"
717 __copy_to_user_big(to
, from
, n
,
721 " movew (%1)+,%%d0\n"
722 "22:movesw %%d0,(%0)+\n"
724 ".section __ex_table,\"a\"\n"
730 __copy_to_user_big(to
, from
, n
,
735 " movew (%1)+,%%d0\n"
736 "23:movesw %%d0,(%0)+\n"
737 "3: moveb (%1)+,%%d0\n"
738 "24:movesb %%d0,(%0)+\n"
740 ".section __ex_table,\"a\"\n"
753 #define copy_from_user(to, from, n) \
754 (__builtin_constant_p(n) ? \
755 __constant_copy_from_user(to, from, n) : \
756 __generic_copy_from_user(to, from, n))
758 #define copy_to_user(to, from, n) \
759 (__builtin_constant_p(n) ? \
760 __constant_copy_to_user(to, from, n) : \
761 __generic_copy_to_user(to, from, n))
763 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
764 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
767 * Copy a null terminated string from userspace.
771 strncpy_from_user(char *dst
, const char __user
*src
, long count
)
774 if (count
== 0) return count
;
776 ("1: movesb (%2)+,%%d0\n"
777 "12:moveb %%d0,(%1)+\n"
783 ".section .fixup,\"ax\"\n"
788 ".section __ex_table,\"a\"\n"
793 : "=d"(res
), "=a"(dst
), "=a"(src
), "=d"(count
)
794 : "i"(-EFAULT
), "0"(count
), "1"(dst
), "2"(src
), "3"(count
)
800 * Return the size of a string (including the ending 0)
802 * Return 0 on exception, a value greater than N if too long
804 static inline long strnlen_user(const char __user
*src
, long n
)
808 res
= -(unsigned long)src
;
813 "2: movesb (%1)+,%%d0\n"
824 ".section .fixup,\"ax\"\n"
829 ".section __ex_table,\"a\"\n"
834 : "=d"(res
), "=a"(src
), "=d"(n
)
835 : "i"(0), "0"(res
), "1"(src
), "2"(n
)
840 #define strlen_user(str) strnlen_user(str, 32767)
846 static inline unsigned long
847 clear_user(void __user
*to
, unsigned long n
)
852 "1: movesl %3,(%0)+\n"
858 "24:movesw %3,(%0)+\n"
861 "25:movesb %3,(%0)+\n"
863 ".section .fixup,\"ax\"\n"
874 ".section __ex_table,\"a\"\n"
885 : "r"(n
& 3), "r"(0), "0"(to
), "1"(n
/4));
889 #endif /* _M68K_UACCESS_H */