[PATCH v2 4/5] lib: sbi: Create a spot to place Smrnmi detection before traps and after DT is ready
Anup Patel
anup at brainfault.org
Mon May 4 02:00:53 PDT 2026
On Sat, May 2, 2026 at 2:46 AM Evgeny Voevodin <evvoevod at tenstorrent.com> wrote:
>
> Since Smrnmi is detected from the device tree, move
> sbi_platform_extensions_init() before trap-based feature detection so
> the extension is known when the next commit acts on it.
>
> The Zkr seed-CSR access can trap if Zkr is not implemented. On Smrnmi
> platforms NMIE=0 by default after reset, which routes that trap to
> NMEVEC rather than MTVEC. Until Smrnmi handlers are installed and
> NMIE=1, no NMEVEC handler is in place, so an early-boot trap there
> would crash. Refactor the inline seed loop in fw_base.S into a
> callable __stack_chk_guard_init function and invoke it from
> init_coldboot() after sbi_hart_init() returns; the next commit makes
> sbi_hart_init() install Smrnmi handlers and set NMIE=1, so by the time
> __stack_chk_guard_init runs the trap path is safe.
>
> Signed-off-by: Evgeny Voevodin <evvoevod at tenstorrent.com>
> ---
> firmware/fw_base.S | 64 +++++++++++++++++++++++++++++-----------------
> lib/sbi/sbi_hart.c | 16 +++++++-----
> lib/sbi/sbi_init.c | 10 ++++++++
> 3 files changed, 60 insertions(+), 30 deletions(-)
>
> diff --git a/firmware/fw_base.S b/firmware/fw_base.S
> index 043de7d7..ebecfecc 100644
> --- a/firmware/fw_base.S
> +++ b/firmware/fw_base.S
> @@ -107,30 +107,6 @@ _bss_zero:
> add s4, s4, __SIZEOF_POINTER__
> blt s4, s5, _bss_zero
>
> - /* Trying to initialize the stack guard via the Zkr extension */
> - lla t0, __stack_chk_guard_done
> - csrw CSR_MTVEC, t0
> - li t0, 0
> - li t3, SEED_OPTS_ES16
> - li t4, SEED_ENTROPY_MASK
> - li t5, __SIZEOF_POINTER__
> -__stack_chk_guard_loop:
> - csrrw t1, CSR_SEED, x0
> - li t2, SEED_OPTS_MASK
> - and t2, t2, t1
> - bgtu t2, t3, __stack_chk_guard_done
> - bltu t2, t3, __stack_chk_guard_loop
> - and t1, t1, t4
> - slli t0, t0, 16
> - or t0, t0, t1
> - addi t5, t5, -2
> - bgtz t5, __stack_chk_guard_loop
> - lla t1, __stack_chk_guard
> - REG_S t0, 0(t1)
> - j __stack_chk_guard_done
> - .align 3
> -__stack_chk_guard_done:
> -
> /* Setup temporary trap handler */
> lla s4, _start_hang
> csrw CSR_MTVEC, s4
> @@ -895,6 +871,46 @@ __stack_chk_fail:
> la a0, .Lstack_corrupt_msg
> call sbi_panic
>
> + /*
> + * Initialize __stack_chk_guard from the Zkr seed CSR. Called from C
> + * after Smrnmi has been enabled (NMIE=1), so that a missing-Zkr
> + * illegal-instruction trap is delivered to MTVEC normally and is
> + * caught by our temporary MTVEC redirect below.
> + */
> + .align 3
> + .globl __stack_chk_guard_init
> + .type __stack_chk_guard_init, %function
> +__stack_chk_guard_init:
> + /* Save current MTVEC so we can restore it on return */
> + csrr t6, CSR_MTVEC
> +
> + /* Redirect MTVEC to local skip target for Zkr-not-supported case */
> + lla t0, 1f
> + csrw CSR_MTVEC, t0
> +
> + li t0, 0
> + li t3, SEED_OPTS_ES16
> + li t4, SEED_ENTROPY_MASK
> + li t5, __SIZEOF_POINTER__
> +2:
> + csrrw t1, CSR_SEED, x0
> + li t2, SEED_OPTS_MASK
> + and t2, t2, t1
> + bgtu t2, t3, 1f
> + bltu t2, t3, 2b
> + and t1, t1, t4
> + slli t0, t0, 16
> + or t0, t0, t1
> + addi t5, t5, -2
> + bgtz t5, 2b
> + lla t1, __stack_chk_guard
> + REG_S t0, 0(t1)
> + j 1f
> + .align 3
> +1:
> + csrw CSR_MTVEC, t6
> + ret
> +
Initializing __stack_chk_guard from C code may break stack
canary already pushed on stack hence it is better to initialize
__stack_chk_guard in low-level code before entering C code.
Instead of the approach taken by this patch, my suggestion
is to set mnstatus.NMIE early on so that mtvec based trap
behave normally and setup NMI trap handler later in the
fw_platform_init() or nascent_init().
Something like below, can help ...
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 043de7d7..21d59e71 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -39,6 +39,16 @@
li \tmp, MSTATUS_MDT
csrc CSR_MSTATUS, \tmp
#endif
+.endm
+
+.macro PARTIALLY_ENABLE_SMRNMI tmp
+ lla \tmp, 9999f
+ csrw CSR_MTVEC, \tmp
+ li \tmp, MNSTATUS_NMIE
+ csrs CSR_MNSTATUS, MNSTATUS_NMIE
+ j 9999f
+ .align 3
+9999:
.endm
.section .entry, "ax", %progbits
@@ -107,6 +117,12 @@ _bss_zero:
add s4, s4, __SIZEOF_POINTER__
blt s4, s5, _bss_zero
+ /*
+ * Partially enable Smrnmi early for boot HART so that
+ * normal traps get routed to mtvec trap handler.
+ */
+ PARTIALLY_ENABLE_SMRNMI t0
+
/* Trying to initialize the stack guard via the Zkr extension */
lla t0, __stack_chk_guard_done
csrw CSR_MTVEC, t0
@@ -339,6 +355,12 @@ _wait_for_boot_hart:
bne t0, t1, _wait_for_boot_hart
_start_warm:
+ /*
+ * Partially enable Smrnmi early for current HART so that
+ * normal traps get routed to mtvec trap handler.
+ */
+ PARTIALLY_ENABLE_SMRNMI t0
+
/* Reset all registers except ra, a0, a1, a2, a3 and a4 for
non-boot HART */
li ra, 0
call _reset_regs
Regards,
Anup
More information about the opensbi
mailing list