[RFC] MIPS: R5900: Workaround exception NOP execution bug (FLX05)

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

 



For the R5900, there are cases in which the first two instructions
in an exception handler are executed as NOP instructions, when
certain exceptions occur and then a bus error occurs immediately
before jumping to the exception handler (FLX05).

The corrective measure is to place NOP in the first two instruction
locations in all exception handlers.

Signed-off-by: Fredrik Noring <noring@xxxxxxxxxx>
---
This change has been ported from v2.6 patches.

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index c7b64f4a8ad3..4008298c1880 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -32,6 +32,10 @@
 NESTED(except_vec3_generic, 0, sp)
 	.set	push
 	.set	noat
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 #if R5432_CP0_INTERRUPT_WAR
 #ifdef CONFIG_CPU_R5900
 	sync.p
@@ -62,6 +66,8 @@ NESTED(except_vec3_r4000, 0, sp)
 	.set	arch=r4000
 	.set	noat
 #ifdef CONFIG_CPU_R5900
+	nop
+	nop
 	sync.p
 #endif
 	mfc0	k1, CP0_CAUSE
@@ -174,6 +180,10 @@ LEAF(__r4k_wait)
 	.align	5
 BUILD_ROLLBACK_PROLOGUE handle_int
 NESTED(handle_int, PT_SIZE, sp)
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	.cfi_signal_frame
 #ifdef CONFIG_TRACE_IRQFLAGS
 	/*
@@ -275,6 +285,10 @@ NESTED(handle_int, PT_SIZE, sp)
  * to fit into space reserved for the exception handler.
  */
 NESTED(except_vec4, 0, sp)
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 1:	j	1b			/* Dummy, will be replaced */
 	END(except_vec4)
 
@@ -285,6 +299,10 @@ NESTED(except_vec4, 0, sp)
  * unconditional jump to this vector.
  */
 NESTED(except_vec_ejtag_debug, 0, sp)
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	j	ejtag_debug_handler
 #ifdef CONFIG_CPU_MICROMIPS
 	 nop
@@ -300,6 +318,10 @@ NESTED(except_vec_ejtag_debug, 0, sp)
  */
 BUILD_ROLLBACK_PROLOGUE except_vec_vi
 NESTED(except_vec_vi, 0, sp)
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	SAVE_SOME docfi=1
 	SAVE_AT docfi=1
 	.set	push
@@ -319,6 +341,10 @@ EXPORT(except_vec_vi_end)
  * Complete the register saves and invoke the handler which is passed in $v0
  */
 NESTED(except_vec_vi_handler, 0, sp)
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	SAVE_TEMP
 	SAVE_STATIC
 	CLI
@@ -378,6 +404,10 @@ NESTED(except_vec_vi_handler, 0, sp)
 NESTED(ejtag_debug_handler, PT_SIZE, sp)
 	.set	push
 	.set	noat
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	MTC0	k0, CP0_DESAVE
 #ifdef CONFIG_CPU_R5900
 	sync.p
@@ -424,6 +454,10 @@ EXPORT(ejtag_debug_buffer)
  * unconditional jump to this vector.
  */
 NESTED(except_vec_nmi, 0, sp)
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	j	nmi_handler
 #ifdef CONFIG_CPU_MICROMIPS
 	 nop
@@ -436,6 +470,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	.cfi_signal_frame
 	.set	push
 	.set	noat
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	/*
 	 * Clear ERL - restore segment mapping
 	 * Clear BEV - required for page fault exception handler to work
@@ -521,6 +559,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	NESTED(handle_\exception, PT_SIZE, sp)
 	.cfi_signal_frame
 	.set	noat
+#ifdef CONFIG_CPU_R5900
+	nop
+	nop
+#endif
 	SAVE_ALL
 	FEXPORT(handle_\exception\ext)
 	__build_clear_\clear
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 89b425646647..e56f988b5c20 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -30,6 +30,18 @@ NESTED(handle_sys, PT_SIZE, sp)
 	.set	noat
 #ifdef CONFIG_CPU_R5900
 	/*
+	 * For the R5900, there are cases in which the first two instructions
+	 * in an exception handler are executed as NOP instructions, when
+	 * certain exceptions occur and then a bus error occurs immediately
+	 * before jumping to the exception handler (FLX05).
+	 *
+	 * The corrective measure is to place NOP in the first two instruction
+	 * locations in all exception handlers.
+	 */
+	nop
+	nop
+
+	/*
 	 * We don't want to stumble over broken sign extensions from
 	 * userland. O32 does never use the upper half, but since the
 	 * R5900 does not implement CP0.Status.UX it cannot enforce it.
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index a18b013fd887..fc7ec8f9eed8 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -1308,6 +1308,11 @@ static void build_r4000_tlb_refill_handler(void)
 	memset(relocs, 0, sizeof(relocs));
 	memset(final_handler, 0, sizeof(final_handler));
 
+#ifdef CONFIG_CPU_R5900
+	uasm_i_nop(&p);
+	uasm_i_nop(&p);
+#endif
+
 	if (IS_ENABLED(CONFIG_64BIT) && (scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) {
 		htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
 							  scratch_reg);
@@ -2049,6 +2054,11 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
 {
 	struct work_registers wr = build_get_work_registers(p);
 
+#ifdef CONFIG_CPU_R5900
+	uasm_i_nop(p);
+	uasm_i_nop(p);
+#endif
+
 #ifdef CONFIG_64BIT
 	build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
 #else


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

  Powered by Linux