On Mon, Sep 21, 2026 at 07:15:00PM +0800, Zhanpeng Zhang wrote: > SSE delivery is independent of normal S-mode interrupts. Firmware may also > retain an event registration until Linux explicitly unregisters it. A hart > must therefore stop accepting SSE events before Linux stops servicing the > registered handler. > > Mask SSE on the local hart before panic stop, CPU stop, restart, poweroff, > and crash shutdown paths. This prevents firmware from entering Linux-owned > handler state after the corresponding CPU or kernel context is no longer > valid. > > A crash kernel cannot identify or take ownership of registrations > inherited from the crashed kernel. Reject a later normal kexec while such > SSE state may still exist, rather than transferring unknown firmware state > to another kernel. > > Signed-off-by: Zhanpeng Zhang <[email protected]> > --- > arch/riscv/kernel/machine_kexec.c | 11 +++++++++++ > arch/riscv/kernel/reset.c | 18 ++++++++++++++++++ > arch/riscv/kernel/smp.c | 17 +++++++++++++++++ > 3 files changed, 46 insertions(+) > > diff --git a/arch/riscv/kernel/machine_kexec.c > b/arch/riscv/kernel/machine_kexec.c > index 738df176ff6f..24e7affae70b 100644 > --- a/arch/riscv/kernel/machine_kexec.c > +++ b/arch/riscv/kernel/machine_kexec.c > @@ -14,10 +14,13 @@ > #include <asm/set_memory.h> /* For set_memory_x() */ > #include <linux/compiler.h> /* For unreachable() */ > #include <linux/cpu.h> /* For cpu_down() */ > +#include <linux/crash_dump.h> > #include <linux/reboot.h> > #include <linux/interrupt.h> > #include <linux/irq.h> > > +#include <asm/sse.h> > + > /* > * machine_kexec_prepare - Initialize kexec > * > @@ -36,6 +39,13 @@ machine_kexec_prepare(struct kimage *image) > unsigned int control_code_buffer_sz = 0; > int i = 0; > > + /* A crash kernel cannot tear down registrations inherited from > firmware. */ > + if (is_kdump_kernel() && image->type != KEXEC_TYPE_CRASH && > + riscv_sse_available()) { > + pr_err("Normal kexec from a crash kernel is unsupported with > SSE\n"); > + return -EOPNOTSUPP; > + } > + > /* Find the Flattened Device Tree and save its physical address */ > for (i = 0; i < image->nr_segments; i++) { > if (image->segment[i].memsz <= sizeof(fdt)) > @@ -127,6 +137,7 @@ void > machine_crash_shutdown(struct pt_regs *regs) > { > local_irq_disable(); > + riscv_sse_mask_current_hart(); > > /* shutdown non-crashing cpus */ > crash_smp_send_stop(); > diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c > index 14eb08a6db85..fdab37e7ae52 100644 > --- a/arch/riscv/kernel/reset.c > +++ b/arch/riscv/kernel/reset.c > @@ -6,6 +6,20 @@ > #include <linux/efi.h> > #include <linux/reboot.h> > #include <linux/pm.h> > +#include <linux/smp.h> > + > +#include <asm/sse.h> > + > +#ifndef CONFIG_SMP > +void __noreturn panic_smp_self_stop(void) > +{ > + riscv_sse_mask_current_hart(); > + local_irq_disable(); > + > + for (;;) > + cpu_relax(); > +} > +#endif > > static void __noreturn default_power_off(void) > { > @@ -18,6 +32,8 @@ EXPORT_SYMBOL(pm_power_off); > > void machine_restart(char *cmd) > { > + riscv_sse_mask_current_hart(); > + > /* > * UpdateCapsule() depends on the system being reset via ResetSystem(). > */ > @@ -30,12 +46,14 @@ void machine_restart(char *cmd) > > void machine_halt(void) > { > + riscv_sse_mask_current_hart(); > do_kernel_power_off(); > default_power_off(); > } > > void machine_power_off(void) > { > + riscv_sse_mask_current_hart(); > do_kernel_power_off(); > default_power_off(); > } > diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c > index fa66f9c97d74..7f0d4e7332f1 100644 > --- a/arch/riscv/kernel/smp.c > +++ b/arch/riscv/kernel/smp.c > @@ -23,10 +23,13 @@ > #include <linux/irq.h> > #include <linux/irq_work.h> > #include <linux/nmi.h> > +#include <linux/panic.h> > > #include <asm/tlbflush.h> > #include <asm/cacheflush.h> > #include <asm/cpu_ops.h> > +#include <asm/sbi.h> > +#include <asm/sse.h> > > enum ipi_message_type { > IPI_RESCHEDULE, > @@ -79,8 +82,18 @@ int riscv_hartid_to_cpuid(unsigned long hartid) > return -ENOENT; > } > > +void __noreturn panic_smp_self_stop(void) > +{ > + riscv_sse_mask_current_hart(); > + local_irq_disable(); > + > + for (;;) > + cpu_relax(); > +} > + > static void ipi_stop(void) > { > + riscv_sse_mask_current_hart(); > set_cpu_online(smp_processor_id(), false); > while (1) > wait_for_interrupt(); > @@ -91,6 +104,7 @@ static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0); > > static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs) > { > + riscv_sse_mask_current_hart(); > crash_save_cpu(regs, cpu); > > atomic_dec(&waiting_for_crash_ipi); > @@ -254,6 +268,8 @@ void smp_send_stop(void) > { > unsigned long timeout; > > + riscv_sse_mask_current_hart(); > + > if (num_online_cpus() > 1) { > cpumask_t mask; > > @@ -301,6 +317,7 @@ void crash_smp_send_stop(void) > return; > > cpus_stopped = 1; > + riscv_sse_mask_current_hart(); > > /* > * If this cpu is the only one alive at this point in time, online or
Reviewed-by: Himanshu Chauhan <[email protected]> > -- > 2.50.1 (Apple Git-155) >

