Skip to content

Commit 33b0894

Browse files
bwicaksononvnvmochs
authored andcommitted
NVIDIA: VR: SAUCE: perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
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@nvidia.com> (backported from https://lore.kernel.org/all/20260421203856.3539186-1-bwicaksono@nvidia.com/) Signed-off-by: Matthew R. Ochs <mochs@nvidia.com>
1 parent 5e154c9 commit 33b0894

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

drivers/perf/arm_pmuv3.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* This code is based heavily on the ARMv7 perf event code.
99
*/
1010

11+
#include <asm/cputype.h>
1112
#include <asm/irq_regs.h>
1213
#include <asm/perf_event.h>
1314
#include <asm/virt.h>
@@ -978,6 +979,41 @@ static int armv8pmu_get_chain_idx(struct pmu_hw_events *cpuc,
978979
return -EAGAIN;
979980
}
980981

982+
#ifdef CONFIG_ARM64
983+
/*
984+
* List of CPUs that should avoid using PMCCNTR_EL0.
985+
*/
986+
static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
987+
/*
988+
* The PMCCNTR_EL0 in Olympus CPU may still increment while in WFI/WFE state.
989+
* This is an implementation specific behavior and not an erratum.
990+
*
991+
* From ARM DDI0487 D14.4:
992+
* It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR count
993+
* when the PE is in WFI or WFE state, even if the clocks are not stopped.
994+
*
995+
* From ARM DDI0487 D24.5.2:
996+
* All counters are subject to any changes in clock frequency, including
997+
* clock stopping caused by the WFI and WFE instructions.
998+
* This means that it is CONSTRAINED UNPREDICTABLE whether or not
999+
* PMCCNTR_EL0 continues to increment when clocks are stopped by WFI and
1000+
* WFE instructions.
1001+
*/
1002+
MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
1003+
{}
1004+
};
1005+
1006+
static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
1007+
{
1008+
return is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus);
1009+
}
1010+
#else
1011+
static bool armv8pmu_is_in_avoid_pmccntr_cpus(void)
1012+
{
1013+
return false;
1014+
}
1015+
#endif
1016+
9811017
static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
9821018
struct perf_event *event)
9831019
{
@@ -1011,6 +1047,14 @@ static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
10111047
if (cpu_pmu->has_smt)
10121048
return false;
10131049

1050+
/*
1051+
* On some CPUs, PMCCNTR_EL0 does not match the behavior of CPU_CYCLES
1052+
* programmable counter, so avoid routing cycles through PMCCNTR_EL0 to
1053+
* prevent inconsistency in the results.
1054+
*/
1055+
if (armv8pmu_is_in_avoid_pmccntr_cpus())
1056+
return false;
1057+
10141058
return true;
10151059
}
10161060

0 commit comments

Comments
 (0)