~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-mips64/uaccess.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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 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/errno.h>
 13 #include <linux/sched.h>
 14 
 15 #define STR(x)  __STR(x)
 16 #define __STR(x)  #x
 17 
 18 /*
 19  * The fs value determines whether argument validity checking should be
 20  * performed or not.  If get_fs() == USER_DS, checking is performed, with
 21  * get_fs() == KERNEL_DS, checking is bypassed.
 22  *
 23  * For historical reasons, these macros are grossly misnamed.
 24  */
 25 #define KERNEL_DS       ((mm_segment_t) { (unsigned long) 0L })
 26 #define USER_DS         ((mm_segment_t) { (unsigned long) -1L })
 27 
 28 #define VERIFY_READ    0
 29 #define VERIFY_WRITE   1
 30 
 31 #define get_fs()        (current->thread.current_ds)
 32 #define get_ds()        (KERNEL_DS)
 33 #define set_fs(x)       (current->thread.current_ds=(x))
 34 
 35 #define segment_eq(a,b) ((a).seg == (b).seg)
 36 
 37 
 38 /*
 39  * Is a address valid? This does a straighforward calculation rather
 40  * than tests.
 41  *
 42  * Address valid if:
 43  *  - "addr" doesn't have any high-bits set
 44  *  - AND "size" doesn't have any high-bits set
 45  *  - AND "addr+size" doesn't have any high-bits set
 46  *  - OR we are in kernel mode.
 47  */
 48 #define __access_ok(addr,size,mask) \
 49         (((__signed__ long)((mask)&(addr | size | (addr+size)))) >= 0)
 50 #define __access_mask ((long)(get_fs().seg))
 51 
 52 #define access_ok(type,addr,size) \
 53 __access_ok(((unsigned long)(addr)),(size),__access_mask)
 54 
 55 extern inline int verify_area(int type, const void * addr, unsigned long size)
 56 {
 57         return access_ok(type,addr,size) ? 0 : -EFAULT;
 58 }
 59 
 60 /*
 61  * Uh, these should become the main single-value transfer routines ...
 62  * They automatically use the right size if we just have the right
 63  * pointer type ...
 64  *
 65  * As MIPS uses the same address space for kernel and user data, we
 66  * can just do these as direct assignments.
 67  *
 68  * Careful to not
 69  * (a) re-use the arguments for side effects (sizeof is ok)
 70  * (b) require any knowledge of processes at this stage
 71  */
 72 #define put_user(x,ptr) \
 73         __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 74 #define get_user(x,ptr) \
 75         __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 76 
 77 /*
 78  * The "__xxx" versions do not do address space checking, useful when
 79  * doing multiple accesses to the same area (the user has to do the
 80  * checks by hand with "access_ok()")
 81  */
 82 #define __put_user(x,ptr) \
 83         __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 84 #define __get_user(x,ptr) \
 85         __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 86 
 87 struct __large_struct { unsigned long buf[100]; };
 88 #define __m(x) (*(struct __large_struct *)(x))
 89 
 90 #define __get_user_nocheck(x,ptr,size) ({ \
 91 long __gu_err; \
 92 __typeof(*(ptr)) __gu_val; \
 93 long __gu_addr; \
 94 __asm__("":"=r" (__gu_val)); \
 95 __gu_addr = (long) (ptr); \
 96 __asm__("":"=r" (__gu_err)); \
 97 switch (size) { \
 98 case 1: __get_user_asm("lb"); break; \
 99 case 2: __get_user_asm("lh"); break; \
100 case 4: __get_user_asm("lw"); break; \
101 case 8:  __get_user_asm("ld"); break; \
102 default: __get_user_unknown(); break; \
103 } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
104 
105 #define __get_user_check(x,ptr,size) ({ \
106 long __gu_err; \
107 __typeof__(*(ptr)) __gu_val; \
108 long __gu_addr; \
109 __asm__("":"=r" (__gu_val)); \
110 __gu_addr = (long) (ptr); \
111 __asm__("":"=r" (__gu_err)); \
112 if (__access_ok(__gu_addr,size,__access_mask)) { \
113 switch (size) { \
114 case 1: __get_user_asm("lb"); break; \
115 case 2: __get_user_asm("lh"); break; \
116 case 4: __get_user_asm("lw"); break; \
117 case 8: __get_user_asm("ld"); break; \
118 default: __get_user_unknown(); break; \
119 } } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
120 
121 #define __get_user_asm(insn) \
122 ({ \
123 __asm__ __volatile__( \
124         "1:\t" insn "\t%1,%2\n\t" \
125         "move\t%0,$0\n" \
126         "2:\n\t" \
127         ".section\t.fixup,\"ax\"\n" \
128         "3:\tli\t%0,%3\n\t" \
129         "move\t%1,$0\n\t" \
130         "j\t2b\n\t" \
131         ".previous\n\t" \
132         ".section\t__ex_table,\"a\"\n\t" \
133         ".dword\t1b,3b\n\t" \
134         ".previous" \
135         :"=r" (__gu_err), "=r" (__gu_val) \
136         :"o" (__m(__gu_addr)), "i" (-EFAULT)); })
137 
138 extern void __get_user_unknown(void);
139 
140 #define __put_user_nocheck(x,ptr,size) ({ \
141 long __pu_err; \
142 __typeof__(*(ptr)) __pu_val; \
143 long __pu_addr; \
144 __pu_val = (x); \
145 __pu_addr = (long) (ptr); \
146 __asm__("":"=r" (__pu_err)); \
147 switch (size) { \
148 case 1: __put_user_asm("sb"); break; \
149 case 2: __put_user_asm("sh"); break; \
150 case 4: __put_user_asm("sw"); break; \
151 case 8: __put_user_asm("sd"); break; \
152 default: __put_user_unknown(); break; \
153 } __pu_err; })
154 
155 #define __put_user_check(x,ptr,size) ({ \
156 long __pu_err; \
157 __typeof__(*(ptr)) __pu_val; \
158 long __pu_addr; \
159 __pu_val = (x); \
160 __pu_addr = (long) (ptr); \
161 __asm__("":"=r" (__pu_err)); \
162 if (__access_ok(__pu_addr,size,__access_mask)) { \
163 switch (size) { \
164 case 1: __put_user_asm("sb"); break; \
165 case 2: __put_user_asm("sh"); break; \
166 case 4: __put_user_asm("sw"); break; \
167 case 8: __put_user_asm("sd"); break; \
168 default: __put_user_unknown(); break; \
169 } } __pu_err; })
170 
171 #define __put_user_asm(insn) \
172 ({ \
173 __asm__ __volatile__( \
174         "1:\t" insn "\t%1,%2\n\t" \
175         "move\t%0,$0\n" \
176         "2:\n\t" \
177         ".section\t.fixup,\"ax\"\n" \
178         "3:\tli\t%0,%3\n\t" \
179         "j\t2b\n\t" \
180         ".previous\n\t" \
181         ".section\t__ex_table,\"a\"\n\t" \
182         ".dword\t1b,3b\n\t" \
183         ".previous" \
184         :"=r" (__pu_err) \
185         :"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT)); })
186 
187 extern void __put_user_unknown(void);
188 
189 /*
190  * We're generating jump to subroutines which will be outside the range of
191  * jump instructions
192  */
193 #ifdef MODULE
194 #define __MODULE_JAL(destination) \
195         ".set\tnoat\n\t" \
196         "la\t$1, " #destination "\n\t" \
197         "jalr\t$1\n\t" \
198         ".set\tat\n\t"
199 #else
200 #define __MODULE_JAL(destination) \
201         "jal\t" #destination "\n\t"
202 #endif
203 
204 extern size_t __copy_user(void *__to, const void *__from, size_t __n);
205 
206 #define __copy_to_user(to,from,n) ({ \
207         void *__cu_to; \
208         const void *__cu_from; \
209         long __cu_len; \
210         \
211         __cu_to = (to); \
212         __cu_from = (from); \
213         __cu_len = (n); \
214         __asm__ __volatile__( \
215                 "move\t$4, %1\n\t" \
216                 "move\t$5, %2\n\t" \
217                 "move\t$6, %3\n\t" \
218                 __MODULE_JAL(__copy_user) \
219                 "move\t%0, $6" \
220                 : "=r" (__cu_len) \
221                 : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
222                 : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \
223                   "$24", "$31","memory"); \
224         __cu_len; \
225 })
226 
227 #define __copy_from_user(to,from,n) ({ \
228         void *__cu_to; \
229         const void *__cu_from; \
230         long __cu_len; \
231         \
232         __cu_to = (to); \
233         __cu_from = (from); \
234         __cu_len = (n); \
235         __asm__ __volatile__( \
236                 "move\t$4, %1\n\t" \
237                 "move\t$5, %2\n\t" \
238                 "move\t$6, %3\n\t" \
239                 ".set\tnoreorder\n\t" \
240                 __MODULE_JAL(__copy_user) \
241                 ".set\tnoat\n\t" \
242                 "daddu\t$1, %2, %3\n\t" \
243                 ".set\tat\n\t" \
244                 ".set\treorder\n\t" \
245                 "move\t%0, $6" \
246                 : "=r" (__cu_len) \
247                 : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
248                 : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \
249                   "$24", "$31","memory"); \
250         __cu_len; \
251 })
252 
253 #define copy_to_user(to,from,n) ({ \
254         void *__cu_to; \
255         const void *__cu_from; \
256         long __cu_len; \
257         \
258         __cu_to = (to); \
259         __cu_from = (from); \
260         __cu_len = (n); \
261         if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) \
262                 __asm__ __volatile__( \
263                         "move\t$4, %1\n\t" \
264                         "move\t$5, %2\n\t" \
265                         "move\t$6, %3\n\t" \
266                         __MODULE_JAL(__copy_user) \
267                         "move\t%0, $6" \
268                         : "=r" (__cu_len) \
269                         : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
270                         : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \
271                           "$15", "$24", "$31","memory"); \
272         __cu_len; \
273 })
274 
275 #define copy_from_user(to,from,n) ({ \
276         void *__cu_to; \
277         const void *__cu_from; \
278         long __cu_len; \
279         \
280         __cu_to = (to); \
281         __cu_from = (from); \
282         __cu_len = (n); \
283         if (access_ok(VERIFY_READ, __cu_from, __cu_len)) \
284                 __asm__ __volatile__( \
285                         "move\t$4, %1\n\t" \
286                         "move\t$5, %2\n\t" \
287                         "move\t$6, %3\n\t" \
288                         ".set\tnoreorder\n\t" \
289                         __MODULE_JAL(__copy_user) \
290                         ".set\tnoat\n\t" \
291                         "daddu\t$1, %2, %3\n\t" \
292                         ".set\tat\n\t" \
293                         ".set\treorder\n\t" \
294                         "move\t%0, $6" \
295                         : "=r" (__cu_len) \
296                         : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
297                         : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \
298                           "$15", "$24", "$31","memory"); \
299         __cu_len; \
300 })
301 
302 extern inline __kernel_size_t
303 __clear_user(void *addr, __kernel_size_t size)
304 {
305         __kernel_size_t res;
306 
307         __asm__ __volatile__(
308                 "move\t$4, %1\n\t"
309                 "move\t$5, $0\n\t"
310                 "move\t$6, %2\n\t"
311                 __MODULE_JAL(__bzero)
312                 "move\t%0, $6"
313                 : "=r" (res)
314                 : "r" (addr), "r" (size)
315                 : "$4", "$5", "$6", "$8", "$9", "$31");
316 
317         return res;
318 }
319 
320 #define clear_user(addr,n) ({ \
321 void * __cl_addr = (addr); \
322 unsigned long __cl_size = (n); \
323 if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
324 __cl_size = __clear_user(__cl_addr, __cl_size); \
325 __cl_size; })
326 
327 /*
328  * Returns: -EFAULT if exception before terminator, N if the entire
329  * buffer filled, else strlen.
330  */
331 extern inline long
332 __strncpy_from_user(char *__to, const char *__from, long __len)
333 {
334         long res;
335 
336         __asm__ __volatile__(
337                 "move\t$4, %1\n\t"
338                 "move\t$5, %2\n\t"
339                 "move\t$6, %3\n\t"
340                 __MODULE_JAL(__strncpy_from_user_nocheck_asm)
341                 "move\t%0, $2"
342                 : "=r" (res)
343                 : "r" (__to), "r" (__from), "r" (__len)
344                 : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
345 
346         return res;
347 }
348 
349 extern inline long
350 strncpy_from_user(char *__to, const char *__from, long __len)
351 {
352         long res;
353 
354         __asm__ __volatile__(
355                 "move\t$4, %1\n\t"
356                 "move\t$5, %2\n\t"
357                 "move\t$6, %3\n\t"
358                 __MODULE_JAL(__strncpy_from_user_asm)
359                 "move\t%0, $2"
360                 : "=r" (res)
361                 : "r" (__to), "r" (__from), "r" (__len)
362                 : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
363 
364         return res;
365 }
366 
367 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
368 extern inline long __strlen_user(const char *s)
369 {
370         long res;
371 
372         __asm__ __volatile__(
373                 "move\t$4, %1\n\t"
374                 __MODULE_JAL(__strlen_user_nocheck_asm)
375                 "move\t%0, $2"
376                 : "=r" (res)
377                 : "r" (s)
378                 : "$2", "$4", "$8", "$31");
379 
380         return res;
381 }
382 
383 extern inline long strlen_user(const char *s)
384 {
385         long res;
386 
387         __asm__ __volatile__(
388                 "move\t$4, %1\n\t"
389                 __MODULE_JAL(__strlen_user_asm)
390                 "move\t%0, $2"
391                 : "=r" (res)
392                 : "r" (s)
393                 : "$2", "$4", "$8", "$31");
394 
395         return res;
396 }
397 
398 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
399 extern inline long __strnlen_user(const char *s, long n)
400 {
401         long res;
402 
403         __asm__ __volatile__(
404                 "move\t$4, %1\n\t"
405                 "move\t$5, %2\n\t"
406                 __MODULE_JAL(__strlen_user_nocheck_asm)
407                 "move\t%0, $2"
408                 : "=r" (res)
409                 : "r" (s), "r" (n)
410                 : "$2", "$4", "$5", "$8", "$31");
411 
412         return res;
413 }
414 
415 extern inline long strnlen_user(const char *s, long n)
416 {
417         long res;
418 
419         __asm__ __volatile__(
420                 "move\t$4, %1\n\t"
421                 "move\t$5, %2\n\t"
422                 __MODULE_JAL(__strlen_user_asm)
423                 "move\t%0, $2"
424                 : "=r" (res)
425                 : "r" (s), "r" (n)
426                 : "$2", "$4", "$5", "$8", "$31");
427 
428         return res;
429 }
430 
431 struct exception_table_entry
432 {
433         unsigned long insn;
434         unsigned long nextinsn;
435 };
436 
437 /* Returns 0 if exception not found and fixup.unit otherwise.  */
438 extern unsigned long search_exception_table(unsigned long addr);
439 
440 /* Returns the new pc */
441 #define fixup_exception(map_reg, fixup_unit, pc)                \
442 ({                                                              \
443         fixup_unit;                                             \
444 })
445 
446 #endif /* _ASM_UACCESS_H */
447 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.