debuggers.hg

view xen/include/asm-x86/x86_64/uaccess.h @ 3746:9e80fc0dcac5

bitkeeper revision 1.1159.212.121 (42081031Gcfd1G5fgexBl7vd4XfmLQ)

Use 1:1 pagetables used for guest physical mode emulation for doing
phys_to_machine_mapping as well.

Signed-off-by: Arun Sharma <arun.sharma@intel.com>
Signed-off-by: ian@xensource.com
author iap10@labyrinth.cl.cam.ac.uk
date Tue Feb 08 01:04:49 2005 +0000 (2005-02-08)
parents 7db5b671b347
children f504382b179f 9f7935ea4606
line source
1 #ifndef __X86_64_UACCESS_H
2 #define __X86_64_UACCESS_H
4 /*
5 * User space memory access functions
6 */
7 #include <xen/config.h>
8 #include <xen/compiler.h>
9 #include <xen/errno.h>
10 #include <xen/prefetch.h>
11 #include <asm/page.h>
13 #define __user
15 #define VERIFY_READ 0
16 #define VERIFY_WRITE 1
18 #define __addr_ok(addr) ((unsigned long)(addr) < HYPERVISOR_VIRT_START)
20 /*
21 * Test whether a block of memory is a valid user space address.
22 * Returns 0 if the range is valid, nonzero otherwise.
23 *
24 * This is equivalent to the following test:
25 * ((u65)addr >= (u65)HYPERVISOR_VIRT_END) ?
26 * (((u65)addr + (u65)size) >= ((u65)1 << 64)) :
27 * (((u65)addr + (u65)size) >= ((u65)HYPERVISOR_VIRT_START))
28 */
29 #define __range_not_ok(addr,size) ({ \
30 unsigned long flag,sum; \
31 if ((unsigned long)addr >= HYPERVISOR_VIRT_END) \
32 asm("addq %3,%1 ; sbbq %0,%0" \
33 :"=&r" (flag), "=r" (sum) \
34 :"1" (addr),"g" ((long)(size))); \
35 else \
36 asm("addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0" \
37 :"=&r" (flag), "=r" (sum) \
38 :"1" (addr),"g" ((long)(size)),"r" (HYPERVISOR_VIRT_START)); \
39 flag; })
41 #define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
43 #define array_access_ok(type,addr,count,size) \
44 (likely(sizeof(count) <= 4) /* disallow 64-bit counts */ && \
45 access_ok(type,addr,(unsigned long)count*(unsigned long)size))
47 extern long __get_user_bad(void);
48 extern void __put_user_bad(void);
50 /**
51 * get_user: - Get a simple variable from user space.
52 * @x: Variable to store result.
53 * @ptr: Source address, in user space.
54 *
55 * Context: User context only. This function may sleep.
56 *
57 * This macro copies a single simple variable from user space to kernel
58 * space. It supports simple types like char and int, but not larger
59 * data types like structures or arrays.
60 *
61 * @ptr must have pointer-to-simple-variable type, and the result of
62 * dereferencing @ptr must be assignable to @x without a cast.
63 *
64 * Returns zero on success, or -EFAULT on error.
65 * On error, the variable @x is set to zero.
66 */
67 #define get_user(x,ptr) \
68 __get_user_check((x),(ptr),sizeof(*(ptr)))
70 /**
71 * put_user: - Write a simple value into user space.
72 * @x: Value to copy to user space.
73 * @ptr: Destination address, in user space.
74 *
75 * Context: User context only. This function may sleep.
76 *
77 * This macro copies a single simple value from kernel space to user
78 * space. It supports simple types like char and int, but not larger
79 * data types like structures or arrays.
80 *
81 * @ptr must have pointer-to-simple-variable type, and @x must be assignable
82 * to the result of dereferencing @ptr.
83 *
84 * Returns zero on success, or -EFAULT on error.
85 */
86 #define put_user(x,ptr) \
87 __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
90 /**
91 * __get_user: - Get a simple variable from user space, with less checking.
92 * @x: Variable to store result.
93 * @ptr: Source address, in user space.
94 *
95 * Context: User context only. This function may sleep.
96 *
97 * This macro copies a single simple variable from user space to kernel
98 * space. It supports simple types like char and int, but not larger
99 * data types like structures or arrays.
100 *
101 * @ptr must have pointer-to-simple-variable type, and the result of
102 * dereferencing @ptr must be assignable to @x without a cast.
103 *
104 * Caller must check the pointer with access_ok() before calling this
105 * function.
106 *
107 * Returns zero on success, or -EFAULT on error.
108 * On error, the variable @x is set to zero.
109 */
110 #define __get_user(x,ptr) \
111 __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
114 /**
115 * __put_user: - Write a simple value into user space, with less checking.
116 * @x: Value to copy to user space.
117 * @ptr: Destination address, in user space.
118 *
119 * Context: User context only. This function may sleep.
120 *
121 * This macro copies a single simple value from kernel space to user
122 * space. It supports simple types like char and int, but not larger
123 * data types like structures or arrays.
124 *
125 * @ptr must have pointer-to-simple-variable type, and @x must be assignable
126 * to the result of dereferencing @ptr.
127 *
128 * Caller must check the pointer with access_ok() before calling this
129 * function.
130 *
131 * Returns zero on success, or -EFAULT on error.
132 */
133 #define __put_user(x,ptr) \
134 __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
136 #define __put_user_nocheck(x,ptr,size) \
137 ({ \
138 long __pu_err; \
139 __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \
140 __pu_err; \
141 })
143 #define __put_user_check(x,ptr,size) \
144 ({ \
145 long __pu_err = -EFAULT; \
146 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
147 if (__addr_ok(__pu_addr)) \
148 __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \
149 __pu_err; \
150 })
152 #define __put_user_size(x,ptr,size,retval,errret) \
153 do { \
154 retval = 0; \
155 switch (size) { \
156 case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break; \
157 case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \
158 case 4: __put_user_asm(x,ptr,retval,"l","k","ir",errret);break; \
159 case 8: __put_user_asm(x,ptr,retval,"q","","ir",errret);break; \
160 default: __put_user_bad(); \
161 } \
162 } while (0)
164 struct __large_struct { unsigned long buf[100]; };
165 #define __m(x) (*(struct __large_struct *)(x))
167 /*
168 * Tell gcc we read from memory instead of writing: this is because
169 * we do not write to any memory gcc knows about, so there are no
170 * aliasing issues.
171 */
172 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
173 __asm__ __volatile__( \
174 "1: mov"itype" %"rtype"1,%2\n" \
175 "2:\n" \
176 ".section .fixup,\"ax\"\n" \
177 "3: mov %3,%0\n" \
178 " jmp 2b\n" \
179 ".previous\n" \
180 ".section __ex_table,\"a\"\n" \
181 " .align 8\n" \
182 " .quad 1b,3b\n" \
183 ".previous" \
184 : "=r"(err) \
185 : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
187 #define __get_user_nocheck(x,ptr,size) \
188 ({ \
189 long __gu_err, __gu_val; \
190 __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\
191 (x) = (__typeof__(*(ptr)))__gu_val; \
192 __gu_err; \
193 })
195 #define __get_user_check(x,ptr,size) \
196 ({ \
197 long __gu_err, __gu_val; \
198 __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
199 __get_user_size(__gu_val,__gu_addr,(size),__gu_err,-EFAULT); \
200 (x) = (__typeof__(*(ptr)))__gu_val; \
201 if (!__addr_ok(__gu_addr)) __gu_err = -EFAULT; \
202 __gu_err; \
203 })
205 #define __get_user_size(x,ptr,size,retval,errret) \
206 do { \
207 retval = 0; \
208 switch (size) { \
209 case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break; \
210 case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break; \
211 case 4: __get_user_asm(x,ptr,retval,"l","k","=r",errret);break; \
212 case 8: __get_user_asm(x,ptr,retval,"q","","=r",errret); break; \
213 default: (x) = __get_user_bad(); \
214 } \
215 } while (0)
217 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
218 __asm__ __volatile__( \
219 "1: mov"itype" %2,%"rtype"1\n" \
220 "2:\n" \
221 ".section .fixup,\"ax\"\n" \
222 "3: mov %3,%0\n" \
223 " xor"itype" %"rtype"1,%"rtype"1\n" \
224 " jmp 2b\n" \
225 ".previous\n" \
226 ".section __ex_table,\"a\"\n" \
227 " .align 8\n" \
228 " .quad 1b,3b\n" \
229 ".previous" \
230 : "=r"(err), ltype (x) \
231 : "m"(__m(addr)), "i"(errret), "0"(err))
234 /*
235 * Copy To/From Userspace
236 */
238 /* Handles exceptions in both to and from, but doesn't do access_ok */
239 unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned n);
240 unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned n);
242 unsigned long copy_to_user(void __user *to, const void *from, unsigned len);
243 unsigned long copy_from_user(void *to, const void __user *from, unsigned len);
245 static always_inline int __copy_from_user(void *dst, const void __user *src, unsigned size)
246 {
247 int ret = 0;
248 if (!__builtin_constant_p(size))
249 return __copy_from_user_ll(dst,(void *)src,size);
250 switch (size) {
251 case 1:__get_user_asm(*(u8*)dst,(u8 __user *)src,ret,"b","b","=q",1);
252 return ret;
253 case 2:__get_user_asm(*(u16*)dst,(u16 __user *)src,ret,"w","w","=r",2);
254 return ret;
255 case 4:__get_user_asm(*(u32*)dst,(u32 __user *)src,ret,"l","k","=r",4);
256 return ret;
257 case 8:__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",8);
258 return ret;
259 case 10:
260 __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
261 if (unlikely(ret)) return ret;
262 __get_user_asm(*(u16*)(8+(char*)dst),(u16 __user *)(8+(char __user *)src),ret,"w","w","=r",2);
263 return ret;
264 case 16:
265 __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
266 if (unlikely(ret)) return ret;
267 __get_user_asm(*(u64*)(8+(char*)dst),(u64 __user *)(8+(char __user *)src),ret,"q","","=r",8);
268 return ret;
269 default:
270 return __copy_from_user_ll(dst,(void *)src,size);
271 }
272 }
274 static always_inline int __copy_to_user(void __user *dst, const void *src, unsigned size)
275 {
276 int ret = 0;
277 if (!__builtin_constant_p(size))
278 return __copy_to_user_ll((void *)dst,src,size);
279 switch (size) {
280 case 1:__put_user_asm(*(u8*)src,(u8 __user *)dst,ret,"b","b","iq",1);
281 return ret;
282 case 2:__put_user_asm(*(u16*)src,(u16 __user *)dst,ret,"w","w","ir",2);
283 return ret;
284 case 4:__put_user_asm(*(u32*)src,(u32 __user *)dst,ret,"l","k","ir",4);
285 return ret;
286 case 8:__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",8);
287 return ret;
288 case 10:
289 __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",10);
290 if (unlikely(ret)) return ret;
291 asm("":::"memory");
292 __put_user_asm(4[(u16*)src],4+(u16 __user *)dst,ret,"w","w","ir",2);
293 return ret;
294 case 16:
295 __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",16);
296 if (unlikely(ret)) return ret;
297 asm("":::"memory");
298 __put_user_asm(1[(u64*)src],1+(u64 __user *)dst,ret,"q","","ir",8);
299 return ret;
300 default:
301 return __copy_to_user_ll((void *)dst,src,size);
302 }
303 }
305 unsigned long clear_user(void __user *mem, unsigned long len);
306 unsigned long __clear_user(void __user *mem, unsigned long len);
308 #endif /* __X86_64_UACCESS_H */