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 > >

