Linux 2.6.31.6
[linux/fpc-iii.git] / arch / mn10300 / include / asm / uaccess.h
blob8a3a4dd55763eba744552c46c825831569e90610
1 /* MN10300 userspace access functions
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
11 #ifndef _ASM_UACCESS_H
12 #define _ASM_UACCESS_H
15 * User space memory access functions
17 #include <linux/sched.h>
18 #include <asm/page.h>
19 #include <asm/pgtable.h>
20 #include <asm/errno.h>
22 #define VERIFY_READ 0
23 #define VERIFY_WRITE 1
26 * The fs value determines whether argument validity checking should be
27 * performed or not. If get_fs() == USER_DS, checking is performed, with
28 * get_fs() == KERNEL_DS, checking is bypassed.
30 * For historical reasons, these macros are grossly misnamed.
33 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
35 #define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF)
36 #define KERNEL_DS MAKE_MM_SEG(0x9FFFFFFF)
37 #define USER_DS MAKE_MM_SEG(TASK_SIZE)
39 #define get_ds() (KERNEL_DS)
40 #define get_fs() (current_thread_info()->addr_limit)
41 #define set_fs(x) (current_thread_info()->addr_limit = (x))
42 #define __kernel_ds_p() (current_thread_info()->addr_limit.seg == 0x9FFFFFFF)
44 #define segment_eq(a, b) ((a).seg == (b).seg)
46 #define __addr_ok(addr) \
47 ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
50 * check that a range of addresses falls within the current address limit
52 static inline int ___range_ok(unsigned long addr, unsigned int size)
54 int flag = 1, tmp;
56 asm(" add %3,%1 \n" /* set C-flag if addr + size > 4Gb */
57 " bcs 0f \n"
58 " cmp %4,%1 \n" /* jump if addr+size>limit (error) */
59 " bhi 0f \n"
60 " clr %0 \n" /* mark okay */
61 "0: \n"
62 : "=r"(flag), "=&r"(tmp)
63 : "1"(addr), "ir"(size),
64 "r"(current_thread_info()->addr_limit.seg), "0"(flag)
65 : "cc"
68 return flag;
71 #define __range_ok(addr, size) ___range_ok((unsigned long)(addr), (u32)(size))
73 #define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0)
74 #define __access_ok(addr, size) (__range_ok((addr), (size)) == 0)
76 static inline int verify_area(int type, const void *addr, unsigned long size)
78 return access_ok(type, addr, size) ? 0 : -EFAULT;
83 * The exception table consists of pairs of addresses: the first is the
84 * address of an instruction that is allowed to fault, and the second is
85 * the address at which the program should continue. No registers are
86 * modified, so it is entirely up to the continuation code to figure out
87 * what to do.
89 * All the routines below use bits of fixup code that are out of line
90 * with the main instruction path. This means when everything is well,
91 * we don't even have to jump over them. Further, they do not intrude
92 * on our cache or tlb entries.
95 struct exception_table_entry
97 unsigned long insn, fixup;
100 /* Returns 0 if exception not found and fixup otherwise. */
101 extern int fixup_exception(struct pt_regs *regs);
103 #define put_user(x, ptr) __put_user_check((x), (ptr), sizeof(*(ptr)))
104 #define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)))
107 * The "__xxx" versions do not do address space checking, useful when
108 * doing multiple accesses to the same area (the user has to do the
109 * checks by hand with "access_ok()")
111 #define __put_user(x, ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
112 #define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
115 * The "xxx_ret" versions return constant specified in third argument, if
116 * something bad happens. These macros can be optimized for the
117 * case of just returning from the function xxx_ret is used.
120 #define put_user_ret(x, ptr, ret) \
121 ({ if (put_user((x), (ptr))) return (ret); })
122 #define get_user_ret(x, ptr, ret) \
123 ({ if (get_user((x), (ptr))) return (ret); })
124 #define __put_user_ret(x, ptr, ret) \
125 ({ if (__put_user((x), (ptr))) return (ret); })
126 #define __get_user_ret(x, ptr, ret) \
127 ({ if (__get_user((x), (ptr))) return (ret); })
129 struct __large_struct { unsigned long buf[100]; };
130 #define __m(x) (*(struct __large_struct *)(x))
132 #define __get_user_nocheck(x, ptr, size) \
133 ({ \
134 __typeof(*(ptr)) __gu_val; \
135 unsigned long __gu_addr; \
136 int __gu_err; \
137 __gu_addr = (unsigned long) (ptr); \
138 switch (size) { \
139 case 1: __get_user_asm("bu"); break; \
140 case 2: __get_user_asm("hu"); break; \
141 case 4: __get_user_asm("" ); break; \
142 default: __get_user_unknown(); break; \
144 x = (__typeof__(*(ptr))) __gu_val; \
145 __gu_err; \
148 #define __get_user_check(x, ptr, size) \
149 ({ \
150 __typeof__(*(ptr)) __gu_val; \
151 unsigned long __gu_addr; \
152 int __gu_err; \
153 __gu_addr = (unsigned long) (ptr); \
154 if (likely(__access_ok(__gu_addr,size))) { \
155 switch (size) { \
156 case 1: __get_user_asm("bu"); break; \
157 case 2: __get_user_asm("hu"); break; \
158 case 4: __get_user_asm("" ); break; \
159 default: __get_user_unknown(); break; \
162 else { \
163 __gu_err = -EFAULT; \
164 __gu_val = 0; \
166 x = (__typeof__(*(ptr))) __gu_val; \
167 __gu_err; \
170 #define __get_user_asm(INSN) \
171 ({ \
172 asm volatile( \
173 "1:\n" \
174 " mov"INSN" %2,%1\n" \
175 " mov 0,%0\n" \
176 "2:\n" \
177 " .section .fixup,\"ax\"\n" \
178 "3:\n\t" \
179 " mov %3,%0\n" \
180 " jmp 2b\n" \
181 " .previous\n" \
182 " .section __ex_table,\"a\"\n" \
183 " .balign 4\n" \
184 " .long 1b, 3b\n" \
185 " .previous" \
186 : "=&r" (__gu_err), "=&r" (__gu_val) \
187 : "m" (__m(__gu_addr)), "i" (-EFAULT)); \
190 extern int __get_user_unknown(void);
192 #define __put_user_nocheck(x, ptr, size) \
193 ({ \
194 union { \
195 __typeof__(*(ptr)) val; \
196 u32 bits[2]; \
197 } __pu_val; \
198 unsigned long __pu_addr; \
199 int __pu_err; \
200 __pu_val.val = (x); \
201 __pu_addr = (unsigned long) (ptr); \
202 switch (size) { \
203 case 1: __put_user_asm("bu"); break; \
204 case 2: __put_user_asm("hu"); break; \
205 case 4: __put_user_asm("" ); break; \
206 case 8: __put_user_asm8(); break; \
207 default: __pu_err = __put_user_unknown(); break; \
209 __pu_err; \
212 #define __put_user_check(x, ptr, size) \
213 ({ \
214 union { \
215 __typeof__(*(ptr)) val; \
216 u32 bits[2]; \
217 } __pu_val; \
218 unsigned long __pu_addr; \
219 int __pu_err; \
220 __pu_val.val = (x); \
221 __pu_addr = (unsigned long) (ptr); \
222 if (likely(__access_ok(__pu_addr, size))) { \
223 switch (size) { \
224 case 1: __put_user_asm("bu"); break; \
225 case 2: __put_user_asm("hu"); break; \
226 case 4: __put_user_asm("" ); break; \
227 case 8: __put_user_asm8(); break; \
228 default: __pu_err = __put_user_unknown(); break; \
231 else { \
232 __pu_err = -EFAULT; \
234 __pu_err; \
237 #define __put_user_asm(INSN) \
238 ({ \
239 asm volatile( \
240 "1:\n" \
241 " mov"INSN" %1,%2\n" \
242 " mov 0,%0\n" \
243 "2:\n" \
244 " .section .fixup,\"ax\"\n" \
245 "3:\n" \
246 " mov %3,%0\n" \
247 " jmp 2b\n" \
248 " .previous\n" \
249 " .section __ex_table,\"a\"\n" \
250 " .balign 4\n" \
251 " .long 1b, 3b\n" \
252 " .previous" \
253 : "=&r" (__pu_err) \
254 : "r" (__pu_val.val), "m" (__m(__pu_addr)), \
255 "i" (-EFAULT) \
256 ); \
259 #define __put_user_asm8() \
260 ({ \
261 asm volatile( \
262 "1: mov %1,%3 \n" \
263 "2: mov %2,%4 \n" \
264 " mov 0,%0 \n" \
265 "3: \n" \
266 " .section .fixup,\"ax\" \n" \
267 "4: \n" \
268 " mov %5,%0 \n" \
269 " jmp 3b \n" \
270 " .previous \n" \
271 " .section __ex_table,\"a\"\n" \
272 " .balign 4 \n" \
273 " .long 1b, 4b \n" \
274 " .long 2b, 4b \n" \
275 " .previous \n" \
276 : "=&r" (__pu_err) \
277 : "r" (__pu_val.bits[0]), "r" (__pu_val.bits[1]), \
278 "m" (__m(__pu_addr)), "m" (__m(__pu_addr+4)), \
279 "i" (-EFAULT) \
280 ); \
283 extern int __put_user_unknown(void);
287 * Copy To/From Userspace
289 /* Generic arbitrary sized copy. */
290 #define __copy_user(to, from, size) \
291 do { \
292 if (size) { \
293 void *__to = to; \
294 const void *__from = from; \
295 int w; \
296 asm volatile( \
297 "0: movbu (%0),%3;\n" \
298 "1: movbu %3,(%1);\n" \
299 " inc %0;\n" \
300 " inc %1;\n" \
301 " add -1,%2;\n" \
302 " bne 0b;\n" \
303 "2:\n" \
304 " .section .fixup,\"ax\"\n" \
305 "3: jmp 2b\n" \
306 " .previous\n" \
307 " .section __ex_table,\"a\"\n" \
308 " .balign 4\n" \
309 " .long 0b,3b\n" \
310 " .long 1b,3b\n" \
311 " .previous\n" \
312 : "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\
313 : "0"(__from), "1"(__to), "2"(size) \
314 : "memory"); \
316 } while (0)
318 #define __copy_user_zeroing(to, from, size) \
319 do { \
320 if (size) { \
321 void *__to = to; \
322 const void *__from = from; \
323 int w; \
324 asm volatile( \
325 "0: movbu (%0),%3;\n" \
326 "1: movbu %3,(%1);\n" \
327 " inc %0;\n" \
328 " inc %1;\n" \
329 " add -1,%2;\n" \
330 " bne 0b;\n" \
331 "2:\n" \
332 " .section .fixup,\"ax\"\n" \
333 "3:\n" \
334 " mov %2,%0\n" \
335 " clr %3\n" \
336 "4: movbu %3,(%1);\n" \
337 " inc %1;\n" \
338 " add -1,%2;\n" \
339 " bne 4b;\n" \
340 " mov %0,%2\n" \
341 " jmp 2b\n" \
342 " .previous\n" \
343 " .section __ex_table,\"a\"\n" \
344 " .balign 4\n" \
345 " .long 0b,3b\n" \
346 " .long 1b,3b\n" \
347 " .previous\n" \
348 : "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\
349 : "0"(__from), "1"(__to), "2"(size) \
350 : "memory"); \
352 } while (0)
354 /* We let the __ versions of copy_from/to_user inline, because they're often
355 * used in fast paths and have only a small space overhead.
357 static inline
358 unsigned long __generic_copy_from_user_nocheck(void *to, const void *from,
359 unsigned long n)
361 __copy_user_zeroing(to, from, n);
362 return n;
365 static inline
366 unsigned long __generic_copy_to_user_nocheck(void *to, const void *from,
367 unsigned long n)
369 __copy_user(to, from, n);
370 return n;
374 #if 0
375 #error don't use - these macros don't increment to & from pointers
376 /* Optimize just a little bit when we know the size of the move. */
377 #define __constant_copy_user(to, from, size) \
378 do { \
379 asm volatile( \
380 " mov %0,a0;\n" \
381 "0: movbu (%1),d3;\n" \
382 "1: movbu d3,(%2);\n" \
383 " add -1,a0;\n" \
384 " bne 0b;\n" \
385 "2:;" \
386 ".section .fixup,\"ax\"\n" \
387 "3: jmp 2b\n" \
388 ".previous\n" \
389 ".section __ex_table,\"a\"\n" \
390 " .balign 4\n" \
391 " .long 0b,3b\n" \
392 " .long 1b,3b\n" \
393 ".previous" \
395 : "d"(size), "d"(to), "d"(from) \
396 : "d3", "a0"); \
397 } while (0)
399 /* Optimize just a little bit when we know the size of the move. */
400 #define __constant_copy_user_zeroing(to, from, size) \
401 do { \
402 asm volatile( \
403 " mov %0,a0;\n" \
404 "0: movbu (%1),d3;\n" \
405 "1: movbu d3,(%2);\n" \
406 " add -1,a0;\n" \
407 " bne 0b;\n" \
408 "2:;" \
409 ".section .fixup,\"ax\"\n" \
410 "3: jmp 2b\n" \
411 ".previous\n" \
412 ".section __ex_table,\"a\"\n" \
413 " .balign 4\n" \
414 " .long 0b,3b\n" \
415 " .long 1b,3b\n" \
416 ".previous" \
418 : "d"(size), "d"(to), "d"(from) \
419 : "d3", "a0"); \
420 } while (0)
422 static inline
423 unsigned long __constant_copy_to_user(void *to, const void *from,
424 unsigned long n)
426 if (access_ok(VERIFY_WRITE, to, n))
427 __constant_copy_user(to, from, n);
428 return n;
431 static inline
432 unsigned long __constant_copy_from_user(void *to, const void *from,
433 unsigned long n)
435 if (access_ok(VERIFY_READ, from, n))
436 __constant_copy_user_zeroing(to, from, n);
437 return n;
440 static inline
441 unsigned long __constant_copy_to_user_nocheck(void *to, const void *from,
442 unsigned long n)
444 __constant_copy_user(to, from, n);
445 return n;
448 static inline
449 unsigned long __constant_copy_from_user_nocheck(void *to, const void *from,
450 unsigned long n)
452 __constant_copy_user_zeroing(to, from, n);
453 return n;
455 #endif
457 extern unsigned long __generic_copy_to_user(void __user *, const void *,
458 unsigned long);
459 extern unsigned long __generic_copy_from_user(void *, const void __user *,
460 unsigned long);
462 #define __copy_to_user_inatomic(to, from, n) \
463 __generic_copy_to_user_nocheck((to), (from), (n))
464 #define __copy_from_user_inatomic(to, from, n) \
465 __generic_copy_from_user_nocheck((to), (from), (n))
467 #define __copy_to_user(to, from, n) \
468 ({ \
469 might_sleep(); \
470 __copy_to_user_inatomic((to), (from), (n)); \
473 #define __copy_from_user(to, from, n) \
474 ({ \
475 might_sleep(); \
476 __copy_from_user_inatomic((to), (from), (n)); \
480 #define copy_to_user(to, from, n) __generic_copy_to_user((to), (from), (n))
481 #define copy_from_user(to, from, n) __generic_copy_from_user((to), (from), (n))
483 extern long strncpy_from_user(char *dst, const char __user *src, long count);
484 extern long __strncpy_from_user(char *dst, const char __user *src, long count);
485 extern long strnlen_user(const char __user *str, long n);
486 #define strlen_user(str) strnlen_user(str, ~0UL >> 1)
487 extern unsigned long clear_user(void __user *mem, unsigned long len);
488 extern unsigned long __clear_user(void __user *mem, unsigned long len);
490 #endif /* _ASM_UACCESS_H */