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

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

 



Hello Fredrik,

> Gesendet: Sonntag, 11. Februar 2018 um 09:29 Uhr
> Von: "Fredrik Noring" <noring@xxxxxxxxxx>
> An: "Maciej W. Rozycki" <macro@xxxxxxxx>, "Jürgen Urban" <JuergenUrban@xxxxxx>
> Cc: linux-mips@xxxxxxxxxxxxxx
> Betreff: [RFC] MIPS: R5900: Use mandatory SYNC.L in exception handlers
>
> 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?

The tx79architecture.pdf says:
2.4 kuseg becomes an uncached area when an error exception (Status.ERL = 1) occurs (FLX04)
2.4.1 Phenomenon
There are cases in which kuseg (0x0000_0000 – 0x7FFF_FFFF) becomes uncached in an error exception handler (Status.ERL==1) and data consistency with cached area (kseg, ksseg, kseg0) is lost.
2.4.2 Corrective measures
In an error exception handler (Status.ERL==1), when accessing kuseg (0x0000_0000 – 0x7FFF_FFFF), access it after guarding using SYNC.L as follows:
SYNC.L
SW ku seg

Best regards
Jürgen

> 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