2 * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
4 #ifndef __M68K_CF_UACCESS_H
5 #define __M68K_CF_UACCESS_H
8 * User space memory access functions
11 /* The "moves" command is not available in the CF instruction set. */
12 #include <linux/compiler.h>
13 #include <linux/errno.h>
14 #include <linux/types.h>
15 #include <linux/sched.h>
16 #include <asm/segment.h>
19 #define VERIFY_WRITE 1
21 /* We let the MMU do all checking */
22 #define access_ok(type, addr, size) 1
25 * The exception table consists of pairs of addresses: the first is the
26 * address of an instruction that is allowed to fault, and the second is
27 * the address at which the program should continue. No registers are
28 * modified, so it is entirely up to the continuation code to figure out
31 * All the routines below use bits of fixup code that are out of line
32 * with the main instruction path. This means when everything is well,
33 * we don't even have to jump over them. Further, they do not intrude
34 * on our cache or tlb entries.
37 struct exception_table_entry
39 unsigned long insn
, fixup
;
42 extern int __put_user_bad(void);
43 extern int __get_user_bad(void);
45 #define __put_user_asm(res, x, ptr, bwl, reg, err) \
47 "1: move."#bwl" %2,%1\n" \
49 " .section .fixup,\"ax\"\n" \
51 "10: moveq.l %3,%0\n" \
55 " .section __ex_table,\"a\"\n" \
60 : "+d" (res), "=m" (*(ptr)) \
61 : #reg (x), "i" (err))
64 * These are the main single-value transfer routines. They automatically
65 * use the right size if we just have the right pointer type.
68 #define __put_user(x, ptr) \
70 typeof(*(ptr)) __pu_val = (x); \
72 __chk_user_ptr(ptr); \
73 switch (sizeof (*(ptr))) { \
75 __put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT); \
78 __put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT); \
81 __put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT); \
85 const void __user *__pu_ptr = (ptr); \
87 "1: move.l %2,(%1)+\n" \
88 "2: move.l %R2,(%1)\n" \
90 " .section .fixup,\"ax\"\n" \
96 " .section __ex_table,\"a\"\n" \
102 : "+d" (__pu_err), "+a" (__pu_ptr) \
103 : "r" (__pu_val), "i" (-EFAULT) \
108 __pu_err = __put_user_bad(); \
113 #define put_user(x, ptr) __put_user(x, ptr)
116 #define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \
119 "1: move."#bwl" %2,%1\n" \
121 " .section .fixup,\"ax\"\n" \
123 "10: move.l %3,%0\n" \
128 " .section __ex_table,\"a\"\n" \
132 : "+d" (res), "=&" #reg (__gu_val) \
133 : "m" (*(ptr)), "i" (err)); \
134 (x) = (typeof(*(ptr)))(unsigned long)__gu_val; \
137 #define __get_user(x, ptr) \
140 __chk_user_ptr(ptr); \
141 switch (sizeof(*(ptr))) { \
143 __get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT); \
146 __get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT); \
149 __get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT); \
151 /* case 8: disabled because gcc-4.1 has a broken typeof \
153 const void *__gu_ptr = (ptr); \
156 "1: move.l (%2)+,%1\n" \
157 "2: move.l (%2),%R1\n" \
159 " .section .fixup,\"ax\"\n" \
161 "10: move.l %3,%0\n" \
167 " .section __ex_table,\"a\"\n" \
172 : "+d" (__gu_err), "=&r" (__gu_val), \
176 (x) = (typeof(*(ptr)))__gu_val; \
180 __gu_err = __get_user_bad(); \
185 #define get_user(x, ptr) __get_user(x, ptr)
187 unsigned long __generic_copy_from_user(void *to
, const void __user
*from
,
189 unsigned long __generic_copy_to_user(void __user
*to
, const void *from
,
192 #define __constant_copy_from_user_asm(res, to, from, tmp, n, s1, s2, s3)\
194 "1: move."#s1" (%2)+,%3\n" \
195 " move."#s1" %3,(%1)+\n" \
196 "2: move."#s2" (%2)+,%3\n" \
197 " move."#s2" %3,(%1)+\n" \
198 " .ifnc \""#s3"\",\"\"\n" \
199 "3: move."#s3" (%2)+,%3\n" \
200 " move."#s3" %3,(%1)+\n" \
203 " .section __ex_table,\"a\"\n" \
207 " .ifnc \""#s3"\",\"\"\n" \
212 " .section .fixup,\"ax\"\n" \
214 "10: clr."#s1" (%1)+\n" \
215 "20: clr."#s2" (%1)+\n" \
216 " .ifnc \""#s3"\",\"\"\n" \
217 "30: clr."#s3" (%1)+\n" \
219 " moveq.l #"#n",%0\n" \
222 : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp) \
225 static __always_inline
unsigned long
226 __constant_copy_from_user(void *to
, const void __user
*from
, unsigned long n
)
228 unsigned long res
= 0, tmp
;
232 __get_user_asm(res
, *(u8
*)to
, (u8 __user
*)from
, u8
, b
, d
, 1);
235 __get_user_asm(res
, *(u16
*)to
, (u16 __user
*)from
, u16
, w
,
239 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 3, w
, b
,);
242 __get_user_asm(res
, *(u32
*)to
, (u32 __user
*)from
, u32
, l
,
246 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 5, l
, b
,);
249 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 6, l
, w
,);
252 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 7, l
, w
, b
);
255 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 8, l
, l
,);
258 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 9, l
, l
, b
);
261 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 10, l
, l
, w
);
264 __constant_copy_from_user_asm(res
, to
, from
, tmp
, 12, l
, l
, l
);
267 /* we limit the inlined version to 3 moves */
268 return __generic_copy_from_user(to
, from
, n
);
274 #define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3) \
276 " move."#s1" (%2)+,%3\n" \
277 "11: move."#s1" %3,(%1)+\n" \
278 "12: move."#s2" (%2)+,%3\n" \
279 "21: move."#s2" %3,(%1)+\n" \
281 " .ifnc \""#s3"\",\"\"\n" \
282 " move."#s3" (%2)+,%3\n" \
283 "31: move."#s3" %3,(%1)+\n" \
288 " .section __ex_table,\"a\"\n" \
294 " .ifnc \""#s3"\",\"\"\n" \
300 " .section .fixup,\"ax\"\n" \
302 "5: moveq.l #"#n",%0\n" \
305 : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp) \
308 static __always_inline
unsigned long
309 __constant_copy_to_user(void __user
*to
, const void *from
, unsigned long n
)
311 unsigned long res
= 0, tmp
;
315 __put_user_asm(res
, *(u8
*)from
, (u8 __user
*)to
, b
, d
, 1);
318 __put_user_asm(res
, *(u16
*)from
, (u16 __user
*)to
, w
, d
, 2);
321 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 3, w
, b
,);
324 __put_user_asm(res
, *(u32
*)from
, (u32 __user
*)to
, l
, r
, 4);
327 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 5, l
, b
,);
330 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 6, l
, w
,);
333 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 7, l
, w
, b
);
336 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 8, l
, l
,);
339 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 9, l
, l
, b
);
342 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 10, l
, l
, w
);
345 __constant_copy_to_user_asm(res
, to
, from
, tmp
, 12, l
, l
, l
);
348 /* limit the inlined version to 3 moves */
349 return __generic_copy_to_user(to
, from
, n
);
355 #define __copy_from_user(to, from, n) \
356 (__builtin_constant_p(n) ? \
357 __constant_copy_from_user(to, from, n) : \
358 __generic_copy_from_user(to, from, n))
360 #define __copy_to_user(to, from, n) \
361 (__builtin_constant_p(n) ? \
362 __constant_copy_to_user(to, from, n) : \
363 __generic_copy_to_user(to, from, n))
365 #define __copy_to_user_inatomic __copy_to_user
366 #define __copy_from_user_inatomic __copy_from_user
368 #define copy_from_user(to, from, n) __copy_from_user(to, from, n)
369 #define copy_to_user(to, from, n) __copy_to_user(to, from, n)
371 long strncpy_from_user(char *dst
, const char __user
*src
, long count
);
372 long strnlen_user(const char __user
*src
, long n
);
373 unsigned long __clear_user(void __user
*to
, unsigned long n
);
375 #define clear_user __clear_user
377 #define strlen_user(str) strnlen_user(str, 32767)
379 #endif /* _M68K_CF_UACCESS_H */
This page took 0.068766 seconds and 5 git commands to generate.