[PATCH] MIPS: Fix inline assembly in uaccess.h

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The inline assembly of __put_data_asm() and __put_data_asm_ll32()
treat memory addresses to be written as input operands, which may
cause the compiler to incorrectly optimize.

Treat these addresses as output operands. BTW, rewrite the inline
assembly to improve readability.

Signed-off-by: Feiyang Chen <chenfeiyang@xxxxxxxxxxx>
---
 arch/mips/include/asm/uaccess.h | 38 +++++++++++++++++----------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index c0cede273c7c..dc5bca09f39a 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -207,19 +207,19 @@ struct __large_struct { unsigned long buf[100]; };
 	long __gu_tmp;							\
 									\
 	__asm__ __volatile__(						\
-	"1:	"insn("%1", "%3")"				\n"	\
+	"1:	"insn("%1", "%2")"				\n"	\
 	"2:							\n"	\
 	"	.insn						\n"	\
 	"	.section .fixup,\"ax\"				\n"	\
-	"3:	li	%0, %4					\n"	\
+	"3:	li	%0, %3					\n"	\
 	"	move	%1, $0					\n"	\
 	"	j	2b					\n"	\
 	"	.previous					\n"	\
 	"	.section __ex_table,\"a\"			\n"	\
 	"	"__UA_ADDR "\t1b, 3b				\n"	\
 	"	.previous					\n"	\
-	: "=r" (__gu_err), "=r" (__gu_tmp)				\
-	: "0" (0), "o" (__m(addr)), "i" (-EFAULT));			\
+	: "+r" (__gu_err), "=r" (__gu_tmp)				\
+	: "m" (__m(addr)), "i" (-EFAULT));				\
 									\
 	(val) = (__typeof__(*(addr))) __gu_tmp;				\
 }
@@ -234,9 +234,11 @@ struct __large_struct { unsigned long buf[100]; };
 		__typeof__(*(addr))	t;				\
 	} __gu_tmp;							\
 									\
+	void *__addr = (void *)addr;					\
+									\
 	__asm__ __volatile__(						\
-	"1:	" insn("%1", "(%3)")"				\n"	\
-	"2:	" insn("%D1", "4(%3)")"				\n"	\
+	"1:	" insn("%1", "%2")"				\n"	\
+	"2:	" insn("%D1", "%3")"				\n"	\
 	"3:							\n"	\
 	"	.insn						\n"	\
 	"	.section	.fixup,\"ax\"			\n"	\
@@ -249,8 +251,8 @@ struct __large_struct { unsigned long buf[100]; };
 	"	" __UA_ADDR "	1b, 4b				\n"	\
 	"	" __UA_ADDR "	2b, 4b				\n"	\
 	"	.previous					\n"	\
-	: "=r" (__gu_err), "=&r" (__gu_tmp.l)				\
-	: "0" (0), "r" (addr), "i" (-EFAULT));				\
+	: "+r" (__gu_err), "=&r" (__gu_tmp.l)				\
+	: "m" (__m(__addr)), "m" (__m(__addr + 4)), "i" (-EFAULT));	\
 									\
 	(val) = __gu_tmp.t;						\
 }
@@ -298,26 +300,27 @@ do {									\
 #define __put_data_asm(insn, ptr)					\
 {									\
 	__asm__ __volatile__(						\
-	"1:	"insn("%z2", "%3")"	# __put_data_asm	\n"	\
+	"1:	"insn("%z2", "%1")"	# __put_data_asm	\n"	\
 	"2:							\n"	\
 	"	.insn						\n"	\
 	"	.section	.fixup,\"ax\"			\n"	\
-	"3:	li	%0, %4					\n"	\
+	"3:	li	%0, %3					\n"	\
 	"	j	2b					\n"	\
 	"	.previous					\n"	\
 	"	.section	__ex_table,\"a\"		\n"	\
 	"	" __UA_ADDR "	1b, 3b				\n"	\
 	"	.previous					\n"	\
-	: "=r" (__pu_err)						\
-	: "0" (0), "Jr" (__pu_val), "o" (__m(ptr)),			\
-	  "i" (-EFAULT));						\
+	: "+r" (__pu_err), "=m" (__m(ptr))				\
+	: "Jr" (__pu_val), "i" (-EFAULT));				\
 }
 
 #define __put_data_asm_ll32(insn, ptr)					\
 {									\
+	void *__ptr = (void *)ptr;					\
+									\
 	__asm__ __volatile__(						\
-	"1:	"insn("%2", "(%3)")"	# __put_data_asm_ll32	\n"	\
-	"2:	"insn("%D2", "4(%3)")"				\n"	\
+	"1:	"insn("%3", "%1")"	# __put_data_asm_ll32	\n"	\
+	"2:	"insn("%D3", "%2")"				\n"	\
 	"3:							\n"	\
 	"	.insn						\n"	\
 	"	.section	.fixup,\"ax\"			\n"	\
@@ -328,9 +331,8 @@ do {									\
 	"	" __UA_ADDR "	1b, 4b				\n"	\
 	"	" __UA_ADDR "	2b, 4b				\n"	\
 	"	.previous"						\
-	: "=r" (__pu_err)						\
-	: "0" (0), "r" (__pu_val), "r" (ptr),				\
-	  "i" (-EFAULT));						\
+	: "+r" (__pu_err), "=m" (__m(__ptr)), "=m" (__m(__ptr + 4))	\
+	: "r" (__pu_val),  "i" (-EFAULT));				\
 }
 
 #define __put_kernel_nofault(dst, src, type, err_label)			\
-- 
2.27.0




[Index of Archives]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux