aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2005-06-25 17:58:02 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:50 -0400
commitd89559589a588d1a654329d8cd9a3ad33aaad9be (patch)
treec1188aea792cfad9553962f659833ee78eef186c /arch
parent1bc3b91aeed71a904e431d12ca90e9b6bcb42c91 (diff)
[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>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/kernel/reboot.c62
1 files changed, 33 insertions, 29 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,41 +66,47 @@ static int __init reboot_setup(char *str)
66 66
67__setup("reboot=", reboot_setup); 67__setup("reboot=", reboot_setup);
68 68
69#ifdef CONFIG_SMP 69static inline void kb_wait(void)
70static void smp_halt(void)
71{ 70{
72 int cpuid = safe_smp_processor_id(); 71 int i;
73 static int first_entry = 1;
74 72
75 if (reboot_force) 73 for (i=0; i<0x10000; i++)
76 return; 74 if ((inb_p(0x64) & 0x02) == 0)
75 break;
76}
77 77
78 if (first_entry) { 78void machine_shutdown(void)
79 first_entry = 0; 79{
80 smp_call_function((void *)machine_restart, NULL, 1, 0); 80 /* Stop the cpus and apics */
81 } 81#ifdef CONFIG_SMP
82 82 int reboot_cpu_id;
83 smp_stop_cpu();
84 83
85 /* AP calling this. Just halt */ 84 /* The boot cpu is always logical cpu 0 */
86 if (cpuid != boot_cpu_id) { 85 reboot_cpu_id = 0;
87 for (;;) 86
88 asm("hlt"); 87 /* Make certain the cpu I'm about to reboot on is online */
88 if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
89 reboot_cpu_id = smp_processor_id();
89 } 90 }
90 91
91 /* Wait for all other CPUs to have run smp_stop_cpu */ 92 /* Make certain I only run on the appropriate processor */
92 while (!cpus_empty(cpu_online_map)) 93 set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
93 rep_nop(); 94
94} 95 /* O.K Now that I'm on the appropriate processor,
96 * stop all of the others.
97 */
98 smp_send_stop();
95#endif 99#endif
96 100
97static inline void kb_wait(void) 101 local_irq_disable();
98{
99 int i;
100 102
101 for (i=0; i<0x10000; i++) 103#ifndef CONFIG_SMP
102 if ((inb_p(0x64) & 0x02) == 0) 104 disable_local_APIC();
103 break; 105#endif
106
107 disable_IO_APIC();
108
109 local_irq_enable();
104} 110}
105 111
106void machine_restart(char * __unused) 112void machine_restart(char * __unused)
@@ -109,9 +115,7 @@ void machine_restart(char * __unused)
109 115
110 printk("machine restart\n"); 116 printk("machine restart\n");
111 117
112#ifdef CONFIG_SMP 118 machine_shutdown();
113 smp_halt();
114#endif
115 119
116 if (!reboot_force) { 120 if (!reboot_force) {
117 local_irq_disable(); 121 local_irq_disable();