[PATCH v1 4/6] KVM: arm64: Use per guest ID register for ID_AA64DFR0_EL1.PMUVer
Reiji Watanabe
reijiw at google.com
Mon Feb 6 21:29:48 PST 2023
Hi Jing,
On Tue, Jan 31, 2023 at 6:51 PM Jing Zhang <jingzhangos at google.com> wrote:
>
> 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 <jingzhangos at google.com>
> ---
> 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)
Thanks,
Reiji
>
> return 0;
> }
> @@ -303,10 +304,9 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
> if (val)
> return -EINVAL;
>
> - if (valid_pmu)
> - vcpu->kvm->arch.dfr0_pmuver.imp = perfmon_to_pmuver(perfmon);
> - else
> - vcpu->kvm->arch.dfr0_pmuver.unimp = perfmon_to_pmuver(perfmon);
> + IDREG(vcpu->kvm, SYS_ID_DFR0_EL1) &= ~ARM64_FEATURE_MASK(ID_DFR0_EL1_PerfMon);
> + IDREG(vcpu->kvm, SYS_ID_DFR0_EL1) |=
> + FIELD_PREP(ARM64_FEATURE_MASK(ID_DFR0_EL1_PerfMon), perfmon_to_pmuver(perfmon));
>
> return 0;
> }
> @@ -530,4 +530,13 @@ void kvm_arm_set_default_id_regs(struct kvm *kvm)
> }
>
> IDREG(kvm, SYS_ID_AA64PFR0_EL1) = val;
> +
> + /*
> + * Initialise the default PMUver before there is a chance to
> + * create an actual PMU.
> + */
> + IDREG(kvm, SYS_ID_AA64DFR0_EL1) &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer);
> + IDREG(kvm, SYS_ID_AA64DFR0_EL1) |=
> + FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer),
> + kvm_arm_pmu_get_pmuver_limit());
> }
> diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
> index 628775334d5e..eef67b7d9751 100644
> --- a/include/kvm/arm_pmu.h
> +++ b/include/kvm/arm_pmu.h
> @@ -92,8 +92,10 @@ void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu);
> /*
> * Evaluates as true when emulating PMUv3p5, and false otherwise.
> */
> -#define kvm_pmu_is_3p5(vcpu) \
> - (vcpu->kvm->arch.dfr0_pmuver.imp >= ID_AA64DFR0_EL1_PMUVer_V3P5)
> +#define kvm_pmu_is_3p5(vcpu) \
> + (kvm_vcpu_has_pmu(vcpu) && \
> + FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), \
> + IDREG(vcpu->kvm, SYS_ID_AA64DFR0_EL1)) >= ID_AA64DFR0_EL1_PMUVer_V3P5)
>
> u8 kvm_arm_pmu_get_pmuver_limit(void);
>
> --
> 2.39.1.456.gfc5497dd1b-goog
>
More information about the linux-arm-kernel
mailing list