diff options
Diffstat (limited to 'arch/x86/kernel/nmi.c')
-rw-r--r-- | arch/x86/kernel/nmi.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index e88f37b58dd..de8d4b333f4 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c | |||
@@ -408,6 +408,18 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs) | |||
408 | dotraplinkage notrace __kprobes void | 408 | dotraplinkage notrace __kprobes void |
409 | do_nmi(struct pt_regs *regs, long error_code) | 409 | do_nmi(struct pt_regs *regs, long error_code) |
410 | { | 410 | { |
411 | int update_debug_stack = 0; | ||
412 | |||
413 | /* | ||
414 | * If we interrupted a breakpoint, it is possible that | ||
415 | * the nmi handler will have breakpoints too. We need to | ||
416 | * change the IDT such that breakpoints that happen here | ||
417 | * continue to use the NMI stack. | ||
418 | */ | ||
419 | if (unlikely(is_debug_stack(regs->sp))) { | ||
420 | debug_stack_set_zero(); | ||
421 | update_debug_stack = 1; | ||
422 | } | ||
411 | nmi_enter(); | 423 | nmi_enter(); |
412 | 424 | ||
413 | inc_irq_stat(__nmi_count); | 425 | inc_irq_stat(__nmi_count); |
@@ -416,6 +428,9 @@ do_nmi(struct pt_regs *regs, long error_code) | |||
416 | default_do_nmi(regs); | 428 | default_do_nmi(regs); |
417 | 429 | ||
418 | nmi_exit(); | 430 | nmi_exit(); |
431 | |||
432 | if (unlikely(update_debug_stack)) | ||
433 | debug_stack_reset(); | ||
419 | } | 434 | } |
420 | 435 | ||
421 | void stop_nmi(void) | 436 | void stop_nmi(void) |