[RFC] MIPS: R5900: Workaround for CACHE instruction near branch delay slot

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

 



Signed-off-by: Fredrik Noring <noring@xxxxxxxxxx>
---
This change has been ported from v2.6 patches. I have not found any note
describing this in the TX79 manual.

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 4008298c1880..a0b0fbedad8c 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -52,6 +52,14 @@ NESTED(except_vec3_generic, 0, sp)
 #endif
 	PTR_L	k0, exception_handlers(k1)
 	jr	k0
+#ifdef CONFIG_CPU_R5900
+	/* There should be nothing which looks like a cache instruction. */
+	nop
+	nop
+	nop
+	nop
+	nop
+#endif
 	.set	pop
 	END(except_vec3_generic)
 
@@ -709,6 +717,14 @@ isrdhwr:
 	.set	arch=r4000
 	eret
 	.set	mips0
+#ifdef CONFIG_CPU_R5900
+	/* There should be nothing which looks like cache instruction. */
+	nop
+	nop
+	nop
+	nop
+	nop
+#endif
 #endif
 	.set	pop
 	END(handle_ri_rdhwr)
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 761b6c369321..795c490a429f 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1950,12 +1950,36 @@ void __init *set_except_vector(int n, void *addr)
 		u32 *buf = (u32 *)(ebase + 0x200);
 		unsigned int k0 = 26;
 		if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
+#ifdef CONFIG_CPU_R5900
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+#endif
 			uasm_i_j(&buf, handler & ~jump_mask);
 			uasm_i_nop(&buf);
+#ifdef CONFIG_CPU_R5900
+			/* There are no data allowed which could be interpreted as cache instruction. */
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+#endif
 		} else {
+#ifdef CONFIG_CPU_R5900
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+#endif
 			UASM_i_LA(&buf, k0, handler);
 			uasm_i_jr(&buf, k0);
 			uasm_i_nop(&buf);
+#ifdef CONFIG_CPU_R5900
+			/* There are no data allowed which could be interpreted as cache instruction. */
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+			uasm_i_nop(&buf);
+#endif
 		}
 		local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
 	}


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

  Powered by Linux