Messages in this thread Patch in this message | | | Date | Wed, 2 Nov 2005 17:32:32 -0800 (PST) | From | Zwane Mwaikambo <> | Subject | [PATCH] i386 LVT entries remaining unmasked on reboot |
| |
Excerpt from bugzilla entry
http://bugzilla.kernel.org/show_bug.cgi?id=5518
"i386 version of Reboot-through-BIOS is unsafe: it forgets to mask APIC LVT interrupts before jumping to a BIOS entry point. As a result, BIOS ends up bombarded with interrupts early on boot. The BIOS does not expect it since following a "normal" hardware cpu reset, all APIC LVT registers have the Mask bit (16) set and can't generate interrupts.
For example, the version of Phoenix BIOS used by VMware enables interrupts for the first time before masking/clearing APIC LVT. The APIC Timer LVT register is still set up for a timer interrupt delivery with a high vector from the previous Linux incarnation (0xef in our case). The BIOS has not fully initialized its IDT at this point and the real mode gate for 0xef remains all zeros. Vector 0xef dispatches BIOS to address 0:0, BIOS takes a #GP and eventually hangs.
machine_shutdown() does attempt to shut down APIC before jumping to BIOS, but it is ineffective"
Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Index: linux-2.6.14-rc5-mm1/arch/i386/kernel/apic.c =================================================================== RCS file: /home/cvsroot/linux-2.6.14-rc5-mm1/arch/i386/kernel/apic.c,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 apic.c --- linux-2.6.14-rc5-mm1/arch/i386/kernel/apic.c 24 Oct 2005 15:38:38 -0000 1.1.1.1 +++ linux-2.6.14-rc5-mm1/arch/i386/kernel/apic.c 1 Nov 2005 08:02:21 -0000 @@ -559,14 +559,20 @@ void __devinit setup_local_APIC(void) * If Linux enabled the LAPIC against the BIOS default * disable it down before re-entering the BIOS on shutdown. * Otherwise the BIOS may get confused and not power-off. + * Additionally clear all LVT entries before disable_local_APIC + * for the case where Linux didn't enable the LAPIC. */ void lapic_shutdown(void) { - if (!cpu_has_apic || !enabled_via_apicbase) + if (!cpu_has_apic) return; local_irq_disable(); - disable_local_APIC(); + clear_local_APIC(); + + if (enabled_via_apicbase) + disable_local_APIC(); + local_irq_enable(); } - 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/
| |