When the PMU is partitioned, PMCCNTR_EL0 is reserved for the guest and removed from cpuc->cntr_mask. Move the PMCCNTR_EL0 availability checks (cpuc->cntr_mask and cpuc->used_mask) into armv8pmu_can_use_pmccntr() and un-nest the 64-bit user-access fallback check in armv8pmu_get_event_idx() so host CPU_CYCLES events fall back to general-purpose event counters when PMCCNTR_EL0 is unavailable.
Signed-off-by: Colton Lewis <[email protected]> --- drivers/perf/arm_pmuv3.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c index 49289e5993dd7..c15a34684137a 100644 --- a/drivers/perf/arm_pmuv3.c +++ b/drivers/perf/arm_pmuv3.c @@ -1015,6 +1015,10 @@ static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc, if (cpu_pmu->avoid_pmccntr) return false; + if (!test_bit(ARMV8_PMU_CYCLE_IDX, cpuc->cntr_mask) || + test_bit(ARMV8_PMU_CYCLE_IDX, cpuc->used_mask)) + return false; + return true; } @@ -1027,14 +1031,15 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, /* Always prefer to place a cycle counter into the cycle counter. */ if (armv8pmu_can_use_pmccntr(cpuc, event)) { - if (!test_and_set_bit(ARMV8_PMU_CYCLE_IDX, cpuc->used_mask)) - return ARMV8_PMU_CYCLE_IDX; - else if (armv8pmu_event_is_64bit(event) && - armv8pmu_event_want_user_access(event) && - !armv8pmu_has_long_event(cpu_pmu)) - return -EAGAIN; + set_bit(ARMV8_PMU_CYCLE_IDX, cpuc->used_mask); + return ARMV8_PMU_CYCLE_IDX; } + if (armv8pmu_event_is_64bit(event) && + armv8pmu_event_want_user_access(event) && + !armv8pmu_has_long_event(cpu_pmu)) + return -EAGAIN; + /* * Always prefer to place a instruction counter into the instruction counter, * but don't expose the instruction counter to userspace access as userspace -- 2.56.0.rc1.310.g51773c2048-goog

