1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef __ASM_SH_UACCESS_32_H
14#define __ASM_SH_UACCESS_32_H
15
16#include <linux/errno.h>
17#include <linux/sched.h>
18
19#define VERIFY_READ 0
20#define VERIFY_WRITE 1
21
22
23
24
25
26
27
28
29
30#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
31
32#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL)
33#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
34
35#define segment_eq(a,b) ((a).seg == (b).seg)
36
37#define get_ds() (KERNEL_DS)
38
39#if !defined(CONFIG_MMU)
40
41#define __addr_ok(addr) (1)
42
43static inline mm_segment_t get_fs(void)
44{
45 return USER_DS;
46}
47
48static inline void set_fs(mm_segment_t s)
49{
50}
51
52
53
54
55
56
57
58
59
60
61
62static inline int __access_ok(unsigned long addr, unsigned long size)
63{
64 return ((addr >= memory_start) && ((addr + size) < memory_end));
65}
66#else
67#define __addr_ok(addr) \
68 ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
69
70#define get_fs() (current_thread_info()->addr_limit)
71#define set_fs(x) (current_thread_info()->addr_limit = (x))
72
73
74
75
76
77
78
79
80
81static inline int __access_ok(unsigned long addr, unsigned long size)
82{
83 unsigned long flag, sum;
84
85 __asm__("clrt\n\t"
86 "addc %3, %1\n\t"
87 "movt %0\n\t"
88 "cmp/hi %4, %1\n\t"
89 "rotcl %0"
90 :"=&r" (flag), "=r" (sum)
91 :"1" (addr), "r" (size),
92 "r" (current_thread_info()->addr_limit.seg)
93 :"t");
94 return flag == 0;
95}
96#endif
97
98#define access_ok(type, addr, size) \
99 (__chk_user_ptr(addr), \
100 __access_ok((unsigned long __force)(addr), (size)))
101
102
103
104
105
106
107
108
109
110
111
112
113
114#define put_user(x,ptr) __put_user_check((x), (ptr), sizeof(*(ptr)))
115#define get_user(x,ptr) __get_user_check((x), (ptr), sizeof(*(ptr)))
116
117
118
119
120
121
122#define __put_user(x,ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
123#define __get_user(x,ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
124
125struct __large_struct { unsigned long buf[100]; };
126#define __m(x) (*(struct __large_struct __user *)(x))
127
128#define __get_user_size(x,ptr,size,retval) \
129do { \
130 retval = 0; \
131 switch (size) { \
132 case 1: \
133 __get_user_asm(x, ptr, retval, "b"); \
134 break; \
135 case 2: \
136 __get_user_asm(x, ptr, retval, "w"); \
137 break; \
138 case 4: \
139 __get_user_asm(x, ptr, retval, "l"); \
140 break; \
141 default: \
142 __get_user_unknown(); \
143 break; \
144 } \
145} while (0)
146
147#define __get_user_nocheck(x,ptr,size) \
148({ \
149 long __gu_err; \
150 unsigned long __gu_val; \
151 const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
152 __chk_user_ptr(ptr); \
153 __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
154 (x) = (__typeof__(*(ptr)))__gu_val; \
155 __gu_err; \
156})
157
158#define __get_user_check(x,ptr,size) \
159({ \
160 long __gu_err = -EFAULT; \
161 unsigned long __gu_val = 0; \
162 const __typeof__(*(ptr)) *__gu_addr = (ptr); \
163 if (likely(access_ok(VERIFY_READ, __gu_addr, (size)))) \
164 __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
165 (x) = (__typeof__(*(ptr)))__gu_val; \
166 __gu_err; \
167})
168
169#define __get_user_asm(x, addr, err, insn) \
170({ \
171__asm__ __volatile__( \
172 "1:\n\t" \
173 "mov." insn " %2, %1\n\t" \
174 "2:\n" \
175 ".section .fixup,\"ax\"\n" \
176 "3:\n\t" \
177 "mov #0, %1\n\t" \
178 "mov.l 4f, %0\n\t" \
179 "jmp @%0\n\t" \
180 " mov %3, %0\n\t" \
181 ".balign 4\n" \
182 "4: .long 2b\n\t" \
183 ".previous\n" \
184 ".section __ex_table,\"a\"\n\t" \
185 ".long 1b, 3b\n\t" \
186 ".previous" \
187 :"=&r" (err), "=&r" (x) \
188 :"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
189
190extern void __get_user_unknown(void);
191
192#define __put_user_size(x,ptr,size,retval) \
193do { \
194 retval = 0; \
195 switch (size) { \
196 case 1: \
197 __put_user_asm(x, ptr, retval, "b"); \
198 break; \
199 case 2: \
200 __put_user_asm(x, ptr, retval, "w"); \
201 break; \
202 case 4: \
203 __put_user_asm(x, ptr, retval, "l"); \
204 break; \
205 case 8: \
206 __put_user_u64(x, ptr, retval); \
207 break; \
208 default: \
209 __put_user_unknown(); \
210 } \
211} while (0)
212
213#define __put_user_nocheck(x,ptr,size) \
214({ \
215 long __pu_err; \
216 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
217 __chk_user_ptr(ptr); \
218 __put_user_size((x), __pu_addr, (size), __pu_err); \
219 __pu_err; \
220})
221
222#define __put_user_check(x,ptr,size) \
223({ \
224 long __pu_err = -EFAULT; \
225 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
226 if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) \
227 __put_user_size((x), __pu_addr, (size), \
228 __pu_err); \
229 __pu_err; \
230})
231
232#define __put_user_asm(x, addr, err, insn) \
233({ \
234__asm__ __volatile__( \
235 "1:\n\t" \
236 "mov." insn " %1, %2\n\t" \
237 "2:\n" \
238 ".section .fixup,\"ax\"\n" \
239 "3:\n\t" \
240 "mov.l 4f, %0\n\t" \
241 "jmp @%0\n\t" \
242 " mov %3, %0\n\t" \
243 ".balign 4\n" \
244 "4: .long 2b\n\t" \
245 ".previous\n" \
246 ".section __ex_table,\"a\"\n\t" \
247 ".long 1b, 3b\n\t" \
248 ".previous" \
249 :"=&r" (err) \
250 :"r" (x), "m" (__m(addr)), "i" (-EFAULT), "0" (err) \
251 :"memory"); })
252
253#if defined(CONFIG_CPU_LITTLE_ENDIAN)
254#define __put_user_u64(val,addr,retval) \
255({ \
256__asm__ __volatile__( \
257 "1:\n\t" \
258 "mov.l %R1,%2\n\t" \
259 "mov.l %S1,%T2\n\t" \
260 "2:\n" \
261 ".section .fixup,\"ax\"\n" \
262 "3:\n\t" \
263 "mov.l 4f,%0\n\t" \
264 "jmp @%0\n\t" \
265 " mov %3,%0\n\t" \
266 ".balign 4\n" \
267 "4: .long 2b\n\t" \
268 ".previous\n" \
269 ".section __ex_table,\"a\"\n\t" \
270 ".long 1b, 3b\n\t" \
271 ".previous" \
272 : "=r" (retval) \
273 : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
274 : "memory"); })
275#else
276#define __put_user_u64(val,addr,retval) \
277({ \
278__asm__ __volatile__( \
279 "1:\n\t" \
280 "mov.l %S1,%2\n\t" \
281 "mov.l %R1,%T2\n\t" \
282 "2:\n" \
283 ".section .fixup,\"ax\"\n" \
284 "3:\n\t" \
285 "mov.l 4f,%0\n\t" \
286 "jmp @%0\n\t" \
287 " mov %3,%0\n\t" \
288 ".balign 4\n" \
289 "4: .long 2b\n\t" \
290 ".previous\n" \
291 ".section __ex_table,\"a\"\n\t" \
292 ".long 1b, 3b\n\t" \
293 ".previous" \
294 : "=r" (retval) \
295 : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
296 : "memory"); })
297#endif
298
299extern void __put_user_unknown(void);
300
301
302
303__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
304
305
306static __always_inline unsigned long
307__copy_from_user(void *to, const void __user *from, unsigned long n)
308{
309 return __copy_user(to, (__force void *)from, n);
310}
311
312static __always_inline unsigned long __must_check
313__copy_to_user(void __user *to, const void *from, unsigned long n)
314{
315 return __copy_user((__force void *)to, from, n);
316}
317
318#define __copy_to_user_inatomic __copy_to_user
319#define __copy_from_user_inatomic __copy_from_user
320
321
322
323
324
325extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
326
327#define clear_user(addr,n) ({ \
328void * __cl_addr = (addr); \
329unsigned long __cl_size = (n); \
330if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \
331__cl_size = __clear_user(__cl_addr, __cl_size); \
332__cl_size; })
333
334static __inline__ int
335__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count)
336{
337 __kernel_size_t res;
338 unsigned long __dummy, _d, _s, _c;
339
340 __asm__ __volatile__(
341 "9:\n"
342 "mov.b @%2+, %1\n\t"
343 "cmp/eq #0, %1\n\t"
344 "bt/s 2f\n"
345 "1:\n"
346 "mov.b %1, @%3\n\t"
347 "dt %4\n\t"
348 "bf/s 9b\n\t"
349 " add #1, %3\n\t"
350 "2:\n\t"
351 "sub %4, %0\n"
352 "3:\n"
353 ".section .fixup,\"ax\"\n"
354 "4:\n\t"
355 "mov.l 5f, %1\n\t"
356 "jmp @%1\n\t"
357 " mov %9, %0\n\t"
358 ".balign 4\n"
359 "5: .long 3b\n"
360 ".previous\n"
361 ".section __ex_table,\"a\"\n"
362 " .balign 4\n"
363 " .long 9b,4b\n"
364 ".previous"
365 : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c)
366 : "0" (__count), "2" (__src), "3" (__dest), "4" (__count),
367 "i" (-EFAULT)
368 : "memory", "t");
369
370 return res;
371}
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391#define strncpy_from_user(dest,src,count) ({ \
392unsigned long __sfu_src = (unsigned long) (src); \
393int __sfu_count = (int) (count); \
394long __sfu_res = -EFAULT; \
395if(__access_ok(__sfu_src, __sfu_count)) { \
396__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
397} __sfu_res; })
398
399
400
401
402
403static __inline__ long __strnlen_user(const char __user *__s, long __n)
404{
405 unsigned long res;
406 unsigned long __dummy;
407
408 __asm__ __volatile__(
409 "1:\t"
410 "mov.b @(%0,%3), %1\n\t"
411 "cmp/eq %4, %0\n\t"
412 "bt/s 2f\n\t"
413 " add #1, %0\n\t"
414 "tst %1, %1\n\t"
415 "bf 1b\n\t"
416 "2:\n"
417 ".section .fixup,\"ax\"\n"
418 "3:\n\t"
419 "mov.l 4f, %1\n\t"
420 "jmp @%1\n\t"
421 " mov #0, %0\n"
422 ".balign 4\n"
423 "4: .long 2b\n"
424 ".previous\n"
425 ".section __ex_table,\"a\"\n"
426 " .balign 4\n"
427 " .long 1b,3b\n"
428 ".previous"
429 : "=z" (res), "=&r" (__dummy)
430 : "0" (0), "r" (__s), "r" (__n)
431 : "t");
432 return res;
433}
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448static __inline__ long strnlen_user(const char __user *s, long n)
449{
450 if (!__addr_ok(s))
451 return 0;
452 else
453 return __strnlen_user(s, n);
454}
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485struct exception_table_entry
486{
487 unsigned long insn, fixup;
488};
489
490extern int fixup_exception(struct pt_regs *regs);
491
492#endif
493