Re: [PATCH v9 02/16] KVM: arm64: PMU: Stop updating MDCR_EL2.HPMN
Fuad Tabba <[email protected]> Wed, 29 Jul 2026 16:16:46 +0100
| Newsgroups | org.kernel.vger.linux-hardening,dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.kvm,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest |
|---|---|
| Message-ID | <CA+EHjTwCFXkQ=VHjQt3zt0TORh5YwPVCPBqFqTJF7YULxM-11g@mail.gmail.com> |
On Mon, 20 Jul 2026 at 06:39, Akihiko Odaki <[email protected]> wrote: > > KVM allows userspace to write any value to MDCR_EL2.HPMN. However, > kvm_arm_set_nr_counters() rewrites HPMN for every vCPU whenever > userspace changes the PMU or its counter count. This can discard a > value previously restored with KVM_SET_ONE_REG. > > The architecture only defines HPMN's value on warm reset. Stop > rewriting it after vCPU initialization and update nr_pmu_counters > directly instead. reset_mdcr() continues to initialize HPMN from the > counter count current at KVM_ARM_VCPU_INIT. > > Fixes: c8823e51b534 ("KVM: arm64: Fix MDCR_EL2.HPMN reset value") > Closes: https://sashiko.dev/#/patchset/20260706-hybrid-v8-0-de459617b59d%40rsg.ci.i.u-tokyo.ac.jp?part=6 > Assisted-by: Codex:gpt-5.5 > Signed-off-by: Akihiko Odaki <[email protected]> Reviewed-by: Fuad Tabba <[email protected]> Cheers, /fuad > --- > arch/arm64/kvm/pmu-emul.c | 22 ++-------------------- > 1 file changed, 2 insertions(+), 20 deletions(-) > > diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c > index 98305bbfc095..b5df6843dbcd 100644 > --- a/arch/arm64/kvm/pmu-emul.c > +++ b/arch/arm64/kvm/pmu-emul.c > @@ -1022,30 +1022,12 @@ u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm) > return bitmap_weight(arm_pmu->cntr_mask, ARMV8_PMU_MAX_GENERAL_COUNTERS); > } > > -static void kvm_arm_set_nr_counters(struct kvm *kvm, unsigned int nr) > -{ > - kvm->arch.nr_pmu_counters = nr; > - > - /* Reset MDCR_EL2.HPMN behind the vcpus' back... */ > - if (test_bit(KVM_ARM_VCPU_HAS_EL2, kvm->arch.vcpu_features)) { > - struct kvm_vcpu *vcpu; > - unsigned long i; > - > - kvm_for_each_vcpu(i, vcpu, kvm) { > - u64 val = __vcpu_sys_reg(vcpu, MDCR_EL2); > - val &= ~MDCR_EL2_HPMN; > - val |= FIELD_PREP(MDCR_EL2_HPMN, kvm->arch.nr_pmu_counters); > - __vcpu_assign_sys_reg(vcpu, MDCR_EL2, val); > - } > - } > -} > - > static void kvm_arm_set_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu) > { > lockdep_assert_held(&kvm->arch.config_lock); > > kvm->arch.arm_pmu = arm_pmu; > - kvm_arm_set_nr_counters(kvm, kvm_arm_pmu_get_max_counters(kvm)); > + kvm->arch.nr_pmu_counters = kvm_arm_pmu_get_max_counters(kvm); > } > > /** > @@ -1111,7 +1093,7 @@ static int kvm_arm_pmu_v3_set_nr_counters(struct kvm_vcpu *vcpu, unsigned int n) > if (n > kvm_arm_pmu_get_max_counters(kvm)) > return -EINVAL; > > - kvm_arm_set_nr_counters(kvm, n); > + kvm->arch.nr_pmu_counters = n; > return 0; > } > > > -- > 2.55.0 > >