sh: Various nommu fixes.
[safe/jmp/linux-2.6] / include / asm-sh / uaccess.h
1 /* $Id: uaccess.h,v 1.11 2003/10/13 07:21:20 lethal Exp $
2  *
3  * User space memory access functions
4  *
5  * Copyright (C) 1999, 2002  Niibe Yutaka
6  * Copyright (C) 2003  Paul Mundt
7  *
8  *  Based on:
9  *     MIPS implementation version 1.15 by
10  *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
11  *     and i386 version.
12  */
13 #ifndef __ASM_SH_UACCESS_H
14 #define __ASM_SH_UACCESS_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  * The fs value determines whether argument validity checking should be
24  * performed or not.  If get_fs() == USER_DS, checking is performed, with
25  * get_fs() == KERNEL_DS, checking is bypassed.
26  *
27  * For historical reasons (Data Segment Register?), these macros are misnamed.
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 __addr_ok(addr) \
38         ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
39
40 #define get_ds()        (KERNEL_DS)
41
42 #if !defined(CONFIG_MMU)
43 static inline mm_segment_t get_fs(void)
44 {
45         return USER_DS;
46 }
47
48 static inline void set_fs(mm_segment_t s)
49 {
50 }
51
52 /*
53  * __access_ok: Check if address with size is OK or not.
54  *
55  * If we don't have an MMU (or if its disabled) the only thing we really have
56  * to look out for is if the address resides somewhere outside of what
57  * available RAM we have.
58  *
59  * TODO: This check could probably also stand to be restricted somewhat more..
60  * though it still does the Right Thing(tm) for the time being.
61  */
62 static inline int __access_ok(unsigned long addr, unsigned long size)
63 {
64         extern unsigned long memory_start, memory_end;
65
66         return ((addr >= memory_start) && ((addr + size) < memory_end));
67 }
68 #else /* CONFIG_MMU */
69 #define get_fs()        (current_thread_info()->addr_limit)
70 #define set_fs(x)       (current_thread_info()->addr_limit = (x))
71
72 /*
73  * __access_ok: Check if address with size is OK or not.
74  *
75  * We do three checks:
76  * (1) is it user space? 
77  * (2) addr + size --> carry?
78  * (3) addr + size >= 0x80000000  (PAGE_OFFSET)
79  *
80  * (1) (2) (3) | RESULT
81  *  0   0   0  |  ok
82  *  0   0   1  |  ok
83  *  0   1   0  |  bad
84  *  0   1   1  |  bad
85  *  1   0   0  |  ok
86  *  1   0   1  |  bad
87  *  1   1   0  |  bad
88  *  1   1   1  |  bad
89  */
90 static inline int __access_ok(unsigned long addr, unsigned long size)
91 {
92         unsigned long flag, tmp;
93
94         __asm__("stc    r7_bank, %0\n\t"
95                 "mov.l  @(8,%0), %0\n\t"
96                 "clrt\n\t"
97                 "addc   %2, %1\n\t"
98                 "and    %1, %0\n\t"
99                 "rotcl  %0\n\t"
100                 "rotcl  %0\n\t"
101                 "and    #3, %0"
102                 : "=&z" (flag), "=r" (tmp)
103                 : "r" (addr), "1" (size)
104                 : "t");
105
106         return flag == 0;
107 }
108 #endif /* CONFIG_MMU */
109
110 static inline int access_ok(int type, const void __user *p, unsigned long size)
111 {
112         unsigned long addr = (unsigned long)p;
113         return __access_ok(addr, size);
114 }
115
116 /*
117  * Uh, these should become the main single-value transfer routines ...
118  * They automatically use the right size if we just have the right
119  * pointer type ...
120  *
121  * As SuperH uses the same address space for kernel and user data, we
122  * can just do these as direct assignments.
123  *
124  * Careful to not
125  * (a) re-use the arguments for side effects (sizeof is ok)
126  * (b) require any knowledge of processes at this stage
127  */
128 #define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr)))
129 #define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
130
131 /*
132  * The "__xxx" versions do not do address space checking, useful when
133  * doing multiple accesses to the same area (the user has to do the
134  * checks by hand with "access_ok()")
135  */
136 #define __put_user(x,ptr) \
137   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
138 #define __get_user(x,ptr) \
139   __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
140
141 struct __large_struct { unsigned long buf[100]; };
142 #define __m(x) (*(struct __large_struct *)(x))
143
144 #define __get_user_size(x,ptr,size,retval)                      \
145 do {                                                            \
146         retval = 0;                                             \
147         switch (size) {                                         \
148         case 1:                                                 \
149                 __get_user_asm(x, ptr, retval, "b");            \
150                 break;                                          \
151         case 2:                                                 \
152                 __get_user_asm(x, ptr, retval, "w");            \
153                 break;                                          \
154         case 4:                                                 \
155                 __get_user_asm(x, ptr, retval, "l");            \
156                 break;                                          \
157         default:                                                \
158                 __get_user_unknown();                           \
159                 break;                                          \
160         }                                                       \
161 } while (0)
162
163 #define __get_user_nocheck(x,ptr,size)                          \
164 ({                                                              \
165         long __gu_err, __gu_val;                                \
166         __get_user_size(__gu_val, (ptr), (size), __gu_err);     \
167         (x) = (__typeof__(*(ptr)))__gu_val;                     \
168         __gu_err;                                               \
169 })
170
171 #ifdef CONFIG_MMU
172 #define __get_user_check(x,ptr,size)                            \
173 ({                                                              \
174         long __gu_err, __gu_val;                                \
175         switch (size) {                                         \
176         case 1:                                                 \
177                 __get_user_1(__gu_val, (ptr), __gu_err);        \
178                 break;                                          \
179         case 2:                                                 \
180                 __get_user_2(__gu_val, (ptr), __gu_err);        \
181                 break;                                          \
182         case 4:                                                 \
183                 __get_user_4(__gu_val, (ptr), __gu_err);        \
184                 break;                                          \
185         default:                                                \
186                 __get_user_unknown();                           \
187                 break;                                          \
188         }                                                       \
189                                                                 \
190         (x) = (__typeof__(*(ptr)))__gu_val;                     \
191         __gu_err;                                               \
192 })
193
194 #define __get_user_1(x,addr,err) ({             \
195 __asm__("stc    r7_bank, %1\n\t"                \
196         "mov.l  @(8,%1), %1\n\t"                \
197         "and    %2, %1\n\t"                     \
198         "cmp/pz %1\n\t"                         \
199         "bt/s   1f\n\t"                         \
200         " mov   #0, %0\n\t"                     \
201         "0:\n"                                  \
202         "mov    #-14, %0\n\t"                   \
203         "bra    2f\n\t"                         \
204         " mov   #0, %1\n"                       \
205         "1:\n\t"                                \
206         "mov.b  @%2, %1\n\t"                    \
207         "extu.b %1, %1\n"                       \
208         "2:\n"                                  \
209         ".section       __ex_table,\"a\"\n\t"   \
210         ".long  1b, 0b\n\t"                     \
211         ".previous"                             \
212         : "=&r" (err), "=&r" (x)                \
213         : "r" (addr)                            \
214         : "t");                                 \
215 })
216
217 #define __get_user_2(x,addr,err) ({             \
218 __asm__("stc    r7_bank, %1\n\t"                \
219         "mov.l  @(8,%1), %1\n\t"                \
220         "and    %2, %1\n\t"                     \
221         "cmp/pz %1\n\t"                         \
222         "bt/s   1f\n\t"                         \
223         " mov   #0, %0\n\t"                     \
224         "0:\n"                                  \
225         "mov    #-14, %0\n\t"                   \
226         "bra    2f\n\t"                         \
227         " mov   #0, %1\n"                       \
228         "1:\n\t"                                \
229         "mov.w  @%2, %1\n\t"                    \
230         "extu.w %1, %1\n"                       \
231         "2:\n"                                  \
232         ".section       __ex_table,\"a\"\n\t"   \
233         ".long  1b, 0b\n\t"                     \
234         ".previous"                             \
235         : "=&r" (err), "=&r" (x)                \
236         : "r" (addr)                            \
237         : "t");                                 \
238 })
239
240 #define __get_user_4(x,addr,err) ({             \
241 __asm__("stc    r7_bank, %1\n\t"                \
242         "mov.l  @(8,%1), %1\n\t"                \
243         "and    %2, %1\n\t"                     \
244         "cmp/pz %1\n\t"                         \
245         "bt/s   1f\n\t"                         \
246         " mov   #0, %0\n\t"                     \
247         "0:\n"                                  \
248         "mov    #-14, %0\n\t"                   \
249         "bra    2f\n\t"                         \
250         " mov   #0, %1\n"                       \
251         "1:\n\t"                                \
252         "mov.l  @%2, %1\n\t"                    \
253         "2:\n"                                  \
254         ".section       __ex_table,\"a\"\n\t"   \
255         ".long  1b, 0b\n\t"                     \
256         ".previous"                             \
257         : "=&r" (err), "=&r" (x)                \
258         : "r" (addr)                            \
259         : "t");                                 \
260 })
261 #else /* CONFIG_MMU */
262 #define __get_user_check(x,ptr,size)                                    \
263 ({                                                                      \
264         long __gu_err, __gu_val;                                        \
265         if (__access_ok((unsigned long)(ptr), (size))) {                \
266                 __get_user_size(__gu_val, (ptr), (size), __gu_err);     \
267                 (x) = (__typeof__(*(ptr)))__gu_val;                     \
268         } else                                                          \
269                 __gu_err = -EFAULT;                                     \
270         __gu_err;                                                       \
271 })
272 #endif
273
274 #define __get_user_asm(x, addr, err, insn) \
275 ({ \
276 __asm__ __volatile__( \
277         "1:\n\t" \
278         "mov." insn "   %2, %1\n\t" \
279         "mov    #0, %0\n" \
280         "2:\n" \
281         ".section       .fixup,\"ax\"\n" \
282         "3:\n\t" \
283         "mov    #0, %1\n\t" \
284         "mov.l  4f, %0\n\t" \
285         "jmp    @%0\n\t" \
286         " mov   %3, %0\n" \
287         "4:     .long   2b\n\t" \
288         ".previous\n" \
289         ".section       __ex_table,\"a\"\n\t" \
290         ".long  1b, 3b\n\t" \
291         ".previous" \
292         :"=&r" (err), "=&r" (x) \
293         :"m" (__m(addr)), "i" (-EFAULT)); })
294
295 extern void __get_user_unknown(void);
296
297 #define __put_user_size(x,ptr,size,retval)              \
298 do {                                                    \
299         retval = 0;                                     \
300         switch (size) {                                 \
301         case 1:                                         \
302                 __put_user_asm(x, ptr, retval, "b");    \
303                 break;                                  \
304         case 2:                                         \
305                 __put_user_asm(x, ptr, retval, "w");    \
306                 break;                                  \
307         case 4:                                         \
308                 __put_user_asm(x, ptr, retval, "l");    \
309                 break;                                  \
310         case 8:                                         \
311                 __put_user_u64(x, ptr, retval);         \
312                 break;                                  \
313         default:                                        \
314                 __put_user_unknown();                   \
315         }                                               \
316 } while (0)
317
318 #define __put_user_nocheck(x,ptr,size)                  \
319 ({                                                      \
320         long __pu_err;                                  \
321         __put_user_size((x),(ptr),(size),__pu_err);     \
322         __pu_err;                                       \
323 })
324
325 #define __put_user_check(x,ptr,size)                            \
326 ({                                                              \
327         long __pu_err = -EFAULT;                                \
328         __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
329                                                                 \
330         if (__access_ok((unsigned long)__pu_addr,size))         \
331                 __put_user_size((x),__pu_addr,(size),__pu_err); \
332         __pu_err;                                               \
333 })
334
335 #define __put_user_asm(x, addr, err, insn) \
336 ({ \
337 __asm__ __volatile__( \
338         "1:\n\t" \
339         "mov." insn "   %1, %2\n\t" \
340         "mov    #0, %0\n" \
341         "2:\n" \
342         ".section       .fixup,\"ax\"\n" \
343         "3:\n\t" \
344         "nop\n\t" \
345         "mov.l  4f, %0\n\t" \
346         "jmp    @%0\n\t" \
347         "mov    %3, %0\n" \
348         "4:     .long   2b\n\t" \
349         ".previous\n" \
350         ".section       __ex_table,\"a\"\n\t" \
351         ".long  1b, 3b\n\t" \
352         ".previous" \
353         :"=&r" (err) \
354         :"r" (x), "m" (__m(addr)), "i" (-EFAULT) \
355         :"memory"); })
356
357 #if defined(__LITTLE_ENDIAN__)
358 #define __put_user_u64(val,addr,retval) \
359 ({ \
360 __asm__ __volatile__( \
361         "1:\n\t" \
362         "mov.l  %R1,%2\n\t" \
363         "mov.l  %S1,%T2\n\t" \
364         "mov    #0,%0\n" \
365         "2:\n" \
366         ".section       .fixup,\"ax\"\n" \
367         "3:\n\t" \
368         "nop\n\t" \
369         "mov.l  4f,%0\n\t" \
370         "jmp    @%0\n\t" \
371         " mov   %3,%0\n" \
372         "4:     .long   2b\n\t" \
373         ".previous\n" \
374         ".section       __ex_table,\"a\"\n\t" \
375         ".long  1b, 3b\n\t" \
376         ".previous" \
377         : "=r" (retval) \
378         : "r" (val), "m" (__m(addr)), "i" (-EFAULT) \
379         : "memory"); })
380 #else
381 #define __put_user_u64(val,addr,retval) \
382 ({ \
383 __asm__ __volatile__( \
384         "1:\n\t" \
385         "mov.l  %S1,%2\n\t" \
386         "mov.l  %R1,%T2\n\t" \
387         "mov    #0,%0\n" \
388         "2:\n" \
389         ".section       .fixup,\"ax\"\n" \
390         "3:\n\t" \
391         "nop\n\t" \
392         "mov.l  4f,%0\n\t" \
393         "jmp    @%0\n\t" \
394         " mov   %3,%0\n" \
395         "4:     .long   2b\n\t" \
396         ".previous\n" \
397         ".section       __ex_table,\"a\"\n\t" \
398         ".long  1b, 3b\n\t" \
399         ".previous" \
400         : "=r" (retval) \
401         : "r" (val), "m" (__m(addr)), "i" (-EFAULT) \
402         : "memory"); })
403 #endif
404
405 extern void __put_user_unknown(void);
406 \f
407 /* Generic arbitrary sized copy.  */
408 /* Return the number of bytes NOT copied */
409 extern __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
410
411 #define copy_to_user(to,from,n) ({ \
412 void *__copy_to = (void *) (to); \
413 __kernel_size_t __copy_size = (__kernel_size_t) (n); \
414 __kernel_size_t __copy_res; \
415 if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \
416 __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \
417 } else __copy_res = __copy_size; \
418 __copy_res; })
419
420 #define __copy_to_user(to,from,n)               \
421         __copy_user((void *)(to),               \
422                     (void *)(from), n)
423
424 #define __copy_to_user_inatomic __copy_to_user
425 #define __copy_from_user_inatomic __copy_from_user
426
427
428 #define copy_from_user(to,from,n) ({ \
429 void *__copy_to = (void *) (to); \
430 void *__copy_from = (void *) (from); \
431 __kernel_size_t __copy_size = (__kernel_size_t) (n); \
432 __kernel_size_t __copy_res; \
433 if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \
434 __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \
435 } else __copy_res = __copy_size; \
436 __copy_res; })
437
438 #define __copy_from_user(to,from,n)             \
439         __copy_user((void *)(to),               \
440                     (void *)(from), n)
441
442 /*
443  * Clear the area and return remaining number of bytes
444  * (on failure.  Usually it's 0.)
445  */
446 extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
447
448 #define clear_user(addr,n) ({ \
449 void * __cl_addr = (addr); \
450 unsigned long __cl_size = (n); \
451 if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \
452 __cl_size = __clear_user(__cl_addr, __cl_size); \
453 __cl_size; })
454
455 static __inline__ int
456 __strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count)
457 {
458         __kernel_size_t res;
459         unsigned long __dummy, _d, _s;
460
461         __asm__ __volatile__(
462                 "9:\n"
463                 "mov.b  @%2+, %1\n\t"
464                 "cmp/eq #0, %1\n\t"
465                 "bt/s   2f\n"
466                 "1:\n"
467                 "mov.b  %1, @%3\n\t"
468                 "dt     %7\n\t"
469                 "bf/s   9b\n\t"
470                 " add   #1, %3\n\t"
471                 "2:\n\t"
472                 "sub    %7, %0\n"
473                 "3:\n"
474                 ".section .fixup,\"ax\"\n"
475                 "4:\n\t"
476                 "mov.l  5f, %1\n\t"
477                 "jmp    @%1\n\t"
478                 " mov   %8, %0\n\t"
479                 ".balign 4\n"
480                 "5:     .long 3b\n"
481                 ".previous\n"
482                 ".section __ex_table,\"a\"\n"
483                 "       .balign 4\n"
484                 "       .long 9b,4b\n"
485                 ".previous"
486                 : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d)
487                 : "0" (__count), "2" (__src), "3" (__dest), "r" (__count),
488                   "i" (-EFAULT)
489                 : "memory", "t");
490
491         return res;
492 }
493
494 #define strncpy_from_user(dest,src,count) ({ \
495 unsigned long __sfu_src = (unsigned long) (src); \
496 int __sfu_count = (int) (count); \
497 long __sfu_res = -EFAULT; \
498 if(__access_ok(__sfu_src, __sfu_count)) { \
499 __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
500 } __sfu_res; })
501
502 /*
503  * Return the size of a string (including the ending 0!)
504  */
505 static __inline__ long __strnlen_user(const char __user *__s, long __n)
506 {
507         unsigned long res;
508         unsigned long __dummy;
509
510         __asm__ __volatile__(
511                 "9:\n"
512                 "cmp/eq %4, %0\n\t"
513                 "bt     2f\n"
514                 "1:\t"
515                 "mov.b  @(%0,%3), %1\n\t"
516                 "tst    %1, %1\n\t"
517                 "bf/s   9b\n\t"
518                 " add   #1, %0\n"
519                 "2:\n"
520                 ".section .fixup,\"ax\"\n"
521                 "3:\n\t"
522                 "mov.l  4f, %1\n\t"
523                 "jmp    @%1\n\t"
524                 " mov   #0, %0\n"
525                 ".balign 4\n"
526                 "4:     .long 2b\n"
527                 ".previous\n"
528                 ".section __ex_table,\"a\"\n"
529                 "       .balign 4\n"
530                 "       .long 1b,3b\n"
531                 ".previous"
532                 : "=z" (res), "=&r" (__dummy)
533                 : "0" (0), "r" (__s), "r" (__n)
534                 : "t");
535         return res;
536 }
537
538 static __inline__ long strnlen_user(const char __user *s, long n)
539 {
540         if (!__addr_ok(s))
541                 return 0;
542         else
543                 return __strnlen_user(s, n);
544 }
545
546 #define strlen_user(str)        strnlen_user(str, ~0UL >> 1)
547
548 /*
549  * The exception table consists of pairs of addresses: the first is the
550  * address of an instruction that is allowed to fault, and the second is
551  * the address at which the program should continue.  No registers are
552  * modified, so it is entirely up to the continuation code to figure out
553  * what to do.
554  *
555  * All the routines below use bits of fixup code that are out of line
556  * with the main instruction path.  This means when everything is well,
557  * we don't even have to jump over them.  Further, they do not intrude
558  * on our cache or tlb entries.
559  */
560
561 struct exception_table_entry
562 {
563         unsigned long insn, fixup;
564 };
565
566 extern int fixup_exception(struct pt_regs *regs);
567
568 #endif /* __ASM_SH_UACCESS_H */