@@ -207,6 +207,10 @@
#endif
+#define MNSTATUS_NMIE (_UL(0x8))
+#define MNSTATUS_MNPV (_UL(0x80))
+#define MNSTATUS_MNPP (_UL(0x1800))
+
#define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000)
#define ENVCFG_STCE (_ULL(1) << 63)
@@ -738,6 +742,12 @@
#define CSR_MSTATEEN3 0x30F
#define CSR_MSTATEEN3H 0x31F
+/* Smrnmi extension registers */
+#define CSR_MNSCRATCH 0x740
+#define CSR_MNEPC 0x741
+#define CSR_MNCAUSE 0x742
+#define CSR_MNSTATUS 0x744
+
/* Machine-Level High-Half CSRs (AIA) */
#define CSR_MIDELEGH 0x313
#define CSR_MIEH 0x314
@@ -63,6 +63,8 @@ enum sbi_hart_extensions {
SBI_HART_EXT_SSCSRIND,
/** Hart has Ssccfg extension */
SBI_HART_EXT_SSCCFG,
+ /** Hart has Smrnmi extension */
+ SBI_HART_EXT_SMRNMI,
/** Maximum index of Hart extension */
SBI_HART_EXT_MAX,
@@ -668,6 +668,7 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
__SBI_HART_EXT_DATA(smcdeleg, SBI_HART_EXT_SMCDELEG),
__SBI_HART_EXT_DATA(sscsrind, SBI_HART_EXT_SSCSRIND),
__SBI_HART_EXT_DATA(ssccfg, SBI_HART_EXT_SSCCFG),
+ __SBI_HART_EXT_DATA(smrnmi, SBI_HART_EXT_SMRNMI),
};
_Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),
@@ -706,6 +707,20 @@ void sbi_hart_get_extensions_str(struct sbi_scratch *scratch,
sbi_strncpy(extensions_str, "none", nestr);
}
+static int hart_smrnmi_get_allowed(void)
+{
+ unsigned long val;
+ struct sbi_trap_info trap = {0};
+
+ val = csr_read_allowed(CSR_MNSTATUS, (unsigned long)&trap);
+ if (!trap.cause) {
+ val |= MNSTATUS_NMIE;
+ csr_write(CSR_MNSTATUS, val);
+ return true;
+ } else {
+ return false;
+ }
+
static unsigned long hart_pmp_get_allowed_addr(void)
{
unsigned long val = 0;
@@ -775,6 +790,13 @@ static int hart_detect_features(struct sbi_scratch *scratch)
hfeatures->mhpm_mask = 0;
hfeatures->priv_version = SBI_HART_PRIV_VER_UNKNOWN;
+ /*
+ * Detect Resumable Non-Maskable Interrupts
+ * If it exists we must enable it before all traps.
+ */
+ if (hart_smrnmi_get_allowed())
+ __sbi_hart_update_extension(hfeatures, SBI_HART_EXT_SMRNMI, true);
+
#define __check_hpm_csr(__csr, __mask) \
oldval = csr_read_allowed(__csr, (ulong)&trap); \
if (!trap.cause) { \