Commit | Line | Data |
---|---|---|
1965aae3 PA |
1 | #ifndef _ASM_X86_UACCESS_64_H |
2 | #define _ASM_X86_UACCESS_64_H | |
1da177e4 LT |
3 | |
4 | /* | |
5 | * User space memory access functions | |
6 | */ | |
1da177e4 LT |
7 | #include <linux/compiler.h> |
8 | #include <linux/errno.h> | |
1da177e4 | 9 | #include <linux/prefetch.h> |
16dbc6c9 | 10 | #include <linux/lockdep.h> |
1da177e4 LT |
11 | #include <asm/page.h> |
12 | ||
1da177e4 LT |
13 | /* |
14 | * Copy To/From Userspace | |
15 | */ | |
16 | ||
17 | /* Handles exceptions in both to and from, but doesn't do access_ok */ | |
95912008 AK |
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 __always_inline __must_check | |
29 | int __copy_from_user(void *dst, const void __user *src, unsigned size) | |
b896313e | 30 | { |
383d079b | 31 | int ret = 0; |
1da177e4 | 32 | if (!__builtin_constant_p(size)) |
b896313e JP |
33 | return copy_user_generic(dst, (__force void *)src, size); |
34 | switch (size) { | |
35 | case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src, | |
36 | ret, "b", "b", "=q", 1); | |
1da177e4 | 37 | return ret; |
b896313e JP |
38 | case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src, |
39 | ret, "w", "w", "=r", 2); | |
1da177e4 | 40 | return ret; |
b896313e JP |
41 | case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src, |
42 | ret, "l", "k", "=r", 4); | |
43 | return ret; | |
44 | case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src, | |
45 | ret, "q", "", "=r", 8); | |
1da177e4 | 46 | return ret; |
1da177e4 | 47 | case 10: |
b896313e JP |
48 | __get_user_asm(*(u64 *)dst, (u64 __user *)src, |
49 | ret, "q", "", "=r", 16); | |
50 | if (unlikely(ret)) | |
51 | return ret; | |
52 | __get_user_asm(*(u16 *)(8 + (char *)dst), | |
53 | (u16 __user *)(8 + (char __user *)src), | |
54 | ret, "w", "w", "=r", 2); | |
55 | return ret; | |
1da177e4 | 56 | case 16: |
b896313e JP |
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(*(u64 *)(8 + (char *)dst), | |
62 | (u64 __user *)(8 + (char __user *)src), | |
63 | ret, "q", "", "=r", 8); | |
64 | return ret; | |
1da177e4 | 65 | default: |
b896313e | 66 | return copy_user_generic(dst, (__force void *)src, size); |
1da177e4 | 67 | } |
b896313e | 68 | } |
1da177e4 | 69 | |
95912008 AK |
70 | static __always_inline __must_check |
71 | int __copy_to_user(void __user *dst, const void *src, unsigned size) | |
b896313e | 72 | { |
383d079b | 73 | int ret = 0; |
1da177e4 | 74 | if (!__builtin_constant_p(size)) |
b896313e JP |
75 | return copy_user_generic((__force void *)dst, src, size); |
76 | switch (size) { | |
77 | case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst, | |
78 | ret, "b", "b", "iq", 1); | |
1da177e4 | 79 | return ret; |
b896313e JP |
80 | case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst, |
81 | ret, "w", "w", "ir", 2); | |
1da177e4 | 82 | return ret; |
b896313e JP |
83 | case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst, |
84 | ret, "l", "k", "ir", 4); | |
85 | return ret; | |
86 | case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst, | |
87 | ret, "q", "", "ir", 8); | |
1da177e4 | 88 | return ret; |
1da177e4 | 89 | case 10: |
b896313e JP |
90 | __put_user_asm(*(u64 *)src, (u64 __user *)dst, |
91 | ret, "q", "", "ir", 10); | |
92 | if (unlikely(ret)) | |
93 | return ret; | |
1da177e4 | 94 | asm("":::"memory"); |
b896313e JP |
95 | __put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst, |
96 | ret, "w", "w", "ir", 2); | |
97 | return ret; | |
1da177e4 | 98 | case 16: |
b896313e JP |
99 | __put_user_asm(*(u64 *)src, (u64 __user *)dst, |
100 | ret, "q", "", "ir", 16); | |
101 | if (unlikely(ret)) | |
102 | return ret; | |
1da177e4 | 103 | asm("":::"memory"); |
b896313e JP |
104 | __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst, |
105 | ret, "q", "", "ir", 8); | |
106 | return ret; | |
1da177e4 | 107 | default: |
b896313e | 108 | return copy_user_generic((__force void *)dst, src, size); |
1da177e4 | 109 | } |
b896313e | 110 | } |
1da177e4 | 111 | |
95912008 AK |
112 | static __always_inline __must_check |
113 | int __copy_in_user(void __user *dst, const void __user *src, unsigned size) | |
b896313e | 114 | { |
383d079b | 115 | int ret = 0; |
1da177e4 | 116 | if (!__builtin_constant_p(size)) |
b896313e JP |
117 | return copy_user_generic((__force void *)dst, |
118 | (__force void *)src, size); | |
119 | switch (size) { | |
120 | case 1: { | |
1da177e4 | 121 | u8 tmp; |
b896313e JP |
122 | __get_user_asm(tmp, (u8 __user *)src, |
123 | ret, "b", "b", "=q", 1); | |
1da177e4 | 124 | if (likely(!ret)) |
b896313e JP |
125 | __put_user_asm(tmp, (u8 __user *)dst, |
126 | ret, "b", "b", "iq", 1); | |
1da177e4 LT |
127 | return ret; |
128 | } | |
b896313e | 129 | case 2: { |
1da177e4 | 130 | u16 tmp; |
b896313e JP |
131 | __get_user_asm(tmp, (u16 __user *)src, |
132 | ret, "w", "w", "=r", 2); | |
1da177e4 | 133 | if (likely(!ret)) |
b896313e JP |
134 | __put_user_asm(tmp, (u16 __user *)dst, |
135 | ret, "w", "w", "ir", 2); | |
1da177e4 LT |
136 | return ret; |
137 | } | |
138 | ||
b896313e | 139 | case 4: { |
1da177e4 | 140 | u32 tmp; |
b896313e JP |
141 | __get_user_asm(tmp, (u32 __user *)src, |
142 | ret, "l", "k", "=r", 4); | |
1da177e4 | 143 | if (likely(!ret)) |
b896313e JP |
144 | __put_user_asm(tmp, (u32 __user *)dst, |
145 | ret, "l", "k", "ir", 4); | |
1da177e4 LT |
146 | return ret; |
147 | } | |
b896313e | 148 | case 8: { |
1da177e4 | 149 | u64 tmp; |
b896313e JP |
150 | __get_user_asm(tmp, (u64 __user *)src, |
151 | ret, "q", "", "=r", 8); | |
1da177e4 | 152 | if (likely(!ret)) |
b896313e JP |
153 | __put_user_asm(tmp, (u64 __user *)dst, |
154 | ret, "q", "", "ir", 8); | |
1da177e4 LT |
155 | return ret; |
156 | } | |
157 | default: | |
b896313e JP |
158 | return copy_user_generic((__force void *)dst, |
159 | (__force void *)src, size); | |
1da177e4 | 160 | } |
b896313e | 161 | } |
1da177e4 | 162 | |
b896313e | 163 | __must_check long |
95912008 | 164 | strncpy_from_user(char *dst, const char __user *src, long count); |
b896313e | 165 | __must_check long |
95912008 AK |
166 | __strncpy_from_user(char *dst, const char __user *src, long count); |
167 | __must_check long strnlen_user(const char __user *str, long n); | |
168 | __must_check long __strnlen_user(const char __user *str, long n); | |
169 | __must_check long strlen_user(const char __user *str); | |
170 | __must_check unsigned long clear_user(void __user *mem, unsigned long len); | |
171 | __must_check unsigned long __clear_user(void __user *mem, unsigned long len); | |
172 | ||
b896313e JP |
173 | __must_check long __copy_from_user_inatomic(void *dst, const void __user *src, |
174 | unsigned size); | |
b885808e AK |
175 | |
176 | static __must_check __always_inline int | |
177 | __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) | |
178 | { | |
179 | return copy_user_generic((__force void *)dst, src, size); | |
180 | } | |
1da177e4 | 181 | |
b896313e JP |
182 | extern long __copy_user_nocache(void *dst, const void __user *src, |
183 | unsigned size, int zerorest); | |
0812a579 | 184 | |
b896313e JP |
185 | static inline int __copy_from_user_nocache(void *dst, const void __user *src, |
186 | unsigned size) | |
0812a579 AK |
187 | { |
188 | might_sleep(); | |
ecb7524c | 189 | return __copy_user_nocache(dst, src, size, 1); |
0812a579 AK |
190 | } |
191 | ||
b896313e JP |
192 | static inline int __copy_from_user_inatomic_nocache(void *dst, |
193 | const void __user *src, | |
194 | unsigned size) | |
0812a579 | 195 | { |
ecb7524c | 196 | return __copy_user_nocache(dst, src, size, 0); |
0812a579 AK |
197 | } |
198 | ||
1129585a VM |
199 | unsigned long |
200 | copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest); | |
201 | ||
1965aae3 | 202 | #endif /* _ASM_X86_UACCESS_64_H */ |