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"
168 ".section __ex_table,\"a\"\n"
174 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
175 : "r"(n
& 3), "0"(to
), "1"(from
), "2"(n
/4)
180 static inline unsigned long
181 __generic_copy_to_user(void *to
, const void *from
, unsigned long n
)
187 "1: movel (%1)+,%3\n"
188 "22:movesl %3,(%0)+\n"
195 "24:movesw %3,(%0)+\n"
199 "25:movesb %3,(%0)+\n"
201 ".section .fixup,\"ax\"\n"
212 ".section __ex_table,\"a\"\n"
223 : "=a"(to
), "=a"(from
), "=d"(n
), "=&d"(tmp
)
224 : "r"(n
& 3), "0"(to
), "1"(from
), "2"(n
/ 4));
228 #define __copy_from_user_big(to, from, n, fixup, copy) \
229 __asm__ __volatile__ \
230 ("10: movesl (%1)+,%%d0\n" \
231 " movel %%d0,(%0)+\n" \
234 ".section .fixup,\"ax\"\n" \
240 ".section __ex_table,\"a\"\n" \
246 : "=a"(to), "=a"(from), "=d"(n) \
247 : "0"(to), "1"(from), "2"(n/4) \
250 static inline unsigned long
251 __constant_copy_from_user(void *to
, const void *from
, unsigned long n
)
258 ("1: movesb (%1)+,%%d0\n"
259 " moveb %%d0,(%0)+\n"
261 ".section .fixup,\"ax\"\n"
266 ".section __ex_table,\"a\"\n"
270 : "=a"(to
), "=a"(from
), "=d"(n
)
271 : "0"(to
), "1"(from
), "2"(0)
276 ("1: movesw (%1)+,%%d0\n"
277 " movew %%d0,(%0)+\n"
279 ".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"
296 "2: movesb (%1)+,%%d0\n"
297 " moveb %%d0,(%0)+\n"
299 ".section .fixup,\"ax\"\n"
305 ".section __ex_table,\"a\"\n"
310 : "=a"(to
), "=a"(from
), "=d"(n
)
311 : "0"(to
), "1"(from
), "2"(0)
316 ("1: movesl (%1)+,%%d0\n"
317 " movel %%d0,(%0)+\n"
319 ".section .fixup,\"ax\"\n"
324 ".section __ex_table,\"a\"\n"
328 : "=a"(to
), "=a"(from
), "=d"(n
)
329 : "0"(to
), "1"(from
), "2"(0)
334 ("1: movesl (%1)+,%%d0\n"
335 " movel %%d0,(%0)+\n"
336 "2: movesl (%1)+,%%d0\n"
337 " movel %%d0,(%0)+\n"
339 ".section .fixup,\"ax\"\n"
345 ".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"
360 "3: movesl (%1)+,%%d0\n"
361 " movel %%d0,(%0)+\n"
363 ".section .fixup,\"ax\"\n"
370 ".section __ex_table,\"a\"\n"
376 : "=a"(to
), "=a"(from
), "=d"(n
)
377 : "0"(to
), "1"(from
), "2"(0)
382 ("1: movesl (%1)+,%%d0\n"
383 " movel %%d0,(%0)+\n"
384 "2: movesl (%1)+,%%d0\n"
385 " movel %%d0,(%0)+\n"
386 "3: movesl (%1)+,%%d0\n"
387 " movel %%d0,(%0)+\n"
388 "4: movesl (%1)+,%%d0\n"
389 " movel %%d0,(%0)+\n"
391 ".section .fixup,\"ax\"\n"
399 ".section __ex_table,\"a\"\n"
406 : "=a"(to
), "=a"(from
), "=d"(n
)
407 : "0"(to
), "1"(from
), "2"(0)
413 __copy_from_user_big(to
, from
, n
, "", "");
416 __copy_from_user_big(to
, from
, n
,
420 "2: movesb (%1)+,%%d0\n"
421 " moveb %%d0,(%0)+\n"
422 ".section __ex_table,\"a\"\n"
427 __copy_from_user_big(to
, from
, n
,
431 "2: movesw (%1)+,%%d0\n"
432 " movew %%d0,(%0)+\n"
433 ".section __ex_table,\"a\"\n"
438 __copy_from_user_big(to
, from
, n
,
443 "3: movesw (%1)+,%%d0\n"
444 " movew %%d0,(%0)+\n"
445 "4: movesb (%1)+,%%d0\n"
446 " moveb %%d0,(%0)+\n"
447 ".section __ex_table,\"a\"\n"
458 #define __copy_to_user_big(to, from, n, fixup, copy) \
459 __asm__ __volatile__ \
460 ("10: movel (%1)+,%%d0\n" \
461 "31: movesl %%d0,(%0)+\n" \
462 "11: subql #1,%2\n" \
465 ".section .fixup,\"ax\"\n" \
467 "22: addql #1,%2\n" \
472 ".section __ex_table,\"a\"\n" \
481 : "=a"(to), "=a"(from), "=d"(n) \
482 : "0"(to), "1"(from), "2"(n/4) \
485 static inline unsigned long
486 __constant_copy_to_user(void *to
, const void *from
, unsigned long n
)
493 (" moveb (%1)+,%%d0\n"
494 "21:movesb %%d0,(%0)+\n"
496 ".section .fixup,\"ax\"\n"
501 ".section __ex_table,\"a\"\n"
506 : "=a"(to
), "=a"(from
), "=d"(n
)
507 : "0"(to
), "1"(from
), "2"(0)
512 (" movew (%1)+,%%d0\n"
513 "21:movesw %%d0,(%0)+\n"
515 ".section .fixup,\"ax\"\n"
520 ".section __ex_table,\"a\"\n"
525 : "=a"(to
), "=a"(from
), "=d"(n
)
526 : "0"(to
), "1"(from
), "2"(0)
531 (" movew (%1)+,%%d0\n"
532 "21:movesw %%d0,(%0)+\n"
533 "1: moveb (%1)+,%%d0\n"
534 "22:movesb %%d0,(%0)+\n"
536 ".section .fixup,\"ax\"\n"
542 ".section __ex_table,\"a\"\n"
549 : "=a"(to
), "=a"(from
), "=d"(n
)
550 : "0"(to
), "1"(from
), "2"(0)
555 (" movel (%1)+,%%d0\n"
556 "21:movesl %%d0,(%0)+\n"
558 ".section .fixup,\"ax\"\n"
563 ".section __ex_table,\"a\"\n"
568 : "=a"(to
), "=a"(from
), "=d"(n
)
569 : "0"(to
), "1"(from
), "2"(0)
574 (" movel (%1)+,%%d0\n"
575 "21:movesl %%d0,(%0)+\n"
576 "1: movel (%1)+,%%d0\n"
577 "22:movesl %%d0,(%0)+\n"
579 ".section .fixup,\"ax\"\n"
585 ".section __ex_table,\"a\"\n"
592 : "=a"(to
), "=a"(from
), "=d"(n
)
593 : "0"(to
), "1"(from
), "2"(0)
598 (" movel (%1)+,%%d0\n"
599 "21:movesl %%d0,(%0)+\n"
600 "1: movel (%1)+,%%d0\n"
601 "22:movesl %%d0,(%0)+\n"
602 "2: movel (%1)+,%%d0\n"
603 "23:movesl %%d0,(%0)+\n"
605 ".section .fixup,\"ax\"\n"
612 ".section __ex_table,\"a\"\n"
621 : "=a"(to
), "=a"(from
), "=d"(n
)
622 : "0"(to
), "1"(from
), "2"(0)
627 (" movel (%1)+,%%d0\n"
628 "21:movesl %%d0,(%0)+\n"
629 "1: movel (%1)+,%%d0\n"
630 "22:movesl %%d0,(%0)+\n"
631 "2: movel (%1)+,%%d0\n"
632 "23:movesl %%d0,(%0)+\n"
633 "3: movel (%1)+,%%d0\n"
634 "24:movesl %%d0,(%0)+\n"
636 ".section .fixup,\"ax\"\n"
644 ".section __ex_table,\"a\"\n"
655 : "=a"(to
), "=a"(from
), "=d"(n
)
656 : "0"(to
), "1"(from
), "2"(0)
662 __copy_to_user_big(to
, from
, n
, "", "");
665 __copy_to_user_big(to
, from
, n
,
669 " moveb (%1)+,%%d0\n"
670 "22:movesb %%d0,(%0)+\n"
672 ".section __ex_table,\"a\"\n"
678 __copy_to_user_big(to
, from
, n
,
682 " movew (%1)+,%%d0\n"
683 "22:movesw %%d0,(%0)+\n"
685 ".section __ex_table,\"a\"\n"
691 __copy_to_user_big(to
, from
, n
,
696 " movew (%1)+,%%d0\n"
697 "23:movesw %%d0,(%0)+\n"
698 "3: moveb (%1)+,%%d0\n"
699 "24:movesb %%d0,(%0)+\n"
701 ".section __ex_table,\"a\"\n"
714 #define copy_from_user(to, from, n) \
715 (__builtin_constant_p(n) ? \
716 __constant_copy_from_user(to, from, n) : \
717 __generic_copy_from_user(to, from, n))
719 #define copy_to_user(to, from, n) \
720 (__builtin_constant_p(n) ? \
721 __constant_copy_to_user(to, from, n) : \
722 __generic_copy_to_user(to, from, n))
724 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
725 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
728 * Copy a null terminated string from userspace.
732 strncpy_from_user(char *dst
, const char *src
, long count
)
735 if (count
== 0) return count
;
737 ("1: movesb (%2)+,%%d0\n"
738 "12:moveb %%d0,(%1)+\n"
744 ".section .fixup,\"ax\"\n"
749 ".section __ex_table,\"a\"\n"
754 : "=d"(res
), "=a"(dst
), "=a"(src
), "=d"(count
)
755 : "i"(-EFAULT
), "0"(count
), "1"(dst
), "2"(src
), "3"(count
)
761 * Return the size of a string (including the ending 0)
765 static inline long strlen_user(const char * src
)
767 long res
= -(long) src
;
769 ("1: movesb (%1)+,%%d0\n"
774 ".section .fixup,\"ax\"\n"
779 ".section __ex_table,\"a\"\n"
784 : "=d"(res
), "=a"(src
)
785 : "i"(0), "0"(res
), "1"(src
)
794 static inline unsigned long
795 clear_user(void *to
, unsigned long n
)
800 "1: movesl %3,(%0)+\n"
806 "24:movesw %3,(%0)+\n"
809 "25:movesb %3,(%0)+\n"
811 ".section .fixup,\"ax\"\n"
822 ".section __ex_table,\"a\"\n"
833 : "r"(n
& 3), "r"(0), "0"(to
), "1"(n
/4));
837 #endif /* _M68K_UACCESS_H */