162 lines
5.3 KiB
Diff
162 lines
5.3 KiB
Diff
commit 9f73bd8bb445e0cbe4bcef6d4cfc788f1e184007
|
|
Author: Russell King <rmk+kernel@arm.linux.org.uk>
|
|
Date: Thu Feb 4 16:54:45 2016 +0000
|
|
|
|
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>
|
|
|
|
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);
|
|
extern int __put_user_4(void *, unsigned int);
|
|
extern int __put_user_8(void *, unsigned long long);
|
|
|
|
-#define __put_user_x(__r2, __p, __e, __l, __s) \
|
|
- __asm__ __volatile__ ( \
|
|
- __asmeq("%0", "r0") __asmeq("%2", "r2") \
|
|
- __asmeq("%3", "r1") \
|
|
- "bl __put_user_" #__s \
|
|
- : "=&r" (__e) \
|
|
- : "0" (__p), "r" (__r2), "r" (__l) \
|
|
- : "ip", "lr", "cc")
|
|
-
|
|
-#define __put_user_check(x, p) \
|
|
+#define __put_user_check(__pu_val, __ptr, __err, __s) \
|
|
({ \
|
|
unsigned long __limit = current_thread_info()->addr_limit - 1; \
|
|
- const typeof(*(p)) __user *__tmp_p = (p); \
|
|
- register const typeof(*(p)) __r2 asm("r2") = (x); \
|
|
- register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
|
|
+ register typeof(__pu_val) __r2 asm("r2") = __pu_val; \
|
|
+ register const void __user *__p asm("r0") = __ptr; \
|
|
register unsigned long __l asm("r1") = __limit; \
|
|
register int __e asm("r0"); \
|
|
- unsigned int __ua_flags = uaccess_save_and_enable(); \
|
|
- switch (sizeof(*(__p))) { \
|
|
- case 1: \
|
|
- __put_user_x(__r2, __p, __e, __l, 1); \
|
|
- break; \
|
|
- case 2: \
|
|
- __put_user_x(__r2, __p, __e, __l, 2); \
|
|
- break; \
|
|
- case 4: \
|
|
- __put_user_x(__r2, __p, __e, __l, 4); \
|
|
- break; \
|
|
- case 8: \
|
|
- __put_user_x(__r2, __p, __e, __l, 8); \
|
|
- break; \
|
|
- default: __e = __put_user_bad(); break; \
|
|
- } \
|
|
- uaccess_restore(__ua_flags); \
|
|
- __e; \
|
|
+ __asm__ __volatile__ ( \
|
|
+ __asmeq("%0", "r0") __asmeq("%2", "r2") \
|
|
+ __asmeq("%3", "r1") \
|
|
+ "bl __put_user_" #__s \
|
|
+ : "=&r" (__e) \
|
|
+ : "0" (__p), "r" (__r2), "r" (__l) \
|
|
+ : "ip", "lr", "cc"); \
|
|
+ __err = __e; \
|
|
})
|
|
|
|
-#define put_user(x, p) \
|
|
- ({ \
|
|
- might_fault(); \
|
|
- __put_user_check(x, p); \
|
|
- })
|
|
-
|
|
#else /* CONFIG_MMU */
|
|
|
|
/*
|
|
@@ -290,7 +264,7 @@ static inline void set_fs(mm_segment_t fs)
|
|
}
|
|
|
|
#define get_user(x, p) __get_user(x, p)
|
|
-#define put_user(x, p) __put_user(x, p)
|
|
+#define __put_user_check __put_user_nocheck
|
|
|
|
#endif /* CONFIG_MMU */
|
|
|
|
@@ -381,36 +355,54 @@ do { \
|
|
#define __get_user_asm_word(x, addr, err) \
|
|
__get_user_asm(x, addr, err, ldr)
|
|
|
|
+
|
|
+#define __put_user_switch(x, ptr, __err, __fn) \
|
|
+ do { \
|
|
+ const __typeof__(*(ptr)) __user *__pu_ptr = (ptr); \
|
|
+ __typeof__(*(ptr)) __pu_val = (x); \
|
|
+ unsigned int __ua_flags; \
|
|
+ might_fault(); \
|
|
+ __ua_flags = uaccess_save_and_enable(); \
|
|
+ switch (sizeof(*(ptr))) { \
|
|
+ case 1: __fn(__pu_val, __pu_ptr, __err, 1); break; \
|
|
+ case 2: __fn(__pu_val, __pu_ptr, __err, 2); break; \
|
|
+ case 4: __fn(__pu_val, __pu_ptr, __err, 4); break; \
|
|
+ case 8: __fn(__pu_val, __pu_ptr, __err, 8); break; \
|
|
+ default: __err = __put_user_bad(); break; \
|
|
+ } \
|
|
+ uaccess_restore(__ua_flags); \
|
|
+ } while (0)
|
|
+
|
|
+#define put_user(x, ptr) \
|
|
+({ \
|
|
+ int __pu_err = 0; \
|
|
+ __put_user_switch((x), (ptr), __pu_err, __put_user_check); \
|
|
+ __pu_err; \
|
|
+})
|
|
+
|
|
#define __put_user(x, ptr) \
|
|
({ \
|
|
long __pu_err = 0; \
|
|
- __put_user_err((x), (ptr), __pu_err); \
|
|
+ __put_user_switch((x), (ptr), __pu_err, __put_user_nocheck); \
|
|
__pu_err; \
|
|
})
|
|
|
|
#define __put_user_error(x, ptr, err) \
|
|
({ \
|
|
- __put_user_err((x), (ptr), err); \
|
|
+ __put_user_switch((x), (ptr), (err), __put_user_nocheck); \
|
|
(void) 0; \
|
|
})
|
|
|
|
-#define __put_user_err(x, ptr, err) \
|
|
-do { \
|
|
- unsigned long __pu_addr = (unsigned long)(ptr); \
|
|
- unsigned int __ua_flags; \
|
|
- __typeof__(*(ptr)) __pu_val = (x); \
|
|
- __chk_user_ptr(ptr); \
|
|
- might_fault(); \
|
|
- __ua_flags = uaccess_save_and_enable(); \
|
|
- switch (sizeof(*(ptr))) { \
|
|
- case 1: __put_user_asm_byte(__pu_val, __pu_addr, err); break; \
|
|
- case 2: __put_user_asm_half(__pu_val, __pu_addr, err); break; \
|
|
- case 4: __put_user_asm_word(__pu_val, __pu_addr, err); break; \
|
|
- case 8: __put_user_asm_dword(__pu_val, __pu_addr, err); break; \
|
|
- default: __put_user_bad(); \
|
|
- } \
|
|
- uaccess_restore(__ua_flags); \
|
|
-} while (0)
|
|
+#define __put_user_nocheck(x, __pu_ptr, __err, __size) \
|
|
+ do { \
|
|
+ unsigned long __pu_addr = (unsigned long)__pu_ptr; \
|
|
+ __put_user_nocheck_##__size(x, __pu_addr, __err); \
|
|
+ } while (0)
|
|
+
|
|
+#define __put_user_nocheck_1 __put_user_asm_byte
|
|
+#define __put_user_nocheck_2 __put_user_asm_half
|
|
+#define __put_user_nocheck_4 __put_user_asm_word
|
|
+#define __put_user_nocheck_8 __put_user_asm_dword
|
|
|
|
#define __put_user_asm(x, __pu_addr, err, instr) \
|
|
__asm__ __volatile__( \
|