mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2026-05-23 14:21:32 +01:00
lib: sbi: hart: Detect and enable Smrnmi before trap-based feature detection
The location of the RNMI/E trap vectors in the Smrnmi extension is
implementation-defined, so platforms with vendor-specific NMI vector
mechanisms must install the firmware's NMI entry points themselves.
Add an smrnmi_handlers_init() callback to sbi_platform_operations that
receives the firmware entry points and lets platform code install them
at the hardware-specific vector locations. Two pointers are passed:
- _trap_rnmi_handler: the dedicated RNMI entry point that saves
context using the Smrnmi MN* CSRs and returns via mnret.
- _trap_handler: the regular M-mode trap entry since RNME is taken
as a regular M-mode trap with NMIE=0.
When Smrnmi is present, install the platform's NMI vectors via the new
callback, initialize MNSCRATCH with the per-hart scratch pointer, and
set MNSTATUS.NMIE.
Smrnmi-enabled platforms must register smrnmi_handlers_init; if the
extension is detected but no callback is registered, sbi_panic() is
called since enabling NMIs without handlers in place would route
subsequent traps into nowhere.
Signed-off-by: Evgeny Voevodin <evvoevod@tenstorrent.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/88b1470e1e3348d454b4b995a11a85c01914f7af.1778176768.git.evvoevod@tenstorrent.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
committed by
Anup Patel
parent
0cfd6c0b5e
commit
2d211fe6f9
@@ -150,6 +150,10 @@ struct sbi_platform_operations {
|
||||
/** platform specific pmp disable on current HART */
|
||||
void (*pmp_disable)(unsigned int n);
|
||||
|
||||
/** platform specific Smrnmi handlers init on current HART */
|
||||
void (*smrnmi_handlers_init)(void (*rnmi_handler)(void),
|
||||
void (*rnme_handler)(void));
|
||||
|
||||
/** platform specific Smrnmi NMI handler.
|
||||
* Returns SBI_SUCCESS on success, error code if NMI cannot be handled. */
|
||||
int (*rnmi_handler)(struct sbi_trap_context *tcntx);
|
||||
|
||||
@@ -532,6 +532,26 @@ static int hart_detect_features(struct sbi_scratch *scratch)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMRNMI)) {
|
||||
const struct sbi_platform *plat = sbi_platform_thishart_ptr();
|
||||
const struct sbi_platform_operations *ops = sbi_platform_ops(plat);
|
||||
extern void _trap_rnmi_handler(void);
|
||||
extern void _trap_handler(void);
|
||||
|
||||
if (!ops || !ops->smrnmi_handlers_init)
|
||||
sbi_panic("Smrnmi detected, but platform lacks smrnmi_handlers_init callback\n");
|
||||
|
||||
/* Reuse _trap_handler for the RNME slot since RNME is taken
|
||||
* as a regular M-mode trap with NMIE=0. */
|
||||
ops->smrnmi_handlers_init(_trap_rnmi_handler, _trap_handler);
|
||||
|
||||
/* Initialize MNSCRATCH for the RNMI handler */
|
||||
csr_write(CSR_MNSCRATCH, scratch);
|
||||
|
||||
/* Enable NMIs */
|
||||
csr_set(CSR_MNSTATUS, MNSTATUS_NMIE);
|
||||
}
|
||||
|
||||
#define __check_hpm_csr(__csr, __mask) \
|
||||
oldval = csr_read_allowed(__csr, &trap); \
|
||||
if (!trap.cause) { \
|
||||
|
||||
Reference in New Issue
Block a user