[PATCH] firmware: fw_base: Improve exception stack setup in trap handler
Jessica Clarke
jrtc27 at jrtc27.com
Mon Aug 10 10:05:05 EDT 2020
On 10 Aug 2020, at 14:52, Anup Patel <Anup.Patel at wdc.com> wrote:
>
> 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
This relies on PRIV 0b10 currently being unallocated, which doesn't
make me feel warm and fuzzy inside.
> Exception_Stack = TP ^ (Came_From_M_Mode * (SP ^ TP))
This relies on MUL with 0/1 being fast, but that may well be a different
pipeline in your processor (in an OoO core) with fewer available, or a
higher-latency path to an M-box in a simpler in-order pipeline. The MUL
is also not compressible. You probably do want a branch, but in a way
that macro-op fusion will hopefully turn it into a conditional move:
mv Exception_Stack, tp
beqz Came_From_M_Mode, 1f
mv Exception_Stack, sp
1:
Same number of instructions, but all compressible, no multiplications
required and the lone branch can be macro-op fused.
Jess
> 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
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
More information about the opensbi
mailing list