[PATCH v2 4/5] lib: sbi: Create a spot to place Smrnmi detection before traps and after DT is ready

Evgeny Voevodin evvoevod at tenstorrent.com
Fri May 1 14:16:26 PDT 2026


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
+
 	/* Initial value of the stack guard variable */
 	.section .data
 	.align 3
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 4aefb759..781161e5 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -522,6 +522,16 @@ static int hart_detect_features(struct sbi_scratch *scratch)
 	hfeatures->mhpm_mask = 0;
 	hfeatures->priv_version = SBI_HART_PRIV_VER_UNKNOWN;
 
+	/*
+	 * Parse device tree extensions early, before any trap-based checks.
+	 * Needed to detect Smrnmi and install NMI handlers before CSR probes
+	 * that may trigger traps.
+	 */
+	rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(),
+					  hfeatures);
+	if (rc)
+		return rc;
+
 #define __check_hpm_csr(__csr, __mask) 					  \
 	oldval = csr_read_allowed(__csr, &trap);			  \
 	if (!trap.cause) {						  \
@@ -676,12 +686,6 @@ __pmp_skip:
 
 #undef __check_csr_existence
 
-	/* Let platform populate extensions */
-	rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(),
-					  hfeatures);
-	if (rc)
-		return rc;
-
 	/* Zicntr should only be detected using traps */
 	__sbi_hart_update_extension(hfeatures, SBI_HART_EXT_ZICNTR,
 			    sbi_hart_has_csr(scratch, SBI_HART_CSR_CYCLE) &&
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index aae035e1..644f62cb 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -36,6 +36,8 @@
 #include <sbi/sbi_version.h>
 #include <sbi/sbi_unit_test.h>
 
+extern void __stack_chk_guard_init(void);
+
 #define BANNER                                              \
 	"   ____                    _____ ____ _____\n"     \
 	"  / __ \\                  / ____|  _ \\_   _|\n"  \
@@ -269,6 +271,14 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 	if (rc)
 		sbi_hart_hang();
 
+	/*
+	 * Initialize stack-guard canary now that hart_detect_features()
+	 * has enabled Smrnmi (NMIE=1). Done from a __noreturn function so
+	 * the canary mutation doesn't trip our own exit check. The asm
+	 * helper saves and restores MTVEC around its operation.
+	 */
+	__stack_chk_guard_init();
+
 	rc = sbi_timer_init(scratch, true);
 	if (rc)
 		sbi_hart_hang();
-- 
2.43.0




More information about the opensbi mailing list