]> err.no Git - linux-2.6/blob - include/asm-x86/uaccess_64.h
x86: merge put_user.
[linux-2.6] / include / asm-x86 / uaccess_64.h
1 #ifndef __X86_64_UACCESS_H
2 #define __X86_64_UACCESS_H
3
4 /*
5  * User space memory access functions
6  */
7 #include <linux/compiler.h>
8 #include <linux/errno.h>
9 #include <linux/prefetch.h>
10 #include <asm/page.h>
11
12 #define ARCH_HAS_SEARCH_EXTABLE
13
14 #define __get_user(x, ptr)                                              \
15         __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
16 #define __put_user(x, ptr)                                              \
17         __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
18
19 #define __get_user_unaligned __get_user
20 #define __put_user_unaligned __put_user
21
22 /*
23  * Copy To/From Userspace
24  */
25
26 /* Handles exceptions in both to and from, but doesn't do access_ok */
27 __must_check unsigned long
28 copy_user_generic(void *to, const void *from, unsigned len);
29
30 __must_check unsigned long
31 copy_to_user(void __user *to, const void *from, unsigned len);
32 __must_check unsigned long
33 copy_from_user(void *to, const void __user *from, unsigned len);
34 __must_check unsigned long
35 copy_in_user(void __user *to, const void __user *from, unsigned len);
36
37 static __always_inline __must_check
38 int __copy_from_user(void *dst, const void __user *src, unsigned size)
39 {
40         int ret = 0;
41         if (!__builtin_constant_p(size))
42                 return copy_user_generic(dst, (__force void *)src, size);
43         switch (size) {
44         case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src,
45                               ret, "b", "b", "=q", 1);
46                 return ret;
47         case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src,
48                               ret, "w", "w", "=r", 2);
49                 return ret;
50         case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src,
51                               ret, "l", "k", "=r", 4);
52                 return ret;
53         case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src,
54                               ret, "q", "", "=r", 8);
55                 return ret;
56         case 10:
57                 __get_user_asm(*(u64 *)dst, (u64 __user *)src,
58                                ret, "q", "", "=r", 16);
59                 if (unlikely(ret))
60                         return ret;
61                 __get_user_asm(*(u16 *)(8 + (char *)dst),
62                                (u16 __user *)(8 + (char __user *)src),
63                                ret, "w", "w", "=r", 2);
64                 return ret;
65         case 16:
66                 __get_user_asm(*(u64 *)dst, (u64 __user *)src,
67                                ret, "q", "", "=r", 16);
68                 if (unlikely(ret))
69                         return ret;
70                 __get_user_asm(*(u64 *)(8 + (char *)dst),
71                                (u64 __user *)(8 + (char __user *)src),
72                                ret, "q", "", "=r", 8);
73                 return ret;
74         default:
75                 return copy_user_generic(dst, (__force void *)src, size);
76         }
77 }
78
79 static __always_inline __must_check
80 int __copy_to_user(void __user *dst, const void *src, unsigned size)
81 {
82         int ret = 0;
83         if (!__builtin_constant_p(size))
84                 return copy_user_generic((__force void *)dst, src, size);
85         switch (size) {
86         case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst,
87                               ret, "b", "b", "iq", 1);
88                 return ret;
89         case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst,
90                               ret, "w", "w", "ir", 2);
91                 return ret;
92         case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst,
93                               ret, "l", "k", "ir", 4);
94                 return ret;
95         case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
96                               ret, "q", "", "ir", 8);
97                 return ret;
98         case 10:
99                 __put_user_asm(*(u64 *)src, (u64 __user *)dst,
100                                ret, "q", "", "ir", 10);
101                 if (unlikely(ret))
102                         return ret;
103                 asm("":::"memory");
104                 __put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
105                                ret, "w", "w", "ir", 2);
106                 return ret;
107         case 16:
108                 __put_user_asm(*(u64 *)src, (u64 __user *)dst,
109                                ret, "q", "", "ir", 16);
110                 if (unlikely(ret))
111                         return ret;
112                 asm("":::"memory");
113                 __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
114                                ret, "q", "", "ir", 8);
115                 return ret;
116         default:
117                 return copy_user_generic((__force void *)dst, src, size);
118         }
119 }
120
121 static __always_inline __must_check
122 int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
123 {
124         int ret = 0;
125         if (!__builtin_constant_p(size))
126                 return copy_user_generic((__force void *)dst,
127                                          (__force void *)src, size);
128         switch (size) {
129         case 1: {
130                 u8 tmp;
131                 __get_user_asm(tmp, (u8 __user *)src,
132                                ret, "b", "b", "=q", 1);
133                 if (likely(!ret))
134                         __put_user_asm(tmp, (u8 __user *)dst,
135                                        ret, "b", "b", "iq", 1);
136                 return ret;
137         }
138         case 2: {
139                 u16 tmp;
140                 __get_user_asm(tmp, (u16 __user *)src,
141                                ret, "w", "w", "=r", 2);
142                 if (likely(!ret))
143                         __put_user_asm(tmp, (u16 __user *)dst,
144                                        ret, "w", "w", "ir", 2);
145                 return ret;
146         }
147
148         case 4: {
149                 u32 tmp;
150                 __get_user_asm(tmp, (u32 __user *)src,
151                                ret, "l", "k", "=r", 4);
152                 if (likely(!ret))
153                         __put_user_asm(tmp, (u32 __user *)dst,
154                                        ret, "l", "k", "ir", 4);
155                 return ret;
156         }
157         case 8: {
158                 u64 tmp;
159                 __get_user_asm(tmp, (u64 __user *)src,
160                                ret, "q", "", "=r", 8);
161                 if (likely(!ret))
162                         __put_user_asm(tmp, (u64 __user *)dst,
163                                        ret, "q", "", "ir", 8);
164                 return ret;
165         }
166         default:
167                 return copy_user_generic((__force void *)dst,
168                                          (__force void *)src, size);
169         }
170 }
171
172 __must_check long
173 strncpy_from_user(char *dst, const char __user *src, long count);
174 __must_check long
175 __strncpy_from_user(char *dst, const char __user *src, long count);
176 __must_check long strnlen_user(const char __user *str, long n);
177 __must_check long __strnlen_user(const char __user *str, long n);
178 __must_check long strlen_user(const char __user *str);
179 __must_check unsigned long clear_user(void __user *mem, unsigned long len);
180 __must_check unsigned long __clear_user(void __user *mem, unsigned long len);
181
182 __must_check long __copy_from_user_inatomic(void *dst, const void __user *src,
183                                             unsigned size);
184
185 static __must_check __always_inline int
186 __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
187 {
188         return copy_user_generic((__force void *)dst, src, size);
189 }
190
191 #define ARCH_HAS_NOCACHE_UACCESS 1
192 extern long __copy_user_nocache(void *dst, const void __user *src,
193                                 unsigned size, int zerorest);
194
195 static inline int __copy_from_user_nocache(void *dst, const void __user *src,
196                                            unsigned size)
197 {
198         might_sleep();
199         return __copy_user_nocache(dst, src, size, 1);
200 }
201
202 static inline int __copy_from_user_inatomic_nocache(void *dst,
203                                                     const void __user *src,
204                                                     unsigned size)
205 {
206         return __copy_user_nocache(dst, src, size, 0);
207 }
208
209 #endif /* __X86_64_UACCESS_H */