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