* [PATCH v2] riscv: disable local interrupts and stop other CPUs before reboot/shutdown
@ 2026-03-17 8:48 Troy Mitchell
2026-03-18 1:20 ` Troy Mitchell
2026-03-18 20:18 ` Aurelien Jarno
0 siblings, 2 replies; 3+ messages in thread
From: Troy Mitchell @ 2026-03-17 8:48 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-riscv, linux-kernel, spacemit, Troy Mitchell
Currently, the RISC-V implementation of machine_restart(), machine_halt(),
and machine_power_off() invokes the kernel teardown chains (e.g.,
do_kernel_restart()) with local interrupts enabled and other CPUs still
running.
This implementation fails to provide a deterministic execution environment
for registered handlers in the restart or power-off notifier chains. These
chains are intended to be executed in a strict atomic and single-threaded
context.
Specifically, under CONFIG_PREEMPT_RCU, rcu_read_lock() does not increment
the preempt_count. If local interrupts remain enabled, the environment
is not guaranteed to be atomic. This can lead to a context misidentification
within generic kernel teardown code, causing it to incorrectly enter
non-atomic paths (such as attempting to acquire sleeping locks), which
results in fatal "scheduling while atomic" splats or system hangs.
Additionally, stopping other CPUs ensures the primary CPU has exclusive
access to the hardware state during the final teardown phase, preventing
unpredictable interference from other active cores.
Align RISC-V with other major architectures by disabling local interrupts
and stopping other CPUs at the beginning of the shutdown sequences. This
guarantees the architectural expectations of the kernel's restart and
power-off handlers are met.
Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev>
---
Changes in v2:
- expand the fix to cover machine_halt() and machine_power_off() for
architectural consistency.
- update commit message
- Link to v1: https://lore.kernel.org/r/20260311-v7-0-rc1-rv-dis-int-before-restart-v1-1-bc46b4351cac@linux.dev
---
arch/riscv/kernel/reset.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c
index 912288572226..8c48466c50e9 100644
--- a/arch/riscv/kernel/reset.c
+++ b/arch/riscv/kernel/reset.c
@@ -5,6 +5,7 @@
#include <linux/reboot.h>
#include <linux/pm.h>
+#include <linux/smp.h>
static void default_power_off(void)
{
@@ -17,18 +18,27 @@ EXPORT_SYMBOL(pm_power_off);
void machine_restart(char *cmd)
{
+ local_irq_disable();
+ smp_send_stop();
+
do_kernel_restart(cmd);
while (1);
}
void machine_halt(void)
{
+ local_irq_disable();
+ smp_send_stop();
+
do_kernel_power_off();
default_power_off();
}
void machine_power_off(void)
{
+ local_irq_disable();
+ smp_send_stop();
+
do_kernel_power_off();
default_power_off();
}
---
base-commit: 31489a8c1e95cfa2039b7ec4abf124d1fdda31a6
change-id: 20260311-v7-0-rc1-rv-dis-int-before-restart-5b3e52a4b419
Best regards,
--
Troy Mitchell <troy.mitchell@linux.dev>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] riscv: disable local interrupts and stop other CPUs before reboot/shutdown
2026-03-17 8:48 [PATCH v2] riscv: disable local interrupts and stop other CPUs before reboot/shutdown Troy Mitchell
@ 2026-03-18 1:20 ` Troy Mitchell
2026-03-18 20:18 ` Aurelien Jarno
1 sibling, 0 replies; 3+ messages in thread
From: Troy Mitchell @ 2026-03-18 1:20 UTC (permalink / raw)
To: Troy Mitchell, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti
Cc: linux-riscv, linux-kernel, spacemit, troy.mitchell
On Tue Mar 17, 2026 at 4:48 PM CST, Troy Mitchell wrote:
> Currently, the RISC-V implementation of machine_restart(), machine_halt(),
> and machine_power_off() invokes the kernel teardown chains (e.g.,
> do_kernel_restart()) with local interrupts enabled and other CPUs still
> running.
>
> This implementation fails to provide a deterministic execution environment
> for registered handlers in the restart or power-off notifier chains. These
> chains are intended to be executed in a strict atomic and single-threaded
> context.
>
> Specifically, under CONFIG_PREEMPT_RCU, rcu_read_lock() does not increment
> the preempt_count. If local interrupts remain enabled, the environment
> is not guaranteed to be atomic. This can lead to a context misidentification
> within generic kernel teardown code, causing it to incorrectly enter
> non-atomic paths (such as attempting to acquire sleeping locks), which
> results in fatal "scheduling while atomic" splats or system hangs.
>
> Additionally, stopping other CPUs ensures the primary CPU has exclusive
> access to the hardware state during the final teardown phase, preventing
> unpredictable interference from other active cores.
>
> Align RISC-V with other major architectures by disabling local interrupts
> and stopping other CPUs at the beginning of the shutdown sequences. This
> guarantees the architectural expectations of the kernel's restart and
> power-off handlers are met.
>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev>
Sry I forgot to add Aurelien's tag [1]
Link: https://lore.kernel.org/all/abEP80FoCn4S4-WG@aurel32.net/ [1]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] riscv: disable local interrupts and stop other CPUs before reboot/shutdown
2026-03-17 8:48 [PATCH v2] riscv: disable local interrupts and stop other CPUs before reboot/shutdown Troy Mitchell
2026-03-18 1:20 ` Troy Mitchell
@ 2026-03-18 20:18 ` Aurelien Jarno
1 sibling, 0 replies; 3+ messages in thread
From: Aurelien Jarno @ 2026-03-18 20:18 UTC (permalink / raw)
To: Troy Mitchell
Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-riscv, linux-kernel, spacemit
Hi Troy,
On 2026-03-17 16:48, Troy Mitchell wrote:
> Currently, the RISC-V implementation of machine_restart(), machine_halt(),
> and machine_power_off() invokes the kernel teardown chains (e.g.,
> do_kernel_restart()) with local interrupts enabled and other CPUs still
> running.
>
> This implementation fails to provide a deterministic execution environment
> for registered handlers in the restart or power-off notifier chains. These
> chains are intended to be executed in a strict atomic and single-threaded
> context.
>
> Specifically, under CONFIG_PREEMPT_RCU, rcu_read_lock() does not increment
> the preempt_count. If local interrupts remain enabled, the environment
> is not guaranteed to be atomic. This can lead to a context misidentification
> within generic kernel teardown code, causing it to incorrectly enter
> non-atomic paths (such as attempting to acquire sleeping locks), which
> results in fatal "scheduling while atomic" splats or system hangs.
>
> Additionally, stopping other CPUs ensures the primary CPU has exclusive
> access to the hardware state during the final teardown phase, preventing
> unpredictable interference from other active cores.
>
> Align RISC-V with other major architectures by disabling local interrupts
> and stopping other CPUs at the beginning of the shutdown sequences. This
> guarantees the architectural expectations of the kernel's restart and
> power-off handlers are met.
>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev>
> ---
> Changes in v2:
> - expand the fix to cover machine_halt() and machine_power_off() for
> architectural consistency.
> - update commit message
> - Link to v1: https://lore.kernel.org/r/20260311-v7-0-rc1-rv-dis-int-before-restart-v1-1-bc46b4351cac@linux.dev
> ---
> arch/riscv/kernel/reset.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c
> index 912288572226..8c48466c50e9 100644
> --- a/arch/riscv/kernel/reset.c
> +++ b/arch/riscv/kernel/reset.c
> @@ -5,6 +5,7 @@
>
> #include <linux/reboot.h>
> #include <linux/pm.h>
> +#include <linux/smp.h>
>
> static void default_power_off(void)
> {
> @@ -17,18 +18,27 @@ EXPORT_SYMBOL(pm_power_off);
>
> void machine_restart(char *cmd)
> {
> + local_irq_disable();
> + smp_send_stop();
> +
> do_kernel_restart(cmd);
> while (1);
> }
>
> void machine_halt(void)
> {
> + local_irq_disable();
> + smp_send_stop();
> +
> do_kernel_power_off();
> default_power_off();
> }
>
> void machine_power_off(void)
> {
> + local_irq_disable();
> + smp_send_stop();
> +
> do_kernel_power_off();
> default_power_off();
> }
>
> ---
> base-commit: 31489a8c1e95cfa2039b7ec4abf124d1fdda31a6
> change-id: 20260311-v7-0-rc1-rv-dis-int-before-restart-5b3e52a4b419
>
> Best regards,
> --
> Troy Mitchell <troy.mitchell@linux.dev>
Thanks for this new version. I confirm it works fine.
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Regards
Aurelien
--
Aurelien Jarno GPG: 4096R/1DDD8C9B
aurelien@aurel32.net http://aurel32.net
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-03-18 20:19 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-17 8:48 [PATCH v2] riscv: disable local interrupts and stop other CPUs before reboot/shutdown Troy Mitchell
2026-03-18 1:20 ` Troy Mitchell
2026-03-18 20:18 ` Aurelien Jarno
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox