[PATCH] m68k: clean up uaccess.h
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / include / asm-m68k / uaccess.h
blobb761ef218ceac1df13ae556b9906322171aad6c3
1 #ifndef __M68K_UACCESS_H
2 #define __M68K_UACCESS_H
4 /*
5 * User space memory access functions
6 */
7 #include <linux/compiler.h>
8 #include <linux/errno.h>
9 #include <linux/types.h>
10 #include <asm/segment.h>
12 #define VERIFY_READ 0
13 #define VERIFY_WRITE 1
15 /* We let the MMU do all checking */
16 #define access_ok(type,addr,size) 1
19 * The exception table consists of pairs of addresses: the first is the
20 * address of an instruction that is allowed to fault, and the second is
21 * the address at which the program should continue. No registers are
22 * modified, so it is entirely up to the continuation code to figure out
23 * what to do.
25 * All the routines below use bits of fixup code that are out of line
26 * with the main instruction path. This means when everything is well,
27 * we don't even have to jump over them. Further, they do not intrude
28 * on our cache or tlb entries.
31 struct exception_table_entry
33 unsigned long insn, fixup;
36 extern int __put_user_bad(void);
37 extern int __get_user_bad(void);
39 #define __put_user_asm(res, x, ptr, bwl, reg, err) \
40 asm volatile ("\n" \
41 "1: moves."#bwl" %2,%1\n" \
42 "2:\n" \
43 " .section .fixup,\"ax\"\n" \
44 " .even\n" \
45 "10: moveq.l %3,%0\n" \
46 " jra 2b\n" \
47 " .previous\n" \
48 "\n" \
49 " .section __ex_table,\"a\"\n" \
50 " .align 4\n" \
51 " .long 1b,10b\n" \
52 " .long 2b,10b\n" \
53 " .previous" \
54 : "+d" (res), "=m" (*(ptr)) \
55 : #reg (x), "i" (err))
58 * These are the main single-value transfer routines. They automatically
59 * use the right size if we just have the right pointer type.
62 #define __put_user(x, ptr) \
63 ({ \
64 typeof(*(ptr)) __pu_val = (x); \
65 int __pu_err = 0; \
66 __chk_user_ptr(ptr); \
67 switch (sizeof (*(ptr))) { \
68 case 1: \
69 __put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT); \
70 break; \
71 case 2: \
72 __put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT); \
73 break; \
74 case 4: \
75 __put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT); \
76 break; \
77 case 8: \
78 { \
79 const void *__pu_ptr = (ptr); \
80 asm volatile ("\n" \
81 "1: moves.l %2,(%1)+\n" \
82 "2: moves.l %R2,(%1)\n" \
83 "3:\n" \
84 " .section .fixup,\"ax\"\n" \
85 " .even\n" \
86 "10: movel %3,%0\n" \
87 " jra 3b\n" \
88 " .previous\n" \
89 "\n" \
90 " .section __ex_table,\"a\"\n" \
91 " .align 4\n" \
92 " .long 1b,10b\n" \
93 " .long 2b,10b\n" \
94 " .long 3b,10b\n" \
95 " .previous" \
96 : "+d" (__pu_err), "+a" (__pu_ptr) \
97 : "r" (__pu_val), "i" (-EFAULT) \
98 : "memory"); \
99 break; \
101 default: \
102 __pu_err = __put_user_bad(); \
103 break; \
105 __pu_err; \
107 #define put_user(x, ptr) __put_user(x, ptr)
110 #define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \
111 type __gu_val; \
112 asm volatile ("\n" \
113 "1: moves."#bwl" %2,%1\n" \
114 "2:\n" \
115 " .section .fixup,\"ax\"\n" \
116 " .even\n" \
117 "10: move.l %3,%0\n" \
118 " sub."#bwl" %1,%1\n" \
119 " jra 2b\n" \
120 " .previous\n" \
121 "\n" \
122 " .section __ex_table,\"a\"\n" \
123 " .align 4\n" \
124 " .long 1b,10b\n" \
125 " .previous" \
126 : "+d" (res), "=&" #reg (__gu_val) \
127 : "m" (*(ptr)), "i" (err)); \
128 (x) = (typeof(*(ptr)))(long)__gu_val; \
131 #define __get_user(x, ptr) \
132 ({ \
133 int __gu_err = 0; \
134 __chk_user_ptr(ptr); \
135 switch (sizeof(*(ptr))) { \
136 case 1: \
137 __get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT); \
138 break; \
139 case 2: \
140 __get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT); \
141 break; \
142 case 4: \
143 __get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT); \
144 break; \
145 /* case 8: disabled because gcc-4.1 has a broken typeof \
147 const void *__gu_ptr = (ptr); \
148 u64 __gu_val; \
149 asm volatile ("\n" \
150 "1: moves.l (%2)+,%1\n" \
151 "2: moves.l (%2),%R1\n" \
152 "3:\n" \
153 " .section .fixup,\"ax\"\n" \
154 " .even\n" \
155 "10: move.l %3,%0\n" \
156 " sub.l %1,%1\n" \
157 " sub.l %R1,%R1\n" \
158 " jra 3b\n" \
159 " .previous\n" \
160 "\n" \
161 " .section __ex_table,\"a\"\n" \
162 " .align 4\n" \
163 " .long 1b,10b\n" \
164 " .long 2b,10b\n" \
165 " .previous" \
166 : "+d" (__gu_err), "=&r" (__gu_val), \
167 "+a" (__gu_ptr) \
168 : "i" (-EFAULT) \
169 : "memory"); \
170 (x) = (typeof(*(ptr)))__gu_val; \
171 break; \
172 } */ \
173 default: \
174 __gu_err = __get_user_bad(); \
175 break; \
177 __gu_err; \
179 #define get_user(x, ptr) __get_user(x, ptr)
181 unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n);
182 unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n);
184 static __always_inline unsigned long
185 __constant_copy_from_user(void *to, const void __user *from, unsigned long n)
187 unsigned long res = 0, tmp;
189 /* limit the inlined version to 3 moves */
190 if (n == 11 || n > 12)
191 return __generic_copy_from_user(to, from, n);
193 switch (n) {
194 case 1:
195 __get_user_asm(res, *(u8 *)to, (u8 *)from, u8, b, d, 1);
196 return res;
197 case 2:
198 __get_user_asm(res, *(u16 *)to, (u16 *)from, u16, w, d, 2);
199 return res;
200 case 4:
201 __get_user_asm(res, *(u32 *)to, (u32 *)from, u32, l, r, 4);
202 return res;
205 asm volatile ("\n"
206 " .ifndef .Lfrom_user\n"
207 " .set .Lfrom_user,1\n"
208 " .macro copy_from_user to,from,tmp\n"
209 " .if .Lcnt >= 4\n"
210 "1: moves.l (\\from)+,\\tmp\n"
211 " move.l \\tmp,(\\to)+\n"
212 " .set .Lcnt,.Lcnt-4\n"
213 " .elseif .Lcnt & 2\n"
214 "1: moves.w (\\from)+,\\tmp\n"
215 " move.w \\tmp,(\\to)+\n"
216 " .set .Lcnt,.Lcnt-2\n"
217 " .elseif .Lcnt & 1\n"
218 "1: moves.b (\\from)+,\\tmp\n"
219 " move.b \\tmp,(\\to)+\n"
220 " .set .Lcnt,.Lcnt-1\n"
221 " .else\n"
222 " .exitm\n"
223 " .endif\n"
224 "\n"
225 " .section __ex_table,\"a\"\n"
226 " .align 4\n"
227 " .long 1b,3f\n"
228 " .previous\n"
229 " .endm\n"
230 " .endif\n"
231 "\n"
232 " .set .Lcnt,%c4\n"
233 " copy_from_user %1,%2,%3\n"
234 " copy_from_user %1,%2,%3\n"
235 " copy_from_user %1,%2,%3\n"
236 "2:\n"
237 " .section .fixup,\"ax\"\n"
238 " .even\n"
239 "3: moveq.l %4,%0\n"
240 " move.l %5,%1\n"
241 " .rept %c4 / 4\n"
242 " clr.l (%1)+\n"
243 " .endr\n"
244 " .if %c4 & 2\n"
245 " clr.w (%1)+\n"
246 " .endif\n"
247 " .if %c4 & 1\n"
248 " clr.b (%1)+\n"
249 " .endif\n"
250 " jra 2b\n"
251 " .previous\n"
252 : "+r" (res), "+a" (to), "+a" (from), "=&d" (tmp)
253 : "i" (n), "g" (to)
254 : "memory");
256 return res;
259 static __always_inline unsigned long
260 __constant_copy_to_user(void __user *to, const void *from, unsigned long n)
262 unsigned long res = 0, tmp;
264 /* limit the inlined version to 3 moves */
265 if (n == 11 || n > 12)
266 return __generic_copy_to_user(to, from, n);
268 switch (n) {
269 case 1:
270 __put_user_asm(res, *(u8 *)from, (u8 *)to, b, d, 1);
271 return res;
272 case 2:
273 __put_user_asm(res, *(u16 *)from, (u16 *)to, w, d, 2);
274 return res;
275 case 4:
276 __put_user_asm(res, *(u32 *)from, (u32 *)to, l, r, 4);
277 return res;
280 asm volatile ("\n"
281 " .ifndef .Lto_user\n"
282 " .set .Lto_user,1\n"
283 " .macro copy_to_user to,from,tmp\n"
284 " .if .Lcnt >= 4\n"
285 " move.l (\\from)+,\\tmp\n"
286 "11: moves.l \\tmp,(\\to)+\n"
287 "12: .set .Lcnt,.Lcnt-4\n"
288 " .elseif .Lcnt & 2\n"
289 " move.w (\\from)+,\\tmp\n"
290 "11: moves.w \\tmp,(\\to)+\n"
291 "12: .set .Lcnt,.Lcnt-2\n"
292 " .elseif .Lcnt & 1\n"
293 " move.b (\\from)+,\\tmp\n"
294 "11: moves.b \\tmp,(\\to)+\n"
295 "12: .set .Lcnt,.Lcnt-1\n"
296 " .else\n"
297 " .exitm\n"
298 " .endif\n"
299 "\n"
300 " .section __ex_table,\"a\"\n"
301 " .align 4\n"
302 " .long 11b,3f\n"
303 " .long 12b,3f\n"
304 " .previous\n"
305 " .endm\n"
306 " .endif\n"
307 "\n"
308 " .set .Lcnt,%c4\n"
309 " copy_to_user %1,%2,%3\n"
310 " copy_to_user %1,%2,%3\n"
311 " copy_to_user %1,%2,%3\n"
312 "2:\n"
313 " .section .fixup,\"ax\"\n"
314 " .even\n"
315 "3: moveq.l %4,%0\n"
316 " jra 2b\n"
317 " .previous\n"
318 : "+r" (res), "+a" (to), "+a" (from), "=&d" (tmp)
319 : "i" (n)
320 : "memory");
322 return res;
325 #define __copy_from_user(to, from, n) \
326 (__builtin_constant_p(n) ? \
327 __constant_copy_from_user(to, from, n) : \
328 __generic_copy_from_user(to, from, n))
330 #define __copy_to_user(to, from, n) \
331 (__builtin_constant_p(n) ? \
332 __constant_copy_to_user(to, from, n) : \
333 __generic_copy_to_user(to, from, n))
335 #define __copy_to_user_inatomic __copy_to_user
336 #define __copy_from_user_inatomic __copy_from_user
338 #define copy_from_user(to, from, n) __copy_from_user(to, from, n)
339 #define copy_to_user(to, from, n) __copy_to_user(to, from, n)
341 long strncpy_from_user(char *dst, const char __user *src, long count);
342 long strnlen_user(const char __user *src, long n);
343 unsigned long clear_user(void __user *to, unsigned long n);
345 #define strlen_user(str) strnlen_user(str, 32767)
347 #endif /* _M68K_UACCESS_H */