diff mbox series

[013/120] MIPS: R5900: Avoid pipeline hazard with the TLBR instruction

Message ID 815e58a51f40c56ea8b02bc39f9ed5f1639a69ee.1567326213.git.noring@nocrew.org (mailing list archive)
State RFC
Headers show
Series Linux for the PlayStation 2 | expand

Commit Message

Fredrik Noring Sept. 1, 2019, 3:40 p.m. UTC
On the R5900, the TLBR instruction must be immediately followed by an
ERET or a SYNC.P instruction[1].

References:

[1] "TX System RISC TX79 Core Architecture" manual, revision 2.0,
    Toshiba Corporation, p. C-38, https://wiki.qemu.org/File:C790.pdf

Signed-off-by: Fredrik Noring <noring@nocrew.org>
---
 arch/mips/include/asm/mipsregs.h |  4 ++++
 arch/mips/mm/tlbex.c             | 24 ++++++++++++++++++++++++
 2 files changed, 28 insertions(+)
diff mbox series

Patch

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 2aa947b3d0d1..ec22406c800f 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -2728,6 +2728,10 @@  static inline void tlb_read(void)
 
 	__asm__ __volatile__(
 		".set noreorder\n\t"
+#ifdef CONFIG_CPU_R5900
+		/* instruction must not be at the end of a page. */
+		".align 8\n\t"
+#endif
 		"tlbr\n\t"
 #ifdef CONFIG_CPU_R5900
 		"sync.p\n\t"
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 89ff0eae5397..1caa0214d57a 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -2185,6 +2185,18 @@  static void build_r4000_tlb_load_handler(void)
 
 		uasm_i_tlbr(&p);
 
+#ifdef CONFIG_CPU_R5900
+		/*
+		 * On the R5900, the TLBR instruction must be immediately
+		 * followed by an ERET or a SYNC.P instruction.
+		 */
+		uasm_i_syncp(&p);
+		uasm_i_nop(&p);
+		uasm_i_nop(&p);
+		uasm_i_nop(&p);
+		uasm_i_nop(&p);
+#endif
+
 		switch (current_cpu_type()) {
 		default:
 			if (cpu_has_mips_r2_exec_hazard) {
@@ -2260,6 +2272,18 @@  static void build_r4000_tlb_load_handler(void)
 
 		uasm_i_tlbr(&p);
 
+#ifdef CONFIG_CPU_R5900
+		/*
+		 * On the R5900, the TLBR instruction must be immediately
+		 * followed by an ERET or a SYNC.P instruction.
+		 */
+		uasm_i_syncp(&p);
+		uasm_i_nop(&p);
+		uasm_i_nop(&p);
+		uasm_i_nop(&p);
+		uasm_i_nop(&p);
+#endif
+
 		switch (current_cpu_type()) {
 		default:
 			if (cpu_has_mips_r2_exec_hazard) {