perfcounters: fix "perf counters kills oprofile" bug, v2
authorIngo Molnar <mingo@elte.hu>
Thu, 5 Feb 2009 14:23:08 +0000 (15:23 +0100)
committerIngo Molnar <mingo@elte.hu>
Thu, 5 Feb 2009 14:24:14 +0000 (15:24 +0100)
Impact: fix kernel crash

Both oprofile and perfcounters register an NMI die handler, but only one
can handle the NMI.  Conveniently, oprofile unregisters it's notifier
when not actively in use, so setting it's notifier priority higher than
perfcounter's allows oprofile to borrow the NMI for the duration of it's
run.  Tested/works both as module and built-in.

While testing, I found that if kerneltop was generating NMIs at very
high frequency, the kernel may panic when oprofile registered it's
handler.  This turned out to be because oprofile registers it's handler
before reset_value has been allocated, so if an NMI comes in while it's
still setting up, kabOom.  Rather than try more invasive changes, I
followed the lead of other places in op_model_ppro.c, and simply
returned in that highly unlikely event.  (debug warnings attached)

Signed-off-by: Mike Galbraith <efault@gmx.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/oprofile/op_model_ppro.c

index 07c914555a5eedacbdc20d6aa41fad2df459218c..85eb6268374f561ac187170fafbee15d7a618cdd 100644 (file)
@@ -126,6 +126,13 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
        u64 val;
        int i;
 
+       /*
+        * This can happen if perf counters are in use when
+        * we steal the die notifier NMI.
+        */
+       if (unlikely(!reset_value))
+               goto out;
+
        for (i = 0 ; i < num_counters; ++i) {
                if (!reset_value[i])
                        continue;
@@ -136,6 +143,7 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
                }
        }
 
+out:
        /* Only P6 based Pentium M need to re-unmask the apic vector but it
         * doesn't hurt other P6 variant */
        apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);