From: Eric W. Biederman 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: Andrew Morton --- 25-akpm/arch/x86_64/kernel/reboot.c | 59 +++++++++++++++++------------------- 1 files changed, 28 insertions(+), 31 deletions(-) diff -puN arch/x86_64/kernel/reboot.c~kexec-machine_shutdownx86_64 arch/x86_64/kernel/reboot.c --- 25/arch/x86_64/kernel/reboot.c~kexec-machine_shutdownx86_64 Fri Aug 20 15:22:19 2004 +++ 25-akpm/arch/x86_64/kernel/reboot.c Fri Aug 20 15:22:19 2004 @@ -91,31 +91,6 @@ static void reboot_warm(void) [target] "b" (WARMBOOT_TRAMP)); } -#ifdef CONFIG_SMP -static void smp_halt(void) -{ - int cpuid = safe_smp_processor_id(); - static int first_entry = 1; - - 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; @@ -125,23 +100,45 @@ static inline void kb_wait(void) break; } -void machine_restart(char * __unused) +void machine_shutdown(void) { - int i; - + /* Stop the cpus and apics */ #ifdef CONFIG_SMP - smp_halt(); + 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; + + machine_shutdown(); /* Tell the BIOS if we want cold or warm reboot */ *((unsigned short *)__va(0x472)) = reboot_mode; _