summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sbi/sbi_platform.h4
-rw-r--r--lib/sbi/sbi_hart.c20
2 files changed, 24 insertions, 0 deletions
diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index 715df499..fe382b56 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -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);
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 781161e5..92c602aa 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -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) { \