X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fx86_64%2Fkernel%2Freboot.c;h=3dac33924170818ef55c8f82d549b5aa67daddd6;hb=3f5a17d40f109b370e21e7451cf05b23cf578698;hp=ce789144fbc634462fd137d68663b19ec6e14392;hpb=8d40237c730b8be87c1b80a5d96b9c603fefa829;p=linux-2.6.git diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index ce789144f..3dac33924 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c @@ -91,54 +91,47 @@ static void reboot_warm(void) [target] "b" (WARMBOOT_TRAMP)); } -static inline void kb_wait(void) -{ - int i; - - for (i=0; i<0x10000; i++) - if ((inb_p(0x64) & 0x02) == 0) - 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(); +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"); } - /* 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(); + /* Wait for all other CPUs to have run smp_stop_cpu */ + while (!cpus_empty(cpu_online_map)) + rep_nop(); +} #endif - disable_IO_APIC(); +static inline void kb_wait(void) +{ + int i; - local_irq_enable(); + for (i=0; i<0x10000; i++) + if ((inb_p(0x64) & 0x02) == 0) + break; } void machine_restart(char * __unused) { int i; - machine_shutdown(); +#ifdef CONFIG_SMP + smp_halt(); +#endif local_irq_disable();