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