Commit 63e6be6d authored by Robert Richter's avatar Robert Richter Committed by Ingo Molnar

perf, x86: Catch spurious interrupts after disabling counters

Some cpus still deliver spurious interrupts after disabling a
counter. This caused 'undelivered NMI' messages. This patch
fixes this. Introduced by:

  4177c42a: perf, x86: Try to handle unknown nmis with an enabled PMU
Reported-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarRobert Richter <robert.richter@amd.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: gorcunov@gmail.com <gorcunov@gmail.com>
Cc: fweisbec@gmail.com <fweisbec@gmail.com>
Cc: ying.huang@intel.com <ying.huang@intel.com>
Cc: ming.m.lin@intel.com <ming.m.lin@intel.com>
Cc: yinghai@kernel.org <yinghai@kernel.org>
Cc: andi@firstfloor.org <andi@firstfloor.org>
Cc: eranian@google.com <eranian@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
LKML-Reference: <20100915162034.GO13563@erda.amd.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 258af474
...@@ -102,6 +102,7 @@ struct cpu_hw_events { ...@@ -102,6 +102,7 @@ struct cpu_hw_events {
*/ */
struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */
unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
int enabled; int enabled;
int n_events; int n_events;
...@@ -1010,6 +1011,7 @@ static int x86_pmu_start(struct perf_event *event) ...@@ -1010,6 +1011,7 @@ static int x86_pmu_start(struct perf_event *event)
x86_perf_event_set_period(event); x86_perf_event_set_period(event);
cpuc->events[idx] = event; cpuc->events[idx] = event;
__set_bit(idx, cpuc->active_mask); __set_bit(idx, cpuc->active_mask);
__set_bit(idx, cpuc->running);
x86_pmu.enable(event); x86_pmu.enable(event);
perf_event_update_userpage(event); perf_event_update_userpage(event);
...@@ -1141,8 +1143,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) ...@@ -1141,8 +1143,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
cpuc = &__get_cpu_var(cpu_hw_events); cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx < x86_pmu.num_counters; idx++) { for (idx = 0; idx < x86_pmu.num_counters; idx++) {
if (!test_bit(idx, cpuc->active_mask)) if (!test_bit(idx, cpuc->active_mask)) {
/*
* Though we deactivated the counter some cpus
* might still deliver spurious interrupts still
* in flight. Catch them:
*/
if (__test_and_clear_bit(idx, cpuc->running))
handled++;
continue; continue;
}
event = cpuc->events[idx]; event = cpuc->events[idx];
hwc = &event->hw; hwc = &event->hw;
......
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