Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f73bd8b authored by Russell King's avatar Russell King Committed by Russell King
Browse files

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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 9f85eae6
Loading
Loading
Loading
Loading
+49 −57
Original line number Diff line number Diff line
@@ -230,47 +230,21 @@ 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)				\
#define __put_user_check(__pu_val, __ptr, __err, __s)			\
	({								\
		unsigned long __limit = current_thread_info()->addr_limit - 1; \
		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");				\
		__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)						\
	({								\
		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 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;							\
	})

#define put_user(x, p)							\
	({								\
		might_fault();						\
		__put_user_check(x, p);					\
			: "ip", "lr", "cc");				\
		__err = __e;						\
	})

#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,37 +355,55 @@ 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)					\
#define __put_user_nocheck(x, __pu_ptr, __err, __size)			\
	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);					\
		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__(					\
	"1:	" TUSER(instr) " %1, [%2], #0\n"		\