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 static inline int verify_area(int type, const void *addr, unsigned long size)
19 return access_ok(type,addr,size)?0:-EFAULT;
23 * The exception table consists of pairs of addresses: the first is the
24 * address of an instruction that is allowed to fault, and the second is
25 * the address at which the program should continue. No registers are
26 * modified, so it is entirely up to the continuation code to figure out
29 * All the routines below use bits of fixup code that are out of line
30 * with the main instruction path. This means when everything is well,
31 * we don't even have to jump over them. Further, they do not intrude
32 * on our cache or tlb entries.
35 struct exception_table_entry
37 unsigned long insn, fixup;
42 * These are the main single-value transfer routines. They automatically
43 * use the right size if we just have the right pointer type.
46 #define put_user(x, ptr) \
49 typeof(*(ptr)) __pu_val = (x); \
50 switch (sizeof (*(ptr))) { \
52 __put_user_asm(__pu_err, __pu_val, ptr, b); \
55 __put_user_asm(__pu_err, __pu_val, ptr, w); \
58 __put_user_asm(__pu_err, __pu_val, ptr, l); \
61 __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8); \
64 __pu_err = __put_user_bad(); \
69 #define __put_user(x, ptr) put_user(x, ptr)
71 extern int __put_user_bad(void);
74 * Tell gcc we read from memory instead of writing: this is because
75 * we do not write to any memory gcc knows about, so there are no
78 #define __put_user_asm(err,x,ptr,bwl) \
79 __asm__ __volatile__ \
80 ("21:moves" #bwl " %2,%1\n" \
82 ".section .fixup,\"ax\"\n" \
87 ".section __ex_table,\"a\"\n" \
93 : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
95 #define get_user(x, ptr) \
98 typeof(*(ptr)) __gu_val; \
99 switch (sizeof(*(ptr))) { \
101 __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
104 __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \
107 __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \
110 __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \
114 __gu_err = __get_user_bad(); \
120 #define __get_user(x, ptr) get_user(x, ptr)
122 extern int __get_user_bad(void);
124 #define __get_user_asm(err,x,ptr,bwl,reg) \
125 __asm__ __volatile__ \
126 ("1: moves" #bwl " %2,%1\n" \
128 ".section .fixup,\"ax\"\n" \
131 " sub" #bwl " %1,%1\n" \
134 ".section __ex_table,\"a\"\n" \
138 : "=d"(err), reg(x) \
139 : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
141 static inline unsigned long
142 __generic_copy_from_user(void *to, const void *from, unsigned long n)
148 "1: movesl (%1)+,%3\n"
155 "3: movesw (%1)+,%3\n"
159 "5: movesb (%1)+,%3\n"
162 ".section .fixup,\"ax\"\n"
184 ".section __ex_table,\"a\"\n"
190 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
191 : "d"(n & 3), "0"(to), "1"(from), "2"(n/4)
196 static inline unsigned long
197 __generic_copy_to_user(void *to, const void *from, unsigned long n)
203 "1: movel (%1)+,%3\n"
204 "22:movesl %3,(%0)+\n"
211 "24:movesw %3,(%0)+\n"
215 "25:movesb %3,(%0)+\n"
217 ".section .fixup,\"ax\"\n"
228 ".section __ex_table,\"a\"\n"
239 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
240 : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
245 #define __copy_from_user_big(to, from, n, fixup, copy) \
246 __asm__ __volatile__ \
247 ("10: movesl (%1)+,%%d0\n" \
248 " movel %%d0,(%0)+\n" \
251 ".section .fixup,\"ax\"\n" \
253 "11: movel %2,%%d0\n" \
261 ".section __ex_table,\"a\"\n" \
267 : "=a"(to), "=a"(from), "=d"(n) \
268 : "0"(to), "1"(from), "2"(n/4) \
271 static inline unsigned long
272 __constant_copy_from_user(void *to, const void *from, unsigned long n)
279 ("1: movesb (%1)+,%%d0\n"
280 " moveb %%d0,(%0)+\n"
282 ".section .fixup,\"ax\"\n"
288 ".section __ex_table,\"a\"\n"
292 : "=a"(to), "=a"(from), "=d"(n)
293 : "0"(to), "1"(from), "2"(0)
298 ("1: movesw (%1)+,%%d0\n"
299 " movew %%d0,(%0)+\n"
301 ".section .fixup,\"ax\"\n"
307 ".section __ex_table,\"a\"\n"
311 : "=a"(to), "=a"(from), "=d"(n)
312 : "0"(to), "1"(from), "2"(0)
317 ("1: movesw (%1)+,%%d0\n"
318 " movew %%d0,(%0)+\n"
319 "2: movesb (%1)+,%%d0\n"
320 " moveb %%d0,(%0)+\n"
322 ".section .fixup,\"ax\"\n"
330 ".section __ex_table,\"a\"\n"
335 : "=a"(to), "=a"(from), "=d"(n)
336 : "0"(to), "1"(from), "2"(0)
341 ("1: movesl (%1)+,%%d0\n"
342 " movel %%d0,(%0)+\n"
344 ".section .fixup,\"ax\"\n"
350 ".section __ex_table,\"a\"\n"
354 : "=a"(to), "=a"(from), "=d"(n)
355 : "0"(to), "1"(from), "2"(0)
360 ("1: movesl (%1)+,%%d0\n"
361 " movel %%d0,(%0)+\n"
362 "2: movesl (%1)+,%%d0\n"
363 " movel %%d0,(%0)+\n"
365 ".section .fixup,\"ax\"\n"
373 ".section __ex_table,\"a\"\n"
378 : "=a"(to), "=a"(from), "=d"(n)
379 : "0"(to), "1"(from), "2"(0)
384 ("1: movesl (%1)+,%%d0\n"
385 " movel %%d0,(%0)+\n"
386 "2: movesl (%1)+,%%d0\n"
387 " movel %%d0,(%0)+\n"
388 "3: movesl (%1)+,%%d0\n"
389 " movel %%d0,(%0)+\n"
391 ".section .fixup,\"ax\"\n"
401 ".section __ex_table,\"a\"\n"
407 : "=a"(to), "=a"(from), "=d"(n)
408 : "0"(to), "1"(from), "2"(0)
413 ("1: movesl (%1)+,%%d0\n"
414 " movel %%d0,(%0)+\n"
415 "2: movesl (%1)+,%%d0\n"
416 " movel %%d0,(%0)+\n"
417 "3: movesl (%1)+,%%d0\n"
418 " movel %%d0,(%0)+\n"
419 "4: movesl (%1)+,%%d0\n"
420 " movel %%d0,(%0)+\n"
422 ".section .fixup,\"ax\"\n"
434 ".section __ex_table,\"a\"\n"
441 : "=a"(to), "=a"(from), "=d"(n)
442 : "0"(to), "1"(from), "2"(0)
448 __copy_from_user_big(to, from, n, "", "");
451 __copy_from_user_big(to, from, n,
456 "2: movesb (%1)+,%%d0\n"
457 " moveb %%d0,(%0)+\n"
458 ".section __ex_table,\"a\"\n"
463 __copy_from_user_big(to, from, n,
468 "2: movesw (%1)+,%%d0\n"
469 " movew %%d0,(%0)+\n"
470 ".section __ex_table,\"a\"\n"
475 __copy_from_user_big(to, from, n,
482 "3: movesw (%1)+,%%d0\n"
483 " movew %%d0,(%0)+\n"
484 "4: movesb (%1)+,%%d0\n"
485 " moveb %%d0,(%0)+\n"
486 ".section __ex_table,\"a\"\n"
497 #define __copy_to_user_big(to, from, n, fixup, copy) \
498 __asm__ __volatile__ \
499 ("10: movel (%1)+,%%d0\n" \
500 "31: movesl %%d0,(%0)+\n" \
501 "11: subql #1,%2\n" \
504 ".section .fixup,\"ax\"\n" \
506 "22: addql #1,%2\n" \
511 ".section __ex_table,\"a\"\n" \
520 : "=a"(to), "=a"(from), "=d"(n) \
521 : "0"(to), "1"(from), "2"(n/4) \
524 static inline unsigned long
525 __constant_copy_to_user(void *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 *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 *src, long n)
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 *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 */