1 #ifndef __M68K_UACCESS_H
2 #define __M68K_UACCESS_H
5 * User space memory access functions
7 #include <linux/sched.h>
8 #include <asm/segment.h>
11 #define VERIFY_WRITE 1
13 /* We let the MMU do all checking */
14 #define access_ok(type,addr,size) 1
16 extern inline int verify_area(int type, const void * addr, unsigned long size)
18 return access_ok(type,addr,size)?0:-EFAULT;
22 * The exception table consists of pairs of addresses: the first is the
23 * address of an instruction that is allowed to fault, and the second is
24 * the address at which the program should continue. No registers are
25 * modified, so it is entirely up to the continuation code to figure out
28 * All the routines below use bits of fixup code that are out of line
29 * with the main instruction path. This means when everything is well,
30 * we don't even have to jump over them. Further, they do not intrude
31 * on our cache or tlb entries.
34 struct exception_table_entry
36 unsigned long insn, fixup;
39 /* Returns 0 if exception not found and fixup otherwise. */
40 extern unsigned long search_exception_table(unsigned long);
44 * These are the main single-value transfer routines. They automatically
45 * use the right size if we just have the right pointer type.
48 #define put_user(x, ptr) \
51 typeof(*(ptr)) __pu_val = (x); \
52 switch (sizeof (*(ptr))) { \
54 __put_user_asm(__pu_err, __pu_val, ptr, b); \
57 __put_user_asm(__pu_err, __pu_val, ptr, w); \
60 __put_user_asm(__pu_err, __pu_val, ptr, l); \
63 __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8); \
66 __pu_err = __put_user_bad(); \
71 #define __put_user(x, ptr) put_user(x, ptr)
73 extern int __put_user_bad(void);
76 * Tell gcc we read from memory instead of writing: this is because
77 * we do not write to any memory gcc knows about, so there are no
80 #define __put_user_asm(err,x,ptr,bwl) \
81 __asm__ __volatile__ \
82 ("21:moves" #bwl " %2,%1\n" \
84 ".section .fixup,\"ax\"\n" \
89 ".section __ex_table,\"a\"\n" \
95 : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
97 #define get_user(x, ptr) \
100 typeof(*(ptr)) __gu_val; \
101 switch (sizeof(*(ptr))) { \
103 __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
106 __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \
109 __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \
112 __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \
116 __gu_err = __get_user_bad(); \
122 #define __get_user(x, ptr) get_user(x, ptr)
124 extern int __get_user_bad(void);
126 #define __get_user_asm(err,x,ptr,bwl,reg) \
127 __asm__ __volatile__ \
128 ("1: moves" #bwl " %2,%1\n" \
130 ".section .fixup,\"ax\"\n" \
133 " sub" #bwl " %1,%1\n" \
136 ".section __ex_table,\"a\"\n" \
140 : "=d"(err), reg(x) \
141 : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
143 static inline unsigned long
144 __generic_copy_from_user(void *to, const void *from, unsigned long n)
150 "1: movesl (%1)+,%3\n"
157 "3: movesw (%1)+,%3\n"
161 "5: movesb (%1)+,%3\n"
164 ".section .fixup,\"ax\"\n"
186 ".section __ex_table,\"a\"\n"
192 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
193 : "d"(n & 3), "0"(to), "1"(from), "2"(n/4)
198 static inline unsigned long
199 __generic_copy_to_user(void *to, const void *from, unsigned long n)
205 "1: movel (%1)+,%3\n"
206 "22:movesl %3,(%0)+\n"
213 "24:movesw %3,(%0)+\n"
217 "25:movesb %3,(%0)+\n"
219 ".section .fixup,\"ax\"\n"
230 ".section __ex_table,\"a\"\n"
241 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
242 : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
247 #define __copy_from_user_big(to, from, n, fixup, copy) \
248 __asm__ __volatile__ \
249 ("10: movesl (%1)+,%%d0\n" \
250 " movel %%d0,(%0)+\n" \
253 ".section .fixup,\"ax\"\n" \
255 "11: movel %2,%%d0\n" \
263 ".section __ex_table,\"a\"\n" \
269 : "=a"(to), "=a"(from), "=d"(n) \
270 : "0"(to), "1"(from), "2"(n/4) \
273 static inline unsigned long
274 __constant_copy_from_user(void *to, const void *from, unsigned long n)
281 ("1: movesb (%1)+,%%d0\n"
282 " moveb %%d0,(%0)+\n"
284 ".section .fixup,\"ax\"\n"
290 ".section __ex_table,\"a\"\n"
294 : "=a"(to), "=a"(from), "=d"(n)
295 : "0"(to), "1"(from), "2"(0)
300 ("1: movesw (%1)+,%%d0\n"
301 " movew %%d0,(%0)+\n"
303 ".section .fixup,\"ax\"\n"
309 ".section __ex_table,\"a\"\n"
313 : "=a"(to), "=a"(from), "=d"(n)
314 : "0"(to), "1"(from), "2"(0)
319 ("1: movesw (%1)+,%%d0\n"
320 " movew %%d0,(%0)+\n"
321 "2: movesb (%1)+,%%d0\n"
322 " moveb %%d0,(%0)+\n"
324 ".section .fixup,\"ax\"\n"
332 ".section __ex_table,\"a\"\n"
337 : "=a"(to), "=a"(from), "=d"(n)
338 : "0"(to), "1"(from), "2"(0)
343 ("1: movesl (%1)+,%%d0\n"
344 " movel %%d0,(%0)+\n"
346 ".section .fixup,\"ax\"\n"
352 ".section __ex_table,\"a\"\n"
356 : "=a"(to), "=a"(from), "=d"(n)
357 : "0"(to), "1"(from), "2"(0)
362 ("1: movesl (%1)+,%%d0\n"
363 " movel %%d0,(%0)+\n"
364 "2: movesl (%1)+,%%d0\n"
365 " movel %%d0,(%0)+\n"
367 ".section .fixup,\"ax\"\n"
375 ".section __ex_table,\"a\"\n"
380 : "=a"(to), "=a"(from), "=d"(n)
381 : "0"(to), "1"(from), "2"(0)
386 ("1: movesl (%1)+,%%d0\n"
387 " movel %%d0,(%0)+\n"
388 "2: movesl (%1)+,%%d0\n"
389 " movel %%d0,(%0)+\n"
390 "3: movesl (%1)+,%%d0\n"
391 " movel %%d0,(%0)+\n"
393 ".section .fixup,\"ax\"\n"
403 ".section __ex_table,\"a\"\n"
409 : "=a"(to), "=a"(from), "=d"(n)
410 : "0"(to), "1"(from), "2"(0)
415 ("1: movesl (%1)+,%%d0\n"
416 " movel %%d0,(%0)+\n"
417 "2: movesl (%1)+,%%d0\n"
418 " movel %%d0,(%0)+\n"
419 "3: movesl (%1)+,%%d0\n"
420 " movel %%d0,(%0)+\n"
421 "4: movesl (%1)+,%%d0\n"
422 " movel %%d0,(%0)+\n"
424 ".section .fixup,\"ax\"\n"
436 ".section __ex_table,\"a\"\n"
443 : "=a"(to), "=a"(from), "=d"(n)
444 : "0"(to), "1"(from), "2"(0)
450 __copy_from_user_big(to, from, n, "", "");
453 __copy_from_user_big(to, from, n,
458 "2: movesb (%1)+,%%d0\n"
459 " moveb %%d0,(%0)+\n"
460 ".section __ex_table,\"a\"\n"
465 __copy_from_user_big(to, from, n,
470 "2: movesw (%1)+,%%d0\n"
471 " movew %%d0,(%0)+\n"
472 ".section __ex_table,\"a\"\n"
477 __copy_from_user_big(to, from, n,
484 "3: movesw (%1)+,%%d0\n"
485 " movew %%d0,(%0)+\n"
486 "4: movesb (%1)+,%%d0\n"
487 " moveb %%d0,(%0)+\n"
488 ".section __ex_table,\"a\"\n"
499 #define __copy_to_user_big(to, from, n, fixup, copy) \
500 __asm__ __volatile__ \
501 ("10: movel (%1)+,%%d0\n" \
502 "31: movesl %%d0,(%0)+\n" \
503 "11: subql #1,%2\n" \
506 ".section .fixup,\"ax\"\n" \
508 "22: addql #1,%2\n" \
513 ".section __ex_table,\"a\"\n" \
522 : "=a"(to), "=a"(from), "=d"(n) \
523 : "0"(to), "1"(from), "2"(n/4) \
526 static inline unsigned long
527 __constant_copy_to_user(void *to, const void *from, unsigned long n)
534 (" moveb (%1)+,%%d0\n"
535 "21:movesb %%d0,(%0)+\n"
537 ".section .fixup,\"ax\"\n"
542 ".section __ex_table,\"a\"\n"
547 : "=a"(to), "=a"(from), "=d"(n)
548 : "0"(to), "1"(from), "2"(0)
553 (" movew (%1)+,%%d0\n"
554 "21:movesw %%d0,(%0)+\n"
556 ".section .fixup,\"ax\"\n"
561 ".section __ex_table,\"a\"\n"
566 : "=a"(to), "=a"(from), "=d"(n)
567 : "0"(to), "1"(from), "2"(0)
572 (" movew (%1)+,%%d0\n"
573 "21:movesw %%d0,(%0)+\n"
574 "1: moveb (%1)+,%%d0\n"
575 "22:movesb %%d0,(%0)+\n"
577 ".section .fixup,\"ax\"\n"
583 ".section __ex_table,\"a\"\n"
590 : "=a"(to), "=a"(from), "=d"(n)
591 : "0"(to), "1"(from), "2"(0)
596 (" movel (%1)+,%%d0\n"
597 "21:movesl %%d0,(%0)+\n"
599 ".section .fixup,\"ax\"\n"
604 ".section __ex_table,\"a\"\n"
609 : "=a"(to), "=a"(from), "=d"(n)
610 : "0"(to), "1"(from), "2"(0)
615 (" movel (%1)+,%%d0\n"
616 "21:movesl %%d0,(%0)+\n"
617 "1: movel (%1)+,%%d0\n"
618 "22:movesl %%d0,(%0)+\n"
620 ".section .fixup,\"ax\"\n"
626 ".section __ex_table,\"a\"\n"
633 : "=a"(to), "=a"(from), "=d"(n)
634 : "0"(to), "1"(from), "2"(0)
639 (" movel (%1)+,%%d0\n"
640 "21:movesl %%d0,(%0)+\n"
641 "1: movel (%1)+,%%d0\n"
642 "22:movesl %%d0,(%0)+\n"
643 "2: movel (%1)+,%%d0\n"
644 "23:movesl %%d0,(%0)+\n"
646 ".section .fixup,\"ax\"\n"
653 ".section __ex_table,\"a\"\n"
662 : "=a"(to), "=a"(from), "=d"(n)
663 : "0"(to), "1"(from), "2"(0)
668 (" movel (%1)+,%%d0\n"
669 "21:movesl %%d0,(%0)+\n"
670 "1: movel (%1)+,%%d0\n"
671 "22:movesl %%d0,(%0)+\n"
672 "2: movel (%1)+,%%d0\n"
673 "23:movesl %%d0,(%0)+\n"
674 "3: movel (%1)+,%%d0\n"
675 "24:movesl %%d0,(%0)+\n"
677 ".section .fixup,\"ax\"\n"
685 ".section __ex_table,\"a\"\n"
696 : "=a"(to), "=a"(from), "=d"(n)
697 : "0"(to), "1"(from), "2"(0)
703 __copy_to_user_big(to, from, n, "", "");
706 __copy_to_user_big(to, from, n,
710 " moveb (%1)+,%%d0\n"
711 "22:movesb %%d0,(%0)+\n"
713 ".section __ex_table,\"a\"\n"
719 __copy_to_user_big(to, from, n,
723 " movew (%1)+,%%d0\n"
724 "22:movesw %%d0,(%0)+\n"
726 ".section __ex_table,\"a\"\n"
732 __copy_to_user_big(to, from, n,
737 " movew (%1)+,%%d0\n"
738 "23:movesw %%d0,(%0)+\n"
739 "3: moveb (%1)+,%%d0\n"
740 "24:movesb %%d0,(%0)+\n"
742 ".section __ex_table,\"a\"\n"
755 #define copy_from_user(to, from, n) \
756 (__builtin_constant_p(n) ? \
757 __constant_copy_from_user(to, from, n) : \
758 __generic_copy_from_user(to, from, n))
760 #define copy_to_user(to, from, n) \
761 (__builtin_constant_p(n) ? \
762 __constant_copy_to_user(to, from, n) : \
763 __generic_copy_to_user(to, from, n))
765 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
766 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
769 * Copy a null terminated string from userspace.
773 strncpy_from_user(char *dst, const char *src, long count)
776 if (count == 0) return count;
778 ("1: movesb (%2)+,%%d0\n"
779 "12:moveb %%d0,(%1)+\n"
785 ".section .fixup,\"ax\"\n"
790 ".section __ex_table,\"a\"\n"
795 : "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
796 : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
802 * Return the size of a string (including the ending 0)
804 * Return 0 on exception, a value greater than N if too long
806 static inline long strnlen_user(const char *src, long n)
815 "2: movesb (%1)+,%%d0\n"
826 ".section .fixup,\"ax\"\n"
831 ".section __ex_table,\"a\"\n"
836 : "=d"(res), "=a"(src), "=d"(n)
837 : "i"(0), "0"(res), "1"(src), "2"(n)
842 #define strlen_user(str) strnlen_user(str, 32767)
848 static inline unsigned long
849 clear_user(void *to, unsigned long n)
854 "1: movesl %3,(%0)+\n"
860 "24:movesw %3,(%0)+\n"
863 "25:movesb %3,(%0)+\n"
865 ".section .fixup,\"ax\"\n"
876 ".section __ex_table,\"a\"\n"
887 : "r"(n & 3), "r"(0), "0"(to), "1"(n/4));
891 #endif /* _M68K_UACCESS_H */