diff options
Diffstat (limited to 'arch/x86_64/kernel/nmi.c')
-rw-r--r-- | arch/x86_64/kernel/nmi.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index d42374a952d7..f6b881b23a70 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c | |||
@@ -682,16 +682,18 @@ void touch_nmi_watchdog (void) | |||
682 | touch_softlockup_watchdog(); | 682 | touch_softlockup_watchdog(); |
683 | } | 683 | } |
684 | 684 | ||
685 | void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | 685 | int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) |
686 | { | 686 | { |
687 | int sum; | 687 | int sum; |
688 | int touched = 0; | 688 | int touched = 0; |
689 | struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); | 689 | struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); |
690 | u64 dummy; | 690 | u64 dummy; |
691 | int rc=0; | ||
691 | 692 | ||
692 | /* check for other users first */ | 693 | /* check for other users first */ |
693 | if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) | 694 | if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) |
694 | == NOTIFY_STOP) { | 695 | == NOTIFY_STOP) { |
696 | rc = 1; | ||
695 | touched = 1; | 697 | touched = 1; |
696 | } | 698 | } |
697 | 699 | ||
@@ -746,10 +748,18 @@ void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
746 | } | 748 | } |
747 | /* start the cycle over again */ | 749 | /* start the cycle over again */ |
748 | wrmsrl(wd->perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz)); | 750 | wrmsrl(wd->perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz)); |
749 | } | 751 | rc = 1; |
752 | } else if (nmi_watchdog == NMI_IO_APIC) { | ||
753 | /* don't know how to accurately check for this. | ||
754 | * just assume it was a watchdog timer interrupt | ||
755 | * This matches the old behaviour. | ||
756 | */ | ||
757 | rc = 1; | ||
758 | } else | ||
759 | printk(KERN_WARNING "Unknown enabled NMI hardware?!\n"); | ||
750 | } | 760 | } |
751 | done: | 761 | done: |
752 | return; | 762 | return rc; |
753 | } | 763 | } |
754 | 764 | ||
755 | static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu) | 765 | static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu) |
@@ -761,15 +771,17 @@ static nmi_callback_t nmi_callback = dummy_nmi_callback; | |||
761 | 771 | ||
762 | asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) | 772 | asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) |
763 | { | 773 | { |
764 | int cpu = safe_smp_processor_id(); | ||
765 | |||
766 | nmi_enter(); | 774 | nmi_enter(); |
767 | add_pda(__nmi_count,1); | 775 | add_pda(__nmi_count,1); |
768 | if (!rcu_dereference(nmi_callback)(regs, cpu)) | 776 | default_do_nmi(regs); |
769 | default_do_nmi(regs); | ||
770 | nmi_exit(); | 777 | nmi_exit(); |
771 | } | 778 | } |
772 | 779 | ||
780 | int do_nmi_callback(struct pt_regs * regs, int cpu) | ||
781 | { | ||
782 | return rcu_dereference(nmi_callback)(regs, cpu); | ||
783 | } | ||
784 | |||
773 | void set_nmi_callback(nmi_callback_t callback) | 785 | void set_nmi_callback(nmi_callback_t callback) |
774 | { | 786 | { |
775 | vmalloc_sync_all(); | 787 | vmalloc_sync_all(); |