Commit dd2a1305 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds

[PATCH] kexec: x86: 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.

By switching to the bootstrap cpu by default on reboot I can delete/simplify
some motherboard fixups well.
Signed-off-by: default avatarEric Biederman <ebiederm@xmission.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 50cccc69
...@@ -26,7 +26,6 @@ static int reboot_mode; ...@@ -26,7 +26,6 @@ static int reboot_mode;
static int reboot_thru_bios; static int reboot_thru_bios;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int reboot_smp = 0;
static int reboot_cpu = -1; static int reboot_cpu = -1;
/* shamelessly grabbed from lib/vsprintf.c for readability */ /* shamelessly grabbed from lib/vsprintf.c for readability */
#define is_digit(c) ((c) >= '0' && (c) <= '9') #define is_digit(c) ((c) >= '0' && (c) <= '9')
...@@ -49,7 +48,6 @@ static int __init reboot_setup(char *str) ...@@ -49,7 +48,6 @@ static int __init reboot_setup(char *str)
break; break;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
reboot_smp = 1;
if (is_digit(*(str+1))) { if (is_digit(*(str+1))) {
reboot_cpu = (int) (*(str+1) - '0'); reboot_cpu = (int) (*(str+1) - '0');
if (is_digit(*(str+2))) if (is_digit(*(str+2)))
...@@ -88,33 +86,9 @@ static int __init set_bios_reboot(struct dmi_system_id *d) ...@@ -88,33 +86,9 @@ static int __init set_bios_reboot(struct dmi_system_id *d)
return 0; return 0;
} }
/*
* Some machines require the "reboot=s" commandline option, this quirk makes that automatic.
*/
static int __init set_smp_reboot(struct dmi_system_id *d)
{
#ifdef CONFIG_SMP
if (!reboot_smp) {
reboot_smp = 1;
printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
}
#endif
return 0;
}
/*
* Some machines require the "reboot=b,s" commandline option, this quirk makes that automatic.
*/
static int __init set_smp_bios_reboot(struct dmi_system_id *d)
{
set_smp_reboot(d);
set_bios_reboot(d);
return 0;
}
static struct dmi_system_id __initdata reboot_dmi_table[] = { static struct dmi_system_id __initdata reboot_dmi_table[] = {
{ /* Handle problems with rebooting on Dell 1300's */ { /* Handle problems with rebooting on Dell 1300's */
.callback = set_smp_bios_reboot, .callback = set_bios_reboot,
.ident = "Dell PowerEdge 1300", .ident = "Dell PowerEdge 1300",
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
...@@ -301,41 +275,32 @@ void machine_real_restart(unsigned char *code, int length) ...@@ -301,41 +275,32 @@ void machine_real_restart(unsigned char *code, int length)
EXPORT_SYMBOL(machine_real_restart); EXPORT_SYMBOL(machine_real_restart);
#endif #endif
void machine_restart(char * __unused) void machine_shutdown(void)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int cpuid; int reboot_cpu_id;
cpuid = GET_APIC_ID(apic_read(APIC_ID)); /* The boot cpu is always logical cpu 0 */
reboot_cpu_id = 0;
if (reboot_smp) {
/* See if there has been given a command line override */
/* check to see if reboot_cpu is valid if ((reboot_cpu_id != -1) && (reboot_cpu < NR_CPUS) &&
if its not, default to the BSP */ cpu_isset(reboot_cpu, cpu_online_map)) {
if ((reboot_cpu == -1) || reboot_cpu_id = reboot_cpu;
(reboot_cpu > (NR_CPUS -1)) ||
!physid_isset(cpuid, phys_cpu_present_map))
reboot_cpu = boot_cpu_physical_apicid;
reboot_smp = 0; /* use this as a flag to only go through this once*/
/* re-run this function on the other CPUs
it will fall though this section since we have
cleared reboot_smp, and do the reboot if it is the
correct CPU, otherwise it halts. */
if (reboot_cpu != cpuid)
smp_call_function((void *)machine_restart , NULL, 1, 0);
} }
/* if reboot_cpu is still -1, then we want a tradional reboot, /* Make certain the cpu I'm rebooting on is online */
and if we are not running on the reboot_cpu,, halt */ if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) { reboot_cpu_id = smp_processor_id();
for (;;)
__asm__ __volatile__ ("hlt");
} }
/*
* Stop all CPUs and turn off local APICs and the IO-APIC, so /* Make certain I only run on the appropriate processor */
* other OSs see a clean IRQ state. 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, and disable their local APICs.
*/ */
smp_send_stop(); smp_send_stop();
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
...@@ -344,6 +309,11 @@ void machine_restart(char * __unused) ...@@ -344,6 +309,11 @@ void machine_restart(char * __unused)
#ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_X86_IO_APIC
disable_IO_APIC(); disable_IO_APIC();
#endif #endif
}
void machine_restart(char * __unused)
{
machine_shutdown();
if (!reboot_thru_bios) { if (!reboot_thru_bios) {
if (efi_enabled) { if (efi_enabled) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment