OProfile: small NMI shutdown fix
PATCH 1/3 OProfile: small NMI shutdown fix
Reduce the possibility of dazed-and-confuseds.
arch/i386/oprofile/nmi_int.c +1 -1
@@ -182,8 +182,8 @@static void nmi_shutdown (void ) { nmi_enabled =0 ; -unset_nmi_callback ();on_each_cpu (nmi_cpu_shutdown,NULL ,0 ,1 ); +unset_nmi_callback ();enable_lapic_nmi_watchdog (); }
PATCH 2/3 OProfile: IO-APIC based NMI delivery
Use the IO-APIC NMI delivery when the local APIC performance counter delivery is not available. By Zwane Mwaikambo.
arch/i386/kernel/nmi.c +37 -9
@@ -23,17 +23,27 @@#include <linux/mc146818rtc.h> #include <linux/kernel_stat.h> #include <linux/module.h> +#include <linux/nmi.h> #include <linux/sysdev.h> #include <asm/smp.h> #include <asm/mtrr.h> #include <asm/mpspec.h> +#include <asm/nmi.h> unsigned int nmi_watchdog =NMI_NONE ;static unsigned int nmi_hz =HZ ;unsigned int nmi_perfctr_msr;/* the MSR to reset in NMI handler */ extern void show_registers (struct pt_regs *regs); +/* nmi_active: +* +1: the lapic NMI watchdog is active, but can be disabled +* 0: the lapic NMI watchdog has not been set up, and cannot +* be enabled +* -1: the lapic NMI watchdog is disabled, but can be enabled +*/ +static int nmi_active; +#define K7_EVNTSEL_ENABLE (1 << 22)#define K7_EVNTSEL_INT (1 << 20)#define K7_EVNTSEL_OS (1 << 17)
@@ -91,6 +101,7 @@continue ;if (nmi_count (cpu) - prev_nmi_count[cpu] <=5 ) {printk ("CPU#%d: NMI appears to be stuck!\n" , cpu); + nmi_active =0 ;return -1 ; } }
@@ -131,21 +142,15 @@* We can enable the IO-APIC watchdog * unconditionally. */ -if (nmi ==NMI_IO_APIC ) +if (nmi ==NMI_IO_APIC ) { + nmi_active =1 ; nmi_watchdog = nmi; + }return 1 ; }__setup ("nmi_watchdog=" , setup_nmi_watchdog); -/* nmi_active: -* +1: the lapic NMI watchdog is active, but can be disabled -* 0: the lapic NMI watchdog has not been set up, and cannot -* be enabled -* -1: the lapic NMI watchdog is disabled, but can be enabled -*/ -static int nmi_active; -void disable_lapic_nmi_watchdog (void ) {if (nmi_active <=0 )
@@ -179,6 +184,27 @@ } } +void disable_timer_nmi_watchdog (void ) +{ +if ((nmi_watchdog !=NMI_IO_APIC ) || (nmi_active <=0 )) +return ; + +disable_irq (0 ); +unset_nmi_callback (); + nmi_active =-1 ; + nmi_watchdog =NMI_NONE ; +} + +void enable_timer_nmi_watchdog (void ) +{ +if (nmi_active <0 ) { + nmi_watchdog =NMI_IO_APIC ; +touch_nmi_watchdog (); + nmi_active =1 ; +enable_irq (0 ); + } +} +#ifdef CONFIG_PM static int nmi_pm_active;/* nmi_active before suspend */
@@ -429,3 +455,5 @@EXPORT_SYMBOL (nmi_watchdog);EXPORT_SYMBOL (disable_lapic_nmi_watchdog);EXPORT_SYMBOL (enable_lapic_nmi_watchdog); +EXPORT_SYMBOL (disable_timer_nmi_watchdog); +EXPORT_SYMBOL (enable_timer_nmi_watchdog);
arch/i386/oprofile/init.c +9 -3
@@ -16,15 +16,21 @@*/ extern int nmi_init (struct oprofile_operations ** ops); +extern int nmi_timer_init (struct oprofile_operations **ops);extern void nmi_exit (void );int __init oprofile_arch_init (struct oprofile_operations ** ops) { +int ret = -ENODEV ;#ifdef CONFIG_X86_LOCAL_APIC -return nmi_init (ops); -#else -return -ENODEV ; + ret =nmi_init (ops);#endif + +#ifdef CONFIG_X86_IO_APIC +if (ret <0 ) + ret =nmi_timer_init (ops); +#endif +return ret; }
arch/i386/oprofile/Makefile +1 -0
@@ -9,3 +9,4 @@ oprofile-y := $(DRIVER_OBJS) init.o oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ op_model_ppro.o op_model_p4.o +oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o
arch/i386/oprofile/nmi_timer_int.c +57 -0
57 lines not on this page · raw message
include/asm-i386/apic.h +2 -0
@@ -81,6 +81,8 @@extern void setup_apic_nmi_watchdog (void );extern void disable_lapic_nmi_watchdog (void );extern void enable_lapic_nmi_watchdog (void ); +extern void disable_timer_nmi_watchdog (void ); +extern void enable_timer_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 );
PATCH 3/3 OProfile: thread switching performance fix
Avoid the linear list walk of get_exec_dcookie() when we've switched to a task using the same mm.
drivers/oprofile/buffer_sync.c +6 -4
@@ -425,7 +425,7 @@ {struct mm_struct * mm =0 ;struct task_struct * new; -unsigned long cookie; +unsigned long cookie =0 ;int in_kernel =1 ;unsigned int i;
@@ -442,13 +442,15 @@ in_kernel = s->event;add_kernel_ctx_switch (s->event); }else { +struct mm_struct * oldmm = mm; +/* userspace context switch */ new = (struct task_struct *)s->event; -release_mm (mm); +release_mm (oldmm); mm =take_tasks_mm (new); - - cookie =get_exec_dcookie (mm); +if (mm != oldmm) + cookie =get_exec_dcookie (mm);add_user_ctx_switch (new, cookie); } }else {