Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kexec: migrate to reboot cpu

Commit 1b3a5d02ee07 ("reboot: move arch/x86 reboot= handling to generic
kernel") moved reboot= handling to generic code. In the process it also
removed the code in native_machine_shutdown() which are moving reboot
process to reboot_cpu/cpu0.

I guess that thought must have been that all reboot paths are calling
migrate_to_reboot_cpu(), so we don't need this special handling. But
kexec reboot path (kernel_kexec()) is not calling
migrate_to_reboot_cpu() so above change broke kexec. Now reboot can
happen on non-boot cpu and when INIT is sent in second kerneo to bring
up BP, it brings down the machine.

So start calling migrate_to_reboot_cpu() in kexec reboot path to avoid
this problem.

Bisected by WANG Chao.

Reported-by: Matthew Whitehead <mwhitehe@redhat.com>
Reported-by: Dave Young <dyoung@redhat.com>
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Tested-by: Baoquan He <bhe@redhat.com>
Tested-by: WANG Chao <chaowang@redhat.com>
Acked-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Vivek Goyal and committed by
Linus Torvalds
c97102ba b0031f22

+3 -1
+1
include/linux/reboot.h
··· 43 43 * Architecture-specific implementations of sys_reboot commands. 44 44 */ 45 45 46 + extern void migrate_to_reboot_cpu(void); 46 47 extern void machine_restart(char *cmd); 47 48 extern void machine_halt(void); 48 49 extern void machine_power_off(void);
+1
kernel/kexec.c
··· 1680 1680 { 1681 1681 kexec_in_progress = true; 1682 1682 kernel_restart_prepare(NULL); 1683 + migrate_to_reboot_cpu(); 1683 1684 printk(KERN_EMERG "Starting new kernel\n"); 1684 1685 machine_shutdown(); 1685 1686 }
+1 -1
kernel/reboot.c
··· 104 104 } 105 105 EXPORT_SYMBOL(unregister_reboot_notifier); 106 106 107 - static void migrate_to_reboot_cpu(void) 107 + void migrate_to_reboot_cpu(void) 108 108 { 109 109 /* The boot cpu is always logical cpu 0 */ 110 110 int cpu = reboot_cpu;