[PATCH] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus

From: Besar Wicaksono

Date: Mon Apr 06 2026 - 19:21:14 EST


The PMCCNTR_EL0 in NVIDIA Olympus CPU may increment while
in WFI/WFE, which does not align with counting CPU_CYCLES
on a programmable counter. Add a MIDR range entry and
refuse PMCCNTR_EL0 for cycle events on affected parts so
perf does not mix the two behaviors.

Signed-off-by: Besar Wicaksono <bwicaksono@xxxxxxxxxx>
---
drivers/perf/arm_pmuv3.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 8014ff766cff..b5d2f60af6f0 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -978,6 +978,29 @@ static int armv8pmu_get_chain_idx(struct pmu_hw_events *cpuc,
return -EAGAIN;
}

+/*
+ * List of CPUs that should avoid using PMCCNTR_EL0.
+ */
+static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
+ /*
+ * The PMCCNTR_EL0 in Olympus CPU may still increment while in WFI/WFE state.
+ * This is an implementation specific behavior and not an erratum.
+ *
+ * From ARM DDI0487 D14.4:
+ * It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR count
+ * when the PE is in WFI or WFE state, even if the clocks are not stopped.
+ *
+ * From ARM DDI0487 D24.5.2:
+ * All counters are subject to any changes in clock frequency, including
+ * clock stopping caused by the WFI and WFE instructions.
+ * This means that it is CONSTRAINED UNPREDICTABLE whether or not
+ * PMCCNTR_EL0 continues to increment when clocks are stopped by WFI and
+ * WFE instructions.
+ */
+ MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
+ {}
+};
+
static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
struct perf_event *event)
{
@@ -1011,6 +1034,14 @@ static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
if (cpu_pmu->has_smt)
return false;

+ /*
+ * On some CPUs, PMCCNTR_EL0 does not match the behavior of CPU_CYCLES
+ * programmable counter, so avoid routing cycles through PMCCNTR_EL0 to
+ * prevent inconsistency in the results.
+ */
+ if (is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus))
+ return false;
+
return true;
}

--
2.43.0