[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAEEQ3w=Wy9J1q-n+iPu2ZeTLnoY63y+7iCFyAPe_r7v4hC9y8g@mail.gmail.com>
Date: Thu, 27 Nov 2025 18:09:00 +0800
From: yunhui cui <cuiyunhui@...edance.com>
To: conor@...nel.org, paul.walmsley@...ive.com, palmer@...belt.com,
aou@...s.berkeley.edu, alex@...ti.fr, cuiyunhui@...edance.com,
luxu.kernel@...edance.com, linux-kernel@...r.kernel.org,
linux-riscv@...ts.infradead.org, jassisinghbrar@...il.com,
conor.dooley@...rochip.com, valentina.fernandezalanis@...rochip.com,
catalin.marinas@....com, will@...nel.org, maz@...nel.org,
timothy.hayes@....com, lpieralisi@...nel.org, arnd@...db.de, kees@...nel.org,
tglx@...utronix.de, viresh.kumar@...aro.org, boqun.feng@...il.com,
linux-arm-kernel@...ts.infradead.org, cleger@...osinc.com,
atishp@...osinc.com, ajones@...tanamicro.com
Subject: Re: [PATCH v2 1/8] drivers: firmware: riscv: add SSE NMI support
Hi All,
On Tue, Nov 18, 2025 at 10:50 AM Yunhui Cui <cuiyunhui@...edance.com> wrote:
>
> Add support for handling Non-Maskable Interrupts (NMIs) through the
> RISC-V Supervisor Software Events (SSE) framework. Add basic NMI
> functionality via SBI_SSE_EVENT_LOCAL_SOFTWARE_INJECTED registration
> and enabling.
>
> Signed-off-by: Yunhui Cui <cuiyunhui@...edance.com>
> ---
> MAINTAINERS | 8 +++
> drivers/firmware/riscv/Kconfig | 10 +++
> drivers/firmware/riscv/Makefile | 1 +
> drivers/firmware/riscv/riscv_sse_nmi.c | 89 ++++++++++++++++++++++++++
> include/linux/riscv_sse_nmi.h | 26 ++++++++
> 5 files changed, 134 insertions(+)
> create mode 100644 drivers/firmware/riscv/riscv_sse_nmi.c
> create mode 100644 include/linux/riscv_sse_nmi.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8bf5416953f45..c06658da8af96 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -22057,6 +22057,14 @@ S: Maintained
> F: drivers/firmware/riscv/riscv_sse.c
> F: include/linux/riscv_sse.h
>
> +RISC-V SSE NMI SUPPORT
> +M: Yunhui Cui <cuiyunhui@...edance.com>
> +R: Xu Lu <luxu.kernel@...edance.com>
> +L: linux-riscv@...ts.infradead.org
> +S: Maintained
> +F: drivers/firmware/riscv/riscv_sse_nmi.c
> +F: include/linux/riscv_sse_nmi.h
> +
> RISC-V THEAD SoC SUPPORT
> M: Drew Fustini <fustini@...nel.org>
> M: Guo Ren <guoren@...nel.org>
> diff --git a/drivers/firmware/riscv/Kconfig b/drivers/firmware/riscv/Kconfig
> index ed5b663ac5f91..6c77c7823571a 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 && SMP
> + 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 can deliver local, unknown and
> + other types of NMIs.
> +
> endmenu
> diff --git a/drivers/firmware/riscv/Makefile b/drivers/firmware/riscv/Makefile
> index c8795d4bbb2ea..fbc182b53ae53 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) += riscv_sse_nmi.o
> diff --git a/drivers/firmware/riscv/riscv_sse_nmi.c b/drivers/firmware/riscv/riscv_sse_nmi.c
> new file mode 100644
> index 0000000000000..1763f43961ab6
> --- /dev/null
> +++ b/drivers/firmware/riscv/riscv_sse_nmi.c
> @@ -0,0 +1,89 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +#define pr_fmt(fmt) "SSE NMI: " fmt
> +
> +#include <linux/atomic.h>
> +#include <linux/riscv_sbi_sse.h>
> +#include <linux/riscv_sse_nmi.h>
> +
> +#include <asm/irq_regs.h>
> +#include <asm/sbi.h>
> +#include <asm/smp.h>
> +
> +bool nmi_available;
> +static struct sse_event *local_nmi_evt;
> +static atomic_t local_nmi_arg = ATOMIC_INIT(LOCAL_NMI_NONE);
> +
> +bool nmi_support(void)
> +{
> + return READ_ONCE(nmi_available);
> +}
> +
> +static inline struct sbiret sbi_sse_ecall(int fid, unsigned long arg0,
> + unsigned long arg1)
> +{
> + return sbi_ecall(SBI_EXT_SSE, fid, arg0, arg1, 0, 0, 0, 0);
> +}
> +
> +void send_nmi_single(unsigned int cpu, enum local_nmi_type type)
> +{
> + unsigned int hart_id = cpuid_to_hartid_map(cpu);
> + u32 evt = SBI_SSE_EVENT_LOCAL_SOFTWARE_INJECTED;
> + struct sbiret ret;
> +
> + atomic_or(type, &local_nmi_arg);
> + ret = sbi_sse_ecall(SBI_SSE_EVENT_INJECT, evt, hart_id);
> + if (ret.error)
> + pr_err("Failed to signal event %x to hartid %d, error %ld\n",
> + evt, hart_id, ret.error);
> +}
> +
> +void send_nmi_mask(cpumask_t *mask, enum local_nmi_type type)
> +{
> + unsigned int cpu;
> +
> + for_each_cpu(cpu, mask)
> + send_nmi_single(cpu, type);
> +}
> +
> +static int local_nmi_handler(u32 evt, void *arg, struct pt_regs *regs)
> +{
> + return 0;
> +}
> +
> +static int __init local_nmi_init(void)
> +{
> + int ret;
> +
> + local_nmi_evt = sse_event_register(SBI_SSE_EVENT_LOCAL_SOFTWARE_INJECTED, 0,
> + local_nmi_handler, &local_nmi_arg);
local_nmi_arg is used to represent the local NMI types (Crash, Stop,
Backtrace, Kgdb) for multiple CPUs, which may lead to certain issues:
for example, if CPU A sends a Backtrace to CPU C and CPU B sends a
Stop to CPU D, both CPU C and CPU D may end up responding to both
Backtrace and Stop. It is preferable to use the per-CPU variable
local_nmi_type instead of local_nmi_arg.
> + if (IS_ERR(local_nmi_evt))
> + return PTR_ERR(local_nmi_evt);
> +
> + ret = sse_event_enable(local_nmi_evt);
> + if (ret) {
> + sse_event_unregister(local_nmi_evt);
> + return ret;
> + }
> +
> + pr_info("Using SSE for Local NMI event delivery\n");
> +
> + return 0;
> +}
> +
> +static int __init sse_nmi_init(void)
> +{
> + int ret;
> +
> + ret = local_nmi_init();
> + if (ret) {
> + pr_err("Local_nmi_init failed with error %d\n", ret);
> + return ret;
> + }
> +
> + WRITE_ONCE(nmi_available, true);
> +
> + return 0;
> +}
> +
> +late_initcall(sse_nmi_init);
> diff --git a/include/linux/riscv_sse_nmi.h b/include/linux/riscv_sse_nmi.h
> new file mode 100644
> index 0000000000000..16db85c5162f5
> --- /dev/null
> +++ b/include/linux/riscv_sse_nmi.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +#ifndef __LINUX_RISCV_SSE_NMI_H
> +#define __LINUX_RISCV_SSE_NMI_H
> +
> +#include <linux/cpumask.h>
> +
> +enum local_nmi_type {
> + LOCAL_NMI_NONE = 0U,
> + LOCAL_NMI_STOP = BIT(0),
> + LOCAL_NMI_CRASH = BIT(1),
> + LOCAL_NMI_BACKTRACE = BIT(2),
> + LOCAL_NMI_KGDB = BIT(3),
> +};
> +
> +#ifdef CONFIG_RISCV_SSE_NMI
> +bool nmi_support(void);
> +void send_nmi_mask(cpumask_t *mask, enum local_nmi_type type);
> +void send_nmi_single(unsigned int cpu, enum local_nmi_type type);
> +#else
> +static inline bool nmi_support(void) { return false; }
> +static inline void send_nmi_mask(cpumask_t *mask) { };
> +static inline void send_nmi_single(unsigned int cpu) { };
> +#endif
> +
> +#endif
> --
> 2.39.5
>
Thanks,
Yunhui
Powered by blists - more mailing lists