mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v5] riscv: disable local interrupts and stop other CPUs before reboot/shutdown
@ 2026-11-04  7:05 Troy Mitchell
  2026-11-09 11:00 ` Frédéric Mahé
  0 siblings, 1 reply; 2+ messages in thread
From: Troy Mitchell @ 2026-11-04  7:05 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-riscv, linux-kernel, spacemit, Troy Mitchell,
	Aurelien Jarno, Anand Moon, Jisheng Zhang, Yixun Lan,
	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>
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: Anand Moon <linux.amoon@gmail.com>
Reviewed-by: Jisheng Zhang <jszhang@kernel.org>
---
Changes in v5:
- Rebase onto v7.4-rc1.
- Add Jisheng's Reviewed-by tag.
- Link to v4: https://patch.msgid.link/20260907-v7-0-rc1-rv-dis-int-before-restart-v4-1-42bb460c4afe@linux.dev

Changes in v4:
- Rebase onto v7.3-rc1.
- Link to v3: https://lore.kernel.org/r/20260330-v7-0-rc1-rv-dis-int-before-restart-v3-1-5a0577fcd136@linux.spacemit.com

Changes in v3:
- add Aurelien's tag
- Link to v2: https://lore.kernel.org/all/20260317-v7-0-rc1-rv-dis-int-before-restart-v2-1-0ecc85fbb7ff@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

To: Paul Walmsley <pjw@kernel.org>
To: Palmer Dabbelt <palmer@dabbelt.com>
To: Albert Ou <aou@eecs.berkeley.edu>
To: Alexandre Ghiti <alex@ghiti.fr>
To: Yixun Lan <dlan@kernel.org>
To: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Cc: linux-riscv@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: spacemit@lists.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 14eb08a6db85..ec84e3c94a3a 100644
--- a/arch/riscv/kernel/reset.c
+++ b/arch/riscv/kernel/reset.c
@@ -6,6 +6,7 @@
 #include <linux/efi.h>
 #include <linux/reboot.h>
 #include <linux/pm.h>
+#include <linux/smp.h>
 
 static void __noreturn default_power_off(void)
 {
@@ -18,6 +19,9 @@ EXPORT_SYMBOL(pm_power_off);
 
 void machine_restart(char *cmd)
 {
+	local_irq_disable();
+	smp_send_stop();
+
 	/*
 	 * UpdateCapsule() depends on the system being reset via ResetSystem().
 	 */
@@ -30,12 +34,18 @@ void machine_restart(char *cmd)
 
 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: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20260311-v7-0-rc1-rv-dis-int-before-restart-5b3e52a4b419

Best regards,
--  
Troy Mitchell <troy.mitchell@linux.dev>


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v5] riscv: disable local interrupts and stop other CPUs before reboot/shutdown
  2026-11-04  7:05 [PATCH v5] riscv: disable local interrupts and stop other CPUs before reboot/shutdown Troy Mitchell
@ 2026-11-09 11:00 ` Frédéric Mahé
  0 siblings, 0 replies; 2+ messages in thread
From: Frédéric Mahé @ 2026-11-09 11:00 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Yixun Lan, Troy Mitchell, Aurelien Jarno, Anand Moon,
	Jisheng Zhang, linux-riscv, linux-kernel, spacemit,
	Frédéric Mahé

On Wed, Nov 04, 2026 at 07:05:40AM +0000, Troy Mitchell wrote:
> 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.

On Banana Pi BPI-F3 (SpacemiT K1), v7.4-rc1 defconfig, every reboot warns:

  WARNING: kernel/rcu/tree_plugin.h:330 at rcu_note_context_switch+0x46a/0x48a
  ...
  spacemit_i2c_xfer_common+0x342/0x5f6
  ...
  spacemit_p1_restart_handler+0x24/0x5a
  do_kernel_restart+0x1e/0x26

With this patch the warning is gone (2/2 clean reboots, 2/2 warnings
without it). Testing done with the help of Claude (AI assistant).

Tested-by: Frédéric Mahé <frederic.mahe@cirad.fr>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-09 11:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04  7:05 [PATCH v5] riscv: disable local interrupts and stop other CPUs before reboot/shutdown Troy Mitchell
2026-11-09 11:00 ` Frédéric Mahé

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®