[RFC] MIPS: R5900: Use mandatory SYNC.L in exception handlers

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

 



Hi Jürgen,

Would you be able to explain the notes

	/* In an error exception handler the user space could be uncached. */

in the patch ported from v2.6 below?

Fredrik

diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index b463f2aa5a61..79390b194e6d 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -19,9 +19,12 @@
 extern void _mcount(void);
 #define mcount _mcount
 
+#ifdef CONFIG_CPU_R5900
 #define safe_load(load, src, dst, error)		\
 do {							\
 	asm volatile (					\
+		/* In an error exception handler the user space could be uncached. */ \
+		"sync.l							\n"	\
 		"1: " load " %[tmp_dst], 0(%[tmp_src])\n"	\
 		"   li %[tmp_err], 0\n"			\
 		"2: .insn\n"				\
@@ -40,7 +43,55 @@ do {							\
 		: "memory"				\
 	);						\
 } while (0)
+#else
+#define safe_load(load, src, dst, error)		\
+do {							\
+	asm volatile (					\
+		"1: " load " %[" STR(dst) "], 0(%[" STR(src) "])\n"\
+		"   li %[" STR(error) "], 0\n"		\
+		"2:\n"					\
+							\
+		".section .fixup, \"ax\"\n"		\
+		"3: li %[" STR(error) "], 1\n"		\
+		"   j 2b\n"				\
+		".previous\n"				\
+							\
+		".section\t__ex_table,\"a\"\n\t"	\
+		STR(PTR) "\t1b, 3b\n\t"			\
+		".previous\n"				\
+							\
+		: [dst] "=&r" (dst), [error] "=r" (error)\
+		: [src] "r" (src)			\
+		: "memory"				\
+	);						\
+} while (0)
+#endif
 
+#ifdef CONFIG_CPU_R5900
+#define safe_store(store, src, dst, error)	\
+do {						\
+	asm volatile (				\
+		/* In an error exception handler the user space could be uncached. */ \
+		"sync.l							\n"	\
+		"1: " store " %[" STR(src) "], 0(%[" STR(dst) "])\n"\
+		"   li %[" STR(error) "], 0\n"	\
+		"2:\n"				\
+						\
+		".section .fixup, \"ax\"\n"	\
+		"3: li %[" STR(error) "], 1\n"	\
+		"   j 2b\n"			\
+		".previous\n"			\
+						\
+		".section\t__ex_table,\"a\"\n\t"\
+		STR(PTR) "\t1b, 3b\n\t"		\
+		".previous\n"			\
+						\
+		: [error] "=r" (error)		\
+		: [dst] "r" (dst), [src] "r" (src)\
+		: "memory"			\
+	);					\
+} while (0)
+#else
 #define safe_store(store, src, dst, error)	\
 do {						\
 	asm volatile (				\
@@ -62,6 +113,7 @@ do {						\
 		: "memory"			\
 	);					\
 } while (0)
+#endif
 
 #define safe_load_code(dst, src, error) \
 	safe_load(STR(lw), src, dst, error)
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index b71306947290..a4eecafc524b 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -315,11 +315,14 @@ do {									\
 	__gu_err;							\
 })
 
+#ifdef CONFIG_CPU_R5900
 #define __get_data_asm(val, insn, addr)					\
 {									\
 	long __gu_tmp;							\
 									\
 	__asm__ __volatile__(						\
+	/* In an error exception handler the user space could be uncached. */ \
+	"sync.l							\n"	\
 	"1:	"insn("%1", "%3")"				\n"	\
 	"2:							\n"	\
 	"	.insn						\n"	\
@@ -336,10 +339,32 @@ do {									\
 									\
 	(val) = (__typeof__(*(addr))) __gu_tmp;				\
 }
+#else
+#define __get_data_asm(val, insn, addr)					\
+{									\
+	long __gu_tmp;							\
+									\
+	__asm__ __volatile__(						\
+	"1:	"insn("%1", "%3")"				\n"	\
+	"2:							\n"	\
+	"	.section .fixup,\"ax\"				\n"	\
+	"3:	li	%0, %4					\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));			\
+									\
+	(val) = (__typeof__(*(addr))) __gu_tmp;				\
+}
+#endif
 
 /*
  * Get a long long 64 using 32 bit registers.
  */
+#ifdef CONFIG_CPU_R5900
 #define __get_data_asm_ll32(val, insn, addr)				\
 {									\
 	union {								\
@@ -348,7 +373,11 @@ do {									\
 	} __gu_tmp;							\
 									\
 	__asm__ __volatile__(						\
+	/* In an error exception handler the user space could be uncached. */ \
+	"sync.l							\n"	\
 	"1:	" insn("%1", "(%3)")"				\n"	\
+	/* In an error exception handler the user space could be uncached. */ \
+	"sync.l							\n"	\
 	"2:	" insn("%D1", "4(%3)")"				\n"	\
 	"3:							\n"	\
 	"	.insn						\n"	\
@@ -367,6 +396,33 @@ do {									\
 									\
 	(val) = __gu_tmp.t;						\
 }
+#else
+#define __get_data_asm_ll32(val, insn, addr)				\
+{									\
+	union {								\
+		unsigned long long	l;				\
+		__typeof__(*(addr))	t;				\
+	} __gu_tmp;							\
+									\
+	__asm__ __volatile__(						\
+	"1:	" insn("%1", "(%3)")"				\n"	\
+	"2:	" insn("%D1", "4(%3)")"				\n"	\
+	"3:	.section	.fixup,\"ax\"			\n"	\
+	"4:	li	%0, %4					\n"	\
+	"	move	%1, $0					\n"	\
+	"	move	%D1, $0					\n"	\
+	"	j	3b					\n"	\
+	"	.previous					\n"	\
+	"	.section	__ex_table,\"a\"		\n"	\
+	"	" __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));				\
+									\
+	(val) = __gu_tmp.t;						\
+}
+#endif
 
 #ifndef CONFIG_EVA
 #define __put_kernel_common(ptr, size) __put_user_common(ptr, size)
@@ -456,6 +512,38 @@ do {									\
 	__pu_err;							\
 })
 
+#define __put_user_check_atomic(x, ptr, size)				\
+({									\
+	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
+	__typeof__(*(ptr)) __pu_val = (x);				\
+	int __pu_err = -EFAULT;						\
+									\
+	if (likely(access_ok(VERIFY_WRITE,  __pu_addr, size))) {	\
+		__put_kernel_common(ptr, size);				\
+	}								\
+	__pu_err;							\
+})
+
+#ifdef CONFIG_CPU_R5900
+#define __put_data_asm(insn, ptr)					\
+{									\
+	__asm__ __volatile__(						\
+	/* In an error exception handler the user space could be uncached. */ \
+	"sync.l							\n"	\
+	"1:	"insn("%z2", "%3")"	# __put_data_asm	\n"	\
+	"2:							\n"	\
+	"	.section	.fixup,\"ax\"			\n"	\
+	"3:	li	%0, %4					\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));						\
+}
+#else
 #define __put_data_asm(insn, ptr)					\
 {									\
 	__asm__ __volatile__(						\
@@ -473,7 +561,32 @@ do {									\
 	: "0" (0), "Jr" (__pu_val), "o" (__m(ptr)),			\
 	  "i" (-EFAULT));						\
 }
+#endif
 
+#ifdef CONFIG_CPU_R5900
+#define __put_data_asm_ll32(insn, ptr)					\
+{									\
+	__asm__ __volatile__(						\
+	/* In an error exception handler the user space could be uncached. */ \
+	"sync.l							\n"	\
+	"1:	"insn("%2", "(%3)")"	# __put_data_asm_ll32	\n"	\
+	/* In an error exception handler the user space could be uncached. */ \
+	"sync.l							\n"	\
+	"2:	"insn("%D2", "4(%3)")"				\n"	\
+	"3:							\n"	\
+	"	.section	.fixup,\"ax\"			\n"	\
+	"4:	li	%0, %4					\n"	\
+	"	j	3b					\n"	\
+	"	.previous					\n"	\
+	"	.section	__ex_table,\"a\"		\n"	\
+	"	" __UA_ADDR "	1b, 4b				\n"	\
+	"	" __UA_ADDR "	2b, 4b				\n"	\
+	"	.previous"						\
+	: "=r" (__pu_err)						\
+	: "0" (0), "r" (__pu_val), "r" (ptr),				\
+	  "i" (-EFAULT));						\
+}
+#else
 #define __put_data_asm_ll32(insn, ptr)					\
 {									\
 	__asm__ __volatile__(						\
@@ -493,6 +606,7 @@ do {									\
 	: "0" (0), "r" (__pu_val), "r" (ptr),				\
 	  "i" (-EFAULT));						\
 }
+#endif
 
 extern void __put_user_unknown(void);
 
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index b280a3d775a1..625b74de1ce4 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -488,10 +488,15 @@ do {                                                        \
 
 #else /* __BIG_ENDIAN */
 
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
+	/* FIXME: Is ".set push\n" etc. needed? */
+	/* In an error exception handler the user space could be uncached. */
 #define     _LoadHW(addr, value, res, type)  \
 do {                                                        \
 		__asm__ __volatile__ (".set\tnoat\n"        \
+			"sync.l\n\t"                        \
 			"1:\t"type##_lb("%0", "1(%2)")"\n"  \
+			"sync.l\n\t"                        \
 			"2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
 			"sll\t%0, 0x8\n\t"                  \
 			"or\t%0, $1\n\t"                    \
@@ -511,10 +516,14 @@ do {                                                        \
 } while(0)
 
 #ifndef CONFIG_CPU_MIPSR6
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
+	/* In an error exception handler the user space could be uncached. */
 #define     _LoadW(addr, value, res, type)   \
 do {                                                        \
 		__asm__ __volatile__ (                      \
+			"sync.l\n\t"                        \
 			"1:\t"type##_lwl("%0", "3(%2)")"\n" \
+			"sync.l\n\t"                        \
 			"2:\t"type##_lwr("%0", "(%2)")"\n\t"\
 			"li\t%1, 0\n"                       \
 			"3:\n\t"                            \
@@ -569,11 +578,15 @@ do {                                                        \
 #endif /* CONFIG_CPU_MIPSR6 */
 
 
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
+	/* In an error exception handler the user space could be uncached. */
 #define     _LoadHWU(addr, value, res, type) \
 do {                                                        \
 		__asm__ __volatile__ (                      \
 			".set\tnoat\n"                      \
+			"sync.l\n\t"                        \
 			"1:\t"type##_lbu("%0", "1(%2)")"\n" \
+			"sync.l\n\t"                        \
 			"2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
 			"sll\t%0, 0x8\n\t"                  \
 			"or\t%0, $1\n\t"                    \
@@ -594,10 +607,14 @@ do {                                                        \
 } while(0)
 
 #ifndef CONFIG_CPU_MIPSR6
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
+	/* In an error exception handler the user space could be uncached. */
 #define     _LoadWU(addr, value, res, type)  \
 do {                                                        \
 		__asm__ __volatile__ (                      \
+			"sync.l\n\t"                        \
 			"1:\t"type##_lwl("%0", "3(%2)")"\n" \
+			"sync.l\n\t"                        \
 			"2:\t"type##_lwr("%0", "(%2)")"\n\t"\
 			"dsll\t%0, %0, 32\n\t"              \
 			"dsrl\t%0, %0, 32\n\t"              \
@@ -616,10 +633,14 @@ do {                                                        \
 			: "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
+	/* In an error exception handler the user space could be uncached. */
 #define     _LoadDW(addr, value, res)  \
 do {                                                        \
 		__asm__ __volatile__ (                      \
+			"sync.l\n\t"                        \
 			"1:\tldl\t%0, 7(%2)\n"              \
+			"sync.l\n\t"                        \
 			"2:\tldr\t%0, (%2)\n\t"             \
 			"li\t%1, 0\n"                       \
 			"3:\n\t"                            \
@@ -721,11 +742,15 @@ do {                                                        \
 } while(0)
 #endif /* CONFIG_CPU_MIPSR6 */
 
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
+	/* In an error exception handler the user space could be uncached. */
 #define     _StoreHW(addr, value, res, type) \
 do {                                                        \
 		__asm__ __volatile__ (                      \
 			".set\tnoat\n"                      \
+			"sync.l\n\t"                        \
 			"1:\t"type##_sb("%1", "0(%2)")"\n"  \
+			"sync.l\n\t"                        \
 			"srl\t$1,%1, 0x8\n"                 \
 			"2:\t"type##_sb("$1", "1(%2)")"\n"  \
 			".set\tat\n\t"                      \
@@ -745,10 +770,13 @@ do {                                                        \
 } while(0)
 
 #ifndef CONFIG_CPU_MIPSR6
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
 #define     _StoreW(addr, value, res, type)  \
 do {                                                        \
 		__asm__ __volatile__ (                      \
+			"sync.l\n\t"                        \
 			"1:\t"type##_swl("%1", "3(%2)")"\n" \
+			"sync.l\n\t"                        \
 			"2:\t"type##_swr("%1", "(%2)")"\n\t"\
 			"li\t%0, 0\n"                       \
 			"3:\n\t"                            \
@@ -765,10 +793,14 @@ do {                                                        \
 		: "r" (value), "r" (addr), "i" (-EFAULT));  \
 } while(0)
 
+	/* FIXME: Use #ifdef CONFIG_CPU_R5900 */
+	/* In an error exception handler the user space could be uncached. */
 #define     _StoreDW(addr, value, res) \
 do {                                                        \
 		__asm__ __volatile__ (                      \
+			"sync.l\n\t"                        \
 			"1:\tsdl\t%1, 7(%2)\n"              \
+			"sync.l\n\t"                        \
 			"2:\tsdr\t%1, (%2)\n\t"             \
 			"li\t%0, 0\n"                       \
 			"3:\n\t"                            \
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index 2ff84f4b1717..36e48682e1e1 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -357,7 +357,10 @@ EXPORT_SYMBOL(csum_partial)
  * addr    : Address
  * handler : Exception handler
  */
+/* FIXME: #ifdef CONFIG_CPU_R5900 */
 #define EXC(insn, type, reg, addr, handler)	\
+	/* In an error exception handler the user space could be uncached. */ \
+	sync.l;						\
 	.if \mode == LEGACY_MODE;		\
 9:		insn reg, addr;			\
 		.section __ex_table,"a";	\
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index 489bc9cffcbd..b37731f53f46 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -46,6 +46,11 @@
 #define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr)
 
 #define EX(insn,reg,addr,handler)			\
+	/* In an error exception handler the user space could be uncached. */ \
+	.set push;					\
+	.set noreorder;					\
+	sync.l;						\
+	.set pop;					\
 	.if \mode == LEGACY_MODE;			\
 9:		insn	reg, addr;			\
 	.else;						\
@@ -171,6 +176,19 @@
 #ifdef CONFIG_CPU_MICROMIPS
 	LONG_SRL	t7, t0, 1
 #endif
+#ifdef CONFIG_CPU_R5900
+	/* Each instruction has a leading sync.l */
+#if LONGSIZE == 4
+	.set		noat
+	/* 2 instructions for 4 Byte. */
+	LONG_SLL	AT, t0, 1
+	PTR_SUBU	t1, AT
+	.set		at
+#else
+	/* Verify memset for R5900 with 64 bit. 2 instructions for 8 Byte. */
+	PTR_SUBU	t1, t0
+#endif
+#else
 #if LONGSIZE == 4
 	PTR_SUBU	t1, FILLPTRG
 #else
@@ -179,6 +197,7 @@
 	PTR_SUBU	t1, AT
 	.set		at
 #endif
+#endif /* CONFIG_CPU_R5900 */
 	jr		t1
 	PTR_ADDU	a0, t0			/* dest ptr */
 
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
index 44cc346fd400..0cf9a6660130 100644
--- a/arch/mips/lib/strncpy_user.S
+++ b/arch/mips/lib/strncpy_user.S
@@ -13,6 +13,8 @@
 #include <asm/regdef.h>
 
 #define EX(insn,reg,addr,handler)			\
+	/* In an error exception handler the user space could be uncached. */ \
+	sync.l;							\
 9:	insn	reg, addr;				\
 	.section __ex_table,"a";			\
 	PTR	9b, handler;				\
diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S
index 474979641a8d..55f7e069a960 100644
--- a/arch/mips/lib/strnlen_user.S
+++ b/arch/mips/lib/strnlen_user.S
@@ -12,6 +12,8 @@
 #include <asm/regdef.h>
 
 #define EX(insn,reg,addr,handler)			\
+	/* In an error exception handler the user space could be uncached. */ \
+	sync.l;							\
 9:	insn	reg, addr;				\
 	.section __ex_table,"a";			\
 	PTR	9b, handler;				\


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

  Powered by Linux