ARM: uaccess: remove put_user() code duplication
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 4 Feb 2016 16:54:45 +0000 (16:54 +0000)
committerRussell King <rmk+kernel@armlinux.org.uk>
Wed, 22 Jun 2016 18:55:11 +0000 (19:55 +0100)
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>
arch/arm/include/asm/uaccess.h

index 7badc3e55109baaaf3a252ce168ce9266de2b97f..62a6f65029e61aebf9b64e1df59fb9383f4064a9 100644 (file)
@@ -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__(                                   \