oprofile - NMI hook
PATCH 4/7 oprofile - NMI hook
This patch provides a simple api to let oprofile hook into the NMI interrupt for the perfctr profiler.
arch/i386/kernel/i386_ksyms.c +7 -0
@@ -29,6 +29,7 @@#include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/tlbflush.h> +#include <asm/nmi.h> extern void dump_thread (struct pt_regs *,struct user *);extern spinlock_t rtc_lock;
@@ -151,6 +152,10 @@EXPORT_SYMBOL (flush_tlb_page);#endif +#if defined(CONFIG_X86_LOCAL_APIC ) && defined(CONFIG_PM ) +EXPORT_SYMBOL_GPL (set_nmi_pm_callback); +EXPORT_SYMBOL_GPL (unset_nmi_pm_callback); +#endif #ifdef CONFIG_X86_IO_APIC EXPORT_SYMBOL (IO_APIC_get_PCI_irq_vector);#endif
@@ -169,6 +174,8 @@EXPORT_SYMBOL_GPL (register_profile_notifier);EXPORT_SYMBOL_GPL (unregister_profile_notifier); +EXPORT_SYMBOL_GPL (set_nmi_callback); +EXPORT_SYMBOL_GPL (unset_nmi_callback);#undef memcpy#undef memset
arch/i386/kernel/nmi.c +12 -0
@@ -175,6 +175,18 @@return 0 ; } +struct pm_dev *set_nmi_pm_callback (pm_callback callback) +{ +apic_pm_unregister (nmi_pmdev); +return apic_pm_register (PM_SYS_DEV ,0 , callback); +} + +void unset_nmi_pm_callback (struct pm_dev * dev) +{ +apic_pm_unregister (dev); + nmi_pmdev =apic_pm_register (PM_SYS_DEV ,0 , nmi_pm_callback); +} +static void nmi_pm_init (void ) {if (!nmi_pmdev)
arch/i386/kernel/traps.c +32 -5
@@ -40,6 +40,7 @@#include <asm/debugreg.h> #include <asm/desc.h> #include <asm/i387.h> +#include <asm/nmi.h> #include <asm/smp.h> #include <asm/pgalloc.h>
@@ -478,17 +479,16 @@ return; }#endif -printk ("Uhhuh. NMI received for unknown reason %02x.\n" , reason); +printk ("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n" , + reason,smp_processor_id ());printk ("Dazed and confused, but trying to continue\n" );printk ("Do you have a strange power saving mode enabled?\n" ); } -asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +static void default_do_nmi (struct pt_regs * regs) {unsigned char reason =inb (0x61 ); - - ++nmi_count (smp_processor_id ()); - +if (!(reason &0xc0 )) {#if CONFIG_X86_LOCAL_APIC /*
@@ -515,6 +515,33 @@inb (0x71 );/* dummy */ outb (0x0f ,0x70 );inb (0x71 );/* dummy */ +} + +static int dummy_nmi_callback (struct pt_regs * regs,int cpu) +{ +return 0 ; +} + +static nmi_callback_t nmi_callback = dummy_nmi_callback; + +asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +{ +int cpu =smp_processor_id (); + + ++nmi_count (cpu); + +if (!nmi_callback (regs, cpu)) +default_do_nmi (regs); +} + +void set_nmi_callback (nmi_callback_t callback) +{ + nmi_callback = callback; +} + +void unset_nmi_callback (void ) +{ + nmi_callback = dummy_nmi_callback; }/*
include/asm-i386/nmi.h +49 -0
49 lines not on this page · raw message
Quoted 2 lines · John Levon
This patch provides a simple api to let oprofile hook into the NMI interrupt for the perfctr profiler.
I would suggest using a notifier list instead (include/linux/notifier.h) This would handle multiple users cleanly.
-Andi
Quoted 5 lines · Andi Kleen
Quoted 2 lines
This patch provides a simple api to let oprofile hook into the NMI interrupt for the perfctr profiler.
I would suggest using a notifier list instead (
include/linux/notifier.h) This would handle multiple users cleanly.
How ? The only safe way I can see would be to spin lock around the NMI (and try lock when an NMI arrives). This would either make every NMI contend on a single spinlock, or require a NR_CPUS-sized array of spinlocks, which is just ugly. And that wouldn't solve the power-management problem - any NMI users need to collaborate to disable NMI generation on a suspend.
regards
john
Signature · 2 lines
"CUT IT OUT FACEHEAD" - jeffk
Quoted 8 lines · John Levon
Quoted 5 lines · Andi Kleen
Quoted 2 lines
This patch provides a simple api to let oprofile hook into the NMI interrupt for the perfctr profiler.
I would suggest using a notifier list instead (
include/linux/notifier.h) This would handle multiple users cleanly.
Quoted 6 lines
How ? The only safe way I can see would be to spin lock around the NMI (and try lock when an NMI arrives). This would either make every NMI contend on a single spinlock, or require a NR_CPUS-sized array of spinlocks, which is just ugly. And that wouldn't solve the power-management problem - any NMI users need to collaborate to disable NMI generation on a suspend.
The locking issues could be fixed with read-copy-update, but you're right that it's not a good solution right now. I take the objection back then.
-Andi
Quoted 2 lines · John Levon
This patch provides a simple api to let oprofile hook into the NMI interrupt for the perfctr profiler.
Both kdb and lkcd use cross cpu NMI for debugging and dumping on SMP. That plus oprofile and the NMI watchdog makes at least four users of NMI. A one level hook is not going to cut it, it should be a list.
I admit that removal of a hook from the NMI list while still handling NMI interrupts is "interesting", but that is a SMOP ;). RCU to the rescue?
Quoted 7 lines · Keith Owens
Both kdb and lkcd use cross cpu NMI for debugging and dumping on SMP. That plus oprofile and the NMI watchdog makes at least four users of NMI. A one level hook is not going to cut it, it should be a list.
I admit that removal of a hook from the NMI list while still handling NMI interrupts is "interesting", but that is a SMOP ;). RCU to the rescue?
Yep, now RCU is merged I'll read up and see if I can come up with a list API
regards
john
Signature · 3 lines
"It's a cardboard universe ... and if you lean too hard against it, you fall through." - Philip K. Dick