ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / i386 / oprofile / nmi_timer_int.c
1 /**
2  * @file nmi_timer_int.c
3  *
4  * @remark Copyright 2003 OProfile authors
5  * @remark Read the file COPYING
6  *
7  * @author Zwane Mwaikambo <zwane@linuxpower.ca>
8  */
9
10 #include <linux/init.h>
11 #include <linux/smp.h>
12 #include <linux/irq.h>
13 #include <linux/oprofile.h>
14 #include <linux/rcupdate.h>
15
16
17 #include <asm/nmi.h>
18 #include <asm/apic.h>
19 #include <asm/ptrace.h>
20  
21 static int nmi_timer_callback(struct pt_regs * regs, int cpu)
22 {
23         unsigned long eip = instruction_pointer(regs);
24  
25         oprofile_add_sample(eip, !user_mode(regs), 0, cpu);
26         return 1;
27 }
28
29 static int timer_start(void)
30 {
31         disable_timer_nmi_watchdog();
32         set_nmi_callback(nmi_timer_callback);
33         return 0;
34 }
35
36
37 static void timer_stop(void)
38 {
39         enable_timer_nmi_watchdog();
40         unset_nmi_callback();
41         synchronize_kernel();
42 }
43
44
45 static struct oprofile_operations nmi_timer_ops = {
46         .start  = timer_start,
47         .stop   = timer_stop,
48         .cpu_type = "timer"
49 };
50
51 int __init nmi_timer_init(struct oprofile_operations ** ops)
52 {
53         extern int nmi_active;
54
55         if (nmi_active <= 0)
56                 return -ENODEV;
57
58         *ops = &nmi_timer_ops;
59         printk(KERN_INFO "oprofile: using NMI timer interrupt.\n");
60         return 0;
61 }