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