]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
generic: mips: add pending patch to fix reboot 23619/head 23656/head
authorJonas Jelonek <jelonek.jonas@gmail.com>
Thu, 4 Jun 2026 17:59:04 +0000 (17:59 +0000)
committerJonas Jelonek <jelonek.jonas@gmail.com>
Fri, 5 Jun 2026 19:51:41 +0000 (21:51 +0200)
Add a pending hotfix to fix reboot functionality on MIPS platforms, at
least the Realtek target being affected.

The kernel bump from 6.18.33 to 6.18.34 introduced a backported commit
intending to fix a use-after-free issue [1]. As a side effect, it also
causes RCU to wait for CPUs which are already dead but RCU doesn't know
of.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-6.18.y&id=18c0456ea2615b1a743a6db739c74411c3b42bc6

Fixes: 94f3f9a845e8 ("kernel: bump 6.18 to 6.18.34")
Link: https://github.com/openwrt/openwrt/pull/23656
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch [new file with mode: 0644]
target/linux/ramips/patches-6.18/933-MIPS-SMP-Wait-for-secondary-CPUs-to-stop-in-smp_send.patch
target/linux/ramips/patches-6.18/934-MIPS-SMP-Properly-stop-secondary-CPUs-for-restart.patch

diff --git a/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch b/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch
new file mode 100644 (file)
index 0000000..fc8cf0f
--- /dev/null
@@ -0,0 +1,53 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jonas Jelonek <jelonek.jonas@gmail.com>
+Date: Thu, 04 Jun 2026 00:00:00 +0200
+Subject: [PATCH] MIPS: smp: report dying CPU to RCU in stop_this_cpu()
+
+smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function
+marks the CPU offline for the scheduler via set_cpu_online(false) but never
+informs RCU, so RCU keeps expecting a quiescent state from CPUs that are
+now spinning forever with interrupts disabled.
+
+As long as nothing waits for an RCU grace period after smp_send_stop() this
+is harmless, which is why it went unnoticed. Since v6.18.34, however,
+irq_work_sync() calls synchronize_rcu() on architectures without an
+irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns false.
+That is the asm-generic default used by MIPS. Any irq_work_sync() issued in
+the reboot/shutdown path after smp_send_stop() then blocks on a grace period
+that can never complete, hanging the reboot:
+
+  WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on
+  ...
+  rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
+  rcu: Offline CPU 1 blocking current GP.
+  rcu: Offline CPU 2 blocking current GP.
+  rcu: Offline CPU 3 blocking current GP.
+
+Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the
+generic CPU-hotplug offline path (and arm64's stop handling), so RCU stops
+waiting on the parked CPUs and grace periods can still complete.
+
+Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT")
+Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
+---
+ arch/mips/kernel/smp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/mips/kernel/smp.c
++++ b/arch/mips/kernel/smp.c
+@@ -20,6 +20,7 @@
+ #include <linux/sched/mm.h>
+ #include <linux/cpumask.h>
+ #include <linux/cpu.h>
++#include <linux/rcupdate.h>
+ #include <linux/err.h>
+ #include <linux/ftrace.h>
+ #include <linux/irqdomain.h>
+@@ -422,6 +423,7 @@ static void stop_this_cpu(void *dummy)
+       set_cpu_online(smp_processor_id(), false);
+       calculate_cpu_foreign_map();
+       local_irq_disable();
++      rcutree_report_cpu_dead();
+       while (1);
+ }
index 4ecca0811d825c5cd5a73ccd64c5417576e58bfb..8fecedeba34f8fd4196134546ccc4cfbb1a488b3 100644 (file)
@@ -16,7 +16,7 @@ Signed-off-by: Rany Hany <rany_hany@riseup.net>
 
 --- a/arch/mips/kernel/smp.c
 +++ b/arch/mips/kernel/smp.c
-@@ -427,7 +427,17 @@ static void stop_this_cpu(void *dummy)
+@@ -429,7 +429,17 @@ static void stop_this_cpu(void *dummy)
  
  void smp_send_stop(void)
  {
index 6b5da2c50b6cf577e1042b364cea5a91027584fb..a84bddfe84e0d41d779a1ae9f0b3c3a41f44fbf5 100644 (file)
@@ -17,7 +17,7 @@ Signed-off-by: Rany Hany <rany_hany@riseup.net>
 
 --- a/arch/mips/kernel/smp.c
 +++ b/arch/mips/kernel/smp.c
-@@ -32,6 +32,7 @@
+@@ -33,6 +33,7 @@
  #include <asm/processor.h>
  #include <asm/idle.h>
  #include <asm/r4k-timer.h>
@@ -25,7 +25,7 @@ Signed-off-by: Rany Hany <rany_hany@riseup.net>
  #include <asm/mips-cps.h>
  #include <asm/mmu_context.h>
  #include <asm/time.h>
-@@ -413,6 +414,8 @@ asmlinkage void start_secondary(void)
+@@ -414,6 +415,8 @@ asmlinkage void start_secondary(void)
        cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
  }
  
@@ -34,10 +34,10 @@ Signed-off-by: Rany Hany <rany_hany@riseup.net>
  static void stop_this_cpu(void *dummy)
  {
        /*
-@@ -422,13 +425,66 @@ static void stop_this_cpu(void *dummy)
-       set_cpu_online(smp_processor_id(), false);
+@@ -424,13 +427,66 @@ static void stop_this_cpu(void *dummy)
        calculate_cpu_foreign_map();
        local_irq_disable();
+       rcutree_report_cpu_dead();
 -      while (1);
 +
 +      if (mips_cm_present() && r4k_blast_dcache) {