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

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

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

  1 /* $Id: uaccess.h,v 1.33 2000/08/29 07:01:58 davem Exp $ */
  2 #ifndef _ASM_UACCESS_H
  3 #define _ASM_UACCESS_H
  4 
  5 /*
  6  * User space memory access functions
  7  */
  8 
  9 #ifdef __KERNEL__
 10 #include <linux/sched.h>
 11 #include <linux/string.h>
 12 #include <asm/a.out.h>
 13 #include <asm/asi.h>
 14 #include <asm/system.h>
 15 #include <asm/spitfire.h>
 16 #endif
 17 
 18 #ifndef __ASSEMBLY__
 19 
 20 /*
 21  * Sparc64 is segmented, though more like the M68K than the I386. 
 22  * We use the secondary ASI to address user memory, which references a
 23  * completely different VM map, thus there is zero chance of the user
 24  * doing something queer and tricking us into poking kernel memory.
 25  *
 26  * What is left here is basically what is needed for the other parts of
 27  * the kernel that expect to be able to manipulate, erum, "segments".
 28  * Or perhaps more properly, permissions.
 29  *
 30  * "For historical reasons, these macros are grossly misnamed." -Linus
 31  */
 32 
 33 #define KERNEL_DS   ((mm_segment_t) { ASI_P })
 34 #define USER_DS     ((mm_segment_t) { ASI_AIUS })       /* har har har */
 35 
 36 #define VERIFY_READ     0
 37 #define VERIFY_WRITE    1
 38 
 39 #define get_fs() (current->thread.current_ds)
 40 #define get_ds() (KERNEL_DS)
 41 
 42 #define segment_eq(a,b)  ((a).seg == (b).seg)
 43 
 44 #define set_fs(val)                                                             \
 45 do {                                                                            \
 46         current->thread.current_ds = (val);                                     \
 47         __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));        \
 48 } while(0)
 49 
 50 #define __user_ok(addr,size) 1
 51 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
 52 #define __access_ok(addr,size) 1
 53 #define access_ok(type,addr,size) 1
 54 
 55 extern inline int verify_area(int type, const void * addr, unsigned long size)
 56 {
 57         return 0;
 58 }
 59 
 60 /*
 61  * The exception table consists of pairs of addresses: the first is the
 62  * address of an instruction that is allowed to fault, and the second is
 63  * the address at which the program should continue.  No registers are
 64  * modified, so it is entirely up to the continuation code to figure out
 65  * what to do.
 66  *
 67  * All the routines below use bits of fixup code that are out of line
 68  * with the main instruction path.  This means when everything is well,
 69  * we don't even have to jump over them.  Further, they do not intrude
 70  * on our cache or tlb entries.
 71  *
 72  * There is a special way how to put a range of potentially faulting
 73  * insns (like twenty ldd/std's with now intervening other instructions)
 74  * You specify address of first in insn and 0 in fixup and in the next
 75  * exception_table_entry you specify last potentially faulting insn + 1
 76  * and in fixup the routine which should handle the fault.
 77  * That fixup code will get
 78  * (faulting_insn_address - first_insn_in_the_range_address)/4
 79  * in %g2 (ie. index of the faulting instruction in the range).
 80  */
 81 
 82 struct exception_table_entry
 83 {
 84         unsigned insn, fixup;
 85 };
 86 
 87 /* Returns 0 if exception not found and fixup otherwise.  */
 88 extern unsigned long search_exception_table(unsigned long, unsigned long *);
 89 
 90 extern void __ret_efault(void);
 91 
 92 /* Uh, these should become the main single-value transfer routines..
 93  * They automatically use the right size if we just have the right
 94  * pointer type..
 95  *
 96  * This gets kind of ugly. We want to return _two_ values in "get_user()"
 97  * and yet we don't want to do any pointers, because that is too much
 98  * of a performance impact. Thus we have a few rather ugly macros here,
 99  * and hide all the uglyness from the user.
100  */
101 #define put_user(x,ptr) ({ \
102 unsigned long __pu_addr = (unsigned long)(ptr); \
103 __put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
104 
105 #define get_user(x,ptr) ({ \
106 unsigned long __gu_addr = (unsigned long)(ptr); \
107 __get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
108 
109 #define __put_user(x,ptr) put_user(x,ptr)
110 #define __get_user(x,ptr) get_user(x,ptr)
111 
112 struct __large_struct { unsigned long buf[100]; };
113 #define __m(x) ((struct __large_struct *)(x))
114 
115 #define __put_user_nocheck(data,addr,size) ({ \
116 register int __pu_ret; \
117 switch (size) { \
118 case 1: __put_user_asm(data,b,addr,__pu_ret); break; \
119 case 2: __put_user_asm(data,h,addr,__pu_ret); break; \
120 case 4: __put_user_asm(data,w,addr,__pu_ret); break; \
121 case 8: __put_user_asm(data,x,addr,__pu_ret); break; \
122 default: __pu_ret = __put_user_bad(); break; \
123 } __pu_ret; })
124 
125 #define __put_user_nocheck_ret(data,addr,size,retval) ({ \
126 register int __foo __asm__ ("l1"); \
127 switch (size) { \
128 case 1: __put_user_asm_ret(data,b,addr,retval,__foo); break; \
129 case 2: __put_user_asm_ret(data,h,addr,retval,__foo); break; \
130 case 4: __put_user_asm_ret(data,w,addr,retval,__foo); break; \
131 case 8: __put_user_asm_ret(data,x,addr,retval,__foo); break; \
132 default: if (__put_user_bad()) return retval; break; \
133 } })
134 
135 #define __put_user_asm(x,size,addr,ret)                                 \
136 __asm__ __volatile__(                                                   \
137         "/* Put user asm, inline. */\n"                                 \
138 "1:\t"  "st"#size "a %1, [%2] %%asi\n\t"                                \
139         "clr    %0\n"                                                   \
140 "2:\n\n\t"                                                              \
141         ".section .fixup,#alloc,#execinstr\n\t"                         \
142         ".align 4\n"                                                    \
143 "3:\n\t"                                                                \
144         "b      2b\n\t"                                                 \
145         " mov   %3, %0\n\n\t"                                           \
146         ".previous\n\t"                                                 \
147         ".section __ex_table,#alloc\n\t"                                \
148         ".align 4\n\t"                                                  \
149         ".word  1b, 3b\n\t"                                             \
150         ".previous\n\n\t"                                               \
151        : "=r" (ret) : "r" (x), "r" (__m(addr)),                         \
152          "i" (-EFAULT))
153 
154 #define __put_user_asm_ret(x,size,addr,ret,foo)                         \
155 if (__builtin_constant_p(ret) && ret == -EFAULT)                        \
156 __asm__ __volatile__(                                                   \
157         "/* Put user asm ret, inline. */\n"                             \
158 "1:\t"  "st"#size "a %1, [%2] %%asi\n\n\t"                              \
159         ".section __ex_table,#alloc\n\t"                                \
160         ".align 4\n\t"                                                  \
161         ".word  1b, __ret_efault\n\n\t"                                 \
162         ".previous\n\n\t"                                               \
163        : "=r" (foo) : "r" (x), "r" (__m(addr)));                        \
164 else                                                                    \
165 __asm__ __volatile(                                                     \
166         "/* Put user asm ret, inline. */\n"                             \
167 "1:\t"  "st"#size "a %1, [%2] %%asi\n\n\t"                              \
168         ".section .fixup,#alloc,#execinstr\n\t"                         \
169         ".align 4\n"                                                    \
170 "3:\n\t"                                                                \
171         "ret\n\t"                                                       \
172         " restore %%g0, %3, %%o0\n\n\t"                                 \
173         ".previous\n\t"                                                 \
174         ".section __ex_table,#alloc\n\t"                                \
175         ".align 4\n\t"                                                  \
176         ".word  1b, 3b\n\n\t"                                           \
177         ".previous\n\n\t"                                               \
178        : "=r" (foo) : "r" (x), "r" (__m(addr)),                         \
179          "i" (ret))
180 
181 extern int __put_user_bad(void);
182 
183 #define __get_user_nocheck(data,addr,size,type) ({ \
184 register int __gu_ret; \
185 register unsigned long __gu_val; \
186 switch (size) { \
187 case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
188 case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
189 case 4: __get_user_asm(__gu_val,uw,addr,__gu_ret); break; \
190 case 8: __get_user_asm(__gu_val,x,addr,__gu_ret); break; \
191 default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
192 } data = (type) __gu_val; __gu_ret; })
193 
194 #define __get_user_nocheck_ret(data,addr,size,type,retval) ({ \
195 register unsigned long __gu_val __asm__ ("l1"); \
196 switch (size) { \
197 case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
198 case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
199 case 4: __get_user_asm_ret(__gu_val,uw,addr,retval); break; \
200 case 8: __get_user_asm_ret(__gu_val,x,addr,retval); break; \
201 default: if (__get_user_bad()) return retval; \
202 } data = (type) __gu_val; })
203 
204 #define __get_user_asm(x,size,addr,ret)                                 \
205 __asm__ __volatile__(                                                   \
206         "/* Get user asm, inline. */\n"                                 \
207 "1:\t"  "ld"#size "a [%2] %%asi, %1\n\t"                                \
208         "clr    %0\n"                                                   \
209 "2:\n\n\t"                                                              \
210         ".section .fixup,#alloc,#execinstr\n\t"                         \
211         ".align 4\n"                                                    \
212 "3:\n\t"                                                                \
213         "clr    %1\n\t"                                                 \
214         "b      2b\n\t"                                                 \
215         " mov   %3, %0\n\n\t"                                           \
216         ".previous\n\t"                                                 \
217         ".section __ex_table,#alloc\n\t"                                \
218         ".align 4\n\t"                                                  \
219         ".word  1b, 3b\n\n\t"                                           \
220         ".previous\n\t"                                                 \
221        : "=r" (ret), "=r" (x) : "r" (__m(addr)),                        \
222          "i" (-EFAULT))
223 
224 #define __get_user_asm_ret(x,size,addr,retval)                          \
225 if (__builtin_constant_p(retval) && retval == -EFAULT)                  \
226 __asm__ __volatile__(                                                   \
227         "/* Get user asm ret, inline. */\n"                             \
228 "1:\t"  "ld"#size "a [%1] %%asi, %0\n\n\t"                              \
229         ".section __ex_table,#alloc\n\t"                                \
230         ".align 4\n\t"                                                  \
231         ".word  1b,__ret_efault\n\n\t"                                  \
232         ".previous\n\t"                                                 \
233        : "=r" (x) : "r" (__m(addr)));                                   \
234 else                                                                    \
235 __asm__ __volatile__(                                                   \
236         "/* Get user asm ret, inline. */\n"                             \
237 "1:\t"  "ld"#size "a [%1] %%asi, %0\n\n\t"                              \
238         ".section .fixup,#alloc,#execinstr\n\t"                         \
239         ".align 4\n"                                                    \
240 "3:\n\t"                                                                \
241         "ret\n\t"                                                       \
242         " restore %%g0, %2, %%o0\n\n\t"                                 \
243         ".previous\n\t"                                                 \
244         ".section __ex_table,#alloc\n\t"                                \
245         ".align 4\n\t"                                                  \
246         ".word  1b, 3b\n\n\t"                                           \
247         ".previous\n\t"                                                 \
248        : "=r" (x) : "r" (__m(addr)), "i" (retval))
249 
250 extern int __get_user_bad(void);
251 
252 extern __kernel_size_t __memcpy_short(void *to, const void *from,
253                                       __kernel_size_t size,
254                                       long asi_src, long asi_dst);
255 
256 extern __kernel_size_t __memcpy_entry(void *to, const void *from,
257                                       __kernel_size_t size,
258                                       long asi_src, long asi_dst);
259 
260 extern __kernel_size_t __memcpy_16plus(void *to, const void *from,
261                                        __kernel_size_t size,
262                                        long asi_src, long asi_dst);
263 
264 extern __kernel_size_t __memcpy_386plus(void *to, const void *from,
265                                         __kernel_size_t size,
266                                         long asi_src, long asi_dst);
267 
268 extern __kernel_size_t __copy_from_user(void *to, const void *from,
269                                         __kernel_size_t size);
270 
271 extern __kernel_size_t __copy_to_user(void *to, const void *from,
272                                       __kernel_size_t size);
273 
274 extern __kernel_size_t __copy_in_user(void *to, const void *from,
275                                       __kernel_size_t size);
276 
277 #define copy_from_user(to,from,n)               \
278         __copy_from_user((void *)(to),  \
279                     (void *)(from), (__kernel_size_t)(n))
280 
281 #define copy_to_user(to,from,n) \
282         __copy_to_user((void *)(to), \
283         (void *) (from), (__kernel_size_t)(n))
284 
285 #define copy_in_user(to,from,n) \
286         __copy_in_user((void *)(to), \
287         (void *) (from), (__kernel_size_t)(n))
288 
289 extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
290 {
291         extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size);
292         
293         return __bzero_noasi(addr, size);
294 }
295 
296 #define clear_user(addr,n) \
297         __clear_user((void *)(addr), (__kernel_size_t)(n))
298 
299 extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count);
300 
301 #define strncpy_from_user(dest,src,count) \
302         __strncpy_from_user((unsigned long)(dest), (unsigned long)(src), (int)(count))
303 
304 extern int __strlen_user(const char *);
305 extern int __strnlen_user(const char *, long len);
306 
307 #define strlen_user __strlen_user
308 #define strnlen_user __strnlen_user
309 
310 #endif  /* __ASSEMBLY__ */
311 
312 #endif /* _ASM_UACCESS_H */
313 

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