diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-08-17 21:05:42 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-23 01:55:20 -0400 |
commit | bb8985586b7a906e116db835c64773b7a7d51663 (patch) | |
tree | de93ae58e88cc563d95cc124a73f3930594c6100 /arch/x86/include/asm/uaccess_32.h | |
parent | 8ede0bdb63305d3353efd97e9af6210afb05734e (diff) |
x86, um: ... and asm-x86 move
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/include/asm/uaccess_32.h')
-rw-r--r-- | arch/x86/include/asm/uaccess_32.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h new file mode 100644 index 000000000000..6b5b57d9c6d1 --- /dev/null +++ b/arch/x86/include/asm/uaccess_32.h | |||
@@ -0,0 +1,218 @@ | |||
1 | #ifndef ASM_X86__UACCESS_32_H | ||
2 | #define ASM_X86__UACCESS_32_H | ||
3 | |||
4 | /* | ||
5 | * User space memory access functions | ||
6 | */ | ||
7 | #include <linux/errno.h> | ||
8 | #include <linux/thread_info.h> | ||
9 | #include <linux/prefetch.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <asm/asm.h> | ||
12 | #include <asm/page.h> | ||
13 | |||
14 | unsigned long __must_check __copy_to_user_ll | ||
15 | (void __user *to, const void *from, unsigned long n); | ||
16 | unsigned long __must_check __copy_from_user_ll | ||
17 | (void *to, const void __user *from, unsigned long n); | ||
18 | unsigned long __must_check __copy_from_user_ll_nozero | ||
19 | (void *to, const void __user *from, unsigned long n); | ||
20 | unsigned long __must_check __copy_from_user_ll_nocache | ||
21 | (void *to, const void __user *from, unsigned long n); | ||
22 | unsigned long __must_check __copy_from_user_ll_nocache_nozero | ||
23 | (void *to, const void __user *from, unsigned long n); | ||
24 | |||
25 | /** | ||
26 | * __copy_to_user_inatomic: - Copy a block of data into user space, with less checking. | ||
27 | * @to: Destination address, in user space. | ||
28 | * @from: Source address, in kernel space. | ||
29 | * @n: Number of bytes to copy. | ||
30 | * | ||
31 | * Context: User context only. | ||
32 | * | ||
33 | * Copy data from kernel space to user space. Caller must check | ||
34 | * the specified block with access_ok() before calling this function. | ||
35 | * The caller should also make sure he pins the user space address | ||
36 | * so that the we don't result in page fault and sleep. | ||
37 | * | ||
38 | * Here we special-case 1, 2 and 4-byte copy_*_user invocations. On a fault | ||
39 | * we return the initial request size (1, 2 or 4), as copy_*_user should do. | ||
40 | * If a store crosses a page boundary and gets a fault, the x86 will not write | ||
41 | * anything, so this is accurate. | ||
42 | */ | ||
43 | |||
44 | static __always_inline unsigned long __must_check | ||
45 | __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) | ||
46 | { | ||
47 | if (__builtin_constant_p(n)) { | ||
48 | unsigned long ret; | ||
49 | |||
50 | switch (n) { | ||
51 | case 1: | ||
52 | __put_user_size(*(u8 *)from, (u8 __user *)to, | ||
53 | 1, ret, 1); | ||
54 | return ret; | ||
55 | case 2: | ||
56 | __put_user_size(*(u16 *)from, (u16 __user *)to, | ||
57 | 2, ret, 2); | ||
58 | return ret; | ||
59 | case 4: | ||
60 | __put_user_size(*(u32 *)from, (u32 __user *)to, | ||
61 | 4, ret, 4); | ||
62 | return ret; | ||
63 | } | ||
64 | } | ||
65 | return __copy_to_user_ll(to, from, n); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * __copy_to_user: - Copy a block of data into user space, with less checking. | ||
70 | * @to: Destination address, in user space. | ||
71 | * @from: Source address, in kernel space. | ||
72 | * @n: Number of bytes to copy. | ||
73 | * | ||
74 | * Context: User context only. This function may sleep. | ||
75 | * | ||
76 | * Copy data from kernel space to user space. Caller must check | ||
77 | * the specified block with access_ok() before calling this function. | ||
78 | * | ||
79 | * Returns number of bytes that could not be copied. | ||
80 | * On success, this will be zero. | ||
81 | */ | ||
82 | static __always_inline unsigned long __must_check | ||
83 | __copy_to_user(void __user *to, const void *from, unsigned long n) | ||
84 | { | ||
85 | might_sleep(); | ||
86 | return __copy_to_user_inatomic(to, from, n); | ||
87 | } | ||
88 | |||
89 | static __always_inline unsigned long | ||
90 | __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) | ||
91 | { | ||
92 | /* Avoid zeroing the tail if the copy fails.. | ||
93 | * If 'n' is constant and 1, 2, or 4, we do still zero on a failure, | ||
94 | * but as the zeroing behaviour is only significant when n is not | ||
95 | * constant, that shouldn't be a problem. | ||
96 | */ | ||
97 | if (__builtin_constant_p(n)) { | ||
98 | unsigned long ret; | ||
99 | |||
100 | switch (n) { | ||
101 | case 1: | ||
102 | __get_user_size(*(u8 *)to, from, 1, ret, 1); | ||
103 | return ret; | ||
104 | case 2: | ||
105 | __get_user_size(*(u16 *)to, from, 2, ret, 2); | ||
106 | return ret; | ||
107 | case 4: | ||
108 | __get_user_size(*(u32 *)to, from, 4, ret, 4); | ||
109 | return ret; | ||
110 | } | ||
111 | } | ||
112 | return __copy_from_user_ll_nozero(to, from, n); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * __copy_from_user: - Copy a block of data from user space, with less checking. | ||
117 | * @to: Destination address, in kernel space. | ||
118 | * @from: Source address, in user space. | ||
119 | * @n: Number of bytes to copy. | ||
120 | * | ||
121 | * Context: User context only. This function may sleep. | ||
122 | * | ||
123 | * Copy data from user space to kernel space. Caller must check | ||
124 | * the specified block with access_ok() before calling this function. | ||
125 | * | ||
126 | * Returns number of bytes that could not be copied. | ||
127 | * On success, this will be zero. | ||
128 | * | ||
129 | * If some data could not be copied, this function will pad the copied | ||
130 | * data to the requested size using zero bytes. | ||
131 | * | ||
132 | * An alternate version - __copy_from_user_inatomic() - may be called from | ||
133 | * atomic context and will fail rather than sleep. In this case the | ||
134 | * uncopied bytes will *NOT* be padded with zeros. See fs/filemap.h | ||
135 | * for explanation of why this is needed. | ||
136 | */ | ||
137 | static __always_inline unsigned long | ||
138 | __copy_from_user(void *to, const void __user *from, unsigned long n) | ||
139 | { | ||
140 | might_sleep(); | ||
141 | if (__builtin_constant_p(n)) { | ||
142 | unsigned long ret; | ||
143 | |||
144 | switch (n) { | ||
145 | case 1: | ||
146 | __get_user_size(*(u8 *)to, from, 1, ret, 1); | ||
147 | return ret; | ||
148 | case 2: | ||
149 | __get_user_size(*(u16 *)to, from, 2, ret, 2); | ||
150 | return ret; | ||
151 | case 4: | ||
152 | __get_user_size(*(u32 *)to, from, 4, ret, 4); | ||
153 | return ret; | ||
154 | } | ||
155 | } | ||
156 | return __copy_from_user_ll(to, from, n); | ||
157 | } | ||
158 | |||
159 | static __always_inline unsigned long __copy_from_user_nocache(void *to, | ||
160 | const void __user *from, unsigned long n) | ||
161 | { | ||
162 | might_sleep(); | ||
163 | if (__builtin_constant_p(n)) { | ||
164 | unsigned long ret; | ||
165 | |||
166 | switch (n) { | ||
167 | case 1: | ||
168 | __get_user_size(*(u8 *)to, from, 1, ret, 1); | ||
169 | return ret; | ||
170 | case 2: | ||
171 | __get_user_size(*(u16 *)to, from, 2, ret, 2); | ||
172 | return ret; | ||
173 | case 4: | ||
174 | __get_user_size(*(u32 *)to, from, 4, ret, 4); | ||
175 | return ret; | ||
176 | } | ||
177 | } | ||
178 | return __copy_from_user_ll_nocache(to, from, n); | ||
179 | } | ||
180 | |||
181 | static __always_inline unsigned long | ||
182 | __copy_from_user_inatomic_nocache(void *to, const void __user *from, | ||
183 | unsigned long n) | ||
184 | { | ||
185 | return __copy_from_user_ll_nocache_nozero(to, from, n); | ||
186 | } | ||
187 | |||
188 | unsigned long __must_check copy_to_user(void __user *to, | ||
189 | const void *from, unsigned long n); | ||
190 | unsigned long __must_check copy_from_user(void *to, | ||
191 | const void __user *from, | ||
192 | unsigned long n); | ||
193 | long __must_check strncpy_from_user(char *dst, const char __user *src, | ||
194 | long count); | ||
195 | long __must_check __strncpy_from_user(char *dst, | ||
196 | const char __user *src, long count); | ||
197 | |||
198 | /** | ||
199 | * strlen_user: - Get the size of a string in user space. | ||
200 | * @str: The string to measure. | ||
201 | * | ||
202 | * Context: User context only. This function may sleep. | ||
203 | * | ||
204 | * Get the size of a NUL-terminated string in user space. | ||
205 | * | ||
206 | * Returns the size of the string INCLUDING the terminating NUL. | ||
207 | * On exception, returns 0. | ||
208 | * | ||
209 | * If there is a limit on the length of a valid string, you may wish to | ||
210 | * consider using strnlen_user() instead. | ||
211 | */ | ||
212 | #define strlen_user(str) strnlen_user(str, LONG_MAX) | ||
213 | |||
214 | long strnlen_user(const char __user *str, long n); | ||
215 | unsigned long __must_check clear_user(void __user *mem, unsigned long len); | ||
216 | unsigned long __must_check __clear_user(void __user *mem, unsigned long len); | ||
217 | |||
218 | #endif /* ASM_X86__UACCESS_32_H */ | ||