Skip to contentSkip to conversation

perf events, x86: Work around the Nehalem AAJ80 erratum

tip:perf/stat tip-bot for Ingo Molnar 1 participant 1 message Apr 27, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw
Commit-ID:  ec75a71634dabe439db91c1ef51d5099f4493808
Gitweb:     http://git.kernel.org/tip/ec75a71634dabe439db91c1ef51d5099f4493808
Author:     Ingo Molnar <[email protected]>
AuthorDate: Wed, 27 Apr 2011 11:51:41 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 26 Apr 2011 19:34:34 +0200

perf events, x86: Work around the Nehalem AAJ80 erratum

On Nehalem CPUs the retired branch-misses event can be completely bogus, when there are no branch-misses occuring. When there are a lot of branch misses then the count is pretty accurate. Still, this leaves us with an event that over-counts a lot.

Detect this erratum and work it around by using BR_MISP_EXEC.ANY events. These will also count speculated branches but still it's a lot more precise in practice than the architectural event.

---
 arch/x86/kernel/cpu/perf_event_intel.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/perf_event_intel.c +14 -2
index 9194b06..9ae4a2a 100644
@@ -25,7 +25,7 @@ struct intel_percore {
 /*
  * Intel PerfMon, used on Core and later.
  */
-static const u64 intel_perfmon_event_map[] =
+static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
 {
   [PERF_COUNT_HW_CPU_CYCLES]		= 0x003c,
   [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,
@@ -1308,7 +1308,7 @@ static void intel_clovertown_quirks(void)
 	 * AJ106 could possibly be worked around by not allowing LBR
 	 *       usage from PEBS, including the fixup.
 	 * AJ68  could possibly be worked around by always programming
-	 * 	 a pebs_event_reset[0] value and coping with the lost events.
+	 *	 a pebs_event_reset[0] value and coping with the lost events.
 	 *
 	 * But taken together it might just make sense to not enable PEBS on
 	 * these chips.
@@ -1412,6 +1412,18 @@ static __init int intel_pmu_init(void)
 		x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
 		x86_pmu.enable_all = intel_pmu_nhm_enable_all;
 		x86_pmu.extra_regs = intel_nehalem_extra_regs;
+
+		if (ebx & 0x40) {
+			/*
+			 * Erratum AAJ80 detected, we work it around by using
+			 * the BR_MISP_EXEC.ANY event. This will over-count
+			 * branch-misses, but it's still much better than the
+			 * architectural event which is often completely bogus:
+			 */
+			intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
+
+			pr_cont("erratum AAJ80 worked around, ");
+		}
 		pr_cont("Nehalem events, ");
 		break;