Skip to content

Commit

Permalink
perf_counter: x86: Robustify interrupt handling
Browse files Browse the repository at this point in the history
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: Peter 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: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed May 15, 2009
1 parent 9e35ad3 commit a4016a7
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions arch/x86/kernel/cpu/perf_counter.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,10 @@ static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi)

counter = cpuc->counters[idx];
hwc = &counter->hw;

if (counter->hw_event.nmi != nmi)
goto next;

val = x86_perf_counter_update(counter, hwc, idx);
if (val & (1ULL << (x86_pmu.counter_bits - 1)))
goto next;
Expand Down Expand Up @@ -869,7 +873,6 @@ perf_counter_nmi_handler(struct notifier_block *self,
{
struct die_args *args = __args;
struct pt_regs *regs;
int ret;

if (!atomic_read(&active_counters))
return NOTIFY_DONE;
Expand All @@ -886,9 +889,16 @@ perf_counter_nmi_handler(struct notifier_block *self,
regs = args->regs;

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 = {
Expand Down

0 comments on commit a4016a7

Please sign in to comment.