diff options
author | Glauber Costa <gcosta@redhat.com> | 2008-06-25 12:17:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-09 03:14:26 -0400 |
commit | e30a44fdbf11c7ca3a0096d71790f176a4a09e03 (patch) | |
tree | 21d173ba08e47cb539c965dfb5119ff9f3b28d04 /include | |
parent | ec840956d269e2beefe3a1c0fd7c1c70a199087f (diff) |
x86: merge put_user.
Move both versions, which are highly similar, to uaccess.h.
Note that, for x86_64, X86_WP_WORKS_OK is always defined.
Signed-off-by: Glauber Costa <gcosta@redhat.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-x86/uaccess.h | 74 | ||||
-rw-r--r-- | include/asm-x86/uaccess_32.h | 79 | ||||
-rw-r--r-- | include/asm-x86/uaccess_64.h | 36 |
3 files changed, 74 insertions, 115 deletions
diff --git a/include/asm-x86/uaccess.h b/include/asm-x86/uaccess.h index 4353b2267a02..3a9092af5af0 100644 --- a/include/asm-x86/uaccess.h +++ b/include/asm-x86/uaccess.h | |||
@@ -178,6 +178,12 @@ extern int __get_user_bad(void); | |||
178 | __ret_gu; \ | 178 | __ret_gu; \ |
179 | }) | 179 | }) |
180 | 180 | ||
181 | #define __put_user_x(size, x, ptr, __ret_pu) \ | ||
182 | asm volatile("call __put_user_" #size : "=a" (__ret_pu) \ | ||
183 | :"0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") | ||
184 | |||
185 | |||
186 | |||
181 | #ifdef CONFIG_X86_32 | 187 | #ifdef CONFIG_X86_32 |
182 | #define __put_user_u64(x, addr, err) \ | 188 | #define __put_user_u64(x, addr, err) \ |
183 | asm volatile("1: movl %%eax,0(%2)\n" \ | 189 | asm volatile("1: movl %%eax,0(%2)\n" \ |
@@ -191,13 +197,71 @@ extern int __get_user_bad(void); | |||
191 | _ASM_EXTABLE(2b, 4b) \ | 197 | _ASM_EXTABLE(2b, 4b) \ |
192 | : "=r" (err) \ | 198 | : "=r" (err) \ |
193 | : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err)) | 199 | : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err)) |
200 | |||
201 | #define __put_user_x8(x, ptr, __ret_pu) \ | ||
202 | asm volatile("call __put_user_8" : "=a" (__ret_pu) \ | ||
203 | : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") | ||
194 | #else | 204 | #else |
195 | #define __put_user_u64(x, ptr, retval) \ | 205 | #define __put_user_u64(x, ptr, retval) \ |
196 | __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT) | 206 | __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT) |
207 | #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) | ||
197 | #endif | 208 | #endif |
198 | 209 | ||
210 | extern void __put_user_bad(void); | ||
211 | |||
212 | /* | ||
213 | * Strange magic calling convention: pointer in %ecx, | ||
214 | * value in %eax(:%edx), return value in %eax. clobbers %rbx | ||
215 | */ | ||
216 | extern void __put_user_1(void); | ||
217 | extern void __put_user_2(void); | ||
218 | extern void __put_user_4(void); | ||
219 | extern void __put_user_8(void); | ||
220 | |||
199 | #ifdef CONFIG_X86_WP_WORKS_OK | 221 | #ifdef CONFIG_X86_WP_WORKS_OK |
200 | 222 | ||
223 | /** | ||
224 | * put_user: - Write a simple value into user space. | ||
225 | * @x: Value to copy to user space. | ||
226 | * @ptr: Destination address, in user space. | ||
227 | * | ||
228 | * Context: User context only. This function may sleep. | ||
229 | * | ||
230 | * This macro copies a single simple value from kernel space to user | ||
231 | * space. It supports simple types like char and int, but not larger | ||
232 | * data types like structures or arrays. | ||
233 | * | ||
234 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
235 | * to the result of dereferencing @ptr. | ||
236 | * | ||
237 | * Returns zero on success, or -EFAULT on error. | ||
238 | */ | ||
239 | #define put_user(x, ptr) \ | ||
240 | ({ \ | ||
241 | int __ret_pu; \ | ||
242 | __typeof__(*(ptr)) __pu_val; \ | ||
243 | __chk_user_ptr(ptr); \ | ||
244 | __pu_val = x; \ | ||
245 | switch (sizeof(*(ptr))) { \ | ||
246 | case 1: \ | ||
247 | __put_user_x(1, __pu_val, ptr, __ret_pu); \ | ||
248 | break; \ | ||
249 | case 2: \ | ||
250 | __put_user_x(2, __pu_val, ptr, __ret_pu); \ | ||
251 | break; \ | ||
252 | case 4: \ | ||
253 | __put_user_x(4, __pu_val, ptr, __ret_pu); \ | ||
254 | break; \ | ||
255 | case 8: \ | ||
256 | __put_user_x8(__pu_val, ptr, __ret_pu); \ | ||
257 | break; \ | ||
258 | default: \ | ||
259 | __put_user_x(X, __pu_val, ptr, __ret_pu); \ | ||
260 | break; \ | ||
261 | } \ | ||
262 | __ret_pu; \ | ||
263 | }) | ||
264 | |||
201 | #define __put_user_size(x, ptr, size, retval, errret) \ | 265 | #define __put_user_size(x, ptr, size, retval, errret) \ |
202 | do { \ | 266 | do { \ |
203 | retval = 0; \ | 267 | retval = 0; \ |
@@ -231,6 +295,16 @@ do { \ | |||
231 | retval = errret; \ | 295 | retval = errret; \ |
232 | } while (0) | 296 | } while (0) |
233 | 297 | ||
298 | #define put_user(x, ptr) \ | ||
299 | ({ \ | ||
300 | int __ret_pu; \ | ||
301 | __typeof__(*(ptr))__pus_tmp = x; \ | ||
302 | __ret_pu = 0; \ | ||
303 | if (unlikely(__copy_to_user_ll(ptr, &__pus_tmp, \ | ||
304 | sizeof(*(ptr))) != 0)) \ | ||
305 | __ret_pu = -EFAULT; \ | ||
306 | __ret_pu; \ | ||
307 | }) | ||
234 | #endif | 308 | #endif |
235 | 309 | ||
236 | #ifdef CONFIG_X86_32 | 310 | #ifdef CONFIG_X86_32 |
diff --git a/include/asm-x86/uaccess_32.h b/include/asm-x86/uaccess_32.h index 2c9067324d2c..e5c0437f509b 100644 --- a/include/asm-x86/uaccess_32.h +++ b/include/asm-x86/uaccess_32.h | |||
@@ -20,85 +20,6 @@ extern struct movsl_mask { | |||
20 | } ____cacheline_aligned_in_smp movsl_mask; | 20 | } ____cacheline_aligned_in_smp movsl_mask; |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | extern void __put_user_bad(void); | ||
24 | |||
25 | /* | ||
26 | * Strange magic calling convention: pointer in %ecx, | ||
27 | * value in %eax(:%edx), return value in %eax, no clobbers. | ||
28 | */ | ||
29 | extern void __put_user_1(void); | ||
30 | extern void __put_user_2(void); | ||
31 | extern void __put_user_4(void); | ||
32 | extern void __put_user_8(void); | ||
33 | |||
34 | #define __put_user_x(size, x, ptr, __ret_pu) \ | ||
35 | asm volatile("call __put_user_" #size : "=a" (__ret_pu) \ | ||
36 | :"0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") | ||
37 | |||
38 | #define __put_user_8(x, ptr, __ret_pu) \ | ||
39 | asm volatile("call __put_user_8" : "=a" (__ret_pu) \ | ||
40 | : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") | ||
41 | |||
42 | |||
43 | /** | ||
44 | * put_user: - Write a simple value into user space. | ||
45 | * @x: Value to copy to user space. | ||
46 | * @ptr: Destination address, in user space. | ||
47 | * | ||
48 | * Context: User context only. This function may sleep. | ||
49 | * | ||
50 | * This macro copies a single simple value from kernel space to user | ||
51 | * space. It supports simple types like char and int, but not larger | ||
52 | * data types like structures or arrays. | ||
53 | * | ||
54 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
55 | * to the result of dereferencing @ptr. | ||
56 | * | ||
57 | * Returns zero on success, or -EFAULT on error. | ||
58 | */ | ||
59 | #ifdef CONFIG_X86_WP_WORKS_OK | ||
60 | |||
61 | #define put_user(x, ptr) \ | ||
62 | ({ \ | ||
63 | int __ret_pu; \ | ||
64 | __typeof__(*(ptr)) __pu_val; \ | ||
65 | __chk_user_ptr(ptr); \ | ||
66 | __pu_val = x; \ | ||
67 | switch (sizeof(*(ptr))) { \ | ||
68 | case 1: \ | ||
69 | __put_user_x(1, __pu_val, ptr, __ret_pu); \ | ||
70 | break; \ | ||
71 | case 2: \ | ||
72 | __put_user_x(2, __pu_val, ptr, __ret_pu); \ | ||
73 | break; \ | ||
74 | case 4: \ | ||
75 | __put_user_x(4, __pu_val, ptr, __ret_pu); \ | ||
76 | break; \ | ||
77 | case 8: \ | ||
78 | __put_user_8(__pu_val, ptr, __ret_pu); \ | ||
79 | break; \ | ||
80 | default: \ | ||
81 | __put_user_x(X, __pu_val, ptr, __ret_pu); \ | ||
82 | break; \ | ||
83 | } \ | ||
84 | __ret_pu; \ | ||
85 | }) | ||
86 | |||
87 | #else | ||
88 | #define put_user(x, ptr) \ | ||
89 | ({ \ | ||
90 | int __ret_pu; \ | ||
91 | __typeof__(*(ptr))__pus_tmp = x; \ | ||
92 | __ret_pu = 0; \ | ||
93 | if (unlikely(__copy_to_user_ll(ptr, &__pus_tmp, \ | ||
94 | sizeof(*(ptr))) != 0)) \ | ||
95 | __ret_pu = -EFAULT; \ | ||
96 | __ret_pu; \ | ||
97 | }) | ||
98 | |||
99 | |||
100 | #endif | ||
101 | |||
102 | /** | 23 | /** |
103 | * __get_user: - Get a simple variable from user space, with less checking. | 24 | * __get_user: - Get a simple variable from user space, with less checking. |
104 | * @x: Variable to store result. | 25 | * @x: Variable to store result. |
diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h index 9139854d37b0..2e75a5d1a17a 100644 --- a/include/asm-x86/uaccess_64.h +++ b/include/asm-x86/uaccess_64.h | |||
@@ -11,18 +11,6 @@ | |||
11 | 11 | ||
12 | #define ARCH_HAS_SEARCH_EXTABLE | 12 | #define ARCH_HAS_SEARCH_EXTABLE |
13 | 13 | ||
14 | extern void __put_user_1(void); | ||
15 | extern void __put_user_2(void); | ||
16 | extern void __put_user_4(void); | ||
17 | extern void __put_user_8(void); | ||
18 | extern void __put_user_bad(void); | ||
19 | |||
20 | #define __put_user_x(size, ret, x, ptr) \ | ||
21 | asm volatile("call __put_user_" #size \ | ||
22 | :"=a" (ret) \ | ||
23 | :"c" (ptr),"a" (x) \ | ||
24 | :"ebx") | ||
25 | |||
26 | #define __get_user(x, ptr) \ | 14 | #define __get_user(x, ptr) \ |
27 | __get_user_nocheck((x), (ptr), sizeof(*(ptr))) | 15 | __get_user_nocheck((x), (ptr), sizeof(*(ptr))) |
28 | #define __put_user(x, ptr) \ | 16 | #define __put_user(x, ptr) \ |
@@ -31,30 +19,6 @@ extern void __put_user_bad(void); | |||
31 | #define __get_user_unaligned __get_user | 19 | #define __get_user_unaligned __get_user |
32 | #define __put_user_unaligned __put_user | 20 | #define __put_user_unaligned __put_user |
33 | 21 | ||
34 | #define put_user(x, ptr) \ | ||
35 | ({ \ | ||
36 | int __pu_err; \ | ||
37 | typeof(*(ptr)) __user *__pu_addr = (ptr); \ | ||
38 | __chk_user_ptr(ptr); \ | ||
39 | switch (sizeof(*(ptr))) { \ | ||
40 | case 1: \ | ||
41 | __put_user_x(1, __pu_err, x, __pu_addr); \ | ||
42 | break; \ | ||
43 | case 2: \ | ||
44 | __put_user_x(2, __pu_err, x, __pu_addr); \ | ||
45 | break; \ | ||
46 | case 4: \ | ||
47 | __put_user_x(4, __pu_err, x, __pu_addr); \ | ||
48 | break; \ | ||
49 | case 8: \ | ||
50 | __put_user_x(8, __pu_err, x, __pu_addr); \ | ||
51 | break; \ | ||
52 | default: \ | ||
53 | __put_user_bad(); \ | ||
54 | } \ | ||
55 | __pu_err; \ | ||
56 | }) | ||
57 | |||
58 | /* | 22 | /* |
59 | * Copy To/From Userspace | 23 | * Copy To/From Userspace |
60 | */ | 24 | */ |