The following identical code piece appears in both
migrate_to_reboot_cpu() and smp_shutdown_nonboot_cpus():

        if (!cpu_online(primary_cpu))
                primary_cpu = cpumask_first(cpu_online_mask);

Although the kexec-reboot task can get through a cpu_down() on its cpu,
this code looks a little confusing.

Make things straight forward by keep cpu hotplug disabled until
smp_shutdown_nonboot_cpus() holds cpu_add_remove_lock. By this way, the
rebooting cpu can keep unchanged.

Signed-off-by: Pingfan Liu <kernelf...@gmail.com>
Cc: Eric Biederman <ebied...@xmission.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Valentin Schneider <valentin.schnei...@arm.com>
Cc: Vincent Donnefort <vincent.donnef...@arm.com>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Mark Rutland <mark.rutl...@arm.com>
Cc: YueHaibing <yuehaib...@huawei.com>
Cc: Baokun Li <libaok...@huawei.com>
Cc: Randy Dunlap <rdun...@infradead.org>
Cc: kexec@lists.infradead.org
To: linux-ker...@vger.kernel.org
---
 kernel/cpu.c        | 16 ++++++++++------
 kernel/kexec_core.c | 10 ++++------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/kernel/cpu.c b/kernel/cpu.c
index 407a2568f35e..bc687d59ca90 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1227,20 +1227,24 @@ int remove_cpu(unsigned int cpu)
 }
 EXPORT_SYMBOL_GPL(remove_cpu);
 
+/* primary_cpu keeps unchanged after migrate_to_reboot_cpu() */
 void smp_shutdown_nonboot_cpus(unsigned int primary_cpu)
 {
        unsigned int cpu;
        int error;
 
+       /*
+        * Block other cpu hotplug event, so primary_cpu is always online if
+        * it is not touched by us
+        */
        cpu_maps_update_begin();
-
        /*
-        * Make certain the cpu I'm about to reboot on is online.
-        *
-        * This is inline to what migrate_to_reboot_cpu() already do.
+        * migrate_to_reboot_cpu() disables CPU hotplug assuming that
+        * no further code needs to use CPU hotplug (which is true in
+        * the reboot case). However, the kexec path depends on using
+        * CPU hotplug again; so re-enable it here.
         */
-       if (!cpu_online(primary_cpu))
-               primary_cpu = cpumask_first(cpu_online_mask);
+       __cpu_hotplug_enable();
 
        for_each_online_cpu(cpu) {
                if (cpu == primary_cpu)
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 68480f731192..db4fa6b174e3 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1168,14 +1168,12 @@ int kernel_kexec(void)
                kexec_in_progress = true;
                kernel_restart_prepare("kexec reboot");
                migrate_to_reboot_cpu();
-
                /*
-                * migrate_to_reboot_cpu() disables CPU hotplug assuming that
-                * no further code needs to use CPU hotplug (which is true in
-                * the reboot case). However, the kexec path depends on using
-                * CPU hotplug again; so re-enable it here.
+                * migrate_to_reboot_cpu() disables CPU hotplug. If an arch
+                * relies on the cpu teardown to achieve reboot, it needs to
+                * re-enable CPU hotplug there.
                 */
-               cpu_hotplug_enable();
+
                pr_notice("Starting new kernel\n");
                machine_shutdown();
        }
-- 
2.31.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to