summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorManeesh Soni <maneesh@in.ibm.com>2006-03-14 10:33:14 +0100
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-14 17:26:44 +0100
commit67963132638e67ad3c5aa16765e6f3f2f3cdd85c (patch)
tree799409dacd6f604d6500bac693da5cb3fafb71cb /arch
parentRevert "[PATCH] x86-64: Fix up handling of non canonical user RIPs" (diff)
downloadlinux-67963132638e67ad3c5aa16765e6f3f2f3cdd85c.tar.xz
linux-67963132638e67ad3c5aa16765e6f3f2f3cdd85c.zip
[PATCH] Plug kdump shutdown race window
lapic_shutdown() re-enables interrupts which is un-desirable for panic case, so use local_irq_save() and local_irq_restore() to keep the irqs disabled for kexec on panic case, and close a possible race window while kdump shutdown as shown in this stack trace -- BUG: spinlock lockup on CPU#1, bash/4396, c52781a0 [<c01c1870>] _raw_spin_lock+0xb7/0xd2 [<c029e148>] _spin_lock+0x6/0x8 [<c011b33f>] scheduler_tick+0xe7/0x328 [<c0128a7c>] update_process_times+0x51/0x5d [<c0114592>] smp_apic_timer_interrupt+0x4f/0x58 [<c01141ff>] lapic_shutdown+0x76/0x7e [<c0104d7c>] apic_timer_interrupt+0x1c/0x30 [<c01141ff>] lapic_shutdown+0x76/0x7e [<c0116659>] machine_crash_shutdown+0x83/0xaa [<c013cc36>] crash_kexec+0xc1/0xe3 [<c029e148>] _spin_lock+0x6/0x8 [<c013cc22>] crash_kexec+0xad/0xe3 [<c0215280>] __handle_sysrq+0x84/0xfd [<c018d937>] write_sysrq_trigger+0x2c/0x35 [<c015e47b>] vfs_write+0xa2/0x13b [<c015ea73>] sys_write+0x3b/0x64 [<c0103c69>] syscall_call+0x7/0xb Signed-off-by: Maneesh Soni <maneesh@in.ibm.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/apic.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index f39e09ef64ec..776c90989e06 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -570,16 +570,18 @@ void __devinit setup_local_APIC(void)
*/
void lapic_shutdown(void)
{
+ unsigned long flags;
+
if (!cpu_has_apic)
return;
- local_irq_disable();
+ local_irq_save(flags);
clear_local_APIC();
if (enabled_via_apicbase)
disable_local_APIC();
- local_irq_enable();
+ local_irq_restore(flags);
}
#ifdef CONFIG_PM