linux/arch/x86/oprofile/nmi_timer_int.c
<<
>>
Prefs
   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/errno.h>
  13#include <linux/oprofile.h>
  14#include <linux/rcupdate.h>
  15#include <linux/kdebug.h>
  16
  17#include <asm/nmi.h>
  18#include <asm/apic.h>
  19#include <asm/ptrace.h>
  20
  21static int profile_timer_exceptions_notify(struct notifier_block *self,
  22                                           unsigned long val, void *data)
  23{
  24        struct die_args *args = (struct die_args *)data;
  25        int ret = NOTIFY_DONE;
  26
  27        switch (val) {
  28        case DIE_NMI:
  29                oprofile_add_sample(args->regs, 0);
  30                ret = NOTIFY_STOP;
  31                break;
  32        default:
  33                break;
  34        }
  35        return ret;
  36}
  37
  38static struct notifier_block profile_timer_exceptions_nb = {
  39        .notifier_call = profile_timer_exceptions_notify,
  40        .next = NULL,
  41        .priority = 0
  42};
  43
  44static int timer_start(void)
  45{
  46        if (register_die_notifier(&profile_timer_exceptions_nb))
  47                return 1;
  48        return 0;
  49}
  50
  51
  52static void timer_stop(void)
  53{
  54        unregister_die_notifier(&profile_timer_exceptions_nb);
  55        synchronize_sched();  /* Allow already-started NMIs to complete. */
  56}
  57
  58
  59int __init op_nmi_timer_init(struct oprofile_operations *ops)
  60{
  61        if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
  62                return -ENODEV;
  63
  64        ops->start = timer_start;
  65        ops->stop = timer_stop;
  66        ops->cpu_type = "timer";
  67        printk(KERN_INFO "oprofile: using NMI timer interrupt.\n");
  68        return 0;
  69}
  70