Commit a4016a79 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

perf_counter: x86: Robustify interrupt handling

Two consecutive NMIs could daze and confuse the machine when the
first would handle the overflow of both counters.

[ Impact: fix false-positive syslog messages under multi-session profiling ]
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
LKML-Reference: <new-submission>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 9e35ad38
...@@ -783,6 +783,10 @@ static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi) ...@@ -783,6 +783,10 @@ static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi)
counter = cpuc->counters[idx]; counter = cpuc->counters[idx];
hwc = &counter->hw; hwc = &counter->hw;
if (counter->hw_event.nmi != nmi)
goto next;
val = x86_perf_counter_update(counter, hwc, idx); val = x86_perf_counter_update(counter, hwc, idx);
if (val & (1ULL << (x86_pmu.counter_bits - 1))) if (val & (1ULL << (x86_pmu.counter_bits - 1)))
goto next; goto next;
...@@ -869,7 +873,6 @@ perf_counter_nmi_handler(struct notifier_block *self, ...@@ -869,7 +873,6 @@ perf_counter_nmi_handler(struct notifier_block *self,
{ {
struct die_args *args = __args; struct die_args *args = __args;
struct pt_regs *regs; struct pt_regs *regs;
int ret;
if (!atomic_read(&active_counters)) if (!atomic_read(&active_counters))
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -886,9 +889,16 @@ perf_counter_nmi_handler(struct notifier_block *self, ...@@ -886,9 +889,16 @@ perf_counter_nmi_handler(struct notifier_block *self,
regs = args->regs; regs = args->regs;
apic_write(APIC_LVTPC, APIC_DM_NMI); apic_write(APIC_LVTPC, APIC_DM_NMI);
ret = x86_pmu.handle_irq(regs, 1); /*
* Can't rely on the handled return value to say it was our NMI, two
* counters could trigger 'simultaneously' raising two back-to-back NMIs.
*
* If the first NMI handles both, the latter will be empty and daze
* the CPU.
*/
x86_pmu.handle_irq(regs, 1);
return ret ? NOTIFY_STOP : NOTIFY_OK; return NOTIFY_STOP;
} }
static __read_mostly struct notifier_block perf_counter_nmi_notifier = { static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment