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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * This file is subject to the terms and conditions of the GNU General Public
3
 * License.  See the file "COPYING" in the main directory of this archive
4
 * for more details.
5
 *
6
 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03 by Ralf Baechle
7
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8
 */
9
#ifndef _ASM_UACCESS_H
10
#define _ASM_UACCESS_H
11
 
12
#include <linux/compiler.h>
13
#include <linux/errno.h>
14
#include <linux/sched.h>
15
 
16
#define STR(x)  __STR(x)
17
#define __STR(x)  #x
18
 
19
/*
20
 * The fs value determines whether argument validity checking should be
21
 * performed or not.  If get_fs() == USER_DS, checking is performed, with
22
 * get_fs() == KERNEL_DS, checking is bypassed.
23
 *
24
 * For historical reasons, these macros are grossly misnamed.
25
 */
26
#define KERNEL_DS       ((mm_segment_t) { 0UL })
27
#define USER_DS         ((mm_segment_t) { -TASK_SIZE })
28
 
29
#define VERIFY_READ    0
30
#define VERIFY_WRITE   1
31
 
32
#define get_fs()        (current->thread.current_ds)
33
#define get_ds()        (KERNEL_DS)
34
#define set_fs(x)       (current->thread.current_ds=(x))
35
 
36
#define segment_eq(a,b) ((a).seg == (b).seg)
37
 
38
 
39
/*
40
 * Is a address valid? This does a straighforward calculation rather
41
 * than tests.
42
 *
43
 * Address valid if:
44
 *  - "addr" doesn't have any high-bits set
45
 *  - AND "size" doesn't have any high-bits set
46
 *  - AND "addr+size" doesn't have any high-bits set
47
 *  - OR we are in kernel mode.
48
 */
49
#define __ua_size(size)                                                 \
50
        ((__builtin_constant_p(size) && (size)) > 0 ? 0 : (size))
51
 
52
#define __access_ok(addr, size, mask)                                   \
53
        (((mask) & ((addr) | ((addr) + (size)) | __ua_size(size))) == 0)
54
 
55
#define __access_mask get_fs().seg
56
 
57
/*
58
 * access_ok: - Checks if a user space pointer is valid
59
 * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
60
 *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
61
 *        to write to a block, it is always safe to read from it.
62
 * @addr: User space pointer to start of block to check
63
 * @size: Size of block to check
64
 *
65
 * Context: User context only.  This function may sleep.
66
 *
67
 * Checks if a pointer to a block of memory in user space is valid.
68
 *
69
 * Returns true (nonzero) if the memory block may be valid, false (zero)
70
 * if it is definitely invalid.
71
 *
72
 * Note that, depending on architecture, this function probably just
73
 * checks that the pointer is in the user space range - after calling
74
 * this function, memory access functions may still return -EFAULT.
75
 */
76
#define access_ok(type, addr, size)                                     \
77
        likely(__access_ok((unsigned long)(addr), (size), __access_mask))
78
 
79
/*
80
 * verify_area: - Obsolete, use access_ok()
81
 * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
82
 * @addr: User space pointer to start of block to check
83
 * @size: Size of block to check
84
 *
85
 * Context: User context only.  This function may sleep.
86
 *
87
 * This function has been replaced by access_ok().
88
 *
89
 * Checks if a pointer to a block of memory in user space is valid.
90
 *
91
 * Returns zero if the memory block may be valid, -EFAULT
92
 * if it is definitely invalid.
93
 *
94
 * See access_ok() for more details.
95
 */
96
static inline int verify_area(int type, const void * addr, unsigned long size)
97
{
98
        return access_ok(type, addr, size) ? 0 : -EFAULT;
99
}
100
 
101
/*
102
 * put_user: - Write a simple value into user space.
103
 * @x:   Value to copy to user space.
104
 * @ptr: Destination address, in user space.
105
 *
106
 * Context: User context only.  This function may sleep.
107
 *
108
 * This macro copies a single simple value from kernel space to user
109
 * space.  It supports simple types like char and int, but not larger
110
 * data types like structures or arrays.
111
 *
112
 * @ptr must have pointer-to-simple-variable type, and @x must be assignable
113
 * to the result of dereferencing @ptr.
114
 *
115
 * Returns zero on success, or -EFAULT on error.
116
 */
117
#define put_user(x,ptr) \
118
        __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
119
 
120
/*
121
 * get_user: - Get a simple variable from user space.
122
 * @x:   Variable to store result.
123
 * @ptr: Source address, in user space.
124
 *
125
 * Context: User context only.  This function may sleep.
126
 *
127
 * This macro copies a single simple variable from user space to kernel
128
 * space.  It supports simple types like char and int, but not larger
129
 * data types like structures or arrays.
130
 *
131
 * @ptr must have pointer-to-simple-variable type, and the result of
132
 * dereferencing @ptr must be assignable to @x without a cast.
133
 *
134
 * Returns zero on success, or -EFAULT on error.
135
 * On error, the variable @x is set to zero.
136
 */
137
#define get_user(x,ptr) \
138
        __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
139
 
140
/*
141
 * __put_user: - Write a simple value into user space, with less checking.
142
 * @x:   Value to copy to user space.
143
 * @ptr: Destination address, in user space.
144
 *
145
 * Context: User context only.  This function may sleep.
146
 *
147
 * This macro copies a single simple value from kernel space to user
148
 * space.  It supports simple types like char and int, but not larger
149
 * data types like structures or arrays.
150
 *
151
 * @ptr must have pointer-to-simple-variable type, and @x must be assignable
152
 * to the result of dereferencing @ptr.
153
 *
154
 * Caller must check the pointer with access_ok() before calling this
155
 * function.
156
 *
157
 * Returns zero on success, or -EFAULT on error.
158
 */
159
#define __put_user(x,ptr) \
160
        __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
161
 
162
/*
163
 * __get_user: - Get a simple variable from user space, with less checking.
164
 * @x:   Variable to store result.
165
 * @ptr: Source address, in user space.
166
 *
167
 * Context: User context only.  This function may sleep.
168
 *
169
 * This macro copies a single simple variable from user space to kernel
170
 * space.  It supports simple types like char and int, but not larger
171
 * data types like structures or arrays.
172
 *
173
 * @ptr must have pointer-to-simple-variable type, and the result of
174
 * dereferencing @ptr must be assignable to @x without a cast.
175
 *
176
 * Caller must check the pointer with access_ok() before calling this
177
 * function.
178
 *
179
 * Returns zero on success, or -EFAULT on error.
180
 * On error, the variable @x is set to zero.
181
 */
182
#define __get_user(x,ptr) \
183
        __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
184
 
185
struct __large_struct { unsigned long buf[100]; };
186
#define __m(x) (*(struct __large_struct *)(x))
187
 
188
#define __get_user_nocheck(x,ptr,size)                                  \
189
({                                                                      \
190
        long __gu_err;                                                  \
191
        __typeof(*(ptr)) __gu_val;                                      \
192
        long __gu_addr;                                                 \
193
        __asm__("":"=r" (__gu_val));                                    \
194
        __gu_addr = (long) (ptr);                                       \
195
        __asm__("":"=r" (__gu_err));                                    \
196
        switch (size) {                                                 \
197
                case 1: __get_user_asm("lb"); break;                    \
198
                case 2: __get_user_asm("lh"); break;                    \
199
                case 4: __get_user_asm("lw"); break;                    \
200
                case 8: __get_user_asm("ld"); break;                    \
201
                default: __get_user_unknown(); break;                   \
202
        } x = (__typeof__(*(ptr))) __gu_val;                            \
203
        __gu_err;                                                       \
204
})
205
 
206
#define __get_user_check(x,ptr,size)                                    \
207
({                                                                      \
208
        long __gu_err;                                                  \
209
        __typeof__(*(ptr)) __gu_val;                                    \
210
        long __gu_addr;                                                 \
211
        __asm__("":"=r" (__gu_val));                                    \
212
        __gu_addr = (long) (ptr);                                       \
213
        __asm__("":"=r" (__gu_err));                                    \
214
        if (access_ok(VERIFY_READ, __gu_addr, size)) {                  \
215
                switch (size) {                                         \
216
                case 1: __get_user_asm("lb"); break;                    \
217
                case 2: __get_user_asm("lh"); break;                    \
218
                case 4: __get_user_asm("lw"); break;                    \
219
                case 8: __get_user_asm("ld"); break;                    \
220
                default: __get_user_unknown(); break;                   \
221
                }                                                       \
222
        } x = (__typeof__(*(ptr))) __gu_val;                            \
223
        __gu_err;                                                       \
224
})
225
 
226
#define __get_user_asm(insn)                                            \
227
({                                                                      \
228
        __asm__ __volatile__(                                           \
229
        "1:\t" insn "\t%1,%2\n\t"                                       \
230
        "move\t%0,$0\n"                                                 \
231
        "2:\n\t"                                                        \
232
        ".section\t.fixup,\"ax\"\n"                                     \
233
        "3:\tli\t%0,%3\n\t"                                             \
234
        "move\t%1,$0\n\t"                                               \
235
        "j\t2b\n\t"                                                     \
236
        ".previous\n\t"                                                 \
237
        ".section\t__ex_table,\"a\"\n\t"                                \
238
        ".dword\t1b,3b\n\t"                                             \
239
        ".previous"                                                     \
240
        :"=r" (__gu_err), "=r" (__gu_val)                               \
241
        :"o" (__m(__gu_addr)), "i" (-EFAULT));                          \
242
})
243
 
244
extern void __get_user_unknown(void);
245
 
246
#define __put_user_nocheck(x,ptr,size)                                  \
247
({                                                                      \
248
        long __pu_err;                                                  \
249
        __typeof__(*(ptr)) __pu_val;                                    \
250
        long __pu_addr;                                                 \
251
        __pu_val = (x);                                                 \
252
        __pu_addr = (long) (ptr);                                       \
253
        __asm__("":"=r" (__pu_err));                                    \
254
        switch (size) {                                                 \
255
                case 1: __put_user_asm("sb"); break;                    \
256
                case 2: __put_user_asm("sh"); break;                    \
257
                case 4: __put_user_asm("sw"); break;                    \
258
                case 8: __put_user_asm("sd"); break;                    \
259
                default: __put_user_unknown(); break;                   \
260
        }                                                               \
261
        __pu_err;                                                       \
262
})
263
 
264
#define __put_user_check(x,ptr,size)                                    \
265
({                                                                      \
266
        long __pu_err;                                                  \
267
        __typeof__(*(ptr)) __pu_val;                                    \
268
        long __pu_addr;                                                 \
269
        __pu_val = (x);                                                 \
270
        __pu_addr = (long) (ptr);                                       \
271
        __asm__("":"=r" (__pu_err));                                    \
272
        if (access_ok(VERIFY_WRITE, __pu_addr, size)) {                 \
273
                switch (size) {                                         \
274
                case 1: __put_user_asm("sb"); break;                    \
275
                case 2: __put_user_asm("sh"); break;                    \
276
                case 4: __put_user_asm("sw"); break;                    \
277
                case 8: __put_user_asm("sd"); break;                    \
278
                default: __put_user_unknown(); break;                   \
279
                }                                                       \
280
        }                                                               \
281
        __pu_err;                                                       \
282
})
283
 
284
#define __put_user_asm(insn)                                            \
285
({                                                                      \
286
        __asm__ __volatile__(                                           \
287
        "1:\t" insn "\t%z1, %2\t\t\t# __put_user_asm\n\t"               \
288
        "move\t%0, $0\n"                                                \
289
        "2:\n\t"                                                        \
290
        ".section\t.fixup,\"ax\"\n"                                     \
291
        "3:\tli\t%0, %3\n\t"                                            \
292
        "j\t2b\n\t"                                                     \
293
        ".previous\n\t"                                                 \
294
        ".section\t__ex_table,\"a\"\n\t"                                \
295
        ".dword\t1b, 3b\n\t"                                            \
296
        ".previous"                                                     \
297
        :"=r" (__pu_err)                                                \
298
        :"Jr" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT));         \
299
})
300
 
301
extern void __put_user_unknown(void);
302
 
303
/*
304
 * We're generating jump to subroutines which will be outside the range of
305
 * jump instructions
306
 */
307
#ifdef MODULE
308
#define __MODULE_JAL(destination)                                       \
309
        ".set\tnoat\n\t"                                                \
310
        "dla\t$1, " #destination "\n\t"                                  \
311
        "jalr\t$1\n\t"                                                  \
312
        ".set\tat\n\t"
313
#else
314
#define __MODULE_JAL(destination)                                       \
315
        "jal\t" #destination "\n\t"
316
#endif
317
 
318
extern size_t __copy_user(void *__to, const void *__from, size_t __n);
319
 
320
#define __invoke_copy_to_user(to,from,n)                                \
321
({                                                                      \
322
        register void *__cu_to_r __asm__ ("$4");                        \
323
        register const void *__cu_from_r __asm__ ("$5");                \
324
        register long __cu_len_r __asm__ ("$6");                        \
325
                                                                        \
326
        __cu_to_r = (to);                                               \
327
        __cu_from_r = (from);                                           \
328
        __cu_len_r = (n);                                               \
329
        __asm__ __volatile__(                                           \
330
        __MODULE_JAL(__copy_user)                                       \
331
        : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)       \
332
        :                                                               \
333
        : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",         \
334
          "memory");                                                    \
335
        __cu_len_r;                                                     \
336
})
337
 
338
/*
339
 * __copy_to_user: - Copy a block of data into user space, with less checking.
340
 * @to:   Destination address, in user space.
341
 * @from: Source address, in kernel space.
342
 * @n:    Number of bytes to copy.
343
 *
344
 * Context: User context only.  This function may sleep.
345
 *
346
 * Copy data from kernel space to user space.  Caller must check
347
 * the specified block with access_ok() before calling this function.
348
 *
349
 * Returns number of bytes that could not be copied.
350
 * On success, this will be zero.
351
 */
352
#define __copy_to_user(to,from,n)                                       \
353
({                                                                      \
354
        void *__cu_to;                                                  \
355
        const void *__cu_from;                                          \
356
        long __cu_len;                                                  \
357
                                                                        \
358
        __cu_to = (to);                                                 \
359
        __cu_from = (from);                                             \
360
        __cu_len = (n);                                                 \
361
        __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len); \
362
        __cu_len;                                                       \
363
})
364
 
365
/*
366
 * copy_to_user: - Copy a block of data into user space.
367
 * @to:   Destination address, in user space.
368
 * @from: Source address, in kernel space.
369
 * @n:    Number of bytes to copy.
370
 *
371
 * Context: User context only.  This function may sleep.
372
 *
373
 * Copy data from kernel space to user space.
374
 *
375
 * Returns number of bytes that could not be copied.
376
 * On success, this will be zero.
377
 */
378
#define copy_to_user(to,from,n)                                         \
379
({                                                                      \
380
        void *__cu_to;                                                  \
381
        const void *__cu_from;                                          \
382
        long __cu_len;                                                  \
383
                                                                        \
384
        __cu_to = (to);                                                 \
385
        __cu_from = (from);                                             \
386
        __cu_len = (n);                                                 \
387
        if (access_ok(VERIFY_WRITE, __cu_to, __cu_len))                 \
388
                __cu_len = __invoke_copy_to_user(__cu_to, __cu_from,    \
389
                                                 __cu_len);             \
390
        __cu_len;                                                       \
391
})
392
 
393
#define __invoke_copy_from_user(to,from,n)                              \
394
({                                                                      \
395
        register void *__cu_to_r __asm__ ("$4");                        \
396
        register const void *__cu_from_r __asm__ ("$5");                \
397
        register long __cu_len_r __asm__ ("$6");                        \
398
                                                                        \
399
        __cu_to_r = (to);                                               \
400
        __cu_from_r = (from);                                           \
401
        __cu_len_r = (n);                                               \
402
        __asm__ __volatile__(                                           \
403
        ".set\tnoreorder\n\t"                                           \
404
        __MODULE_JAL(__copy_user)                                       \
405
        ".set\tnoat\n\t"                                                \
406
        "daddu\t$1, %1, %2\n\t"                                         \
407
        ".set\tat\n\t"                                                  \
408
        ".set\treorder\n\t"                                             \
409
        "move\t%0, $6"                                                  \
410
        : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)       \
411
        :                                                               \
412
        : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",         \
413
          "memory");                                                    \
414
        __cu_len_r;                                                     \
415
})
416
 
417
/*
418
 * __copy_from_user: - Copy a block of data from user space, with less checking. * @to:   Destination address, in kernel space.
419
 * @from: Source address, in user space.
420
 * @n:    Number of bytes to copy.
421
 *
422
 * Context: User context only.  This function may sleep.
423
 *
424
 * Copy data from user space to kernel space.  Caller must check
425
 * the specified block with access_ok() before calling this function.
426
 *
427
 * Returns number of bytes that could not be copied.
428
 * On success, this will be zero.
429
 *
430
 * If some data could not be copied, this function will pad the copied
431
 * data to the requested size using zero bytes.
432
 */
433
#define __copy_from_user(to,from,n)                                     \
434
({                                                                      \
435
        void *__cu_to;                                                  \
436
        const void *__cu_from;                                          \
437
        long __cu_len;                                                  \
438
                                                                        \
439
        __cu_to = (to);                                                 \
440
        __cu_from = (from);                                             \
441
        __cu_len = (n);                                                 \
442
        __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,          \
443
                                           __cu_len);                   \
444
        __cu_len;                                                       \
445
})
446
 
447
/*
448
 * copy_from_user: - Copy a block of data from user space.
449
 * @to:   Destination address, in kernel space.
450
 * @from: Source address, in user space.
451
 * @n:    Number of bytes to copy.
452
 *
453
 * Context: User context only.  This function may sleep.
454
 *
455
 * Copy data from user space to kernel space.
456
 *
457
 * Returns number of bytes that could not be copied.
458
 * On success, this will be zero.
459
 *
460
 * If some data could not be copied, this function will pad the copied
461
 * data to the requested size using zero bytes.
462
 */
463
#define copy_from_user(to,from,n)                                       \
464
({                                                                      \
465
        void *__cu_to;                                                  \
466
        const void *__cu_from;                                          \
467
        long __cu_len;                                                  \
468
                                                                        \
469
        __cu_to = (to);                                                 \
470
        __cu_from = (from);                                             \
471
        __cu_len = (n);                                                 \
472
        if (access_ok(VERIFY_READ, __cu_from, __cu_len))                \
473
                __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,  \
474
                                                   __cu_len);           \
475
        __cu_len;                                                       \
476
})
477
 
478
/*
479
 * __clear_user: - Zero a block of memory in user space, with less checking.
480
 * @to:   Destination address, in user space.
481
 * @n:    Number of bytes to zero.
482
 *
483
 * Zero a block of memory in user space.  Caller must check
484
 * the specified block with access_ok() before calling this function.
485
 *
486
 * Returns number of bytes that could not be cleared.
487
 * On success, this will be zero.
488
 */
489
static inline __kernel_size_t
490
__clear_user(void *addr, __kernel_size_t size)
491
{
492
        __kernel_size_t res;
493
 
494
        __asm__ __volatile__(
495
                "move\t$4, %1\n\t"
496
                "move\t$5, $0\n\t"
497
                "move\t$6, %2\n\t"
498
                __MODULE_JAL(__bzero)
499
                "move\t%0, $6"
500
                : "=r" (res)
501
                : "r" (addr), "r" (size)
502
                : "$4", "$5", "$6", "$8", "$9", "$31");
503
 
504
        return res;
505
}
506
 
507
#define clear_user(addr,n)                                              \
508
({                                                                      \
509
        void * __cl_addr = (addr);                                      \
510
        unsigned long __cl_size = (n);                                  \
511
        if (__cl_size && access_ok(VERIFY_WRITE,                        \
512
                ((unsigned long)(__cl_addr)), __cl_size))               \
513
                __cl_size = __clear_user(__cl_addr, __cl_size);         \
514
        __cl_size;                                                      \
515
})
516
 
517
/*
518
 * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
519
 * @dst:   Destination address, in kernel space.  This buffer must be at
520
 *         least @count bytes long.
521
 * @src:   Source address, in user space.
522
 * @count: Maximum number of bytes to copy, including the trailing NUL.
523
 *
524
 * Copies a NUL-terminated string from userspace to kernel space.
525
 * Caller must check the specified block with access_ok() before calling
526
 * this function.
527
 *
528
 * On success, returns the length of the string (not including the trailing
529
 * NUL).
530
 *
531
 * If access to userspace fails, returns -EFAULT (some data may have been
532
 * copied).
533
 *
534
 * If @count is smaller than the length of the string, copies @count bytes
535
 * and returns @count.
536
 */
537
static inline long
538
__strncpy_from_user(char *__to, const char *__from, long __len)
539
{
540
        long res;
541
 
542
        __asm__ __volatile__(
543
                "move\t$4, %1\n\t"
544
                "move\t$5, %2\n\t"
545
                "move\t$6, %3\n\t"
546
                __MODULE_JAL(__strncpy_from_user_nocheck_asm)
547
                "move\t%0, $2"
548
                : "=r" (res)
549
                : "r" (__to), "r" (__from), "r" (__len)
550
                : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
551
 
552
        return res;
553
}
554
 
555
/*
556
 * strncpy_from_user: - Copy a NUL terminated string from userspace.
557
 * @dst:   Destination address, in kernel space.  This buffer must be at
558
 *         least @count bytes long.
559
 * @src:   Source address, in user space.
560
 * @count: Maximum number of bytes to copy, including the trailing NUL.
561
 *
562
 * Copies a NUL-terminated string from userspace to kernel space.
563
 *
564
 * On success, returns the length of the string (not including the trailing
565
 * NUL).
566
 *
567
 * If access to userspace fails, returns -EFAULT (some data may have been
568
 * copied).
569
 *
570
 * If @count is smaller than the length of the string, copies @count bytes
571
 * and returns @count.
572
 */
573
static inline long
574
strncpy_from_user(char *__to, const char *__from, long __len)
575
{
576
        long res;
577
 
578
        __asm__ __volatile__(
579
                "move\t$4, %1\n\t"
580
                "move\t$5, %2\n\t"
581
                "move\t$6, %3\n\t"
582
                __MODULE_JAL(__strncpy_from_user_asm)
583
                "move\t%0, $2"
584
                : "=r" (res)
585
                : "r" (__to), "r" (__from), "r" (__len)
586
                : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
587
 
588
        return res;
589
}
590
 
591
/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
592
static inline long __strlen_user(const char *s)
593
{
594
        long res;
595
 
596
        __asm__ __volatile__(
597
                "move\t$4, %1\n\t"
598
                __MODULE_JAL(__strlen_user_nocheck_asm)
599
                "move\t%0, $2"
600
                : "=r" (res)
601
                : "r" (s)
602
                : "$2", "$4", "$8", "$31");
603
 
604
        return res;
605
}
606
 
607
/*
608
 * strlen_user: - Get the size of a string in user space.
609
 * @str: The string to measure.
610
 *
611
 * Context: User context only.  This function may sleep.
612
 *
613
 * Get the size of a NUL-terminated string in user space.
614
 *
615
 * Returns the size of the string INCLUDING the terminating NUL.
616
 * On exception, returns 0.
617
 *
618
 * If there is a limit on the length of a valid string, you may wish to
619
 * consider using strnlen_user() instead.
620
 */
621
static inline long strlen_user(const char *s)
622
{
623
        long res;
624
 
625
        __asm__ __volatile__(
626
                "move\t$4, %1\n\t"
627
                __MODULE_JAL(__strlen_user_asm)
628
                "move\t%0, $2"
629
                : "=r" (res)
630
                : "r" (s)
631
                : "$2", "$4", "$8", "$31");
632
 
633
        return res;
634
}
635
 
636
/*
637
 * strlen_user: - Get the size of a string in user space.
638
 * @str: The string to measure.
639
 * @n:   The maximum valid length
640
 *
641
 * Get the size of a NUL-terminated string in user space.
642
 *
643
 * Returns the size of the string INCLUDING the terminating NUL.
644
 * On exception, returns 0.
645
 * If the string is too long, returns a value greater than @n.
646
 */
647
static inline long strnlen_user(const char *s, long n)
648
{
649
        long res;
650
 
651
        __asm__ __volatile__(
652
                "move\t$4, %1\n\t"
653
                "move\t$5, %2\n\t"
654
                __MODULE_JAL(__strnlen_user_asm)
655
                "move\t%0, $2"
656
                : "=r" (res)
657
                : "r" (s), "r" (n)
658
                : "$2", "$4", "$5", "$8", "$31");
659
 
660
        return res;
661
}
662
 
663
struct exception_table_entry
664
{
665
        unsigned long insn;
666
        unsigned long nextinsn;
667
};
668
 
669
/* Returns 0 if exception not found and fixup.unit otherwise.  */
670
extern unsigned long search_exception_table(unsigned long addr);
671
 
672
/* Returns the new pc */
673
#define fixup_exception(map_reg, fixup_unit, pc)                        \
674
({                                                                      \
675
        fixup_unit;                                                     \
676
})
677
 
678
#endif /* _ASM_UACCESS_H */

powered by: WebSVN 2.1.0

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