Skip to content

Commit dd3cc5e

Browse files
ouptonjannau
authored andcommitted
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. Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 1468f11 commit dd3cc5e

1 file changed

Lines changed: 36 additions & 11 deletions

File tree

arch/arm64/kvm/pmu-emul.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -757,8 +757,42 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void)
757757
return pmu;
758758
}
759759

760+
static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
761+
{
762+
u32 hi[2], lo[2];
763+
764+
bitmap_to_arr32(lo, pmu->pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
765+
bitmap_to_arr32(hi, pmu->pmceid_ext_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
766+
767+
return ((u64)hi[pmceid1] << 32) | lo[pmceid1];
768+
}
769+
770+
static u64 compute_pmceid0(struct arm_pmu *pmu)
771+
{
772+
u64 val = __compute_pmceid(pmu, 0);
773+
774+
/* always support CHAIN */
775+
val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
776+
return val;
777+
}
778+
779+
static u64 compute_pmceid1(struct arm_pmu *pmu)
780+
{
781+
u64 val = __compute_pmceid(pmu, 1);
782+
783+
/*
784+
* Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
785+
* as RAZ
786+
*/
787+
val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
788+
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
789+
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
790+
return val;
791+
}
792+
760793
u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
761794
{
795+
struct arm_pmu *cpu_pmu = vcpu->kvm->arch.arm_pmu;
762796
unsigned long *bmap = vcpu->kvm->arch.pmu_filter;
763797
u64 val, mask = 0;
764798
int base, i, nr_events;
@@ -767,19 +801,10 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
767801
return 0;
768802

769803
if (!pmceid1) {
770-
val = read_sysreg(pmceid0_el0);
771-
/* always support CHAIN */
772-
val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
804+
val = compute_pmceid0(cpu_pmu);
773805
base = 0;
774806
} else {
775-
val = read_sysreg(pmceid1_el0);
776-
/*
777-
* Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
778-
* as RAZ
779-
*/
780-
val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
781-
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
782-
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
807+
val = compute_pmceid1(cpu_pmu);
783808
base = 32;
784809
}
785810

0 commit comments

Comments
 (0)