diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2016-02-04 11:54:45 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2016-06-22 14:55:11 -0400 |
commit | 9f73bd8bb445e0cbe4bcef6d4cfc788f1e184007 (patch) | |
tree | e252451345e484c135113d8274fdc8437cf9377b | |
parent | 9f85eae622cd9b63dc44b7dcfa958b3881a09cbb (diff) |
ARM: uaccess: remove put_user() code duplication
Remove the code duplication between put_user() and __put_user(). The
code which selected the implementation based upon the pointer size, and
declared the local variable to hold the value to be put are common to
both implementations.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/include/asm/uaccess.h | 106 |
1 files changed, 49 insertions, 57 deletions
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 7badc3e55109..62a6f65029e6 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
@@ -230,49 +230,23 @@ extern int __put_user_2(void *, unsigned int); | |||
230 | extern int __put_user_4(void *, unsigned int); | 230 | extern int __put_user_4(void *, unsigned int); |
231 | extern int __put_user_8(void *, unsigned long long); | 231 | extern int __put_user_8(void *, unsigned long long); |
232 | 232 | ||
233 | #define __put_user_x(__r2, __p, __e, __l, __s) \ | 233 | #define __put_user_check(__pu_val, __ptr, __err, __s) \ |
234 | __asm__ __volatile__ ( \ | ||
235 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ | ||
236 | __asmeq("%3", "r1") \ | ||
237 | "bl __put_user_" #__s \ | ||
238 | : "=&r" (__e) \ | ||
239 | : "0" (__p), "r" (__r2), "r" (__l) \ | ||
240 | : "ip", "lr", "cc") | ||
241 | |||
242 | #define __put_user_check(x, p) \ | ||
243 | ({ \ | 234 | ({ \ |
244 | unsigned long __limit = current_thread_info()->addr_limit - 1; \ | 235 | unsigned long __limit = current_thread_info()->addr_limit - 1; \ |
245 | const typeof(*(p)) __user *__tmp_p = (p); \ | 236 | register typeof(__pu_val) __r2 asm("r2") = __pu_val; \ |
246 | register const typeof(*(p)) __r2 asm("r2") = (x); \ | 237 | register const void __user *__p asm("r0") = __ptr; \ |
247 | register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \ | ||
248 | register unsigned long __l asm("r1") = __limit; \ | 238 | register unsigned long __l asm("r1") = __limit; \ |
249 | register int __e asm("r0"); \ | 239 | register int __e asm("r0"); \ |
250 | unsigned int __ua_flags = uaccess_save_and_enable(); \ | 240 | __asm__ __volatile__ ( \ |
251 | switch (sizeof(*(__p))) { \ | 241 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ |
252 | case 1: \ | 242 | __asmeq("%3", "r1") \ |
253 | __put_user_x(__r2, __p, __e, __l, 1); \ | 243 | "bl __put_user_" #__s \ |
254 | break; \ | 244 | : "=&r" (__e) \ |
255 | case 2: \ | 245 | : "0" (__p), "r" (__r2), "r" (__l) \ |
256 | __put_user_x(__r2, __p, __e, __l, 2); \ | 246 | : "ip", "lr", "cc"); \ |
257 | break; \ | 247 | __err = __e; \ |
258 | case 4: \ | ||
259 | __put_user_x(__r2, __p, __e, __l, 4); \ | ||
260 | break; \ | ||
261 | case 8: \ | ||
262 | __put_user_x(__r2, __p, __e, __l, 8); \ | ||
263 | break; \ | ||
264 | default: __e = __put_user_bad(); break; \ | ||
265 | } \ | ||
266 | uaccess_restore(__ua_flags); \ | ||
267 | __e; \ | ||
268 | }) | 248 | }) |
269 | 249 | ||
270 | #define put_user(x, p) \ | ||
271 | ({ \ | ||
272 | might_fault(); \ | ||
273 | __put_user_check(x, p); \ | ||
274 | }) | ||
275 | |||
276 | #else /* CONFIG_MMU */ | 250 | #else /* CONFIG_MMU */ |
277 | 251 | ||
278 | /* | 252 | /* |
@@ -290,7 +264,7 @@ static inline void set_fs(mm_segment_t fs) | |||
290 | } | 264 | } |
291 | 265 | ||
292 | #define get_user(x, p) __get_user(x, p) | 266 | #define get_user(x, p) __get_user(x, p) |
293 | #define put_user(x, p) __put_user(x, p) | 267 | #define __put_user_check __put_user_nocheck |
294 | 268 | ||
295 | #endif /* CONFIG_MMU */ | 269 | #endif /* CONFIG_MMU */ |
296 | 270 | ||
@@ -381,36 +355,54 @@ do { \ | |||
381 | #define __get_user_asm_word(x, addr, err) \ | 355 | #define __get_user_asm_word(x, addr, err) \ |
382 | __get_user_asm(x, addr, err, ldr) | 356 | __get_user_asm(x, addr, err, ldr) |
383 | 357 | ||
358 | |||
359 | #define __put_user_switch(x, ptr, __err, __fn) \ | ||
360 | do { \ | ||
361 | const __typeof__(*(ptr)) __user *__pu_ptr = (ptr); \ | ||
362 | __typeof__(*(ptr)) __pu_val = (x); \ | ||
363 | unsigned int __ua_flags; \ | ||
364 | might_fault(); \ | ||
365 | __ua_flags = uaccess_save_and_enable(); \ | ||
366 | switch (sizeof(*(ptr))) { \ | ||
367 | case 1: __fn(__pu_val, __pu_ptr, __err, 1); break; \ | ||
368 | case 2: __fn(__pu_val, __pu_ptr, __err, 2); break; \ | ||
369 | case 4: __fn(__pu_val, __pu_ptr, __err, 4); break; \ | ||
370 | case 8: __fn(__pu_val, __pu_ptr, __err, 8); break; \ | ||
371 | default: __err = __put_user_bad(); break; \ | ||
372 | } \ | ||
373 | uaccess_restore(__ua_flags); \ | ||
374 | } while (0) | ||
375 | |||
376 | #define put_user(x, ptr) \ | ||
377 | ({ \ | ||
378 | int __pu_err = 0; \ | ||
379 | __put_user_switch((x), (ptr), __pu_err, __put_user_check); \ | ||
380 | __pu_err; \ | ||
381 | }) | ||
382 | |||
384 | #define __put_user(x, ptr) \ | 383 | #define __put_user(x, ptr) \ |
385 | ({ \ | 384 | ({ \ |
386 | long __pu_err = 0; \ | 385 | long __pu_err = 0; \ |
387 | __put_user_err((x), (ptr), __pu_err); \ | 386 | __put_user_switch((x), (ptr), __pu_err, __put_user_nocheck); \ |
388 | __pu_err; \ | 387 | __pu_err; \ |
389 | }) | 388 | }) |
390 | 389 | ||
391 | #define __put_user_error(x, ptr, err) \ | 390 | #define __put_user_error(x, ptr, err) \ |
392 | ({ \ | 391 | ({ \ |
393 | __put_user_err((x), (ptr), err); \ | 392 | __put_user_switch((x), (ptr), (err), __put_user_nocheck); \ |
394 | (void) 0; \ | 393 | (void) 0; \ |
395 | }) | 394 | }) |
396 | 395 | ||
397 | #define __put_user_err(x, ptr, err) \ | 396 | #define __put_user_nocheck(x, __pu_ptr, __err, __size) \ |
398 | do { \ | 397 | do { \ |
399 | unsigned long __pu_addr = (unsigned long)(ptr); \ | 398 | unsigned long __pu_addr = (unsigned long)__pu_ptr; \ |
400 | unsigned int __ua_flags; \ | 399 | __put_user_nocheck_##__size(x, __pu_addr, __err); \ |
401 | __typeof__(*(ptr)) __pu_val = (x); \ | 400 | } while (0) |
402 | __chk_user_ptr(ptr); \ | 401 | |
403 | might_fault(); \ | 402 | #define __put_user_nocheck_1 __put_user_asm_byte |
404 | __ua_flags = uaccess_save_and_enable(); \ | 403 | #define __put_user_nocheck_2 __put_user_asm_half |
405 | switch (sizeof(*(ptr))) { \ | 404 | #define __put_user_nocheck_4 __put_user_asm_word |
406 | case 1: __put_user_asm_byte(__pu_val, __pu_addr, err); break; \ | 405 | #define __put_user_nocheck_8 __put_user_asm_dword |
407 | case 2: __put_user_asm_half(__pu_val, __pu_addr, err); break; \ | ||
408 | case 4: __put_user_asm_word(__pu_val, __pu_addr, err); break; \ | ||
409 | case 8: __put_user_asm_dword(__pu_val, __pu_addr, err); break; \ | ||
410 | default: __put_user_bad(); \ | ||
411 | } \ | ||
412 | uaccess_restore(__ua_flags); \ | ||
413 | } while (0) | ||
414 | 406 | ||
415 | #define __put_user_asm(x, __pu_addr, err, instr) \ | 407 | #define __put_user_asm(x, __pu_addr, err, instr) \ |
416 | __asm__ __volatile__( \ | 408 | __asm__ __volatile__( \ |