Root/target/linux/coldfire/files-2.6.31/arch/m68k/include/asm/cf_uaccess.h

1/*
2 * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
3 */
4#ifndef __M68K_CF_UACCESS_H
5#define __M68K_CF_UACCESS_H
6
7/*
8 * User space memory access functions
9 */
10
11/* The "moves" command is not available in the CF instruction set. */
12#include <linux/compiler.h>
13#include <linux/errno.h>
14#include <linux/types.h>
15#include <linux/sched.h>
16#include <asm/segment.h>
17
18#define VERIFY_READ 0
19#define VERIFY_WRITE 1
20
21/* We let the MMU do all checking */
22#define access_ok(type, addr, size) 1
23
24/*
25 * The exception table consists of pairs of addresses: the first is the
26 * address of an instruction that is allowed to fault, and the second is
27 * the address at which the program should continue. No registers are
28 * modified, so it is entirely up to the continuation code to figure out
29 * what to do.
30 *
31 * All the routines below use bits of fixup code that are out of line
32 * with the main instruction path. This means when everything is well,
33 * we don't even have to jump over them. Further, they do not intrude
34 * on our cache or tlb entries.
35 */
36
37struct exception_table_entry
38{
39    unsigned long insn, fixup;
40};
41
42extern int __put_user_bad(void);
43extern int __get_user_bad(void);
44
45#define __put_user_asm(res, x, ptr, bwl, reg, err) \
46asm volatile ("\n" \
47    "1: move."#bwl" %2,%1\n" \
48    "2:\n" \
49    " .section .fixup,\"ax\"\n" \
50    " .even\n" \
51    "10: moveq.l %3,%0\n" \
52    " jra 2b\n" \
53    " .previous\n" \
54    "\n" \
55    " .section __ex_table,\"a\"\n" \
56    " .align 4\n" \
57    " .long 1b,10b\n" \
58    " .long 2b,10b\n" \
59    " .previous" \
60    : "+d" (res), "=m" (*(ptr)) \
61    : #reg (x), "i" (err))
62
63/*
64 * These are the main single-value transfer routines. They automatically
65 * use the right size if we just have the right pointer type.
66 */
67
68#define __put_user(x, ptr) \
69({ \
70    typeof(*(ptr)) __pu_val = (x); \
71    int __pu_err = 0; \
72    __chk_user_ptr(ptr); \
73    switch (sizeof (*(ptr))) { \
74    case 1: \
75        __put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT); \
76        break; \
77    case 2: \
78        __put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT); \
79        break; \
80    case 4: \
81        __put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT); \
82        break; \
83    case 8: \
84        { \
85        const void __user *__pu_ptr = (ptr); \
86        asm volatile ("\n" \
87            "1: move.l %2,(%1)+\n" \
88            "2: move.l %R2,(%1)\n" \
89            "3:\n" \
90            " .section .fixup,\"ax\"\n" \
91            " .even\n" \
92            "10: movel %3,%0\n" \
93            " jra 3b\n" \
94            " .previous\n" \
95            "\n" \
96            " .section __ex_table,\"a\"\n" \
97            " .align 4\n" \
98            " .long 1b,10b\n" \
99            " .long 2b,10b\n" \
100            " .long 3b,10b\n" \
101            " .previous" \
102            : "+d" (__pu_err), "+a" (__pu_ptr) \
103            : "r" (__pu_val), "i" (-EFAULT) \
104            : "memory"); \
105        break; \
106        } \
107    default: \
108        __pu_err = __put_user_bad(); \
109        break; \
110    } \
111    __pu_err; \
112})
113#define put_user(x, ptr) __put_user(x, ptr)
114
115
116#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \
117    type __gu_val; \
118    asm volatile ("\n" \
119        "1: move."#bwl" %2,%1\n" \
120        "2:\n" \
121        " .section .fixup,\"ax\"\n" \
122        " .even\n" \
123        "10: move.l %3,%0\n" \
124        " subl %1,%1\n" \
125        " jra 2b\n" \
126        " .previous\n" \
127        "\n" \
128        " .section __ex_table,\"a\"\n" \
129        " .align 4\n" \
130        " .long 1b,10b\n" \
131        " .previous" \
132        : "+d" (res), "=&" #reg (__gu_val) \
133        : "m" (*(ptr)), "i" (err)); \
134    (x) = (typeof(*(ptr)))(unsigned long)__gu_val; \
135})
136
137#define __get_user(x, ptr) \
138({ \
139    int __gu_err = 0; \
140    __chk_user_ptr(ptr); \
141    switch (sizeof(*(ptr))) { \
142    case 1: \
143        __get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT); \
144        break; \
145    case 2: \
146        __get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT); \
147        break; \
148    case 4: \
149        __get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT); \
150        break; \
151/* case 8: disabled because gcc-4.1 has a broken typeof \
152        { \
153        const void *__gu_ptr = (ptr); \
154        u64 __gu_val; \
155        asm volatile ("\n" \
156            "1: move.l (%2)+,%1\n" \
157            "2: move.l (%2),%R1\n" \
158            "3:\n" \
159            " .section .fixup,\"ax\"\n" \
160            " .even\n" \
161            "10: move.l %3,%0\n" \
162            " subl %1,%1\n" \
163            " subl %R1,%R1\n" \
164            " jra 3b\n" \
165            " .previous\n" \
166            "\n" \
167            " .section __ex_table,\"a\"\n" \
168            " .align 4\n" \
169            " .long 1b,10b\n" \
170            " .long 2b,10b\n" \
171            " .previous" \
172            : "+d" (__gu_err), "=&r" (__gu_val), \
173              "+a" (__gu_ptr) \
174            : "i" (-EFAULT) \
175            : "memory"); \
176        (x) = (typeof(*(ptr)))__gu_val; \
177        break; \
178        } */ \
179    default: \
180        __gu_err = __get_user_bad(); \
181        break; \
182    } \
183    __gu_err; \
184})
185#define get_user(x, ptr) __get_user(x, ptr)
186
187unsigned long __generic_copy_from_user(void *to, const void __user *from,
188    unsigned long n);
189unsigned long __generic_copy_to_user(void __user *to, const void *from,
190    unsigned long n);
191
192#define __constant_copy_from_user_asm(res, to, from, tmp, n, s1, s2, s3)\
193    asm volatile ("\n" \
194        "1: move."#s1" (%2)+,%3\n" \
195        " move."#s1" %3,(%1)+\n" \
196        "2: move."#s2" (%2)+,%3\n" \
197        " move."#s2" %3,(%1)+\n" \
198        " .ifnc \""#s3"\",\"\"\n" \
199        "3: move."#s3" (%2)+,%3\n" \
200        " move."#s3" %3,(%1)+\n" \
201        " .endif\n" \
202        "4:\n" \
203        " .section __ex_table,\"a\"\n" \
204        " .align 4\n" \
205        " .long 1b,10f\n" \
206        " .long 2b,20f\n" \
207        " .ifnc \""#s3"\",\"\"\n" \
208        " .long 3b,30f\n" \
209        " .endif\n" \
210        " .previous\n" \
211        "\n" \
212        " .section .fixup,\"ax\"\n" \
213        " .even\n" \
214        "10: clr."#s1" (%1)+\n" \
215        "20: clr."#s2" (%1)+\n" \
216        " .ifnc \""#s3"\",\"\"\n" \
217        "30: clr."#s3" (%1)+\n" \
218        " .endif\n" \
219        " moveq.l #"#n",%0\n" \
220        " jra 4b\n" \
221        " .previous\n" \
222        : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp) \
223        : : "memory")
224
225static __always_inline unsigned long
226__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
227{
228    unsigned long res = 0, tmp;
229
230    switch (n) {
231    case 1:
232        __get_user_asm(res, *(u8 *)to, (u8 __user *)from, u8, b, d, 1);
233        break;
234    case 2:
235        __get_user_asm(res, *(u16 *)to, (u16 __user *)from, u16, w,
236            d, 2);
237        break;
238    case 3:
239        __constant_copy_from_user_asm(res, to, from, tmp, 3, w, b,);
240        break;
241    case 4:
242        __get_user_asm(res, *(u32 *)to, (u32 __user *)from, u32, l,
243            r, 4);
244        break;
245    case 5:
246        __constant_copy_from_user_asm(res, to, from, tmp, 5, l, b,);
247        break;
248    case 6:
249        __constant_copy_from_user_asm(res, to, from, tmp, 6, l, w,);
250        break;
251    case 7:
252        __constant_copy_from_user_asm(res, to, from, tmp, 7, l, w, b);
253        break;
254    case 8:
255        __constant_copy_from_user_asm(res, to, from, tmp, 8, l, l,);
256        break;
257    case 9:
258        __constant_copy_from_user_asm(res, to, from, tmp, 9, l, l, b);
259        break;
260    case 10:
261        __constant_copy_from_user_asm(res, to, from, tmp, 10, l, l, w);
262        break;
263    case 12:
264        __constant_copy_from_user_asm(res, to, from, tmp, 12, l, l, l);
265        break;
266    default:
267        /* we limit the inlined version to 3 moves */
268        return __generic_copy_from_user(to, from, n);
269    }
270
271    return res;
272}
273
274#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3) \
275    asm volatile ("\n" \
276        " move."#s1" (%2)+,%3\n" \
277        "11: move."#s1" %3,(%1)+\n" \
278        "12: move."#s2" (%2)+,%3\n" \
279        "21: move."#s2" %3,(%1)+\n" \
280        "22:\n" \
281        " .ifnc \""#s3"\",\"\"\n" \
282        " move."#s3" (%2)+,%3\n" \
283        "31: move."#s3" %3,(%1)+\n" \
284        "32:\n" \
285        " .endif\n" \
286        "4:\n" \
287        "\n" \
288        " .section __ex_table,\"a\"\n" \
289        " .align 4\n" \
290        " .long 11b,5f\n" \
291        " .long 12b,5f\n" \
292        " .long 21b,5f\n" \
293        " .long 22b,5f\n" \
294        " .ifnc \""#s3"\",\"\"\n" \
295        " .long 31b,5f\n" \
296        " .long 32b,5f\n" \
297        " .endif\n" \
298        " .previous\n" \
299        "\n" \
300        " .section .fixup,\"ax\"\n" \
301        " .even\n" \
302        "5: moveq.l #"#n",%0\n" \
303        " jra 4b\n" \
304        " .previous\n" \
305        : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp) \
306        : : "memory")
307
308static __always_inline unsigned long
309__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
310{
311    unsigned long res = 0, tmp;
312
313    switch (n) {
314    case 1:
315        __put_user_asm(res, *(u8 *)from, (u8 __user *)to, b, d, 1);
316        break;
317    case 2:
318        __put_user_asm(res, *(u16 *)from, (u16 __user *)to, w, d, 2);
319        break;
320    case 3:
321        __constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,);
322        break;
323    case 4:
324        __put_user_asm(res, *(u32 *)from, (u32 __user *)to, l, r, 4);
325        break;
326    case 5:
327        __constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,);
328        break;
329    case 6:
330        __constant_copy_to_user_asm(res, to, from, tmp, 6, l, w,);
331        break;
332    case 7:
333        __constant_copy_to_user_asm(res, to, from, tmp, 7, l, w, b);
334        break;
335    case 8:
336        __constant_copy_to_user_asm(res, to, from, tmp, 8, l, l,);
337        break;
338    case 9:
339        __constant_copy_to_user_asm(res, to, from, tmp, 9, l, l, b);
340        break;
341    case 10:
342        __constant_copy_to_user_asm(res, to, from, tmp, 10, l, l, w);
343        break;
344    case 12:
345        __constant_copy_to_user_asm(res, to, from, tmp, 12, l, l, l);
346        break;
347    default:
348        /* limit the inlined version to 3 moves */
349        return __generic_copy_to_user(to, from, n);
350    }
351
352    return res;
353}
354
355#define __copy_from_user(to, from, n) \
356(__builtin_constant_p(n) ? \
357 __constant_copy_from_user(to, from, n) : \
358 __generic_copy_from_user(to, from, n))
359
360#define __copy_to_user(to, from, n) \
361(__builtin_constant_p(n) ? \
362 __constant_copy_to_user(to, from, n) : \
363 __generic_copy_to_user(to, from, n))
364
365#define __copy_to_user_inatomic __copy_to_user
366#define __copy_from_user_inatomic __copy_from_user
367
368#define copy_from_user(to, from, n) __copy_from_user(to, from, n)
369#define copy_to_user(to, from, n) __copy_to_user(to, from, n)
370
371long strncpy_from_user(char *dst, const char __user *src, long count);
372long strnlen_user(const char __user *src, long n);
373unsigned long __clear_user(void __user *to, unsigned long n);
374
375#define clear_user __clear_user
376
377#define strlen_user(str) strnlen_user(str, 32767)
378
379#endif /* _M68K_CF_UACCESS_H */
380

Archive Download this file



interactive