public inbox for opensbi@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH v4 0/3] Add support for RISC-V Smrnmi extension
@ 2026-03-13 13:39 Nylon Chen
  2026-03-13 13:39 ` [PATCH v4 1/3] lib: sbi: Add Smrnmi extension detection Nylon Chen
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Nylon Chen @ 2026-03-13 13:39 UTC (permalink / raw)
  To: opensbi
  Cc: zong.li, nick.hu, samuel.holland, yongxuan.wang, anup, rkrcmar,
	atishp, Nylon Chen

This patch series adds support for the RISC-V Smrnmi (Resumable
Non-Maskable Interrupts) extension to OpenSBI.

1. PATCH 1/3: Add Smrnmi extension detection
   - Defines Smrnmi CSR registers (MNSCRATCH, MNEPC, MNCAUSE, MNSTATUS)
   - Defines MNSTATUS bit fields (NMIE, MNPV, MNPELP, MNPP)
   - Registers the Smrnmi extension in hart extension enumeration

2. PATCH 2/3: Enable Smrnmi extension handler
   - Implements rnmi_vector_init() as a static function in sbi_hart.c
   - Sets MNSCRATCH to the scratch pointer (same role as MSCRATCH)
   - Adds platform operation set_rnmi_trap_vector() for trap vector programming
   - Adds suspend/resume support for RNMI CSRs (MNSCRATCH, MNSTATUS)
   - Calls rnmi_vector_init() at the end of sbi_hart_init()
   - Note: Does not yet enable RNMI; trap vector setup deferred to Patch 3

3. PATCH 3/3: Add common NMI trap handler
   - Implements sbi_rnmi_vector assembly entry point in fw_base.S
   - Checks MNSTATUS.MNPP to distinguish S/U-mode vs M-mode interrupts
   - Uses scratch area for S/U-mode interrupts
   - Reuses existing M-mode stack for M-mode interrupts (nested RNMI)
   - Implements default sbi_rnmi_trap_handler() in C (marked __attribute__((weak)))
   - Completes rnmi_vector_init() with platform hook call and NMIE enablement

Changes in v4:
 - Added MNSTATUS.MNPELP bit definition (for Zicfilp extension)
 - Made rnmi_vector_init() a static function and removed global declaration
 - Moved rnmi_vector_init() call from sbi_init.c to end of sbi_hart_init()
 - Changed set_rnmi_trap_vector() parameter type from uintptr_t to unsigned long
 - Changed platform hook requirement from "should" to "must" in documentation
 - Simplified MNSCRATCH setup: directly use scratch pointer instead of allocating
   separate RNMI context (addresses Radim's feedback on stack space)
 - Rewrote sbi_rnmi_vector to check MNSTATUS.MNPP and reuse M-mode stack for
   nested RNMI (addresses Radim's feedback on M-mode stack reuse)
 - Removed RNMI_SAVE_REGS/RNMI_RESTORE_REGS macros in favor of explicit
   register save/restore for better control
 - Added sbi_rnmi_trap_handler() declaration in sbi_trap.h
 - Changed printf format from %016lx to PRILX macro for 32/64-bit compatibility
 - Fixed patch structure: Patch 2 now only sets up MNSCRATCH; Patch 3 completes
   the initialization with trap vector setup and NMIE enablement (ensures each
   patch can be compiled independently)
 - Marked sbi_rnmi_trap_handler() as __attribute__((weak)) to allow platform override

Changes in v3:
 - Split single patch into three-patch series per Anup's feedback:
  * PATCH 1: Add Smrnmi extension detection (without enabling NMI)
  * PATCH 2: Enable Smrnmi extension handler
  * PATCH 3: Add common NMI trap handler in fw_base.S
 - Added platform abstraction via set_rnmi_trap_vector() callback
 - Added per-HART RNMI context allocation
 - Added suspend/resume support for RNMI CSRs

Changes in v2:
 - Remove hart_smrnmi_get_allowed() and use sbi_hart_has_extension() for
   Smrnmi detection

Co-developed-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Zong Li <zong.li@sifive.com>
Suggested-by: Nick Hu <nick.hu@sifive.com>
Suggested-by: Samuel Holland <samuel.holland@sifive.com>
Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>

Nylon Chen (3):
  lib: sbi: Add Smrnmi extension detection
  lib: sbi: Enable Smrnmi extension handler
  firmware: fw_base.S: Add common NMI trap handler

 firmware/fw_base.S           | 141 +++++++++++++++++++++++++++++++++++
 include/sbi/riscv_encoding.h |  12 +++
 include/sbi/sbi_hart.h       |   2 +
 include/sbi/sbi_platform.h   |   8 ++
 include/sbi/sbi_trap.h       |  22 +++++-
 lib/sbi/sbi_hart.c           |  54 +++++++++++++-
 lib/sbi/sbi_hsm.c            |  14 ++++
 lib/sbi/sbi_trap.c           |  17 +++++
 8 files changed, 267 insertions(+), 3 deletions(-)

-- 
2.43.7


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 1/3] lib: sbi: Add Smrnmi extension detection
  2026-03-13 13:39 [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen
@ 2026-03-13 13:39 ` Nylon Chen
  2026-03-13 13:39 ` [PATCH v4 2/3] lib: sbi: Enable Smrnmi extension handler Nylon Chen
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Nylon Chen @ 2026-03-13 13:39 UTC (permalink / raw)
  To: opensbi
  Cc: zong.li, nick.hu, samuel.holland, yongxuan.wang, anup, rkrcmar,
	atishp, Nylon Chen

Add detection support for the RISC-V Smrnmi (Resumable Non-Maskable
Interrupts) extension.

Co-developed-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Zong Li <zong.li@sifive.com>
Suggested-by: Nick Hu <nick.hu@sifive.com>
Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
---
 include/sbi/riscv_encoding.h | 12 ++++++++++++
 include/sbi/sbi_hart.h       |  2 ++
 lib/sbi/sbi_hart.c           |  1 +
 3 files changed, 15 insertions(+)

diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index b5a4ce81..386c1720 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -215,6 +215,12 @@
 
 #endif
 
+/* Smrnmi extension status bits */
+#define MNSTATUS_NMIE			(_UL(0x8))
+#define MNSTATUS_MNPV			(_UL(0x80))
+#define MNSTATUS_MNPELP			(_UL(0x200))
+#define MNSTATUS_MNPP			(_UL(0x1800))
+
 #define MHPMEVENT_SSCOF_MASK		_ULL(0xFF00000000000000)
 
 #define ENVCFG_STCE			(_ULL(1) << 63)
@@ -780,6 +786,12 @@
 #define CSR_MVIPH			0x319
 #define CSR_MIPH			0x354
 
+/* Smrnmi extension registers */
+#define CSR_MNSCRATCH			0x740
+#define CSR_MNEPC			0x741
+#define CSR_MNCAUSE			0x742
+#define CSR_MNSTATUS			0x744
+
 /* Vector extension registers */
 #define CSR_VSTART			0x8
 #define CSR_VL				0xc20
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index a788b34c..937cdf29 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -87,6 +87,8 @@ enum sbi_hart_extensions {
 	SBI_HART_EXT_XSIFIVE_CFLUSH_D_L1,
 	/** Hart has Xsfcease extension */
 	SBI_HART_EXT_XSIFIVE_CEASE,
+	/** Hart has Smrnmi extension */
+	SBI_HART_EXT_SMRNMI,
 
 	/** Maximum index of Hart extension */
 	SBI_HART_EXT_MAX,
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 60e95bca..495ad1d8 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -396,6 +396,7 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
 	__SBI_HART_EXT_DATA(ssstateen, SBI_HART_EXT_SSSTATEEN),
 	__SBI_HART_EXT_DATA(xsfcflushdlone, SBI_HART_EXT_XSIFIVE_CFLUSH_D_L1),
 	__SBI_HART_EXT_DATA(xsfcease, SBI_HART_EXT_XSIFIVE_CEASE),
+	__SBI_HART_EXT_DATA(smrnmi, SBI_HART_EXT_SMRNMI),
 };
 
 _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),
-- 
2.43.7


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 2/3] lib: sbi: Enable Smrnmi extension handler
  2026-03-13 13:39 [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen
  2026-03-13 13:39 ` [PATCH v4 1/3] lib: sbi: Add Smrnmi extension detection Nylon Chen
@ 2026-03-13 13:39 ` Nylon Chen
  2026-03-13 13:39 ` [PATCH v4 3/3] firmware: fw_base.S: Add common NMI trap handler Nylon Chen
  2026-03-13 16:03 ` [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen
  3 siblings, 0 replies; 5+ messages in thread
From: Nylon Chen @ 2026-03-13 13:39 UTC (permalink / raw)
  To: opensbi
  Cc: zong.li, nick.hu, samuel.holland, yongxuan.wang, anup, rkrcmar,
	atishp, Nylon Chen

Introduce rnmi_vector_init() which prepares the hart for Smrnmi:

  1. Checks if the hart supports Smrnmi extension
  2. Writes scratch pointer into MNSCRATCH (same role as MSCRATCH for
     the RNMI entry path)

The function is file-static and called at the end of sbi_hart_init()
so every hart (cold and warm) initializes its own RNMI state before
returning to the firmware boot sequence.

Add set_rnmi_trap_vector() to struct sbi_platform_operations:

  int (*set_rnmi_trap_vector)(unsigned long handler_addr, bool cold_boot);

Use 'unsigned long' rather than 'uintptr_t' for consistency with the
rest of the platform operations interface. Platforms that support Smrnmi
must implement this; others can leave it NULL.

Add suspend/resume support for RNMI CSRs (MNSCRATCH and MNSTATUS) to
ensure proper state preservation across non-retentive suspend.

Note: This patch does not yet enable RNMI interrupts. The trap vector
setup and MNSTATUS.NMIE enablement will be added in the next patch after
the trap handler is implemented.

Co-developed-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Zong Li <zong.li@sifive.com>
Suggested-by: Nick Hu <nick.hu@sifive.com>
Suggested-by: Samuel Holland <samuel.holland@sifive.com>
Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
---
 include/sbi/sbi_platform.h |  8 ++++++++
 lib/sbi/sbi_hart.c         | 27 ++++++++++++++++++++++++++-
 lib/sbi/sbi_hsm.c          | 14 ++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index e65d9877..555e8b79 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -149,6 +149,14 @@ struct sbi_platform_operations {
 			unsigned long log2len);
 	/** platform specific pmp disable on current HART */
 	void (*pmp_disable)(unsigned int n);
+	/**
+	 * Platform-specific helper to program the RNMI trap vector.
+	 *
+	 * Called from rnmi_vector_init() with the firmware RNMI handler
+	 * entry address and the cold_boot flag. Platforms that support
+	 * Smrnmi must implement this; others can leave it NULL.
+	 */
+	int (*set_rnmi_trap_vector)(unsigned long handler_addr, bool cold_boot);
 };
 
 /** Platform default per-HART stack size for exception/interrupt handling */
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 495ad1d8..eca6662f 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -29,6 +29,9 @@ void (*sbi_hart_expected_trap)(void) = &__sbi_expected_trap;
 
 unsigned long hart_features_offset;
 
+/* Forward declaration */
+static int rnmi_vector_init(struct sbi_scratch *scratch, bool cold_boot);
+
 static void mstatus_init(struct sbi_scratch *scratch)
 {
 	int cidx;
@@ -756,7 +759,29 @@ int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot)
 	if (rc)
 		return rc;
 
-	return sbi_hart_reinit(scratch);
+	rc = sbi_hart_reinit(scratch);
+	if (rc)
+		return rc;
+
+	return rnmi_vector_init(scratch, cold_boot);
+}
+
+static int rnmi_vector_init(struct sbi_scratch *scratch, bool cold_boot)
+{
+	/* If the hart does not support Smrnmi then nothing to do. */
+	if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMRNMI))
+		return 0;
+
+	/*
+	 * Set MNSCRATCH to the scratch pointer (same role as MSCRATCH).
+	 * The RNMI handler (to be added in the next patch) will check
+	 * MNSTATUS.MNPP to determine whether to use the scratch area
+	 * (S/U-mode interrupted) or reuse the existing M-mode stack
+	 * (M-mode interrupted).
+	 */
+	csr_write(CSR_MNSCRATCH, (unsigned long)scratch);
+
+	return 0;
 }
 
 void __attribute__((noreturn)) sbi_hart_hang(void)
diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
index 0a355f9c..41115080 100644
--- a/lib/sbi/sbi_hsm.c
+++ b/lib/sbi/sbi_hsm.c
@@ -49,6 +49,8 @@ struct sbi_hsm_data {
 	unsigned long saved_medeleg;
 	unsigned long saved_mideleg;
 	u64 saved_menvcfg;
+	unsigned long saved_mnscratch;
+	unsigned long saved_mnstatus;
 	atomic_t start_ticket;
 };
 
@@ -430,6 +432,12 @@ void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch)
 	hdata->saved_mideleg = csr_read(CSR_MIDELEG);
 	if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_12)
 		hdata->saved_menvcfg = csr_read64(CSR_MENVCFG);
+
+	/* Save RNMI CSRs if Smrnmi is supported */
+	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMRNMI)) {
+		hdata->saved_mnscratch = csr_read(CSR_MNSCRATCH);
+		hdata->saved_mnstatus = csr_read(CSR_MNSTATUS);
+	}
 }
 
 static void __sbi_hsm_suspend_non_ret_restore(struct sbi_scratch *scratch)
@@ -443,6 +451,12 @@ static void __sbi_hsm_suspend_non_ret_restore(struct sbi_scratch *scratch)
 	csr_write(CSR_MEDELEG, hdata->saved_medeleg);
 	csr_write(CSR_MIE, hdata->saved_mie);
 	csr_set(CSR_MIP, (hdata->saved_mip & (MIP_SSIP | MIP_STIP)));
+
+	/* Restore RNMI CSRs if Smrnmi is supported */
+	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMRNMI)) {
+		csr_write(CSR_MNSCRATCH, hdata->saved_mnscratch);
+		csr_write(CSR_MNSTATUS, hdata->saved_mnstatus);
+	}
 }
 
 void sbi_hsm_hart_resume_start(struct sbi_scratch *scratch)
-- 
2.43.7


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 3/3] firmware: fw_base.S: Add common NMI trap handler
  2026-03-13 13:39 [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen
  2026-03-13 13:39 ` [PATCH v4 1/3] lib: sbi: Add Smrnmi extension detection Nylon Chen
  2026-03-13 13:39 ` [PATCH v4 2/3] lib: sbi: Enable Smrnmi extension handler Nylon Chen
@ 2026-03-13 13:39 ` Nylon Chen
  2026-03-13 16:03 ` [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen
  3 siblings, 0 replies; 5+ messages in thread
From: Nylon Chen @ 2026-03-13 13:39 UTC (permalink / raw)
  To: opensbi
  Cc: zong.li, nick.hu, samuel.holland, yongxuan.wang, anup, rkrcmar,
	atishp, Nylon Chen

Implement the firmware-level RNMI entry point and complete the RNMI
initialization:

fw_base.S - sbi_rnmi_vector assembly entry:
  Mirrors the existing _trap_handler pattern.  MNSCRATCH holds the
  per-hart scratch pointer (set by rnmi_vector_init), so the entry
  sequence is structurally identical to _trap_handler:

    csrrw sp, MNSCRATCH, sp      ; sp=scratch_ptr, MNSCRATCH=original_sp
    REG_S t0, TMP0(sp)           ; stash t0 in scratch tmp0 slot
    check MNSTATUS.MNPP          ; same bit layout as MSTATUS.MPP

  S/U-mode interrupted:
    frame allocated below scratch area (same as _trap_handler_s_mode)

  M-mode interrupted:
    frame allocated on the existing M-mode stack so no separate RNMI
    stack is required (same as _trap_handler_m_mode)

  After saving all registers, MNEPC/MNSTATUS are saved into the
  standard sbi_trap_regs mepc/mstatus fields so the C handler can
  inspect them with the same accessors used for normal traps.

  The handler is called as:
    sbi_rnmi_trap_handler(regs, mncause)

  On return registers are restored and mnret is executed.  The mnret
  opcode is emitted as a raw .word (0x70200073) because older toolchain
  versions do not recognise the mnemonic.

sbi_trap.c - sbi_rnmi_trap_handler default implementation:
  Prints mnepc, mncause, and mnstatus, then hangs the hart.  This is
  the correct behaviour for an unexpected NMI; a platform that can
  actually handle and resume from an NMI should override this function.

sbi_trap.h - declarations for sbi_rnmi_vector and sbi_rnmi_trap_handler.

sbi_hart.c - complete rnmi_vector_init():
  Adds the platform set_rnmi_trap_vector() call and MNSTATUS.NMIE
  enablement that were deferred from the previous patch.

Co-developed-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Zong Li <zong.li@sifive.com>
Suggested-by: Nick Hu <nick.hu@sifive.com>
Suggested-by: Samuel Holland <samuel.holland@sifive.com>
Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
---
 firmware/fw_base.S     | 141 +++++++++++++++++++++++++++++++++++++++++
 include/sbi/sbi_trap.h |  22 ++++++-
 lib/sbi/sbi_hart.c     |  34 ++++++++--
 lib/sbi/sbi_trap.c     |  17 +++++
 4 files changed, 208 insertions(+), 6 deletions(-)

diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index bce9e226..641f314a 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -643,6 +643,147 @@ memcmp:
 	REG_L	a0, SBI_TRAP_REGS_OFFSET(a0)(a0)
 .endm
 
+/* Smrnmi mnret instruction encoding (0x70200073) */
+.macro MNRET
+	.word 0x70200073
+.endm
+
+	.align 4
+	.section .entry, "ax", %progbits
+	.globl sbi_rnmi_vector
+sbi_rnmi_vector:
+	/* Swap SP with MNSCRATCH. After: sp=scratch_ptr, MNSCRATCH=original_sp */
+	csrrw	sp, CSR_MNSCRATCH, sp
+
+	/* Save T0 in scratch tmp0 slot */
+	REG_S	t0, SBI_SCRATCH_TMP0_OFFSET(sp)
+
+	/* Check MNSTATUS.MNPP to determine interrupted privilege mode */
+	csrr	t0, CSR_MNSTATUS
+	srl	t0, t0, MSTATUS_MPP_SHIFT
+	and	t0, t0, PRV_M
+	xori	t0, t0, PRV_M
+	beq	t0, zero, _sbi_rnmi_m_mode
+
+	/* Interrupted S/U-mode: use scratch area as exception stack */
+_sbi_rnmi_s_mode:
+	/* Load original SP from MNSCRATCH into T0 */
+	csrr	t0, CSR_MNSCRATCH
+	/* Restore MNSCRATCH = scratch_ptr for future RNMI entries */
+	csrw	CSR_MNSCRATCH, sp
+	/* Allocate exception frame just below scratch area */
+	addi	sp, sp, -(SBI_TRAP_REGS_SIZE)
+	j	_sbi_rnmi_save_regs
+
+	/* Interrupted M-mode: reuse existing M-mode stack */
+_sbi_rnmi_m_mode:
+	/* Load original SP from MNSCRATCH into T0 */
+	csrr	t0, CSR_MNSCRATCH
+	/* Restore MNSCRATCH = scratch_ptr for future RNMI entries */
+	csrw	CSR_MNSCRATCH, sp
+	/* Allocate exception frame on the existing M-mode stack */
+	addi	sp, t0, -(SBI_TRAP_REGS_SIZE)
+
+_sbi_rnmi_save_regs:
+	/* sp = exception frame, t0 = original SP, MNSCRATCH = scratch_ptr */
+
+	/* Save original SP (from T0) */
+	REG_S	t0, SBI_TRAP_REGS_OFFSET(sp)(sp)
+
+	/* Reload saved T0 from scratch tmp0, then save to exception frame */
+	csrr	t0, CSR_MNSCRATCH
+	REG_L	t0, SBI_SCRATCH_TMP0_OFFSET(t0)
+	REG_S	t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
+
+	/* Save all general registers except SP and T0 (already saved) */
+	REG_S	zero, SBI_TRAP_REGS_OFFSET(zero)(sp)
+	REG_S	ra,   SBI_TRAP_REGS_OFFSET(ra)(sp)
+	REG_S	gp,   SBI_TRAP_REGS_OFFSET(gp)(sp)
+	REG_S	tp,   SBI_TRAP_REGS_OFFSET(tp)(sp)
+	REG_S	t1,   SBI_TRAP_REGS_OFFSET(t1)(sp)
+	REG_S	t2,   SBI_TRAP_REGS_OFFSET(t2)(sp)
+	REG_S	s0,   SBI_TRAP_REGS_OFFSET(s0)(sp)
+	REG_S	s1,   SBI_TRAP_REGS_OFFSET(s1)(sp)
+	REG_S	a0,   SBI_TRAP_REGS_OFFSET(a0)(sp)
+	REG_S	a1,   SBI_TRAP_REGS_OFFSET(a1)(sp)
+	REG_S	a2,   SBI_TRAP_REGS_OFFSET(a2)(sp)
+	REG_S	a3,   SBI_TRAP_REGS_OFFSET(a3)(sp)
+	REG_S	a4,   SBI_TRAP_REGS_OFFSET(a4)(sp)
+	REG_S	a5,   SBI_TRAP_REGS_OFFSET(a5)(sp)
+	REG_S	a6,   SBI_TRAP_REGS_OFFSET(a6)(sp)
+	REG_S	a7,   SBI_TRAP_REGS_OFFSET(a7)(sp)
+	REG_S	s2,   SBI_TRAP_REGS_OFFSET(s2)(sp)
+	REG_S	s3,   SBI_TRAP_REGS_OFFSET(s3)(sp)
+	REG_S	s4,   SBI_TRAP_REGS_OFFSET(s4)(sp)
+	REG_S	s5,   SBI_TRAP_REGS_OFFSET(s5)(sp)
+	REG_S	s6,   SBI_TRAP_REGS_OFFSET(s6)(sp)
+	REG_S	s7,   SBI_TRAP_REGS_OFFSET(s7)(sp)
+	REG_S	s8,   SBI_TRAP_REGS_OFFSET(s8)(sp)
+	REG_S	s9,   SBI_TRAP_REGS_OFFSET(s9)(sp)
+	REG_S	s10,  SBI_TRAP_REGS_OFFSET(s10)(sp)
+	REG_S	s11,  SBI_TRAP_REGS_OFFSET(s11)(sp)
+	REG_S	t3,   SBI_TRAP_REGS_OFFSET(t3)(sp)
+	REG_S	t4,   SBI_TRAP_REGS_OFFSET(t4)(sp)
+	REG_S	t5,   SBI_TRAP_REGS_OFFSET(t5)(sp)
+	REG_S	t6,   SBI_TRAP_REGS_OFFSET(t6)(sp)
+
+	/* Save MNEPC into regs->mepc, MNSTATUS into regs->mstatus */
+	csrr	t0, CSR_MNEPC
+	REG_S	t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
+	csrr	t0, CSR_MNSTATUS
+	REG_S	t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
+
+	/* Call C RNMI handler: a0=regs, a1=mncause */
+	add	a0, sp, zero
+	csrr	a1, CSR_MNCAUSE
+	call	sbi_rnmi_trap_handler
+
+	/* Restore MNEPC and MNSTATUS from exception frame */
+	REG_L	t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
+	csrw	CSR_MNEPC, t0
+	REG_L	t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
+	csrw	CSR_MNSTATUS, t0
+
+	/* Restore all general registers except SP and T0 */
+	REG_L	ra,  SBI_TRAP_REGS_OFFSET(ra)(sp)
+	REG_L	gp,  SBI_TRAP_REGS_OFFSET(gp)(sp)
+	REG_L	tp,  SBI_TRAP_REGS_OFFSET(tp)(sp)
+	REG_L	t1,  SBI_TRAP_REGS_OFFSET(t1)(sp)
+	REG_L	t2,  SBI_TRAP_REGS_OFFSET(t2)(sp)
+	REG_L	s0,  SBI_TRAP_REGS_OFFSET(s0)(sp)
+	REG_L	s1,  SBI_TRAP_REGS_OFFSET(s1)(sp)
+	REG_L	a0,  SBI_TRAP_REGS_OFFSET(a0)(sp)
+	REG_L	a1,  SBI_TRAP_REGS_OFFSET(a1)(sp)
+	REG_L	a2,  SBI_TRAP_REGS_OFFSET(a2)(sp)
+	REG_L	a3,  SBI_TRAP_REGS_OFFSET(a3)(sp)
+	REG_L	a4,  SBI_TRAP_REGS_OFFSET(a4)(sp)
+	REG_L	a5,  SBI_TRAP_REGS_OFFSET(a5)(sp)
+	REG_L	a6,  SBI_TRAP_REGS_OFFSET(a6)(sp)
+	REG_L	a7,  SBI_TRAP_REGS_OFFSET(a7)(sp)
+	REG_L	s2,  SBI_TRAP_REGS_OFFSET(s2)(sp)
+	REG_L	s3,  SBI_TRAP_REGS_OFFSET(s3)(sp)
+	REG_L	s4,  SBI_TRAP_REGS_OFFSET(s4)(sp)
+	REG_L	s5,  SBI_TRAP_REGS_OFFSET(s5)(sp)
+	REG_L	s6,  SBI_TRAP_REGS_OFFSET(s6)(sp)
+	REG_L	s7,  SBI_TRAP_REGS_OFFSET(s7)(sp)
+	REG_L	s8,  SBI_TRAP_REGS_OFFSET(s8)(sp)
+	REG_L	s9,  SBI_TRAP_REGS_OFFSET(s9)(sp)
+	REG_L	s10, SBI_TRAP_REGS_OFFSET(s10)(sp)
+	REG_L	s11, SBI_TRAP_REGS_OFFSET(s11)(sp)
+	REG_L	t3,  SBI_TRAP_REGS_OFFSET(t3)(sp)
+	REG_L	t4,  SBI_TRAP_REGS_OFFSET(t4)(sp)
+	REG_L	t5,  SBI_TRAP_REGS_OFFSET(t5)(sp)
+	REG_L	t6,  SBI_TRAP_REGS_OFFSET(t6)(sp)
+
+	/* Restore T0 */
+	REG_L	t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
+
+	/* Restore SP */
+	REG_L	sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
+
+	/* Return from RNMI */
+	MNRET
+
 	.section .entry, "ax", %progbits
 	.align 3
 	.globl _trap_handler
diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
index 731a0c98..6a56e64e 100644
--- a/include/sbi/sbi_trap.h
+++ b/include/sbi/sbi_trap.h
@@ -289,6 +289,24 @@ static inline void sbi_trap_set_context(struct sbi_scratch *scratch,
 
 struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx);
 
-#endif
+/**
+ * Common firmware RNMI trap handler entry in M-mode.
+ *
+ * Platforms program their RNMI trap vector to this address using the
+ * set_rnmi_trap_vector platform operation.
+ */
+void sbi_rnmi_vector(void);
 
-#endif
+/**
+ * Default RNMI trap handler called from sbi_rnmi_vector.
+ *
+ * This is the default handler for Resumable Non-Maskable Interrupts (RNMI).
+ * It prints diagnostic information and hangs the hart. Platforms that can
+ * handle and resume from an NMI should override this function.
+ */
+void __attribute__((weak)) sbi_rnmi_trap_handler(struct sbi_trap_regs *regs,
+						  unsigned long mncause);
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* __SBI_TRAP_H__ */
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index eca6662f..519d29a0 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -766,21 +766,47 @@ int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot)
 	return rnmi_vector_init(scratch, cold_boot);
 }
 
+/* Forward declaration for the RNMI vector entry point in fw_base.S */
+extern void sbi_rnmi_vector(void);
+
 static int rnmi_vector_init(struct sbi_scratch *scratch, bool cold_boot)
 {
+	int ret;
+	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
+	const struct sbi_platform_operations *ops =
+		plat ? sbi_platform_ops(plat) : NULL;
+
 	/* If the hart does not support Smrnmi then nothing to do. */
 	if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMRNMI))
 		return 0;
 
+	/* Platform MUST provide RNMI vector hook if hart supports Smrnmi. */
+	if (!ops || !ops->set_rnmi_trap_vector) {
+		sbi_printf("%s: platform does not support Smrnmi\n", __func__);
+		return SBI_ENOTSUPP;
+	}
+
 	/*
 	 * Set MNSCRATCH to the scratch pointer (same role as MSCRATCH).
-	 * The RNMI handler (to be added in the next patch) will check
-	 * MNSTATUS.MNPP to determine whether to use the scratch area
-	 * (S/U-mode interrupted) or reuse the existing M-mode stack
-	 * (M-mode interrupted).
+	 * The RNMI handler swaps SP/MNSCRATCH on entry, detects the
+	 * interrupted mode via MNSTATUS.MNPP, and then either reuses the
+	 * existing M-mode stack (M-mode interrupted) or uses the scratch
+	 * area as a stack base (S/U-mode interrupted) -- mirroring what
+	 * _trap_handler already does for nested M-mode traps.
 	 */
 	csr_write(CSR_MNSCRATCH, (unsigned long)scratch);
 
+	/* Ask the platform to program the RNMI trap vector. */
+	ret = ops->set_rnmi_trap_vector((unsigned long)sbi_rnmi_vector,
+					cold_boot);
+	if (ret == SBI_ENODEV)
+		return 0;
+	if (ret)
+		return ret;
+
+	/* Enable RNMI now that MNSCRATCH and the trap vector are set up. */
+	csr_set(CSR_MNSTATUS, MNSTATUS_NMIE);
+
 	return 0;
 }
 
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index f41db4d1..38be122a 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -375,3 +375,20 @@ trap_done:
 	sbi_trap_set_context(scratch, tcntx->prev_context);
 	return tcntx;
 }
+
+/**
+ * Default RNMI trap handler.
+ *
+ * This is the default handler for Resumable Non-Maskable Interrupts (RNMI).
+ * It is invoked directly from the firmware RNMI entry (rnmi_handler)
+ * and prints diagnostic information before hanging the hart.
+ */
+void __attribute__((weak)) sbi_rnmi_trap_handler(struct sbi_trap_regs *regs,
+						  unsigned long mncause)
+{
+	sbi_printf("mnepc    = 0x%" PRILX "\n", regs->mepc);
+	sbi_printf("mncause  = 0x%" PRILX "\n", mncause);
+	sbi_printf("mnstatus = 0x%" PRILX "\n", regs->mstatus);
+
+	sbi_hart_hang();
+}
-- 
2.43.7


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 0/3] Add support for RISC-V Smrnmi extension
  2026-03-13 13:39 [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen
                   ` (2 preceding siblings ...)
  2026-03-13 13:39 ` [PATCH v4 3/3] firmware: fw_base.S: Add common NMI trap handler Nylon Chen
@ 2026-03-13 16:03 ` Nylon Chen
  3 siblings, 0 replies; 5+ messages in thread
From: Nylon Chen @ 2026-03-13 16:03 UTC (permalink / raw)
  To: opensbi
  Cc: zong.li, nick.hu, samuel.holland, yongxuan.wang, anup, rkrcmar,
	atishp, npiggin, Evgeny Voevodin

Sorry, please ignore this v4 series. It was sent before I had fully
reviewed the ongoing discussion, particularly Nick's comments and
Evgeny's Smrnmi series for Ascalon.

I will take time to review their work carefully and send a revised
version that better aligns with the direction of the discussion.

Apologies for the noise.

Thanks,
Nylon

Nylon Chen <nylon.chen@sifive.com> 於 2026年3月13日週五 下午9:39寫道:
>
> This patch series adds support for the RISC-V Smrnmi (Resumable
> Non-Maskable Interrupts) extension to OpenSBI.
>
> 1. PATCH 1/3: Add Smrnmi extension detection
>    - Defines Smrnmi CSR registers (MNSCRATCH, MNEPC, MNCAUSE, MNSTATUS)
>    - Defines MNSTATUS bit fields (NMIE, MNPV, MNPELP, MNPP)
>    - Registers the Smrnmi extension in hart extension enumeration
>
> 2. PATCH 2/3: Enable Smrnmi extension handler
>    - Implements rnmi_vector_init() as a static function in sbi_hart.c
>    - Sets MNSCRATCH to the scratch pointer (same role as MSCRATCH)
>    - Adds platform operation set_rnmi_trap_vector() for trap vector programming
>    - Adds suspend/resume support for RNMI CSRs (MNSCRATCH, MNSTATUS)
>    - Calls rnmi_vector_init() at the end of sbi_hart_init()
>    - Note: Does not yet enable RNMI; trap vector setup deferred to Patch 3
>
> 3. PATCH 3/3: Add common NMI trap handler
>    - Implements sbi_rnmi_vector assembly entry point in fw_base.S
>    - Checks MNSTATUS.MNPP to distinguish S/U-mode vs M-mode interrupts
>    - Uses scratch area for S/U-mode interrupts
>    - Reuses existing M-mode stack for M-mode interrupts (nested RNMI)
>    - Implements default sbi_rnmi_trap_handler() in C (marked __attribute__((weak)))
>    - Completes rnmi_vector_init() with platform hook call and NMIE enablement
>
> Changes in v4:
>  - Added MNSTATUS.MNPELP bit definition (for Zicfilp extension)
>  - Made rnmi_vector_init() a static function and removed global declaration
>  - Moved rnmi_vector_init() call from sbi_init.c to end of sbi_hart_init()
>  - Changed set_rnmi_trap_vector() parameter type from uintptr_t to unsigned long
>  - Changed platform hook requirement from "should" to "must" in documentation
>  - Simplified MNSCRATCH setup: directly use scratch pointer instead of allocating
>    separate RNMI context (addresses Radim's feedback on stack space)
>  - Rewrote sbi_rnmi_vector to check MNSTATUS.MNPP and reuse M-mode stack for
>    nested RNMI (addresses Radim's feedback on M-mode stack reuse)
>  - Removed RNMI_SAVE_REGS/RNMI_RESTORE_REGS macros in favor of explicit
>    register save/restore for better control
>  - Added sbi_rnmi_trap_handler() declaration in sbi_trap.h
>  - Changed printf format from %016lx to PRILX macro for 32/64-bit compatibility
>  - Fixed patch structure: Patch 2 now only sets up MNSCRATCH; Patch 3 completes
>    the initialization with trap vector setup and NMIE enablement (ensures each
>    patch can be compiled independently)
>  - Marked sbi_rnmi_trap_handler() as __attribute__((weak)) to allow platform override
>
> Changes in v3:
>  - Split single patch into three-patch series per Anup's feedback:
>   * PATCH 1: Add Smrnmi extension detection (without enabling NMI)
>   * PATCH 2: Enable Smrnmi extension handler
>   * PATCH 3: Add common NMI trap handler in fw_base.S
>  - Added platform abstraction via set_rnmi_trap_vector() callback
>  - Added per-HART RNMI context allocation
>  - Added suspend/resume support for RNMI CSRs
>
> Changes in v2:
>  - Remove hart_smrnmi_get_allowed() and use sbi_hart_has_extension() for
>    Smrnmi detection
>
> Co-developed-by: Zong Li <zong.li@sifive.com>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> Suggested-by: Nick Hu <nick.hu@sifive.com>
> Suggested-by: Samuel Holland <samuel.holland@sifive.com>
> Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
>
> Nylon Chen (3):
>   lib: sbi: Add Smrnmi extension detection
>   lib: sbi: Enable Smrnmi extension handler
>   firmware: fw_base.S: Add common NMI trap handler
>
>  firmware/fw_base.S           | 141 +++++++++++++++++++++++++++++++++++
>  include/sbi/riscv_encoding.h |  12 +++
>  include/sbi/sbi_hart.h       |   2 +
>  include/sbi/sbi_platform.h   |   8 ++
>  include/sbi/sbi_trap.h       |  22 +++++-
>  lib/sbi/sbi_hart.c           |  54 +++++++++++++-
>  lib/sbi/sbi_hsm.c            |  14 ++++
>  lib/sbi/sbi_trap.c           |  17 +++++
>  8 files changed, 267 insertions(+), 3 deletions(-)
>
> --
> 2.43.7
>

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-03-13 16:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-13 13:39 [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen
2026-03-13 13:39 ` [PATCH v4 1/3] lib: sbi: Add Smrnmi extension detection Nylon Chen
2026-03-13 13:39 ` [PATCH v4 2/3] lib: sbi: Enable Smrnmi extension handler Nylon Chen
2026-03-13 13:39 ` [PATCH v4 3/3] firmware: fw_base.S: Add common NMI trap handler Nylon Chen
2026-03-13 16:03 ` [PATCH v4 0/3] Add support for RISC-V Smrnmi extension Nylon Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox