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:
4177c42
: perf, x86: Try to handle unknown nmis with an enabled PMU
Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Robert 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: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
258af47479
commit
63e6be6d98
1 changed files with 11 additions and 1 deletions
|
@ -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)
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue