Skip to contentSkip to conversation

oprofile - NMI hook

PATCH In review John Levon 3 participants 6 messages Oct 15, 2002 – Oct 16, 2002

lore
Share & tools
lore

John Levon

author
#0 lore raw

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
diff -Naur -X dontdiff linux-linus/arch/i386/kernel/i386_ksyms.c linux-linus2/arch/i386/kernel/i386_ksyms.c
@@ -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
diff -Naur -X dontdiff linux-linus/arch/i386/kernel/nmi.c linux-linus2/arch/i386/kernel/nmi.c
@@ -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
diff -Naur -X dontdiff linux-linus/arch/i386/kernel/traps.c linux-linus2/arch/i386/kernel/traps.c
@@ -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

#1 lore raw
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

author
#2 lore raw
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
#3 lore raw
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

#4 lore raw
In reply to John Levon
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?

author
#5 lore raw
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