Add support for handling Non-Maskable Interrupts (NMIs) through the
RISC-V Supervisor Software Events (SSE) framework. Since each NMI
type(e.g., unknown NMI, etc.) requires a distinct SSE event, a newfile
sse_nmi.c is introduced to manage their registration and enabling.
Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
---
MAINTAINERS | 7 +++
arch/riscv/include/asm/sbi.h | 1 +
drivers/firmware/riscv/Kconfig | 10 ++++
drivers/firmware/riscv/Makefile | 1 +
drivers/firmware/riscv/sse_nmi.c | 81 ++++++++++++++++++++++++++++++++
5 files changed, 100 insertions(+)
create mode 100644 drivers/firmware/riscv/sse_nmi.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 8bf5416953f45..6df6cbec4d85d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22057,6 +22057,13 @@ S: Maintained
F: drivers/firmware/riscv/riscv_sse.c
F: include/linux/riscv_sse.h
+RISC-V SSE NMI SUPPORT
+M: Yunhui Cui <cuiyunhui@bytedance.com>
+R: Xu Lu <luxu.kernel@bytedance.com>
+L: linux-riscv@lists.infradead.org
+S: Maintained
+F: drivers/firmware/riscv/sse_nmi.c
+
RISC-V THEAD SoC SUPPORT
M: Drew Fustini <fustini@kernel.org>
M: Guo Ren <guoren@kernel.org>
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index 874cc1d7603a5..52d3fdf2d4cc1 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -486,6 +486,7 @@ enum sbi_sse_attr_id {
#define SBI_SSE_EVENT_LOCAL_LOW_PRIO_RAS 0x00100000
#define SBI_SSE_EVENT_GLOBAL_LOW_PRIO_RAS 0x00108000
#define SBI_SSE_EVENT_LOCAL_SOFTWARE_INJECTED 0xffff0000
+#define SBI_SSE_EVENT_LOCAL_UNKNOWN_NMI 0xffff0001
#define SBI_SSE_EVENT_GLOBAL_SOFTWARE_INJECTED 0xffff8000
#define SBI_SSE_EVENT_PLATFORM BIT(14)
diff --git a/drivers/firmware/riscv/Kconfig b/drivers/firmware/riscv/Kconfig
index ed5b663ac5f91..fd16b4c43cf01 100644
--- a/drivers/firmware/riscv/Kconfig
+++ b/drivers/firmware/riscv/Kconfig
@@ -12,4 +12,14 @@ config RISCV_SBI_SSE
this option provides support to register callbacks on specific SSE
events.
+config RISCV_SSE_NMI
+ bool "Enable SBI Supervisor Software Events NMI support"
+ depends on RISCV_SBI_SSE
+ default y
+ help
+ This option enables support for delivering Non-Maskable Interrupt
+ (NMI) notifications through the Supervisor Software Events (SSE)
+ framework. When enabled, the system supports some common NMI features
+ such as unknown NMI handling.
+
endmenu
diff --git a/drivers/firmware/riscv/Makefile b/drivers/firmware/riscv/Makefile
index c8795d4bbb2ea..ecf2b31935d9c 100644
--- a/drivers/firmware/riscv/Makefile
+++ b/drivers/firmware/riscv/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_RISCV_SBI_SSE) += riscv_sbi_sse.o
+obj-$(CONFIG_RISCV_SSE_NMI) += sse_nmi.o
diff --git a/drivers/firmware/riscv/sse_nmi.c b/drivers/firmware/riscv/sse_nmi.c
new file mode 100644
index 0000000000000..2c1eaea2bbabc
--- /dev/null
+++ b/drivers/firmware/riscv/sse_nmi.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#define pr_fmt(fmt) "SSE NMI: " fmt
+
+#include <linux/nmi.h>
+#include <linux/riscv_sbi_sse.h>
+#include <linux/sysctl.h>
+
+#include <asm/irq_regs.h>
+#include <asm/sbi.h>
+
+int unknown_nmi_panic;
+static struct sse_event *unknown_nmi_evt;
+static struct ctl_table_header *unknown_nmi_sysctl_header;
+
+static int __init setup_unknown_nmi_panic(char *str)
+{
+ unknown_nmi_panic = 1;
+ return 1;
+}
+__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
+
+const struct ctl_table unknown_nmi_table[] = {
+ {
+ .procname = "unknown_nmi_panic",
+ .data = &unknown_nmi_panic,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
+};
+
+static int unknown_nmi_handler(u32 evt, void *arg, struct pt_regs *regs)
+{
+ pr_emerg("NMI received for unknown on CPU %d.\n", smp_processor_id());
+
+ if (unknown_nmi_panic)
+ nmi_panic(regs, "NMI: Not continuing");
+
+ pr_emerg("Dazed and confused, but trying to continue\n");
+
+ return 0;
+}
+
+static int unknown_nmi_init(void)
+{
+ int ret;
+
+ unknown_nmi_evt = sse_event_register(SBI_SSE_EVENT_LOCAL_UNKNOWN_NMI, 0,
+ unknown_nmi_handler, NULL);
+ if (IS_ERR(unknown_nmi_evt))
+ return PTR_ERR(unknown_nmi_evt);
+
+ ret = sse_event_enable(unknown_nmi_evt);
+ if (ret)
+ goto err_unregister;
+
+ unknown_nmi_sysctl_header = register_sysctl("kernel", unknown_nmi_table);
+ if (!unknown_nmi_sysctl_header) {
+ ret = -ENOMEM;
+ goto err_disable;
+ }
+
+ pr_info("Using SSE for unknown NMI event delivery\n");
+ return 0;
+
+err_disable:
+ sse_event_disable(unknown_nmi_evt);
+err_unregister:
+ sse_event_unregister(unknown_nmi_evt);
+ return ret;
+}
+
+static int __init sse_nmi_init(void)
+{
+ return unknown_nmi_init();
+}
+
+late_initcall(sse_nmi_init);
--
2.39.5
On Mon, Oct 27, 2025 at 09:34:29PM +0800, Yunhui Cui wrote:
> Add support for handling Non-Maskable Interrupts (NMIs) through the
> RISC-V Supervisor Software Events (SSE) framework. Since each NMI
> type(e.g., unknown NMI, etc.) requires a distinct SSE event, a newfile
> sse_nmi.c is introduced to manage their registration and enabling.
>
> Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
> ---
> MAINTAINERS | 7 +++
> arch/riscv/include/asm/sbi.h | 1 +
> drivers/firmware/riscv/Kconfig | 10 ++++
> drivers/firmware/riscv/Makefile | 1 +
> drivers/firmware/riscv/sse_nmi.c | 81 ++++++++++++++++++++++++++++++++
> 5 files changed, 100 insertions(+)
> create mode 100644 drivers/firmware/riscv/sse_nmi.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8bf5416953f45..6df6cbec4d85d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -22057,6 +22057,13 @@ S: Maintained
> F: drivers/firmware/riscv/riscv_sse.c
> F: include/linux/riscv_sse.h
>
> +RISC-V SSE NMI SUPPORT
> +M: Yunhui Cui <cuiyunhui@bytedance.com>
> +R: Xu Lu <luxu.kernel@bytedance.com>
> +L: linux-riscv@lists.infradead.org
> +S: Maintained
> +F: drivers/firmware/riscv/sse_nmi.c
Does actually this need a separate entry?
> RISC-V THEAD SoC SUPPORT
> M: Drew Fustini <fustini@kernel.org>
> M: Guo Ren <guoren@kernel.org>
> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
> index 874cc1d7603a5..52d3fdf2d4cc1 100644
> --- a/arch/riscv/include/asm/sbi.h
> +++ b/arch/riscv/include/asm/sbi.h
> @@ -486,6 +486,7 @@ enum sbi_sse_attr_id {
> #define SBI_SSE_EVENT_LOCAL_LOW_PRIO_RAS 0x00100000
> #define SBI_SSE_EVENT_GLOBAL_LOW_PRIO_RAS 0x00108000
> #define SBI_SSE_EVENT_LOCAL_SOFTWARE_INJECTED 0xffff0000
> +#define SBI_SSE_EVENT_LOCAL_UNKNOWN_NMI 0xffff0001
Where is this canonically defined?
I looked at the v3 SBI spec and it says:
0xffff0001 - 0xffff3fff Local events reserved for future use
This needs to be marked RFC until this event is in a frozen version of
the SBI spec.
> #define SBI_SSE_EVENT_GLOBAL_SOFTWARE_INJECTED 0xffff8000
>
> #define SBI_SSE_EVENT_PLATFORM BIT(14)
> diff --git a/drivers/firmware/riscv/Kconfig b/drivers/firmware/riscv/Kconfig
> index ed5b663ac5f91..fd16b4c43cf01 100644
> --- a/drivers/firmware/riscv/Kconfig
> +++ b/drivers/firmware/riscv/Kconfig
> @@ -12,4 +12,14 @@ config RISCV_SBI_SSE
> this option provides support to register callbacks on specific SSE
> events.
>
> +config RISCV_SSE_NMI
I think I'd like to see both the filename and Kconfig option match the
established naming for the base sse support.
> + bool "Enable SBI Supervisor Software Events NMI support"
> + depends on RISCV_SBI_SSE
> + default y
> + help
> + This option enables support for delivering Non-Maskable Interrupt
> + (NMI) notifications through the Supervisor Software Events (SSE)
> + framework.
> When enabled, the system supports some common NMI features
> + such as unknown NMI handling.
No, when enabled the _kernel_ supports these things. The code in this
patch seems to fail gracefully when there's no SSE support in the
underlying system, but you should make the option description match
reality.
Cheers,
Conor.
© 2016 - 2026 Red Hat, Inc.