Skip to content

Commit 335ca49

Browse files
reijiw-kvmMarc Zyngier
authored andcommitted
KVM: arm64: PMU: Avoid inappropriate use of host's PMUVer
Avoid using the PMUVer of the host's PMU hardware to determine the PMU event mask, except in one case, as the value of host's PMUVer may differ from the value of ID_AA64DFR0_EL1.PMUVer for the guest. The exception case is when using the PMUVer to determine the valid range of events for KVM_ARM_VCPU_PMU_V3_FILTER, as it has been allowing userspace to specify events that are valid for the PMU hardware, regardless of the value of the guest's ID_AA64DFR0_EL1.PMUVer. KVM will use a valid range of events based on the value of the guest's ID_AA64DFR0_EL1.PMUVer, in order to effectively filter events that the guest attempts to program though. Signed-off-by: Reiji Watanabe <reijiw@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20230819043947.4100985-3-reijiw@google.com
1 parent ec3eb9e commit 335ca49

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

arch/arm64/kvm/pmu-emul.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,8 @@ static struct kvm_pmc *kvm_vcpu_idx_to_pmc(struct kvm_vcpu *vcpu, int cnt_idx)
3636
return &vcpu->arch.pmu.pmc[cnt_idx];
3737
}
3838

39-
static u32 kvm_pmu_event_mask(struct kvm *kvm)
39+
static u32 __kvm_pmu_event_mask(unsigned int pmuver)
4040
{
41-
unsigned int pmuver;
42-
43-
pmuver = kvm->arch.arm_pmu->pmuver;
44-
4541
switch (pmuver) {
4642
case ID_AA64DFR0_EL1_PMUVer_IMP:
4743
return GENMASK(9, 0);
@@ -56,6 +52,14 @@ static u32 kvm_pmu_event_mask(struct kvm *kvm)
5652
}
5753
}
5854

55+
static u32 kvm_pmu_event_mask(struct kvm *kvm)
56+
{
57+
u64 dfr0 = IDREG(kvm, SYS_ID_AA64DFR0_EL1);
58+
u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, dfr0);
59+
60+
return __kvm_pmu_event_mask(pmuver);
61+
}
62+
5963
/**
6064
* kvm_pmc_is_64bit - determine if counter is 64bit
6165
* @pmc: counter context
@@ -954,11 +958,17 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
954958
return 0;
955959
}
956960
case KVM_ARM_VCPU_PMU_V3_FILTER: {
961+
u8 pmuver = kvm_arm_pmu_get_pmuver_limit();
957962
struct kvm_pmu_event_filter __user *uaddr;
958963
struct kvm_pmu_event_filter filter;
959964
int nr_events;
960965

961-
nr_events = kvm_pmu_event_mask(kvm) + 1;
966+
/*
967+
* Allow userspace to specify an event filter for the entire
968+
* event range supported by PMUVer of the hardware, rather
969+
* than the guest's PMUVer for KVM backward compatibility.
970+
*/
971+
nr_events = __kvm_pmu_event_mask(pmuver) + 1;
962972

963973
uaddr = (struct kvm_pmu_event_filter __user *)(long)attr->addr;
964974

0 commit comments

Comments
 (0)