diff options
author | Michal Simek <monstr@monstr.eu> | 2010-03-22 10:46:56 -0400 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-04-01 02:38:20 -0400 |
commit | 0dcb409de73edeb221aed38d9ff8640cf41ff0de (patch) | |
tree | d58a50ff8fe3e17b43c3db60cb02c6b71d2672ed | |
parent | 8b651aa4a7c047b848f3a7bdf0aba9449e6dc3d3 (diff) |
microblaze: uaccess: sync put/get/clear_user macros
Add macro description and resort.
Signed-off-by: Michal Simek <monstr@monstr.eu>
-rw-r--r-- | arch/microblaze/include/asm/uaccess.h | 106 |
1 files changed, 69 insertions, 37 deletions
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 1e8fa4b76115..6bb9b8fb6655 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
@@ -191,11 +191,38 @@ extern long strnlen_user(const char *src, long count); | |||
191 | 191 | ||
192 | #else /* CONFIG_MMU */ | 192 | #else /* CONFIG_MMU */ |
193 | 193 | ||
194 | /* | 194 | /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */ |
195 | * All the __XXX versions macros/functions below do not perform | 195 | static inline unsigned long __must_check __clear_user(void __user *to, |
196 | * access checking. It is assumed that the necessary checks have been | 196 | unsigned long n) |
197 | * already performed before the finction (macro) is called. | 197 | { |
198 | */ | 198 | /* normal memset with two words to __ex_table */ |
199 | __asm__ __volatile__ ( \ | ||
200 | "1: sb r0, %2, r0;" \ | ||
201 | " addik %0, %0, -1;" \ | ||
202 | " bneid %0, 1b;" \ | ||
203 | " addik %2, %2, 1;" \ | ||
204 | "2: " \ | ||
205 | __EX_TABLE_SECTION \ | ||
206 | ".word 1b,2b;" \ | ||
207 | ".previous;" \ | ||
208 | : "=r"(n) \ | ||
209 | : "0"(n), "r"(to) | ||
210 | ); | ||
211 | return n; | ||
212 | } | ||
213 | |||
214 | static inline unsigned long __must_check clear_user(void __user *to, | ||
215 | unsigned long n) | ||
216 | { | ||
217 | might_sleep(); | ||
218 | if (unlikely(!access_ok(VERIFY_WRITE, to, n))) | ||
219 | return n; | ||
220 | return __clear_user(to, n); | ||
221 | } | ||
222 | |||
223 | /* put_user and get_user macros */ | ||
224 | |||
225 | extern long __user_bad(void); | ||
199 | 226 | ||
200 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | 227 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ |
201 | ({ \ | 228 | ({ \ |
@@ -231,18 +258,53 @@ extern long strnlen_user(const char *src, long count); | |||
231 | __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ | 258 | __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ |
232 | break; \ | 259 | break; \ |
233 | default: \ | 260 | default: \ |
234 | __gu_val = 0; __gu_err = -EINVAL; \ | 261 | /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\ |
235 | } \ | 262 | } \ |
236 | x = (__typeof__(*(ptr))) __gu_val; \ | 263 | x = (__typeof__(*(ptr))) __gu_val; \ |
237 | __gu_err; \ | 264 | __gu_err; \ |
238 | }) | 265 | }) |
239 | 266 | ||
267 | /** | ||
268 | * get_user: - Get a simple variable from user space. | ||
269 | * @x: Variable to store result. | ||
270 | * @ptr: Source address, in user space. | ||
271 | * | ||
272 | * Context: User context only. This function may sleep. | ||
273 | * | ||
274 | * This macro copies a single simple variable from user space to kernel | ||
275 | * space. It supports simple types like char and int, but not larger | ||
276 | * data types like structures or arrays. | ||
277 | * | ||
278 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
279 | * dereferencing @ptr must be assignable to @x without a cast. | ||
280 | * | ||
281 | * Returns zero on success, or -EFAULT on error. | ||
282 | * On error, the variable @x is set to zero. | ||
283 | */ | ||
284 | |||
240 | #define get_user(x, ptr) \ | 285 | #define get_user(x, ptr) \ |
241 | ({ \ | 286 | ({ \ |
242 | access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \ | 287 | access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \ |
243 | ? __get_user((x), (ptr)) : -EFAULT; \ | 288 | ? __get_user((x), (ptr)) : -EFAULT; \ |
244 | }) | 289 | }) |
245 | 290 | ||
291 | /** | ||
292 | * put_user: - Write a simple value into user space. | ||
293 | * @x: Value to copy to user space. | ||
294 | * @ptr: Destination address, in user space. | ||
295 | * | ||
296 | * Context: User context only. This function may sleep. | ||
297 | * | ||
298 | * This macro copies a single simple value from kernel space to user | ||
299 | * space. It supports simple types like char and int, but not larger | ||
300 | * data types like structures or arrays. | ||
301 | * | ||
302 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
303 | * to the result of dereferencing @ptr. | ||
304 | * | ||
305 | * Returns zero on success, or -EFAULT on error. | ||
306 | */ | ||
307 | |||
246 | #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | 308 | #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ |
247 | ({ \ | 309 | ({ \ |
248 | __asm__ __volatile__ ( \ | 310 | __asm__ __volatile__ ( \ |
@@ -299,7 +361,7 @@ extern long strnlen_user(const char *src, long count); | |||
299 | __put_user_asm_8((ptr), __gu_val, __gu_err); \ | 361 | __put_user_asm_8((ptr), __gu_val, __gu_err); \ |
300 | break; \ | 362 | break; \ |
301 | default: \ | 363 | default: \ |
302 | __gu_err = -EINVAL; \ | 364 | /*__gu_err = -EINVAL;*/ __gu_err = __user_bad(); \ |
303 | } \ | 365 | } \ |
304 | __gu_err; \ | 366 | __gu_err; \ |
305 | }) | 367 | }) |
@@ -310,36 +372,6 @@ extern long strnlen_user(const char *src, long count); | |||
310 | ? __put_user((x), (ptr)) : -EFAULT; \ | 372 | ? __put_user((x), (ptr)) : -EFAULT; \ |
311 | }) | 373 | }) |
312 | 374 | ||
313 | /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */ | ||
314 | static inline unsigned long __must_check __clear_user(void __user *to, | ||
315 | unsigned long n) | ||
316 | { | ||
317 | /* normal memset with two words to __ex_table */ | ||
318 | __asm__ __volatile__ ( \ | ||
319 | "1: sb r0, %2, r0;" \ | ||
320 | " addik %0, %0, -1;" \ | ||
321 | " bneid %0, 1b;" \ | ||
322 | " addik %2, %2, 1;" \ | ||
323 | "2: " \ | ||
324 | __EX_TABLE_SECTION \ | ||
325 | ".word 1b,2b;" \ | ||
326 | ".previous;" \ | ||
327 | : "=r"(n) \ | ||
328 | : "0"(n), "r"(to) | ||
329 | ); | ||
330 | return n; | ||
331 | } | ||
332 | |||
333 | static inline unsigned long __must_check clear_user(void __user *to, | ||
334 | unsigned long n) | ||
335 | { | ||
336 | might_sleep(); | ||
337 | if (unlikely(!access_ok(VERIFY_WRITE, to, n))) | ||
338 | return n; | ||
339 | |||
340 | return __clear_user(to, n); | ||
341 | } | ||
342 | |||
343 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) | 375 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) |
344 | #define __copy_from_user_inatomic(to, from, n) \ | 376 | #define __copy_from_user_inatomic(to, from, n) \ |
345 | copy_from_user((to), (from), (n)) | 377 | copy_from_user((to), (from), (n)) |