diff options
-rw-r--r-- | arch/x86_64/kernel/reboot.c | 62 |
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 | 69 | static inline void kb_wait(void) |
70 | static 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) { | 78 | void 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 | ||
97 | static 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 | ||
106 | void machine_restart(char * __unused) | 112 | void 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(); |