[PATCH] firmware: fw_base: Improve exception stack setup in trap handler

Anup Patel anup.patel at wdc.com
Mon Aug 10 09:52:45 EDT 2020


Currently, the low-level trap handler (i.e. _trap_handler()) uses
branch instructions to conditionally setup exception stack based
on which mode trap occured.

This patch implements exception stack setup using xor instructions
which is 2 instructions less compared to previous approach and faster
due to lack of branch instructions.

The new exception stack setup approach can be best described by the
following pseudocode:

Came_From_M_Mode = (MSTATUS.MPP & 0x2) >> 1
Exception_Stack = TP ^ (Came_From_M_Mode * (SP ^ TP))

Came_From_M_Mode = 0    ==>    Exception_Stack = TP
Came_From_M_Mode = 1    ==>    Exception_Stack = SP

Signed-off-by: Anup Patel <anup.patel at wdc.com>
---
 firmware/fw_base.S | 49 ++++++++++++++++++++--------------------------
 1 file changed, 21 insertions(+), 28 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index b66ac41..53a9a48 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -490,35 +490,28 @@ _trap_handler:
 	/* Save T0 in scratch space */
 	REG_S	t0, SBI_SCRATCH_TMP0_OFFSET(tp)
 
-	/* Check which mode we came from */
+	/*
+	 * Set T0 to appropriate exception stack
+	 *
+	 * Came_From_M_Mode = (MSTATUS.MPP & 0x2) >> 1
+	 * Exception_Stack = TP ^ (Came_From_M_Mode * (SP ^ TP))
+	 *
+	 * Came_From_M_Mode = 0    ==>    Exception_Stack = TP
+	 * Came_From_M_Mode = 1    ==>    Exception_Stack = SP
+	 */
 	csrr	t0, CSR_MSTATUS
-	srl	t0, t0, MSTATUS_MPP_SHIFT
-	and	t0, t0, PRV_M
-	xori	t0, t0, PRV_M
-	beq	t0, zero, _trap_handler_m_mode
-
-	/* We came from S-mode or U-mode */
-_trap_handler_s_mode:
-	/* Set T0 to original SP */
-	add	t0, sp, zero
-
-	/* Setup exception stack */
-	add	sp, tp, -(SBI_TRAP_REGS_SIZE)
-
-	/* Jump to code common for all modes */
-	j	_trap_handler_all_mode
-
-	/* We came from M-mode */
-_trap_handler_m_mode:
-	/* Set T0 to original SP */
-	add	t0, sp, zero
-
-	/* Re-use current SP as exception stack */
-	add	sp, sp, -(SBI_TRAP_REGS_SIZE)
-
-_trap_handler_all_mode:
-	/* Save original SP (from T0) on stack */
-	REG_S	t0, SBI_TRAP_REGS_OFFSET(sp)(sp)
+	srl	t0, t0, (MSTATUS_MPP_SHIFT + 1)
+	and	t0, t0, 0x1
+	xor	sp, sp, tp
+	mul	t0, t0, sp
+	xor	sp, sp, tp
+	xor	t0, tp, t0
+
+	/* Save original SP on exception stack */
+	REG_S	sp, (SBI_TRAP_REGS_OFFSET(sp) - SBI_TRAP_REGS_SIZE)(t0)
+
+	/* Set SP to exception stack and make room for trap registers */
+	add	sp, t0, -(SBI_TRAP_REGS_SIZE)
 
 	/* Restore T0 from scratch space */
 	REG_L	t0, SBI_SCRATCH_TMP0_OFFSET(tp)
-- 
2.25.1




More information about the opensbi mailing list