aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlauber Costa <gcosta@redhat.com>2008-06-25 12:17:43 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-09 03:14:26 -0400
commite30a44fdbf11c7ca3a0096d71790f176a4a09e03 (patch)
tree21d173ba08e47cb539c965dfb5119ff9f3b28d04
parentec840956d269e2beefe3a1c0fd7c1c70a199087f (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>
-rw-r--r--include/asm-x86/uaccess.h74
-rw-r--r--include/asm-x86/uaccess_32.h79
-rw-r--r--include/asm-x86/uaccess_64.h36
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
210extern 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 */
216extern void __put_user_1(void);
217extern void __put_user_2(void);
218extern void __put_user_4(void);
219extern 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) \
202do { \ 266do { \
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
23extern 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 */
29extern void __put_user_1(void);
30extern void __put_user_2(void);
31extern void __put_user_4(void);
32extern 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
14extern void __put_user_1(void);
15extern void __put_user_2(void);
16extern void __put_user_4(void);
17extern void __put_user_8(void);
18extern 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 */