Messages in this thread Patch in this message | | | Date | Tue, 12 Aug 2003 01:33:17 +0200 | From | Mikael Pettersson <> | Subject | [PATCH][2.4.22-rc2] Disable APIC on reboot. |
| |
Here is a patch for 2.4.22-rc2 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.4.22-rc2/arch/i386/kernel/apic.c.~1~ 2003-06-14 13:30:19.000000000 +0200 +++ linux-2.4.22-rc2/arch/i386/kernel/apic.c 2003-08-11 23:42:39.000000000 +0200 @@ -38,6 +38,8 @@ int prof_old_multiplier[NR_CPUS] = { 1, }; int prof_counter[NR_CPUS] = { 1, }; +static int enabled_via_apicbase; + int get_maxlvt(void) { unsigned int v, ver, maxlvt; @@ -142,6 +144,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); + } } /* @@ -464,7 +473,6 @@ static void apic_pm_suspend(void *data) { - unsigned int l, h; unsigned long flags; if (apic_pm_state.perfctr_pmdev) @@ -484,9 +492,6 @@ __save_flags(flags); __cli(); disable_local_APIC(); - rdmsr(MSR_IA32_APICBASE, l, h); - l &= ~MSR_IA32_APICBASE_ENABLE; - wrmsr(MSR_IA32_APICBASE, l, h); __restore_flags(flags); } @@ -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.4.22-rc2/arch/i386/kernel/process.c.~1~ 2003-08-11 21:27:40.000000000 +0200 +++ linux-2.4.22-rc2/arch/i386/kernel/process.c 2003-08-11 23:11:44.000000000 +0200 @@ -47,6 +47,7 @@ #ifdef CONFIG_MATH_EMULATION #include <asm/math_emu.h> #endif +#include <asm/apic.h> #include <linux/irq.h> @@ -399,6 +400,14 @@ * other OSs see a clean IRQ state. */ smp_send_stop(); +#elif CONFIG_X86_LOCAL_APIC + if (cpu_has_apic) { + __cli(); + disable_local_APIC(); + __sti(); + } +#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/
| |