@@ -132,6 +132,7 @@ extern unsigned long hart_features_offset;
struct sbi_scratch;
+int sbi_smrnmi_hart_init(struct sbi_scratch *scratch);
int sbi_hart_reinit(struct sbi_scratch *scratch);
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
@@ -155,7 +155,7 @@ struct sbi_platform_operations {
void (*pmp_disable)(unsigned int n);
/** platform specific Smrnmi handlers init on current HART */
- void (*smrnmi_handlers_init)(void (*rnmi_handler)(void),
+ int (*smrnmi_handlers_init)(void (*rnmi_handler)(void),
void (*rnme_handler)(void));
/** platform specific Smrnmi NMI handler.
@@ -466,6 +466,37 @@ static int hart_mhpm_get_allowed_bits(void)
return num_bits;
}
+int sbi_smrnmi_hart_init(struct sbi_scratch *scratch)
+{
+ extern void _trap_rnmi_handler(void);
+ extern void _trap_handler(void);
+ const struct sbi_platform *plat;
+ const struct sbi_platform_operations *ops;
+ int ret;
+
+ if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMRNMI))
+ return 0;
+
+ plat = sbi_platform_thishart_ptr();
+ ops = plat ? sbi_platform_ops(plat) : NULL;
+
+ /*
+ * Platforms with fixed or mtvec-based NMI vectors need no
+ * vendor register programming; NULL callback is valid.
+ */
+ if (ops && ops->smrnmi_handlers_init) {
+ ret = ops->smrnmi_handlers_init(_trap_rnmi_handler,
+ _trap_handler);
+ if (ret)
+ return ret;
+ }
+
+ csr_write(CSR_MNSCRATCH, scratch);
+ csr_set(CSR_MNSTATUS, MNSTATUS_NMIE);
+
+ return 0;
+}
+
static int hart_detect_features(struct sbi_scratch *scratch, bool cold_boot)
{
struct sbi_trap_info trap = {0};
@@ -487,25 +518,9 @@ static int hart_detect_features(struct sbi_scratch *scratch, bool cold_boot)
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);
- }
+ rc = sbi_smrnmi_hart_init(scratch);
+ if (rc)
+ return rc;
#define __check_hpm_csr(__csr, __mask) \
oldval = csr_read_allowed(__csr, &trap); \
@@ -698,7 +713,7 @@ int sbi_hart_reinit(struct sbi_scratch *scratch)
if (rc)
return rc;
- return 0;
+ return sbi_smrnmi_hart_init(scratch);
}
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot)