From aa41a7c3beb59f9dac4e60c9cf1d146f6c9025c4 Mon Sep 17 00:00:00 2001 From: Colton Lewis Date: Wed, 30 Sep 2026 21:18:33 +0000 Subject: [PATCH] KVM: arm64: Handle ID_AA64DFR0_EL1.PMUVer == NI in __kvm_pmu_event_mask() When userspace initializes a vCPU with KVM_ARM_VCPU_PMU_V3 but sets ID_AA64DFR0_EL1.PMUVer to NI (0) or IMP_DEF (0xf, which is sanitized to NI), resetting the vCPU invokes reset_pmevtyper() and calls kvm_pmu_evtyper_mask(). Because __kvm_pmu_event_mask() does not handle ID_AA64DFR0_EL1_PMUVer_NI, it triggers a WARN_ONCE("Unknown PMU version 0"). Explicitly handle ID_AA64DFR0_EL1_PMUVer_NI in __kvm_pmu_event_mask() by returning an event mask of 0, and drop the redundant kvm_vcpu_has_pmu() check in reset_pmevtyper(). Fixes: bc512d6a9b92 ("KVM: arm64: Make PMEVTYPER_EL0.NSH RES0 if EL2 isn't advertised") Suggested-by: Oliver Upton Assisted-by: LLM Signed-off-by: Colton Lewis Link: https://patch.msgid.link/20260930211834.2773546-2-coltonlewis@google.com Signed-off-by: Marc Zyngier --- arch/arm64/kvm/pmu-emul.c | 5 ++++- arch/arm64/kvm/sys_regs.c | 4 ---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 5b1af7e2176f..e2b28dbc0451 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -50,8 +50,11 @@ static u32 __kvm_pmu_event_mask(unsigned int pmuver) case ID_AA64DFR0_EL1_PMUVer_V3P5: case ID_AA64DFR0_EL1_PMUVer_V3P7: return GENMASK(15, 0); - default: /* Shouldn't be here, just for sanity */ + default: + /* Shouldn't be here, just for sanity */ WARN_ONCE(1, "Unknown PMU version %d\n", pmuver); + fallthrough; + case ID_AA64DFR0_EL1_PMUVer_NI: return 0; } } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 44aae52c473d..87f96c9bd2fe 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1058,10 +1058,6 @@ static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { - /* This thing will UNDEF, who cares about the reset value? */ - if (!kvm_vcpu_has_pmu(vcpu)) - return 0; - reset_unknown(vcpu, r); __vcpu_rmw_sys_reg(vcpu, r->reg, &=, kvm_pmu_evtyper_mask(vcpu->kvm));