OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-ppc/] [uaccess.h] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1276 phoenix
#ifdef __KERNEL__
2
#ifndef _PPC_UACCESS_H
3
#define _PPC_UACCESS_H
4
 
5
#ifndef __ASSEMBLY__
6
#include <linux/sched.h>
7
#include <linux/errno.h>
8
#include <asm/processor.h>
9
 
10
#define VERIFY_READ     0
11
#define VERIFY_WRITE    1
12
 
13
/*
14
 * The fs value determines whether argument validity checking should be
15
 * performed or not.  If get_fs() == USER_DS, checking is performed, with
16
 * get_fs() == KERNEL_DS, checking is bypassed.
17
 *
18
 * For historical reasons, these macros are grossly misnamed.
19
 */
20
 
21
#define KERNEL_DS       ((mm_segment_t) { 0 })
22
#define USER_DS         ((mm_segment_t) { 1 })
23
 
24
#define get_ds()        (KERNEL_DS)
25
#define get_fs()        (current->thread.fs)
26
#define set_fs(val)     (current->thread.fs = (val))
27
 
28
#define segment_eq(a,b) ((a).seg == (b).seg)
29
 
30
#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
31
#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
32
#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
33
#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
34
 
35
extern inline int verify_area(int type, const void * addr, unsigned long size)
36
{
37
        return access_ok(type,addr,size) ? 0 : -EFAULT;
38
}
39
 
40
 
41
/*
42
 * The exception table consists of pairs of addresses: the first is the
43
 * address of an instruction that is allowed to fault, and the second is
44
 * the address at which the program should continue.  No registers are
45
 * modified, so it is entirely up to the continuation code to figure out
46
 * what to do.
47
 *
48
 * All the routines below use bits of fixup code that are out of line
49
 * with the main instruction path.  This means when everything is well,
50
 * we don't even have to jump over them.  Further, they do not intrude
51
 * on our cache or tlb entries.
52
 */
53
 
54
struct exception_table_entry
55
{
56
        unsigned long insn, fixup;
57
};
58
 
59
/* Returns 0 if exception not found and fixup otherwise.  */
60
extern unsigned long search_exception_table(unsigned long);
61
extern void sort_exception_table(void);
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
 * This gets kind of ugly. We want to return _two_ values in "get_user()"
68
 * and yet we don't want to do any pointers, because that is too much
69
 * of a performance impact. Thus we have a few rather ugly macros here,
70
 * and hide all the uglyness from the user.
71
 *
72
 * The "__xxx" versions of the user access functions are versions that
73
 * do not verify the address space, that must have been done previously
74
 * with a separate "access_ok()" call (this is used when we do multiple
75
 * accesses to the same area of user memory).
76
 *
77
 * As we use the same address space for kernel and user data on the
78
 * PowerPC, we can just do these as direct assignments.  (Of course, the
79
 * exception handling means that it's no longer "just"...)
80
 *
81
 * The "user64" versions of the user access functions are versions that
82
 * allow access of 64-bit data. The "get_user" functions do not
83
 * properly handle 64-bit data because the value gets down cast to a long.
84
 * The "put_user" functions already handle 64-bit data properly but we add
85
 * "user64" versions for completeness
86
 */
87
#define get_user(x,ptr) \
88
  __get_user_check((x),(ptr),sizeof(*(ptr)))
89
#define get_user64(x,ptr) \
90
  __get_user64_check((x),(ptr),sizeof(*(ptr)))
91
#define put_user(x,ptr) \
92
  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
93
#define put_user64(x,ptr) put_user(x,ptr)
94
 
95
#define __get_user(x,ptr) \
96
  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
97
#define __get_user64(x,ptr) \
98
  __get_user64_nocheck((x),(ptr),sizeof(*(ptr)))
99
#define __put_user(x,ptr) \
100
  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
101
#define __put_user64(x,ptr) __put_user(x,ptr)
102
 
103
extern long __put_user_bad(void);
104
 
105
#define __put_user_nocheck(x,ptr,size)                  \
106
({                                                      \
107
        long __pu_err;                                  \
108
        __put_user_size((x),(ptr),(size),__pu_err);     \
109
        __pu_err;                                       \
110
})
111
 
112
#define __put_user_check(x,ptr,size)                            \
113
({                                                              \
114
        long __pu_err = -EFAULT;                                \
115
        __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
116
        if (access_ok(VERIFY_WRITE,__pu_addr,size))             \
117
                __put_user_size((x),__pu_addr,(size),__pu_err); \
118
        __pu_err;                                               \
119
})
120
 
121
#define __put_user_size(x,ptr,size,retval)                      \
122
do {                                                            \
123
        retval = 0;                                              \
124
        switch (size) {                                         \
125
          case 1: __put_user_asm(x,ptr,retval,"stb"); break;    \
126
          case 2: __put_user_asm(x,ptr,retval,"sth"); break;    \
127
          case 4: __put_user_asm(x,ptr,retval,"stw"); break;    \
128
          case 8: __put_user_asm2(x,ptr,retval); break;         \
129
          default: __put_user_bad();                            \
130
        }                                                       \
131
} while (0)
132
 
133
struct __large_struct { unsigned long buf[100]; };
134
#define __m(x) (*(struct __large_struct *)(x))
135
 
136
/*
137
 * We don't tell gcc that we are accessing memory, but this is OK
138
 * because we do not write to any memory gcc knows about, so there
139
 * are no aliasing issues.
140
 */
141
#define __put_user_asm(x, addr, err, op)                        \
142
        __asm__ __volatile__(                                   \
143
                "1:     "op" %1,0(%2)\n"                        \
144
                "2:\n"                                          \
145
                ".section .fixup,\"ax\"\n"                      \
146
                "3:     li %0,%3\n"                             \
147
                "       b 2b\n"                                 \
148
                ".previous\n"                                   \
149
                ".section __ex_table,\"a\"\n"                   \
150
                "       .align 2\n"                             \
151
                "       .long 1b,3b\n"                          \
152
                ".previous"                                     \
153
                : "=r"(err)                                     \
154
                : "r"(x), "b"(addr), "i"(-EFAULT), "0"(err))
155
 
156
#define __put_user_asm2(x, addr, err)                           \
157
        __asm__ __volatile__(                                   \
158
                "1:     stw %1,0(%2)\n"                         \
159
                "2:     stw %1+1,4(%2)\n"                               \
160
                "3:\n"                                          \
161
                ".section .fixup,\"ax\"\n"                      \
162
                "4:     li %0,%3\n"                             \
163
                "       b 3b\n"                                 \
164
                ".previous\n"                                   \
165
                ".section __ex_table,\"a\"\n"                   \
166
                "       .align 2\n"                             \
167
                "       .long 1b,4b\n"                          \
168
                "       .long 2b,4b\n"                          \
169
                ".previous"                                     \
170
                : "=r"(err)                                     \
171
                : "r"(x), "b"(addr), "i"(-EFAULT), "0"(err))
172
 
173
#define __get_user_nocheck(x,ptr,size)                          \
174
({                                                              \
175
        long __gu_err, __gu_val;                                \
176
        __get_user_size(__gu_val,(ptr),(size),__gu_err);        \
177
        (x) = (__typeof__(*(ptr)))__gu_val;                     \
178
        __gu_err;                                               \
179
})
180
 
181
#define __get_user64_nocheck(x,ptr,size)                        \
182
({                                                              \
183
        long __gu_err;                                          \
184
        long long __gu_val;                                     \
185
        __get_user_size64(__gu_val,(ptr),(size),__gu_err);      \
186
        (x) = (__typeof__(*(ptr)))__gu_val;                     \
187
        __gu_err;                                               \
188
})
189
 
190
#define __get_user_check(x,ptr,size)                                    \
191
({                                                                      \
192
        long __gu_err = -EFAULT, __gu_val = 0;                           \
193
        const __typeof__(*(ptr)) *__gu_addr = (ptr);                    \
194
        if (access_ok(VERIFY_READ,__gu_addr,size))                      \
195
                __get_user_size(__gu_val,__gu_addr,(size),__gu_err);    \
196
        (x) = (__typeof__(*(ptr)))__gu_val;                             \
197
        __gu_err;                                                       \
198
})
199
 
200
#define __get_user64_check(x,ptr,size)                                  \
201
({                                                                      \
202
        long __gu_err = -EFAULT;                                        \
203
        long long __gu_val = 0;                                          \
204
        const __typeof__(*(ptr)) *__gu_addr = (ptr);                    \
205
        if (access_ok(VERIFY_READ,__gu_addr,size))                      \
206
                __get_user_size64(__gu_val,__gu_addr,(size),__gu_err);  \
207
        (x) = (__typeof__(*(ptr)))__gu_val;                             \
208
        __gu_err;                                                       \
209
})
210
 
211
extern long __get_user_bad(void);
212
 
213
#define __get_user_size(x,ptr,size,retval)                      \
214
do {                                                            \
215
        retval = 0;                                              \
216
        switch (size) {                                         \
217
          case 1: __get_user_asm(x,ptr,retval,"lbz"); break;    \
218
          case 2: __get_user_asm(x,ptr,retval,"lhz"); break;    \
219
          case 4: __get_user_asm(x,ptr,retval,"lwz"); break;    \
220
          default: (x) = __get_user_bad();                      \
221
        }                                                       \
222
} while (0)
223
 
224
#define __get_user_size64(x,ptr,size,retval)                    \
225
do {                                                            \
226
        retval = 0;                                              \
227
        switch (size) {                                         \
228
          case 1: __get_user_asm(x,ptr,retval,"lbz"); break;    \
229
          case 2: __get_user_asm(x,ptr,retval,"lhz"); break;    \
230
          case 4: __get_user_asm(x,ptr,retval,"lwz"); break;    \
231
          case 8: __get_user_asm2(x, ptr, retval); break;       \
232
          default: (x) = __get_user_bad();                      \
233
        }                                                       \
234
} while (0)
235
 
236
#define __get_user_asm(x, addr, err, op)                \
237
        __asm__ __volatile__(                           \
238
                "1:     "op" %1,0(%2)\n"                \
239
                "2:\n"                                  \
240
                ".section .fixup,\"ax\"\n"              \
241
                "3:     li %0,%3\n"                     \
242
                "       li %1,0\n"                      \
243
                "       b 2b\n"                         \
244
                ".previous\n"                           \
245
                ".section __ex_table,\"a\"\n"           \
246
                "       .align 2\n"                     \
247
                "       .long 1b,3b\n"                  \
248
                ".previous"                             \
249
                : "=r"(err), "=r"(x)                    \
250
                : "b"(addr), "i"(-EFAULT), "0"(err))
251
 
252
#define __get_user_asm2(x, addr, err)                   \
253
        __asm__ __volatile__(                           \
254
                "1:     lwz %1,0(%2)\n"                 \
255
                "2:     lwz %1+1,4(%2)\n"               \
256
                "3:\n"                                  \
257
                ".section .fixup,\"ax\"\n"              \
258
                "4:     li %0,%3\n"                     \
259
                "       li %1,0\n"                      \
260
                "       li %1+1,0\n"                    \
261
                "       b 3b\n"                         \
262
                ".previous\n"                           \
263
                ".section __ex_table,\"a\"\n"           \
264
                "       .align 2\n"                     \
265
                "       .long 1b,4b\n"                  \
266
                "       .long 2b,4b\n"                  \
267
                ".previous"                             \
268
                : "=r"(err), "=&r"(x)                   \
269
                : "b"(addr), "i"(-EFAULT), "0"(err))
270
 
271
/* more complex routines */
272
 
273
extern int __copy_tofrom_user(void *to, const void *from, unsigned long size);
274
 
275
extern inline unsigned long
276
copy_from_user(void *to, const void *from, unsigned long n)
277
{
278
        unsigned long over;
279
 
280
        if (access_ok(VERIFY_READ, from, n))
281
                return __copy_tofrom_user(to, from, n);
282
        if ((unsigned long)from < TASK_SIZE) {
283
                over = (unsigned long)from + n - TASK_SIZE;
284
                return __copy_tofrom_user(to, from, n - over) + over;
285
        }
286
        return n;
287
}
288
 
289
extern inline unsigned long
290
copy_to_user(void *to, const void *from, unsigned long n)
291
{
292
        unsigned long over;
293
 
294
        if (access_ok(VERIFY_WRITE, to, n))
295
                return __copy_tofrom_user(to, from, n);
296
        if ((unsigned long)to < TASK_SIZE) {
297
                over = (unsigned long)to + n - TASK_SIZE;
298
                return __copy_tofrom_user(to, from, n - over) + over;
299
        }
300
        return n;
301
}
302
 
303
#define __copy_from_user(to, from, size) \
304
        __copy_tofrom_user((to), (from), (size))
305
#define __copy_to_user(to, from, size) \
306
        __copy_tofrom_user((to), (from), (size))
307
 
308
extern unsigned long __clear_user(void *addr, unsigned long size);
309
 
310
extern inline unsigned long
311
clear_user(void *addr, unsigned long size)
312
{
313
        if (access_ok(VERIFY_WRITE, addr, size))
314
                return __clear_user(addr, size);
315
        if ((unsigned long)addr < TASK_SIZE) {
316
                unsigned long over = (unsigned long)addr + size - TASK_SIZE;
317
                return __clear_user(addr, size - over) + over;
318
        }
319
        return size;
320
}
321
 
322
extern int __strncpy_from_user(char *dst, const char *src, long count);
323
 
324
extern inline long
325
strncpy_from_user(char *dst, const char *src, long count)
326
{
327
        if (access_ok(VERIFY_READ, src, 1))
328
                return __strncpy_from_user(dst, src, count);
329
        return -EFAULT;
330
}
331
 
332
/*
333
 * Return the size of a string (including the ending 0)
334
 *
335
 * Return 0 for error
336
 */
337
 
338
extern int __strnlen_user(const char *str, long len, unsigned long top);
339
 
340
/*
341
 * Returns the length of the string at str (including the null byte),
342
 * or 0 if we hit a page we can't access,
343
 * or something > len if we didn't find a null byte.
344
 *
345
 * The `top' parameter to __strnlen_user is to make sure that
346
 * we can never overflow from the user area into kernel space.
347
 */
348
extern __inline__ int strnlen_user(const char *str, long len)
349
{
350
        unsigned long top = __kernel_ok? ~0UL: TASK_SIZE - 1;
351
 
352
        if ((unsigned long)str > top)
353
                return 0;
354
        return __strnlen_user(str, len, top);
355
}
356
 
357
#define strlen_user(str)        strnlen_user((str), 0x7ffffffe)
358
 
359
#endif  /* __ASSEMBLY__ */
360
 
361
#endif  /* _PPC_UACCESS_H */
362
#endif /* __KERNEL__ */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.