Line data Source code
1 : #ifndef _ASM_X86_UACCESS_64_H
2 : #define _ASM_X86_UACCESS_64_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 <linux/lockdep.h>
11 : #include <asm/page.h>
12 :
13 : /*
14 : * Copy To/From Userspace
15 : */
16 :
17 : /* Handles exceptions in both to and from, but doesn't do access_ok */
18 : __must_check unsigned long
19 : copy_user_generic(void *to, const void *from, unsigned len);
20 :
21 : __must_check unsigned long
22 : _copy_to_user(void __user *to, const void *from, unsigned len);
23 : __must_check unsigned long
24 : _copy_from_user(void *to, const void __user *from, unsigned len);
25 : __must_check unsigned long
26 : copy_in_user(void __user *to, const void __user *from, unsigned len);
27 :
28 : static inline unsigned long __must_check copy_from_user(void *to,
29 : const void __user *from,
30 0 : unsigned long n)
31 0 : {
32 0 : int sz = __compiletime_object_size(to);
33 0 :
34 0 : might_fault();
35 0 : if (likely(sz == -1 || sz >= n))
36 0 : n = _copy_from_user(to, from, n);
37 : #ifdef CONFIG_DEBUG_VM
38 : else
39 : WARN(1, "Buffer overflow detected!\n");
40 : #endif
41 0 : return n;
42 : }
43 :
44 : static __always_inline __must_check
45 : int copy_to_user(void __user *dst, const void *src, unsigned size)
46 : {
47 0 : might_fault();
48 :
49 0 : return _copy_to_user(dst, src, size);
50 : }
51 :
52 : static __always_inline __must_check
53 : int __copy_from_user(void *dst, const void __user *src, unsigned size)
54 : {
55 : int ret = 0;
56 :
57 : might_fault();
58 : if (!__builtin_constant_p(size))
59 : return copy_user_generic(dst, (__force void *)src, size);
60 : switch (size) {
61 : case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src,
62 : ret, "b", "b", "=q", 1);
63 : return ret;
64 : case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src,
65 : ret, "w", "w", "=r", 2);
66 : return ret;
67 : case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src,
68 : ret, "l", "k", "=r", 4);
69 : return ret;
70 : case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src,
71 : ret, "q", "", "=r", 8);
72 : return ret;
73 : case 10:
74 : __get_user_asm(*(u64 *)dst, (u64 __user *)src,
75 : ret, "q", "", "=r", 10);
76 : if (unlikely(ret))
77 : return ret;
78 : __get_user_asm(*(u16 *)(8 + (char *)dst),
79 : (u16 __user *)(8 + (char __user *)src),
80 : ret, "w", "w", "=r", 2);
81 : return ret;
82 : case 16:
83 : __get_user_asm(*(u64 *)dst, (u64 __user *)src,
84 : ret, "q", "", "=r", 16);
85 : if (unlikely(ret))
86 : return ret;
87 : __get_user_asm(*(u64 *)(8 + (char *)dst),
88 : (u64 __user *)(8 + (char __user *)src),
89 : ret, "q", "", "=r", 8);
90 : return ret;
91 : default:
92 : return copy_user_generic(dst, (__force void *)src, size);
93 : }
94 : }
95 :
96 : static __always_inline __must_check
97 : int __copy_to_user(void __user *dst, const void *src, unsigned size)
98 : {
99 0 : int ret = 0;
100 0 :
101 0 : might_fault();
102 0 : if (!__builtin_constant_p(size))
103 0 : return copy_user_generic((__force void *)dst, src, size);
104 : switch (size) {
105 : case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst,
106 : ret, "b", "b", "iq", 1);
107 : return ret;
108 : case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst,
109 : ret, "w", "w", "ir", 2);
110 : return ret;
111 : case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst,
112 : ret, "l", "k", "ir", 4);
113 : return ret;
114 : case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
115 : ret, "q", "", "er", 8);
116 : return ret;
117 : case 10:
118 : __put_user_asm(*(u64 *)src, (u64 __user *)dst,
119 : ret, "q", "", "er", 10);
120 : if (unlikely(ret))
121 : return ret;
122 : asm("":::"memory");
123 : __put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
124 : ret, "w", "w", "ir", 2);
125 : return ret;
126 : case 16:
127 : __put_user_asm(*(u64 *)src, (u64 __user *)dst,
128 : ret, "q", "", "er", 16);
129 : if (unlikely(ret))
130 : return ret;
131 : asm("":::"memory");
132 : __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
133 : ret, "q", "", "er", 8);
134 : return ret;
135 : default:
136 : return copy_user_generic((__force void *)dst, src, size);
137 : }
138 : }
139 :
140 : static __always_inline __must_check
141 : int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
142 : {
143 : int ret = 0;
144 :
145 : might_fault();
146 : if (!__builtin_constant_p(size))
147 : return copy_user_generic((__force void *)dst,
148 : (__force void *)src, size);
149 : switch (size) {
150 : case 1: {
151 : u8 tmp;
152 : __get_user_asm(tmp, (u8 __user *)src,
153 : ret, "b", "b", "=q", 1);
154 : if (likely(!ret))
155 : __put_user_asm(tmp, (u8 __user *)dst,
156 : ret, "b", "b", "iq", 1);
157 : return ret;
158 : }
159 : case 2: {
160 : u16 tmp;
161 : __get_user_asm(tmp, (u16 __user *)src,
162 : ret, "w", "w", "=r", 2);
163 : if (likely(!ret))
164 : __put_user_asm(tmp, (u16 __user *)dst,
165 : ret, "w", "w", "ir", 2);
166 : return ret;
167 : }
168 :
169 : case 4: {
170 : u32 tmp;
171 : __get_user_asm(tmp, (u32 __user *)src,
172 : ret, "l", "k", "=r", 4);
173 : if (likely(!ret))
174 : __put_user_asm(tmp, (u32 __user *)dst,
175 : ret, "l", "k", "ir", 4);
176 : return ret;
177 : }
178 : case 8: {
179 : u64 tmp;
180 : __get_user_asm(tmp, (u64 __user *)src,
181 : ret, "q", "", "=r", 8);
182 : if (likely(!ret))
183 : __put_user_asm(tmp, (u64 __user *)dst,
184 : ret, "q", "", "er", 8);
185 : return ret;
186 : }
187 : default:
188 : return copy_user_generic((__force void *)dst,
189 : (__force void *)src, size);
190 : }
191 : }
192 :
193 : __must_check long
194 : strncpy_from_user(char *dst, const char __user *src, long count);
195 : __must_check long
196 : __strncpy_from_user(char *dst, const char __user *src, long count);
197 : __must_check long strnlen_user(const char __user *str, long n);
198 : __must_check long __strnlen_user(const char __user *str, long n);
199 : __must_check long strlen_user(const char __user *str);
200 : __must_check unsigned long clear_user(void __user *mem, unsigned long len);
201 : __must_check unsigned long __clear_user(void __user *mem, unsigned long len);
202 :
203 : static __must_check __always_inline int
204 : __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
205 : {
206 : return copy_user_generic(dst, (__force const void *)src, size);
207 : }
208 :
209 : static __must_check __always_inline int
210 : __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
211 : {
212 : return copy_user_generic((__force void *)dst, src, size);
213 : }
214 :
215 : extern long __copy_user_nocache(void *dst, const void __user *src,
216 : unsigned size, int zerorest);
217 :
218 : static inline int
219 : __copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
220 : {
221 : might_sleep();
222 : return __copy_user_nocache(dst, src, size, 1);
223 : }
224 :
225 : static inline int
226 : __copy_from_user_inatomic_nocache(void *dst, const void __user *src,
227 : unsigned size)
228 : {
229 : return __copy_user_nocache(dst, src, size, 0);
230 : }
231 :
232 : unsigned long
233 : copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest);
234 :
235 : #endif /* _ASM_X86_UACCESS_64_H */
|