From d89559589a588d1a654329d8cd9a3ad33aaad9be Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" <ebiederm@xmission.com> Date: Sat, 25 Jun 2005 14:58:02 -0700 Subject: [PATCH] [PATCH] kexec: x86_64: factor out apic shutdown code Factor out the apic and smp shutdown code from machine_restart so it can be called by in the kexec reboot path as well. Signed-off-by: Eric Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org> --- arch/x86_64/kernel/reboot.c | 66 ++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index be4b36f762cf..57e71dbdfd69 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c @@ -66,34 +66,6 @@ static int __init reboot_setup(char *str) __setup("reboot=", reboot_setup); -#ifdef CONFIG_SMP -static void smp_halt(void) -{ - int cpuid = safe_smp_processor_id(); - static int first_entry = 1; - - if (reboot_force) - return; - - if (first_entry) { - first_entry = 0; - smp_call_function((void *)machine_restart, NULL, 1, 0); - } - - smp_stop_cpu(); - - /* AP calling this. Just halt */ - if (cpuid != boot_cpu_id) { - for (;;) - asm("hlt"); - } - - /* Wait for all other CPUs to have run smp_stop_cpu */ - while (!cpus_empty(cpu_online_map)) - rep_nop(); -} -#endif - static inline void kb_wait(void) { int i; @@ -103,15 +75,47 @@ static inline void kb_wait(void) break; } +void machine_shutdown(void) +{ + /* Stop the cpus and apics */ +#ifdef CONFIG_SMP + int reboot_cpu_id; + + /* The boot cpu is always logical cpu 0 */ + reboot_cpu_id = 0; + + /* Make certain the cpu I'm about to reboot on is online */ + if (!cpu_isset(reboot_cpu_id, cpu_online_map)) { + reboot_cpu_id = smp_processor_id(); + } + + /* Make certain I only run on the appropriate processor */ + set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id)); + + /* O.K Now that I'm on the appropriate processor, + * stop all of the others. + */ + smp_send_stop(); +#endif + + local_irq_disable(); + +#ifndef CONFIG_SMP + disable_local_APIC(); +#endif + + disable_IO_APIC(); + + local_irq_enable(); +} + void machine_restart(char * __unused) { int i; printk("machine restart\n"); -#ifdef CONFIG_SMP - smp_halt(); -#endif + machine_shutdown(); if (!reboot_force) { local_irq_disable();