Thread (13 messages) 13 messages, 2 authors, 2023-02-10

Re: [PATCH v1 4/6] KVM: arm64: Use per guest ID register for ID_AA64DFR0_EL1.PMUVer

From: Jing Zhang <hidden>
Date: 2023-02-10 17:57:55
Also in: kvm, kvmarm

Hi Reiji,

On Thu, Feb 9, 2023 at 10:16 PM Reiji Watanabe [off-list ref] wrote:
Hi Jing,

On Thu, Feb 9, 2023 at 1:25 PM Jing Zhang [off-list ref] wrote:
quoted
On Mon, Feb 6, 2023 at 9:30 PM Reiji Watanabe [off-list ref] wrote:
quoted
Hi Jing,

On Tue, Jan 31, 2023 at 6:51 PM Jing Zhang [off-list ref] wrote:
quoted
With per guest ID registers, PMUver settings from userspace
can be stored in its corresponding ID register.

No functional change intended.

Signed-off-by: Jing Zhang <redacted>
---
 arch/arm64/include/asm/kvm_host.h |  5 -----
 arch/arm64/kvm/arm.c              |  6 ------
 arch/arm64/kvm/id_regs.c          | 33 ++++++++++++++++++++-----------
 include/kvm/arm_pmu.h             |  6 ++++--
 4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fabb30185a4a..1ab443b52c46 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -225,11 +225,6 @@ struct kvm_arch {

        cpumask_var_t supported_cpus;

-       struct {
-               u8 imp:4;
-               u8 unimp:4;
-       } dfr0_pmuver;
-
        /* Hypercall features firmware registers' descriptor */
        struct kvm_smccc_features smccc_feat;
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index d8ba5106bf51..25bd95650223 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -138,12 +138,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        kvm_arm_set_default_id_regs(kvm);
        kvm_arm_init_hypercalls(kvm);

-       /*
-        * Initialise the default PMUver before there is a chance to
-        * create an actual PMU.
-        */
-       kvm->arch.dfr0_pmuver.imp = kvm_arm_pmu_get_pmuver_limit();
-
        return 0;

 err_free_cpumask:
diff --git a/arch/arm64/kvm/id_regs.c b/arch/arm64/kvm/id_regs.c
index bc5d9bc84eb1..5eade7d380af 100644
--- a/arch/arm64/kvm/id_regs.c
+++ b/arch/arm64/kvm/id_regs.c
@@ -19,10 +19,12 @@

 static u8 vcpu_pmuver(const struct kvm_vcpu *vcpu)
 {
-       if (kvm_vcpu_has_pmu(vcpu))
-               return vcpu->kvm->arch.dfr0_pmuver.imp;
-
-       return vcpu->kvm->arch.dfr0_pmuver.unimp;
+       u8 pmuver = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer),
+                       IDREG(vcpu->kvm, SYS_ID_AA64DFR0_EL1));
+       if (kvm_vcpu_has_pmu(vcpu) || pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+               return pmuver;
+       else
+               return 0;
 }

 static u8 perfmon_to_pmuver(u8 perfmon)
@@ -263,10 +265,9 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
        if (val)
                return -EINVAL;

-       if (valid_pmu)
-               vcpu->kvm->arch.dfr0_pmuver.imp = pmuver;
-       else
-               vcpu->kvm->arch.dfr0_pmuver.unimp = pmuver;
+       IDREG(vcpu->kvm, SYS_ID_AA64DFR0_EL1) &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer);
+       IDREG(vcpu->kvm, SYS_ID_AA64DFR0_EL1) |=
+               FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), pmuver);
Did you consider there could be guests that have vCPUs with and
without PMU ? It looks like the code doesn't work for such guests.
(e.g. for such guests, if setting the register is done for vCPUs
 without PMU, this code seems to make PMUVer zero or 0xf
 even for vCPUs with PMU)
Yes, I did. The PMUVer field is a per-VCPU field, whose value was
determined on the fly in the get_user function. Check the function
kvm_arm_read_id_reg_with_encoding, vcpu_pmuver is called to set the
real value for the VCPU.
The perVM ID registers array we put in the kvm structure save
correctly only for those perVM field, for those pre-VCPU filed, their
real value is determined on the fly during the register reading
(get_user).
Yes, I understand that part.
But, if a guest has 2 VCPUs, one of which has a PMU and the other
does not, the PMUVer for them will be different.  Which value do
you try to save in the per VM field ?

It appears that the code always saves the last value set by
userspace in the per VM field, regardless of whether the vCPU
has PMU or not.
If the last value is set for the vCPU without PMU, the per VM
field will be either 0 or 0xf.  Since the per VM field is always
used by vcpu_pmuver() for vCPUs with PMU, I would think the
PMUVer for the vCPU with PMU will end up being 0 or 0xf in this
case (NOTE: the PMUVer for vCPUs with PMU should not be 0 or 0xf).

Or am I missing something??
Thanks for the clarification. You are right about the issue. I'll fix
it in the next version by utilizing a bit in kvm->arch.flags to
indicate the IMPDEF PMU. The value stored in id_regs would be the one
for vCPU with PMU support.
Thanks,
Reiji
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help