aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/oprofile/nmi_timer_int.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/oprofile/nmi_timer_int.c')
-rw-r--r--arch/i386/oprofile/nmi_timer_int.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c
index a33a73bb502d..93ca48f804ac 100644
--- a/arch/i386/oprofile/nmi_timer_int.c
+++ b/arch/i386/oprofile/nmi_timer_int.c
@@ -17,32 +17,49 @@
17#include <asm/nmi.h> 17#include <asm/nmi.h>
18#include <asm/apic.h> 18#include <asm/apic.h>
19#include <asm/ptrace.h> 19#include <asm/ptrace.h>
20#include <asm/kdebug.h>
20 21
21static int nmi_timer_callback(struct pt_regs * regs, int cpu) 22int profile_timer_exceptions_notify(struct notifier_block *self,
23 unsigned long val, void *data)
22{ 24{
23 oprofile_add_sample(regs, 0); 25 struct die_args *args = (struct die_args *)data;
24 return 1; 26 int ret = NOTIFY_DONE;
27
28 switch(val) {
29 case DIE_NMI:
30 oprofile_add_sample(args->regs, 0);
31 ret = NOTIFY_STOP;
32 break;
33 default:
34 break;
35 }
36 return ret;
25} 37}
26 38
39static struct notifier_block profile_timer_exceptions_nb = {
40 .notifier_call = profile_timer_exceptions_notify,
41 .next = NULL,
42 .priority = 0
43};
44
27static int timer_start(void) 45static int timer_start(void)
28{ 46{
29 disable_timer_nmi_watchdog(); 47 if (register_die_notifier(&profile_timer_exceptions_nb))
30 set_nmi_callback(nmi_timer_callback); 48 return 1;
31 return 0; 49 return 0;
32} 50}
33 51
34 52
35static void timer_stop(void) 53static void timer_stop(void)
36{ 54{
37 enable_timer_nmi_watchdog(); 55 unregister_die_notifier(&profile_timer_exceptions_nb);
38 unset_nmi_callback();
39 synchronize_sched(); /* Allow already-started NMIs to complete. */ 56 synchronize_sched(); /* Allow already-started NMIs to complete. */
40} 57}
41 58
42 59
43int __init op_nmi_timer_init(struct oprofile_operations * ops) 60int __init op_nmi_timer_init(struct oprofile_operations * ops)
44{ 61{
45 if (atomic_read(&nmi_active) <= 0) 62 if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
46 return -ENODEV; 63 return -ENODEV;
47 64
48 ops->start = timer_start; 65 ops->start = timer_start;