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 = __put_user_bad(); \
68 #define __put_user(x, ptr) put_user(x, ptr)
70 extern int __put_user_bad(void);
73 * Tell gcc we read from memory instead of writing: this is because
74 * we do not write to any memory gcc knows about, so there are no
77 #define __put_user_asm(err,x,ptr,bwl) \
78 __asm__ __volatile__ \
79 ("21:moves" #bwl " %2,%1\n" \
81 ".section .fixup,\"ax\"\n" \
86 ".section __ex_table,\"a\"\n" \
92 : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
94 #define get_user(x, ptr) \
97 typeof(*(ptr)) __gu_val; \
98 switch (sizeof(*(ptr))) { \
100 __get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
103 __get_user_asm(__gu_err, __gu_val, ptr, w, "=r"); \
106 __get_user_asm(__gu_err, __gu_val, ptr, l, "=r"); \
110 __gu_err = __get_user_bad(); \
116 #define __get_user(x, ptr) get_user(x, ptr)
118 extern int __get_user_bad(void);
120 #define __get_user_asm(err,x,ptr,bwl,reg) \
121 __asm__ __volatile__ \
122 ("1: moves" #bwl " %2,%1\n" \
124 ".section .fixup,\"ax\"\n" \
127 " sub" #bwl " %1,%1\n" \
130 ".section __ex_table,\"a\"\n" \
134 : "=d"(err), reg(x) \
135 : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
137 static inline unsigned long
138 __generic_copy_from_user(void *to
, const void *from
, unsigned long n
)
144 "1: movesl (%1)+,%3\n"
151 "3: movesw (%1)+,%3\n"
155 "5: movesb (%1)+,%3\n"
158 ".section .fixup,\"ax\"\n"
180 ".section __ex_table,\"a\"\n"
186 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
187 : "d"(n
& 3), "0"(to
), "1"(from
), "2"(n
/4)
192 static inline unsigned long
193 __generic_copy_to_user(void *to
, const void *from
, unsigned long n
)
199 "1: movel (%1)+,%3\n"
200 "22:movesl %3,(%0)+\n"
207 "24:movesw %3,(%0)+\n"
211 "25:movesb %3,(%0)+\n"
213 ".section .fixup,\"ax\"\n"
224 ".section __ex_table,\"a\"\n"
235 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
236 : "r"(n
& 3), "0"(to
), "1"(from
), "2"(n
/ 4)
241 #define __copy_from_user_big(to, from, n, fixup, copy) \
242 __asm__ __volatile__ \
243 ("10: movesl (%1)+,%%d0\n" \
244 " movel %%d0,(%0)+\n" \
247 ".section .fixup,\"ax\"\n" \
249 "11: movel %2,%%d0\n" \
257 ".section __ex_table,\"a\"\n" \
263 : "=a"(to), "=a"(from), "=d"(n) \
264 : "0"(to), "1"(from), "2"(n/4) \
267 static inline unsigned long
268 __constant_copy_from_user(void *to
, const void *from
, unsigned long n
)
275 ("1: movesb (%1)+,%%d0\n"
276 " moveb %%d0,(%0)+\n"
278 ".section .fixup,\"ax\"\n"
284 ".section __ex_table,\"a\"\n"
288 : "=a"(to
), "=a"(from
), "=d"(n
)
289 : "0"(to
), "1"(from
), "2"(0)
294 ("1: movesw (%1)+,%%d0\n"
295 " movew %%d0,(%0)+\n"
297 ".section .fixup,\"ax\"\n"
303 ".section __ex_table,\"a\"\n"
307 : "=a"(to
), "=a"(from
), "=d"(n
)
308 : "0"(to
), "1"(from
), "2"(0)
313 ("1: movesw (%1)+,%%d0\n"
314 " movew %%d0,(%0)+\n"
315 "2: movesb (%1)+,%%d0\n"
316 " moveb %%d0,(%0)+\n"
318 ".section .fixup,\"ax\"\n"
326 ".section __ex_table,\"a\"\n"
331 : "=a"(to
), "=a"(from
), "=d"(n
)
332 : "0"(to
), "1"(from
), "2"(0)
337 ("1: movesl (%1)+,%%d0\n"
338 " movel %%d0,(%0)+\n"
340 ".section .fixup,\"ax\"\n"
346 ".section __ex_table,\"a\"\n"
350 : "=a"(to
), "=a"(from
), "=d"(n
)
351 : "0"(to
), "1"(from
), "2"(0)
356 ("1: movesl (%1)+,%%d0\n"
357 " movel %%d0,(%0)+\n"
358 "2: movesl (%1)+,%%d0\n"
359 " movel %%d0,(%0)+\n"
361 ".section .fixup,\"ax\"\n"
369 ".section __ex_table,\"a\"\n"
374 : "=a"(to
), "=a"(from
), "=d"(n
)
375 : "0"(to
), "1"(from
), "2"(0)
380 ("1: movesl (%1)+,%%d0\n"
381 " movel %%d0,(%0)+\n"
382 "2: movesl (%1)+,%%d0\n"
383 " movel %%d0,(%0)+\n"
384 "3: movesl (%1)+,%%d0\n"
385 " movel %%d0,(%0)+\n"
387 ".section .fixup,\"ax\"\n"
397 ".section __ex_table,\"a\"\n"
403 : "=a"(to
), "=a"(from
), "=d"(n
)
404 : "0"(to
), "1"(from
), "2"(0)
409 ("1: movesl (%1)+,%%d0\n"
410 " movel %%d0,(%0)+\n"
411 "2: movesl (%1)+,%%d0\n"
412 " movel %%d0,(%0)+\n"
413 "3: movesl (%1)+,%%d0\n"
414 " movel %%d0,(%0)+\n"
415 "4: movesl (%1)+,%%d0\n"
416 " movel %%d0,(%0)+\n"
418 ".section .fixup,\"ax\"\n"
430 ".section __ex_table,\"a\"\n"
437 : "=a"(to
), "=a"(from
), "=d"(n
)
438 : "0"(to
), "1"(from
), "2"(0)
444 __copy_from_user_big(to
, from
, n
, "", "");
447 __copy_from_user_big(to
, from
, n
,
452 "2: movesb (%1)+,%%d0\n"
453 " moveb %%d0,(%0)+\n"
454 ".section __ex_table,\"a\"\n"
459 __copy_from_user_big(to
, from
, n
,
464 "2: movesw (%1)+,%%d0\n"
465 " movew %%d0,(%0)+\n"
466 ".section __ex_table,\"a\"\n"
471 __copy_from_user_big(to
, from
, n
,
478 "3: movesw (%1)+,%%d0\n"
479 " movew %%d0,(%0)+\n"
480 "4: movesb (%1)+,%%d0\n"
481 " moveb %%d0,(%0)+\n"
482 ".section __ex_table,\"a\"\n"
493 #define __copy_to_user_big(to, from, n, fixup, copy) \
494 __asm__ __volatile__ \
495 ("10: movel (%1)+,%%d0\n" \
496 "31: movesl %%d0,(%0)+\n" \
497 "11: subql #1,%2\n" \
500 ".section .fixup,\"ax\"\n" \
502 "22: addql #1,%2\n" \
507 ".section __ex_table,\"a\"\n" \
516 : "=a"(to), "=a"(from), "=d"(n) \
517 : "0"(to), "1"(from), "2"(n/4) \
520 static inline unsigned long
521 __constant_copy_to_user(void *to
, const void *from
, unsigned long n
)
528 (" moveb (%1)+,%%d0\n"
529 "21:movesb %%d0,(%0)+\n"
531 ".section .fixup,\"ax\"\n"
536 ".section __ex_table,\"a\"\n"
541 : "=a"(to
), "=a"(from
), "=d"(n
)
542 : "0"(to
), "1"(from
), "2"(0)
547 (" movew (%1)+,%%d0\n"
548 "21:movesw %%d0,(%0)+\n"
550 ".section .fixup,\"ax\"\n"
555 ".section __ex_table,\"a\"\n"
560 : "=a"(to
), "=a"(from
), "=d"(n
)
561 : "0"(to
), "1"(from
), "2"(0)
566 (" movew (%1)+,%%d0\n"
567 "21:movesw %%d0,(%0)+\n"
568 "1: moveb (%1)+,%%d0\n"
569 "22:movesb %%d0,(%0)+\n"
571 ".section .fixup,\"ax\"\n"
577 ".section __ex_table,\"a\"\n"
584 : "=a"(to
), "=a"(from
), "=d"(n
)
585 : "0"(to
), "1"(from
), "2"(0)
590 (" movel (%1)+,%%d0\n"
591 "21:movesl %%d0,(%0)+\n"
593 ".section .fixup,\"ax\"\n"
598 ".section __ex_table,\"a\"\n"
603 : "=a"(to
), "=a"(from
), "=d"(n
)
604 : "0"(to
), "1"(from
), "2"(0)
609 (" movel (%1)+,%%d0\n"
610 "21:movesl %%d0,(%0)+\n"
611 "1: movel (%1)+,%%d0\n"
612 "22:movesl %%d0,(%0)+\n"
614 ".section .fixup,\"ax\"\n"
620 ".section __ex_table,\"a\"\n"
627 : "=a"(to
), "=a"(from
), "=d"(n
)
628 : "0"(to
), "1"(from
), "2"(0)
633 (" movel (%1)+,%%d0\n"
634 "21:movesl %%d0,(%0)+\n"
635 "1: movel (%1)+,%%d0\n"
636 "22:movesl %%d0,(%0)+\n"
637 "2: movel (%1)+,%%d0\n"
638 "23:movesl %%d0,(%0)+\n"
640 ".section .fixup,\"ax\"\n"
647 ".section __ex_table,\"a\"\n"
656 : "=a"(to
), "=a"(from
), "=d"(n
)
657 : "0"(to
), "1"(from
), "2"(0)
662 (" movel (%1)+,%%d0\n"
663 "21:movesl %%d0,(%0)+\n"
664 "1: movel (%1)+,%%d0\n"
665 "22:movesl %%d0,(%0)+\n"
666 "2: movel (%1)+,%%d0\n"
667 "23:movesl %%d0,(%0)+\n"
668 "3: movel (%1)+,%%d0\n"
669 "24:movesl %%d0,(%0)+\n"
671 ".section .fixup,\"ax\"\n"
679 ".section __ex_table,\"a\"\n"
690 : "=a"(to
), "=a"(from
), "=d"(n
)
691 : "0"(to
), "1"(from
), "2"(0)
697 __copy_to_user_big(to
, from
, n
, "", "");
700 __copy_to_user_big(to
, from
, n
,
704 " moveb (%1)+,%%d0\n"
705 "22:movesb %%d0,(%0)+\n"
707 ".section __ex_table,\"a\"\n"
713 __copy_to_user_big(to
, from
, n
,
717 " movew (%1)+,%%d0\n"
718 "22:movesw %%d0,(%0)+\n"
720 ".section __ex_table,\"a\"\n"
726 __copy_to_user_big(to
, from
, n
,
731 " movew (%1)+,%%d0\n"
732 "23:movesw %%d0,(%0)+\n"
733 "3: moveb (%1)+,%%d0\n"
734 "24:movesb %%d0,(%0)+\n"
736 ".section __ex_table,\"a\"\n"
749 #define copy_from_user(to, from, n) \
750 (__builtin_constant_p(n) ? \
751 __constant_copy_from_user(to, from, n) : \
752 __generic_copy_from_user(to, from, n))
754 #define copy_to_user(to, from, n) \
755 (__builtin_constant_p(n) ? \
756 __constant_copy_to_user(to, from, n) : \
757 __generic_copy_to_user(to, from, n))
759 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
760 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
762 #define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
764 #define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
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)
804 static inline long strlen_user(const char * src
)
806 long res
= -(long) src
;
808 ("1: movesb (%1)+,%%d0\n"
813 ".section .fixup,\"ax\"\n"
818 ".section __ex_table,\"a\"\n"
823 : "=d"(res
), "=a"(src
)
824 : "i"(0), "0"(res
), "1"(src
)
833 static inline unsigned long
834 clear_user(void *to
, unsigned long n
)
839 "1: movesl %3,(%0)+\n"
845 "24:movesw %3,(%0)+\n"
848 "25:movesb %3,(%0)+\n"
850 ".section .fixup,\"ax\"\n"
861 ".section __ex_table,\"a\"\n"
872 : "r"(n
& 3), "r"(0), "0"(to
), "1"(n
/4));
876 #endif /* _M68K_UACCESS_H */