Commit 335ca49f authored by Reiji Watanabe's avatar Reiji Watanabe Committed by Marc Zyngier

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: default avatarReiji Watanabe <reijiw@google.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230819043947.4100985-3-reijiw@google.com
parent ec3eb9ed
...@@ -36,12 +36,8 @@ static struct kvm_pmc *kvm_vcpu_idx_to_pmc(struct kvm_vcpu *vcpu, int cnt_idx) ...@@ -36,12 +36,8 @@ static struct kvm_pmc *kvm_vcpu_idx_to_pmc(struct kvm_vcpu *vcpu, int cnt_idx)
return &vcpu->arch.pmu.pmc[cnt_idx]; return &vcpu->arch.pmu.pmc[cnt_idx];
} }
static u32 kvm_pmu_event_mask(struct kvm *kvm) static u32 __kvm_pmu_event_mask(unsigned int pmuver)
{ {
unsigned int pmuver;
pmuver = kvm->arch.arm_pmu->pmuver;
switch (pmuver) { switch (pmuver) {
case ID_AA64DFR0_EL1_PMUVer_IMP: case ID_AA64DFR0_EL1_PMUVer_IMP:
return GENMASK(9, 0); return GENMASK(9, 0);
...@@ -56,6 +52,14 @@ static u32 kvm_pmu_event_mask(struct kvm *kvm) ...@@ -56,6 +52,14 @@ static u32 kvm_pmu_event_mask(struct kvm *kvm)
} }
} }
static u32 kvm_pmu_event_mask(struct kvm *kvm)
{
u64 dfr0 = IDREG(kvm, SYS_ID_AA64DFR0_EL1);
u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, dfr0);
return __kvm_pmu_event_mask(pmuver);
}
/** /**
* kvm_pmc_is_64bit - determine if counter is 64bit * kvm_pmc_is_64bit - determine if counter is 64bit
* @pmc: counter context * @pmc: counter context
...@@ -954,11 +958,17 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) ...@@ -954,11 +958,17 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
return 0; return 0;
} }
case KVM_ARM_VCPU_PMU_V3_FILTER: { case KVM_ARM_VCPU_PMU_V3_FILTER: {
u8 pmuver = kvm_arm_pmu_get_pmuver_limit();
struct kvm_pmu_event_filter __user *uaddr; struct kvm_pmu_event_filter __user *uaddr;
struct kvm_pmu_event_filter filter; struct kvm_pmu_event_filter filter;
int nr_events; int nr_events;
nr_events = kvm_pmu_event_mask(kvm) + 1; /*
* Allow userspace to specify an event filter for the entire
* event range supported by PMUVer of the hardware, rather
* than the guest's PMUVer for KVM backward compatibility.
*/
nr_events = __kvm_pmu_event_mask(pmuver) + 1;
uaddr = (struct kvm_pmu_event_filter __user *)(long)attr->addr; uaddr = (struct kvm_pmu_event_filter __user *)(long)attr->addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment