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

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

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

  1 #ifndef _ASM_IA64_UACCESS_H
  2 #define _ASM_IA64_UACCESS_H
  3 
  4 /*
  5  * This file defines various macros to transfer memory areas across
  6  * the user/kernel boundary.  This needs to be done carefully because
  7  * this code is executed in kernel mode and uses user-specified
  8  * addresses.  Thus, we need to be careful not to let the user to
  9  * trick us into accessing kernel memory that would normally be
 10  * inaccessible.  This code is also fairly performance sensitive,
 11  * so we want to spend as little time doing saftey checks as
 12  * possible.
 13  *
 14  * To make matters a bit more interesting, these macros sometimes also
 15  * called from within the kernel itself, in which case the address
 16  * validity check must be skipped.  The get_fs() macro tells us what
 17  * to do: if get_fs()==USER_DS, checking is performed, if
 18  * get_fs()==KERNEL_DS, checking is bypassed.
 19  *
 20  * Note that even if the memory area specified by the user is in a
 21  * valid address range, it is still possible that we'll get a page
 22  * fault while accessing it.  This is handled by filling out an
 23  * exception handler fixup entry for each instruction that has the
 24  * potential to fault.  When such a fault occurs, the page fault
 25  * handler checks to see whether the faulting instruction has a fixup
 26  * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
 27  * then resumes execution at the continuation point.
 28  * 
 29  * Copyright (C) 1998, 1999 Hewlett-Packard Co
 30  * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
 31  */
 32 
 33 #include <linux/errno.h>
 34 #include <linux/sched.h>
 35 
 36 /*
 37  * For historical reasons, the following macros are grossly misnamed:
 38  */
 39 #define KERNEL_DS       ((mm_segment_t) { ~0UL })               /* cf. access_ok() */
 40 #define USER_DS         ((mm_segment_t) { TASK_SIZE-1 })        /* cf. access_ok() */
 41 
 42 #define VERIFY_READ     0
 43 #define VERIFY_WRITE    1
 44 
 45 #define get_ds()  (KERNEL_DS)
 46 #define get_fs()  (current->addr_limit)
 47 #define set_fs(x) (current->addr_limit = (x))
 48 
 49 #define segment_eq(a,b) ((a).seg == (b).seg)
 50 
 51 /*
 52  * When accessing user memory, we need to make sure the entire area
 53  * really is in user-level space.  In order to do this efficiently, we
 54  * make sure that the page at address TASK_SIZE is never valid (we do
 55  * this by selecting VMALLOC_START as TASK_SIZE+PAGE_SIZE).  This way,
 56  * we can simply check whether the starting address is < TASK_SIZE
 57  * and, if so, start accessing the memory.  If the user specified bad
 58  * length, we will fault on the NaT page and then return the
 59  * appropriate error.
 60  */
 61 #define __access_ok(addr,size,segment)  (((unsigned long) (addr)) <= (segment).seg)
 62 #define access_ok(type,addr,size)       __access_ok((addr),(size),get_fs())
 63 
 64 static inline int
 65 verify_area (int type, const void *addr, unsigned long size)
 66 {
 67         return access_ok(type,addr,size) ? 0 : -EFAULT;
 68 }
 69 
 70 /*
 71  * These are the main single-value transfer routines.  They automatically
 72  * use the right size if we just have the right pointer type.
 73  *
 74  * Careful to not
 75  * (a) re-use the arguments for side effects (sizeof/typeof is ok)
 76  * (b) require any knowledge of processes at this stage
 77  */
 78 #define put_user(x,ptr) __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)),get_fs())
 79 #define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),get_fs())
 80 
 81 /*
 82  * The "__xxx" versions do not do address space checking, useful when
 83  * doing multiple accesses to the same area (the programmer has to do the
 84  * checks by hand with "access_ok()")
 85  */
 86 #define __put_user(x,ptr)       __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 87 #define __get_user(x,ptr)       __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
 88   
 89 extern void __get_user_unknown (void);
 90 
 91 #define __get_user_nocheck(x,ptr,size)                          \
 92 ({                                                              \
 93         register long __gu_err __asm__ ("r8") = 0;              \
 94         register long __gu_val __asm__ ("r9") = 0;              \
 95         switch (size) {                                         \
 96           case 1: __get_user_8(ptr); break;                     \
 97           case 2: __get_user_16(ptr); break;                    \
 98           case 4: __get_user_32(ptr); break;                    \
 99           case 8: __get_user_64(ptr); break;                    \
100           default: __get_user_unknown(); break;                 \
101         }                                                       \
102         (x) = (__typeof__(*(ptr))) __gu_val;                    \
103         __gu_err;                                               \
104 })
105 
106 #define __get_user_check(x,ptr,size,segment)                    \
107 ({                                                              \
108         register long __gu_err __asm__ ("r8") = -EFAULT;        \
109         register long __gu_val __asm__ ("r9") = 0;              \
110         const __typeof__(*(ptr)) *__gu_addr = (ptr);            \
111         if (__access_ok((long)__gu_addr,size,segment)) {        \
112                 __gu_err = 0;                                   \
113                 switch (size) {                                 \
114                   case 1: __get_user_8(__gu_addr); break;       \
115                   case 2: __get_user_16(__gu_addr); break;      \
116                   case 4: __get_user_32(__gu_addr); break;      \
117                   case 8: __get_user_64(__gu_addr); break;      \
118                   default: __get_user_unknown(); break;         \
119                 }                                               \
120         }                                                       \
121         (x) = (__typeof__(*(ptr))) __gu_val;                    \
122         __gu_err;                                               \
123 })
124 
125 struct __large_struct { unsigned long buf[100]; };
126 #define __m(x) (*(struct __large_struct *)(x))
127 
128 /* We need to declare the __ex_table section before we can use it in .xdata.  */
129 __asm__ (".section \"__ex_table\", \"a\"\n\t.previous");
130 
131 #define __get_user_64(addr)                                                                     \
132         __asm__ ("\n1:\tld8 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"      \
133                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n"                        \
134                 : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
135 
136 #define __get_user_32(addr)                                                                     \
137         __asm__ ("\n1:\tld4 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"      \
138                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n"                        \
139                 : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
140 
141 #define __get_user_16(addr)                                                                     \
142         __asm__ ("\n1:\tld2 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"      \
143                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n"                        \
144                 : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
145 
146 #define __get_user_8(addr)                                                                      \
147         __asm__ ("\n1:\tld1 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"      \
148                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n"                        \
149                 : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
150 
151 extern void __put_user_unknown (void);
152 
153 #define __put_user_nocheck(x,ptr,size)                          \
154 ({                                                              \
155         register long __pu_err __asm__ ("r8") = 0;              \
156         switch (size) {                                         \
157           case 1: __put_user_8(x,ptr); break;                   \
158           case 2: __put_user_16(x,ptr); break;                  \
159           case 4: __put_user_32(x,ptr); break;                  \
160           case 8: __put_user_64(x,ptr); break;                  \
161           default: __put_user_unknown(); break;                 \
162         }                                                       \
163         __pu_err;                                               \
164 })
165 
166 #define __put_user_check(x,ptr,size,segment)                    \
167 ({                                                              \
168         register long __pu_err __asm__ ("r8") = -EFAULT;        \
169         __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
170         if (__access_ok((long)__pu_addr,size,segment)) {        \
171                 __pu_err = 0;                                   \
172                 switch (size) {                                 \
173                   case 1: __put_user_8(x,__pu_addr); break;     \
174                   case 2: __put_user_16(x,__pu_addr); break;    \
175                   case 4: __put_user_32(x,__pu_addr); break;    \
176                   case 8: __put_user_64(x,__pu_addr); break;    \
177                   default: __put_user_unknown(); break;         \
178                 }                                               \
179         }                                                       \
180         __pu_err;                                               \
181 })
182 
183 /*
184  * The "__put_user_xx()" macros tell gcc they read from memory
185  * instead of writing: this is because they do not write to
186  * any memory gcc knows about, so there are no aliasing issues
187  */
188 #define __put_user_64(x,addr)                                                           \
189         __asm__ __volatile__ (                                                          \
190                  "\n1:\tst8 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"   \
191                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n"                  \
192                 : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), ""(__pu_err))
193 
194 #define __put_user_32(x,addr)                                                           \
195         __asm__ __volatile__ (                                                          \
196                  "\n1:\tst4 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"   \
197                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n"                  \
198                 : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), ""(__pu_err))
199 
200 #define __put_user_16(x,addr)                                                           \
201         __asm__ __volatile__ (                                                          \
202                  "\n1:\tst2 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"   \
203                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n"                  \
204                 : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), ""(__pu_err))
205 
206 #define __put_user_8(x,addr)                                                            \
207         __asm__ __volatile__ (                                                          \
208                  "\n1:\tst1 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"   \
209                  "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n"                  \
210                 : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), ""(__pu_err))
211 
212 /*
213  * Complex access routines
214  */
215 extern unsigned long __copy_user (void *to, const void *from, unsigned long count);
216 
217 #define __copy_to_user(to,from,n)       __copy_user((to), (from), (n))
218 #define __copy_from_user(to,from,n)     __copy_user((to), (from), (n))
219 
220 #define copy_to_user(to,from,n)   __copy_tofrom_user((to), (from), (n), 1)
221 #define copy_from_user(to,from,n) __copy_tofrom_user((to), (from), (n), 0)
222 
223 #define __copy_tofrom_user(to,from,n,check_to)                                                  \
224 ({                                                                                              \
225         void *__cu_to = (to);                                                                   \
226         const void *__cu_from = (from);                                                         \
227         long __cu_len = (n);                                                                    \
228                                                                                                 \
229         if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs())) {       \
230                 __cu_len = __copy_user(__cu_to, __cu_from, __cu_len);                           \
231         }                                                                                       \
232         __cu_len;                                                                               \
233 })
234 
235 extern unsigned long __do_clear_user (void *, unsigned long);
236 
237 #define __clear_user(to,n)                      \
238 ({                                              \
239         __do_clear_user(to,n);                  \
240 })
241 
242 #define clear_user(to,n)                                        \
243 ({                                                              \
244         unsigned long __cu_len = (n);                           \
245         if (__access_ok((long) to, __cu_len, get_fs())) {       \
246                 __cu_len = __do_clear_user(to, __cu_len);       \
247         }                                                       \
248         __cu_len;                                               \
249 })
250 
251 
252 /* Returns: -EFAULT if exception before terminator, N if the entire
253    buffer filled, else strlen.  */
254 
255 extern long __strncpy_from_user (char *to, const char *from, long to_len);
256 
257 #define strncpy_from_user(to,from,n)                                    \
258 ({                                                                      \
259         const char * __sfu_from = (from);                               \
260         long __sfu_ret = -EFAULT;                                       \
261         if (__access_ok((long) __sfu_from, 0, get_fs()))                \
262                 __sfu_ret = __strncpy_from_user((to), __sfu_from, (n)); \
263         __sfu_ret;                                                      \
264 })
265 
266 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
267 extern unsigned long __strlen_user (const char *);
268 
269 #define strlen_user(str)                                \
270 ({                                                      \
271         const char *__su_str = (str);                   \
272         unsigned long __su_ret = 0;                     \
273         if (__access_ok((long) __su_str, 0, get_fs()))  \
274                 __su_ret = __strlen_user(__su_str);     \
275         __su_ret;                                       \
276 })
277 
278 /*
279  * Returns: 0 if exception before NUL or reaching the supplied limit
280  * (N), a value greater than N if the limit would be exceeded, else
281  * strlen.
282  */
283 extern unsigned long __strnlen_user (const char *, long);
284 
285 #define strnlen_user(str, len)                                  \
286 ({                                                              \
287         const char *__su_str = (str);                           \
288         unsigned long __su_ret = 0;                             \
289         if (__access_ok((long) __su_str, 0, get_fs()))          \
290                 __su_ret = __strnlen_user(__su_str, len);       \
291         __su_ret;                                               \
292 })
293 
294 struct exception_table_entry {
295         int addr;       /* gp-relative address of insn this fixup is for */
296         int skip;       /* number of bytes to skip to get to the continuation point.
297                            Bit 0 tells us if r9 should be cleared to 0*/
298 };
299 
300 extern const struct exception_table_entry *search_exception_table (unsigned long addr);
301 
302 #endif /* _ASM_IA64_UACCESS_H */
303 

~ [ 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.