summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
diff options
context:
space:
mode:
authorJan Beulich2006-01-06 09:11:48 +0100
committerLinus Torvalds2006-01-06 17:33:34 +0100
commite43d674f44dc885a2476cab3537e639d9eaa31a9 (patch)
tree23bf53cc0752000ddee91b8f957181bfc5b70a4c /arch/i386/kernel/traps.c
parent[PATCH] x86: GDT alignment fix (diff)
downloadkernel-qcow2-linux-e43d674f44dc885a2476cab3537e639d9eaa31a9.tar.gz
kernel-qcow2-linux-e43d674f44dc885a2476cab3537e639d9eaa31a9.tar.xz
kernel-qcow2-linux-e43d674f44dc885a2476cab3537e639d9eaa31a9.zip
[PATCH] i386: don't blindly enable interrupts in die()
Rather than blindly re-enabling interrupts in die(), save their state upon entry and then restore that state. If the kernel is in really bad condition and faults with interrupts disabled, re-enabling them in die() may cause even more trouble, implying more chances of data corruption. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r--arch/i386/kernel/traps.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index ab0e9430f775..bb36a989db77 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -306,14 +306,17 @@ void die(const char * str, struct pt_regs * regs, long err)
.lock_owner_depth = 0
};
static int die_counter;
+ unsigned long flags;
if (die.lock_owner != raw_smp_processor_id()) {
console_verbose();
- spin_lock_irq(&die.lock);
+ spin_lock_irqsave(&die.lock, flags);
die.lock_owner = smp_processor_id();
die.lock_owner_depth = 0;
bust_spinlocks(1);
}
+ else
+ local_save_flags(flags);
if (++die.lock_owner_depth < 3) {
int nl = 0;
@@ -340,7 +343,7 @@ void die(const char * str, struct pt_regs * regs, long err)
bust_spinlocks(0);
die.lock_owner = -1;
- spin_unlock_irq(&die.lock);
+ spin_unlock_irqrestore(&die.lock, flags);
if (kexec_should_crash(current))
crash_kexec(regs);