NMI request/release, version 2
PATCH 1/1 NMI request/release, version 2
Add a request/release mechanism to the kernel (x86 only for now) for NMIs.
This version has a lot of updates, mostly changes for comments from John Levon. I have modified the nmi watchdog to use this interface, and it seems to work ok. Keith Owens is copied to see if he would be interested in converting kdb to use this, if it gets put into the kernel.
-Corey
arch/i386/kernel/i386_ksyms.c +3 -0
@@ -90,6 +90,9 @@EXPORT_SYMBOL (cpu_khz);EXPORT_SYMBOL (apm_info); +EXPORT_SYMBOL (request_nmi); +EXPORT_SYMBOL (release_nmi); +#ifdef CONFIG_DEBUG_IOVIRT EXPORT_SYMBOL (__io_virt_debug);#endif
arch/i386/kernel/irq.c +4 -0
@@ -131,6 +131,8 @@* Generic, controller-independent functions: */ +extern void nmi_append_user_names (struct seq_file *p); +int show_interrupts (struct seq_file *p,void *v) {int i, j;
@@ -166,6 +168,8 @@for (j =0 ; j <NR_CPUS ; j++)if (cpu_online (j)) p +=seq_printf (p,"%10u " ,nmi_count (j)); +seq_printf (p," " ); +nmi_append_user_names (p);seq_putc (p,'\n' );#if CONFIG_X86_LOCAL_APIC seq_printf (p,"LOC: " );
arch/i386/kernel/nmi.c +17 -1
@@ -20,6 +20,7 @@#include <linux/interrupt.h> #include <linux/mc146818rtc.h> #include <linux/kernel_stat.h> +#include <linux/notifier.h> #include <asm/smp.h> #include <asm/mtrr.h>
@@ -102,6 +103,16 @@return 0 ; } +static int nmi_watchdog_tick (void * dev_id,struct pt_regs * regs); + +static struct nmi_handler nmi_watchdog_handler = +{ + .dev_name ="nmi_watchdog" , + .dev_id =NULL , + .handler = nmi_watchdog_tick, + .priority =255 /* We want to be relatively high priority. */ +}; +static int __init setup_nmi_watchdog (char *str) {int nmi;
@@ -131,6 +142,9 @@*/ if (nmi ==NMI_IO_APIC ) nmi_watchdog = nmi; + +request_nmi (&nmi_watchdog_handler); +return 1 ; }
@@ -350,7 +364,7 @@ alert_counter[i] =0 ; } -void nmi_watchdog_tick (struct pt_regs * regs) +static int nmi_watchdog_tick (void * dev_id,struct pt_regs * regs) {/*
@@ -401,4 +415,6 @@ }wrmsr (nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000 ),-1 ); } + +return NOTIFY_OK ; }
arch/i386/kernel/traps.c +137 -7
164 lines not on this page · raw message
include/asm-i386/apic.h +0 -1
@@ -79,7 +79,6 @@extern void setup_boot_APIC_clock (void );extern void setup_secondary_APIC_clock (void );extern void setup_apic_nmi_watchdog (void ); -extern inline void nmi_watchdog_tick (struct pt_regs * regs);extern int APIC_init_uniprocessor (void );extern void disable_APIC_timer (void );extern void enable_APIC_timer (void );
include/asm-i386/irq.h +26 -0
@@ -28,4 +28,30 @@#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #endif + +/* Structure for handling NMIs */ +#define HAVE_NMI_HANDLER 1 +struct nmi_handler +{ +char *dev_name; +void *dev_id; +int (*handler)(void *dev_id,struct pt_regs *regs); +int priority;/* Handlers called in priority order. */ + +volatile struct nmi_handler *next; +}; + +/** +* Register a handler to get called when an NMI occurs. If the +* handler actually handles the NMI, it should return NOTIFY_OK. If +* it did not handle the NMI, it should return NOTIFY_DONE. It may or +* on NOTIFY_STOP_MASK to the return value if it does not want other +* handlers after it to be notified. Note that this is a slow-path +* handler, if you have a fast-path handler there's another tie-in +* for you. See the oprofile code. +*/ +int request_nmi (struct nmi_handler *handler); +void release_nmi (struct nmi_handler *handler); + +#endif /* _ASM_IRQ_H */