diff options
Diffstat (limited to 'arch/x86_64/kernel/traps.c')
-rw-r--r-- | arch/x86_64/kernel/traps.c | 37 |
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) | |||
343 | static DEFINE_SPINLOCK(die_lock); | 343 | static DEFINE_SPINLOCK(die_lock); |
344 | static int die_owner = -1; | 344 | static int die_owner = -1; |
345 | 345 | ||
346 | void oops_begin(void) | 346 | unsigned 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 | ||
362 | void oops_end(void) | 365 | void 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 | ||
371 | void __die(const char * str, struct pt_regs * regs, long err) | 374 | void __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 | ||
393 | void die(const char * str, struct pt_regs * regs, long err) | 396 | void 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 | } |
401 | static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) | 405 | static 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 | ||
407 | void die_nmi(char *str, struct pt_regs *regs) | 411 | void 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 | ||