[PATCH] kexec: x86_64: factor out apic shutdown code
Eric W. Biederman [Sat, 25 Jun 2005 21:58:02 +0000 (14:58 -0700)]
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

index be4b36f..57e71db 100644 (file)
@@ -66,41 +66,47 @@ static int __init reboot_setup(char *str)
 
 __setup("reboot=", reboot_setup);
 
-#ifdef CONFIG_SMP
-static void smp_halt(void)
+static inline void kb_wait(void)
 {
-       int cpuid = safe_smp_processor_id(); 
-       static int first_entry = 1;
+       int i;
 
-       if (reboot_force)
-               return;
+       for (i=0; i<0x10000; i++)
+               if ((inb_p(0x64) & 0x02) == 0)
+                       break;
+}
 
-       if (first_entry) {
-               first_entry = 0;
-               smp_call_function((void *)machine_restart, NULL, 1, 0);
-       }
-                       
-       smp_stop_cpu(); 
+void machine_shutdown(void)
+{
+       /* Stop the cpus and apics */
+#ifdef CONFIG_SMP
+       int reboot_cpu_id;
 
-       /* AP calling this. Just halt */
-       if (cpuid != boot_cpu_id) { 
-               for (;;) 
-                       asm("hlt");
+       /* 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();
        }
 
-       /* Wait for all other CPUs to have run smp_stop_cpu */
-       while (!cpus_empty(cpu_online_map))
-               rep_nop(); 
-}
+       /* 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
 
-static inline void kb_wait(void)
-{
-       int i;
+       local_irq_disable();
 
-       for (i=0; i<0x10000; i++)
-               if ((inb_p(0x64) & 0x02) == 0)
-                       break;
+#ifndef CONFIG_SMP
+       disable_local_APIC();
+#endif
+
+       disable_IO_APIC();
+
+       local_irq_enable();
 }
 
 void machine_restart(char * __unused)
@@ -109,9 +115,7 @@ void machine_restart(char * __unused)
 
        printk("machine restart\n");
 
-#ifdef CONFIG_SMP
-       smp_halt(); 
-#endif
+       machine_shutdown();
 
        if (!reboot_force) {
                local_irq_disable();