Skip to content

Commit 93b0152

Browse files
committed
KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
The PMUv3 driver populates a couple of bitmaps with the values of PMCEID{0,1}, from which the guest's PMCEID{0,1} can be derived. This is particularly convenient when virtualizing PMUv3 on IMP DEF hardware, as reading the nonexistent PMCEID registers leads to a rather unpleasant UNDEF. Tested-by: Janne Grunau <[email protected]> Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 46573d9 commit 93b0152

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

arch/arm64/kvm/pmu-emul.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -842,8 +842,42 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void)
842842
return pmu;
843843
}
844844

845+
static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
846+
{
847+
u32 hi[2], lo[2];
848+
849+
bitmap_to_arr32(lo, pmu->pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
850+
bitmap_to_arr32(hi, pmu->pmceid_ext_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
851+
852+
return ((u64)hi[pmceid1] << 32) | lo[pmceid1];
853+
}
854+
855+
static u64 compute_pmceid0(struct arm_pmu *pmu)
856+
{
857+
u64 val = __compute_pmceid(pmu, 0);
858+
859+
/* always support CHAIN */
860+
val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
861+
return val;
862+
}
863+
864+
static u64 compute_pmceid1(struct arm_pmu *pmu)
865+
{
866+
u64 val = __compute_pmceid(pmu, 1);
867+
868+
/*
869+
* Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
870+
* as RAZ
871+
*/
872+
val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
873+
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
874+
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
875+
return val;
876+
}
877+
845878
u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
846879
{
880+
struct arm_pmu *cpu_pmu = vcpu->kvm->arch.arm_pmu;
847881
unsigned long *bmap = vcpu->kvm->arch.pmu_filter;
848882
u64 val, mask = 0;
849883
int base, i, nr_events;
@@ -852,19 +886,10 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
852886
return 0;
853887

854888
if (!pmceid1) {
855-
val = read_sysreg(pmceid0_el0);
856-
/* always support CHAIN */
857-
val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
889+
val = compute_pmceid0(cpu_pmu);
858890
base = 0;
859891
} else {
860-
val = read_sysreg(pmceid1_el0);
861-
/*
862-
* Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
863-
* as RAZ
864-
*/
865-
val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
866-
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
867-
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
892+
val = compute_pmceid1(cpu_pmu);
868893
base = 32;
869894
}
870895

0 commit comments

Comments
 (0)