lkml.org 
[lkml]   [2003]   [Aug]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH][2.6.0-test3] Disable APIC on reboot.
Here is a patch for 2.6.0-test3 to disable the local APIC before
reboot. This fixes BIOS reboot problems reported by a few people.

disable_local_APIC() now checks if detect_init_APIC() enabled the
local APIC via the APIC_BASE MSR, and if so it now disables APIC_BASE.
Previously we would leave APIC_BASE enabled, and that made some
BIOSen unhappy.

The SMP reboot code calls disable_local_APIC(). On SMP HW there is
no change since detect_init_APIC() isn't called and APIC_BASE isn't
enabled by us. An SMP kernel on UP HW behaves just like an UP_APIC
kernel, so it disables APIC_BASE if we enabled it at boot.

The UP_APIC disable-before-suspend code is simplified since the existing
code to disable APIC_BASE is moved into disable_local_APIC().

(Felix Kühling originally reported the BIOS reboot problem. This is a
fixed-up version of his preliminary patch.)

/Mikael

--- linux-2.6.0-test3/arch/i386/kernel/apic.c.~1~ 2003-07-03 12:32:41.000000000 +0200
+++ linux-2.6.0-test3/arch/i386/kernel/apic.c 2003-08-11 23:49:06.000000000 +0200
@@ -61,6 +61,8 @@
static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
static DEFINE_PER_CPU(int, prof_counter) = 1;

+static int enabled_via_apicbase;
+
void enable_NMI_through_LVT0 (void * dummy)
{
unsigned int v, ver;
@@ -190,6 +192,13 @@
value = apic_read(APIC_SPIV);
value &= ~APIC_SPIV_APIC_ENABLED;
apic_write_around(APIC_SPIV, value);
+
+ if (enabled_via_apicbase) {
+ unsigned int l, h;
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ l &= ~MSR_IA32_APICBASE_ENABLE;
+ wrmsr(MSR_IA32_APICBASE, l, h);
+ }
}

/*
@@ -485,7 +494,6 @@

static int lapic_suspend(struct sys_device *dev, u32 state)
{
- unsigned int l, h;
unsigned long flags;

if (!apic_pm_state.active)
@@ -507,9 +515,6 @@

local_irq_save(flags);
disable_local_APIC();
- rdmsr(MSR_IA32_APICBASE, l, h);
- l &= ~MSR_IA32_APICBASE_ENABLE;
- wrmsr(MSR_IA32_APICBASE, l, h);
local_irq_restore(flags);
return 0;
}
@@ -636,6 +641,7 @@
l &= ~MSR_IA32_APICBASE_BASE;
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
wrmsr(MSR_IA32_APICBASE, l, h);
+ enabled_via_apicbase = 1;
}
}
/*
--- linux-2.6.0-test3/arch/i386/kernel/reboot.c.~1~ 2003-05-28 22:15:58.000000000 +0200
+++ linux-2.6.0-test3/arch/i386/kernel/reboot.c 2003-08-11 23:55:58.000000000 +0200
@@ -8,6 +8,7 @@
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
#include <asm/uaccess.h>
+#include <asm/apic.h>
#include "mach_reboot.h"

/*
@@ -249,6 +250,14 @@
* other OSs see a clean IRQ state.
*/
smp_send_stop();
+#elif CONFIG_X86_LOCAL_APIC
+ if (cpu_has_apic) {
+ local_irq_disable();
+ disable_local_APIC();
+ local_irq_enable();
+ }
+#endif
+#ifdef CONFIG_X86_IO_APIC
disable_IO_APIC();
#endif

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 13:47    [W:0.079 / U:0.192 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site