Skip to contentSkip to conversation

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

PATCH In review Cyrill Gorcunov 2 participants 3 messages Aug 5, 2010 – Aug 10, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 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.

CC Lin Ming <[email protected]>
CC Stephane Eranian <[email protected]>
CC Peter Zijlstra <[email protected]>
CC Ingo Molnar <[email protected]>
CC Frederic Weisbecker <[email protected]>
---
 arch/x86/kernel/cpu/perf_event_p4.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
arch/x86/kernel/cpu/perf_event_p4.c +6 -3
Index: linux-2.6.git/arch/x86/kernel/cpu/perf_event_p4.c
=====================================================================
@@ -656,6 +656,7 @@ static int p4_pmu_handle_irq(struct pt_r
 	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_r
 		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_r
 		inc_irq_stat(apic_perf_irqs);
 	}
 
-	return handled;
+	return handled > 0;
 }
 
 /*
#1 lore raw
Quoted 5 lines · Cyrill Gorcunov

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.

Quoted 8 lines
CC Lin Ming <[email protected]>
CC Stephane Eranian <[email protected]>
CC Peter Zijlstra <[email protected]>
CC Ingo Molnar <[email protected]>
CC Frederic Weisbecker <[email protected]>

---

Ping? Frederic, perhaps you'll pick it up?

-- Cyrill

#2 lore raw

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

In reply to Cyrill Gorcunov
Commit-ID:  1c250d709fdc8aa5bf42d90be99428a01a256a55
Gitweb:     http://git.kernel.org/tip/1c250d709fdc8aa5bf42d90be99428a01a256a55
Author:     Cyrill Gorcunov <[email protected]>
AuthorDate: Thu, 5 Aug 2010 19:09:17 +0400
Committer:  Ingo Molnar <[email protected]>
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.

Cc Stephane Eranian <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>

LKML-Reference: <20100805150917.GA6311@lenovo>

---
 arch/x86/kernel/cpu/perf_event_p4.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)
arch/x86/kernel/cpu/perf_event_p4.c +6 -3
index 107711b..febb12c 100644
@@ -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;
 }
 
 /*