diff options
Diffstat (limited to 'arch/x86/kernel/kgdb.c')
-rw-r--r-- | arch/x86/kernel/kgdb.c | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 00354d4919a9..faba5771acad 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
@@ -511,28 +511,37 @@ single_step_cont(struct pt_regs *regs, struct die_args *args) | |||
511 | 511 | ||
512 | static int was_in_debug_nmi[NR_CPUS]; | 512 | static int was_in_debug_nmi[NR_CPUS]; |
513 | 513 | ||
514 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) | 514 | static int kgdb_nmi_handler(unsigned int cmd, struct pt_regs *regs) |
515 | { | 515 | { |
516 | struct pt_regs *regs = args->regs; | ||
517 | |||
518 | switch (cmd) { | 516 | switch (cmd) { |
519 | case DIE_NMI: | 517 | case NMI_LOCAL: |
520 | if (atomic_read(&kgdb_active) != -1) { | 518 | if (atomic_read(&kgdb_active) != -1) { |
521 | /* KGDB CPU roundup */ | 519 | /* KGDB CPU roundup */ |
522 | kgdb_nmicallback(raw_smp_processor_id(), regs); | 520 | kgdb_nmicallback(raw_smp_processor_id(), regs); |
523 | was_in_debug_nmi[raw_smp_processor_id()] = 1; | 521 | was_in_debug_nmi[raw_smp_processor_id()] = 1; |
524 | touch_nmi_watchdog(); | 522 | touch_nmi_watchdog(); |
525 | return NOTIFY_STOP; | 523 | return NMI_HANDLED; |
526 | } | 524 | } |
527 | return NOTIFY_DONE; | 525 | break; |
528 | 526 | ||
529 | case DIE_NMIUNKNOWN: | 527 | case NMI_UNKNOWN: |
530 | if (was_in_debug_nmi[raw_smp_processor_id()]) { | 528 | if (was_in_debug_nmi[raw_smp_processor_id()]) { |
531 | was_in_debug_nmi[raw_smp_processor_id()] = 0; | 529 | was_in_debug_nmi[raw_smp_processor_id()] = 0; |
532 | return NOTIFY_STOP; | 530 | return NMI_HANDLED; |
533 | } | 531 | } |
534 | return NOTIFY_DONE; | 532 | break; |
533 | default: | ||
534 | /* do nothing */ | ||
535 | break; | ||
536 | } | ||
537 | return NMI_DONE; | ||
538 | } | ||
539 | |||
540 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) | ||
541 | { | ||
542 | struct pt_regs *regs = args->regs; | ||
535 | 543 | ||
544 | switch (cmd) { | ||
536 | case DIE_DEBUG: | 545 | case DIE_DEBUG: |
537 | if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { | 546 | if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { |
538 | if (user_mode(regs)) | 547 | if (user_mode(regs)) |
@@ -590,11 +599,6 @@ kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) | |||
590 | 599 | ||
591 | static struct notifier_block kgdb_notifier = { | 600 | static struct notifier_block kgdb_notifier = { |
592 | .notifier_call = kgdb_notify, | 601 | .notifier_call = kgdb_notify, |
593 | |||
594 | /* | ||
595 | * Lowest-prio notifier priority, we want to be notified last: | ||
596 | */ | ||
597 | .priority = NMI_LOCAL_LOW_PRIOR, | ||
598 | }; | 602 | }; |
599 | 603 | ||
600 | /** | 604 | /** |
@@ -605,7 +609,31 @@ static struct notifier_block kgdb_notifier = { | |||
605 | */ | 609 | */ |
606 | int kgdb_arch_init(void) | 610 | int kgdb_arch_init(void) |
607 | { | 611 | { |
608 | return register_die_notifier(&kgdb_notifier); | 612 | int retval; |
613 | |||
614 | retval = register_die_notifier(&kgdb_notifier); | ||
615 | if (retval) | ||
616 | goto out; | ||
617 | |||
618 | retval = register_nmi_handler(NMI_LOCAL, kgdb_nmi_handler, | ||
619 | 0, "kgdb"); | ||
620 | if (retval) | ||
621 | goto out1; | ||
622 | |||
623 | retval = register_nmi_handler(NMI_UNKNOWN, kgdb_nmi_handler, | ||
624 | 0, "kgdb"); | ||
625 | |||
626 | if (retval) | ||
627 | goto out2; | ||
628 | |||
629 | return retval; | ||
630 | |||
631 | out2: | ||
632 | unregister_nmi_handler(NMI_LOCAL, "kgdb"); | ||
633 | out1: | ||
634 | unregister_die_notifier(&kgdb_notifier); | ||
635 | out: | ||
636 | return retval; | ||
609 | } | 637 | } |
610 | 638 | ||
611 | static void kgdb_hw_overflow_handler(struct perf_event *event, | 639 | static void kgdb_hw_overflow_handler(struct perf_event *event, |
@@ -673,6 +701,8 @@ void kgdb_arch_exit(void) | |||
673 | breakinfo[i].pev = NULL; | 701 | breakinfo[i].pev = NULL; |
674 | } | 702 | } |
675 | } | 703 | } |
704 | unregister_nmi_handler(NMI_UNKNOWN, "kgdb"); | ||
705 | unregister_nmi_handler(NMI_LOCAL, "kgdb"); | ||
676 | unregister_die_notifier(&kgdb_notifier); | 706 | unregister_die_notifier(&kgdb_notifier); |
677 | } | 707 | } |
678 | 708 | ||