diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2005-06-25 17:58:02 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-25 19:24:50 -0400 |
| commit | d89559589a588d1a654329d8cd9a3ad33aaad9be (patch) | |
| tree | c1188aea792cfad9553962f659833ee78eef186c | |
| parent | 1bc3b91aeed71a904e431d12ca90e9b6bcb42c91 (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>
| -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(); |
