aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/traps.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2005-09-12 12:49:24 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-12 13:50:57 -0400
commit1209140c3c70aaa32d1a0462d79557f2a44a4ef8 (patch)
tree2dc299ad357392f7d81e85131615bb61f0b1a14c /arch/x86_64/kernel/traps.c
parent059bf0f6c33058680e4381f17d554baaa4f45d68 (diff)
[PATCH] x86-64: Safe interrupts in oops_begin/end
Rather than blindly re-enabling interrupts in oops_end(), save their state in oope_begin() and then restore that state. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/traps.c')
-rw-r--r--arch/x86_64/kernel/traps.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index f238d6078a5a..64a59cb49411 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -343,30 +343,33 @@ void out_of_line_bug(void)
343static DEFINE_SPINLOCK(die_lock); 343static DEFINE_SPINLOCK(die_lock);
344static int die_owner = -1; 344static int die_owner = -1;
345 345
346void oops_begin(void) 346unsigned long oops_begin(void)
347{ 347{
348 int cpu = safe_smp_processor_id(); 348 int cpu = safe_smp_processor_id();
349 /* racy, but better than risking deadlock. */ 349 unsigned long flags;
350 local_irq_disable(); 350
351 /* racy, but better than risking deadlock. */
352 local_irq_save(flags);
351 if (!spin_trylock(&die_lock)) { 353 if (!spin_trylock(&die_lock)) {
352 if (cpu == die_owner) 354 if (cpu == die_owner)
353 /* nested oops. should stop eventually */; 355 /* nested oops. should stop eventually */;
354 else 356 else
355 spin_lock(&die_lock); 357 spin_lock(&die_lock);
356 } 358 }
357 die_owner = cpu; 359 die_owner = cpu;
358 console_verbose(); 360 console_verbose();
359 bust_spinlocks(1); 361 bust_spinlocks(1);
362 return flags;
360} 363}
361 364
362void oops_end(void) 365void oops_end(unsigned long flags)
363{ 366{
364 die_owner = -1; 367 die_owner = -1;
365 bust_spinlocks(0); 368 bust_spinlocks(0);
366 spin_unlock(&die_lock); 369 spin_unlock_irqrestore(&die_lock, flags);
367 if (panic_on_oops) 370 if (panic_on_oops)
368 panic("Oops"); 371 panic("Oops");
369} 372}
370 373
371void __die(const char * str, struct pt_regs * regs, long err) 374void __die(const char * str, struct pt_regs * regs, long err)
372{ 375{
@@ -392,10 +395,11 @@ void __die(const char * str, struct pt_regs * regs, long err)
392 395
393void die(const char * str, struct pt_regs * regs, long err) 396void die(const char * str, struct pt_regs * regs, long err)
394{ 397{
395 oops_begin(); 398 unsigned long flags = oops_begin();
399
396 handle_BUG(regs); 400 handle_BUG(regs);
397 __die(str, regs, err); 401 __die(str, regs, err);
398 oops_end(); 402 oops_end(flags);
399 do_exit(SIGSEGV); 403 do_exit(SIGSEGV);
400} 404}
401static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) 405static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
@@ -406,7 +410,8 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
406 410
407void die_nmi(char *str, struct pt_regs *regs) 411void die_nmi(char *str, struct pt_regs *regs)
408{ 412{
409 oops_begin(); 413 unsigned long flags = oops_begin();
414
410 /* 415 /*
411 * We are in trouble anyway, lets at least try 416 * We are in trouble anyway, lets at least try
412 * to get a message out. 417 * to get a message out.
@@ -416,7 +421,7 @@ void die_nmi(char *str, struct pt_regs *regs)
416 if (panic_on_timeout || panic_on_oops) 421 if (panic_on_timeout || panic_on_oops)
417 panic("nmi watchdog"); 422 panic("nmi watchdog");
418 printk("console shuts up ...\n"); 423 printk("console shuts up ...\n");
419 oops_end(); 424 oops_end(flags);
420 do_exit(SIGSEGV); 425 do_exit(SIGSEGV);
421} 426}
422 427