[tip:perf/urgent] perf, x86: P4 PMU -- update nmi irq statistics and unmask lvt entry properly

From: tip-bot for Cyrill Gorcunov
Date: Tue Aug 10 2010 - 03:10:31 EST


Commit-ID: 1c250d709fdc8aa5bf42d90be99428a01a256a55
Gitweb: http://git.kernel.org/tip/1c250d709fdc8aa5bf42d90be99428a01a256a55
Author: Cyrill Gorcunov <gorcunov@xxxxxxxxxx>
AuthorDate: Thu, 5 Aug 2010 19:09:17 +0400
Committer: Ingo Molnar <mingo@xxxxxxx>
CommitDate: Sun, 8 Aug 2010 22:53:50 +0200

perf, x86: P4 PMU -- update nmi irq statistics and unmask lvt entry properly

In case if last active performance counter is not overflowed at
moment of NMI being triggered by another counter, the irq
statistics may miss an update stage. As a more serious
consequence -- apic quirk may not be triggered so apic lvt entry
stay masked.

Tested-by: Lin Ming <ming.m.lin@xxxxxxxxx>
Signed-off-by: Cyrill Gorcunov <gorcunov@xxxxxxxxxx>
Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Cc: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx>
LKML-Reference: <20100805150917.GA6311@lenovo>
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
---
arch/x86/kernel/cpu/perf_event_p4.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index 107711b..febb12c 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -656,6 +656,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
cpuc = &__get_cpu_var(cpu_hw_events);

for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+ int overflow;

if (!test_bit(idx, cpuc->active_mask))
continue;
@@ -666,12 +667,14 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
WARN_ON_ONCE(hwc->idx != idx);

/* it might be unflagged overflow */
- handled = p4_pmu_clear_cccr_ovf(hwc);
+ overflow = p4_pmu_clear_cccr_ovf(hwc);

val = x86_perf_event_update(event);
- if (!handled && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
+ if (!overflow && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
continue;

+ handled += overflow;
+
/* event overflow for sure */
data.period = event->hw.last_period;

@@ -687,7 +690,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
inc_irq_stat(apic_perf_irqs);
}

- return handled;
+ return handled > 0;
}

/*
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/