diff mbox series

[010/120] MIPS: R5900: Workaround exception NOP execution bug (FLX05)

Message ID 9b8beb1e11159a3a42233c64ea86607a5954d558.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:39 p.m. UTC
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)[1].

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

References:

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

Signed-off-by: Fredrik Noring <noring@nocrew.org>
---
 arch/mips/kernel/genex.S | 5 +++++
 arch/mips/kernel/traps.c | 6 ++++++
 arch/mips/mm/tlbex.c     | 6 ++++++
 3 files changed, 17 insertions(+)

Comments

Philippe Mathieu-Daudé Sept. 1, 2019, 11:01 p.m. UTC | #1
On 9/1/19 5:39 PM, Fredrik Noring wrote:
> 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)[1].
> 
> The corrective measure is to place NOP in the first two instruction
> locations in all exception handlers.
> 
> References:
> 
> [1] "TX System RISC TX79 Core Architecture" manual, revision 2.0,
>     Toshiba Corporation, p. 1-11, https://wiki.qemu.org/File:C790.pdf
> 
> Signed-off-by: Fredrik Noring <noring@nocrew.org>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  arch/mips/kernel/genex.S | 5 +++++
>  arch/mips/kernel/traps.c | 6 ++++++
>  arch/mips/mm/tlbex.c     | 6 ++++++
>  3 files changed, 17 insertions(+)
> 
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index 6eaf057e5d95..f57842b785b2 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -32,6 +32,11 @@
>  NESTED(except_vec3_generic, 0, sp)
>  	.set	push
>  	.set	noat
> +#ifdef CONFIG_CPU_R5900
> +	/* Workaround for R5900 exception execution bug (FLX05). */
> +	nop
> +	nop
> +#endif
>  #if R5432_CP0_INTERRUPT_WAR
>  #ifdef CONFIG_CPU_R5900
>  	sync.p
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 9423b9a2eb67..9c98475c7dc6 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -1953,6 +1953,12 @@ void __init *set_except_vector(int n, void *addr)
>  #endif
>  		u32 *buf = (u32 *)(ebase + 0x200);
>  		unsigned int k0 = 26;
> +
> +#ifdef CONFIG_CPU_R5900
> +		/* Workaround for R5900 exception execution bug (FLX05). */
> +		uasm_i_nop(&buf);
> +		uasm_i_nop(&buf);
> +#endif
>  		if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
>  			uasm_i_j(&buf, handler & ~jump_mask);
>  			uasm_i_nop(&buf);
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 543ddb22b0d9..82136c346885 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -1313,6 +1313,12 @@ static void build_r4000_tlb_refill_handler(void)
>  	memset(relocs, 0, sizeof(relocs));
>  	memset(final_handler, 0, sizeof(final_handler));
>  
> +#ifdef CONFIG_CPU_R5900
> +	/* Workaround for R5900 exception execution bug (FLX05). */
> +	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);
>
diff mbox series

Patch

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 6eaf057e5d95..f57842b785b2 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -32,6 +32,11 @@ 
 NESTED(except_vec3_generic, 0, sp)
 	.set	push
 	.set	noat
+#ifdef CONFIG_CPU_R5900
+	/* Workaround for R5900 exception execution bug (FLX05). */
+	nop
+	nop
+#endif
 #if R5432_CP0_INTERRUPT_WAR
 #ifdef CONFIG_CPU_R5900
 	sync.p
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9423b9a2eb67..9c98475c7dc6 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1953,6 +1953,12 @@  void __init *set_except_vector(int n, void *addr)
 #endif
 		u32 *buf = (u32 *)(ebase + 0x200);
 		unsigned int k0 = 26;
+
+#ifdef CONFIG_CPU_R5900
+		/* Workaround for R5900 exception execution bug (FLX05). */
+		uasm_i_nop(&buf);
+		uasm_i_nop(&buf);
+#endif
 		if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
 			uasm_i_j(&buf, handler & ~jump_mask);
 			uasm_i_nop(&buf);
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 543ddb22b0d9..82136c346885 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -1313,6 +1313,12 @@  static void build_r4000_tlb_refill_handler(void)
 	memset(relocs, 0, sizeof(relocs));
 	memset(final_handler, 0, sizeof(final_handler));
 
+#ifdef CONFIG_CPU_R5900
+	/* Workaround for R5900 exception execution bug (FLX05). */
+	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);