Re: [PATCH v9 02/16] KVM: arm64: PMU: Stop updating MDCR_EL2.HPMN

Fuad Tabba <[email protected]>
Newsgroups dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.kvm,org.kernel.vger.linux-doc,org.kernel.vger.linux-hardening,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
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.