> -----Original Message----- > From: Cornelia Huck <coh...@redhat.com> > Sent: Monday, April 14, 2025 5:39 PM > To: eric.auger....@gmail.com; eric.au...@redhat.com; qemu- > de...@nongnu.org; qemu-...@nongnu.org; kvm...@lists.linux.dev; > peter.mayd...@linaro.org; richard.hender...@linaro.org; > alex.ben...@linaro.org; m...@kernel.org; oliver.up...@linux.dev; > seb...@redhat.com; Shameerali Kolothum Thodi > <shameerali.kolothum.th...@huawei.com>; arm...@redhat.com; > berra...@redhat.com; abolo...@redhat.com; jdene...@redhat.com > Cc: ag...@csgraf.de; shahu...@redhat.com; mark.rutl...@arm.com; > phi...@linaro.org; pbonz...@redhat.com; Cornelia Huck > <coh...@redhat.com> > Subject: [PATCH v3 06/10] arm/kvm: Allow reading all the writable ID > registers > > From: Eric Auger <eric.au...@redhat.com> > > At the moment kvm_arm_get_host_cpu_features() reads a subset of the > ID regs. As we want to introduce properties for all writable ID reg > fields, we want more genericity and read more default host register > values. > > Introduce a new get_host_cpu_idregs() helper and add a new exhaustive > boolean parameter to kvm_arm_get_host_cpu_features() and > kvm_arm_set_cpu_features_from_host() to select the right behavior. > The host cpu model will keep the legacy behavior unless the writable > id register interface is available. > > A writable_map IdRegMap is introduced in the CPU object. A subsequent > patch will populate it. > > Signed-off-by: Eric Auger <eric.au...@redhat.com> > Signed-off-by: Cornelia Huck <coh...@redhat.com> > --- > target/arm/cpu-sysregs.h | 2 ++ > target/arm/cpu.h | 3 ++ > target/arm/cpu64.c | 2 +- > target/arm/kvm.c | 78 ++++++++++++++++++++++++++++++++++++++-- > target/arm/kvm_arm.h | 9 +++-- > target/arm/trace-events | 1 + > 6 files changed, 89 insertions(+), 6 deletions(-) > > diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h > index e89a1105904c..367fab51f19e 100644 > --- a/target/arm/cpu-sysregs.h > +++ b/target/arm/cpu-sysregs.h > @@ -41,6 +41,8 @@ int get_sysreg_idx(ARMSysRegs sysreg); > > #ifdef CONFIG_KVM > uint64_t idregs_sysreg_to_kvm_reg(ARMSysRegs sysreg); > +int kvm_idx_to_idregs_idx(int kidx); > +int idregs_idx_to_kvm_idx(ARMIDRegisterIdx idx); > #endif > > #endif /* ARM_CPU_SYSREGS_H */ > diff --git a/target/arm/cpu.h b/target/arm/cpu.h > index 775a8aebc5d3..8717c5e7695b 100644 > --- a/target/arm/cpu.h > +++ b/target/arm/cpu.h > @@ -1088,6 +1088,9 @@ struct ArchCPU { > */ > ARMIdRegsState writable_id_regs; > > + /* ID reg writable bitmask (KVM only) */ > + IdRegMap *writable_map; > + > /* QOM property to indicate we should use the back-compat CNTFRQ > default */ > bool backcompat_cntfrq; > > diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c > index 839442745ea4..60a709502697 100644 > --- a/target/arm/cpu64.c > +++ b/target/arm/cpu64.c > @@ -757,7 +757,7 @@ static void aarch64_host_initfn(Object *obj) > { > #if defined(CONFIG_KVM) > ARMCPU *cpu = ARM_CPU(obj); > - kvm_arm_set_cpu_features_from_host(cpu); > + kvm_arm_set_cpu_features_from_host(cpu, false); > if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { > aarch64_add_sve_properties(obj); > aarch64_add_pauth_properties(obj); > diff --git a/target/arm/kvm.c b/target/arm/kvm.c > index 6e3cd06e9bc5..b07d5f16db50 100644 > --- a/target/arm/kvm.c > +++ b/target/arm/kvm.c > @@ -41,6 +41,7 @@ > #include "hw/acpi/ghes.h" > #include "target/arm/gtimer.h" > #include "migration/blocker.h" > +#include "cpu-custom.h" > > const KVMCapabilityInfo kvm_arch_required_capabilities[] = { > KVM_CAP_INFO(DEVICE_CTRL), > @@ -270,7 +271,73 @@ static int get_host_cpu_reg(int fd, > ARMHostCPUFeatures *ahcf, ARMIDRegisterIdx i > return ret; > } > > -static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) > +int kvm_idx_to_idregs_idx(int kidx) > +{ > + int op1, crm, op2; > + ARMSysRegs sysreg; > + > + op1 = kidx / 64; > + if (op1 == 2) { > + op1 = 3; > + } > + crm = (kidx % 64) / 8; > + op2 = kidx % 8; > + sysreg = ENCODE_ID_REG(3, op1, 0, crm, op2); > + return get_sysreg_idx(sysreg); > +} > + > +int idregs_idx_to_kvm_idx(ARMIDRegisterIdx idx) > +{ > + ARMSysRegs sysreg = id_register_sysreg[idx]; > + > + return KVM_ARM_FEATURE_ID_RANGE_IDX((sysreg & > CP_REG_ARM64_SYSREG_OP0_MASK) >> > CP_REG_ARM64_SYSREG_OP0_SHIFT, > + (sysreg & > CP_REG_ARM64_SYSREG_OP1_MASK) >> > CP_REG_ARM64_SYSREG_OP1_SHIFT, > + (sysreg & > CP_REG_ARM64_SYSREG_CRN_MASK) >> > CP_REG_ARM64_SYSREG_CRN_SHIFT, > + (sysreg & > CP_REG_ARM64_SYSREG_CRM_MASK) >> > CP_REG_ARM64_SYSREG_CRM_SHIFT, > + (sysreg & > CP_REG_ARM64_SYSREG_OP2_MASK) >> > CP_REG_ARM64_SYSREG_OP2_SHIFT); > +} > + > + > +/* > + * get_host_cpu_idregs: Read all the writable ID reg host values > + * > + * Need to be called once the writable mask has been populated > + * Note we may want to read all the known id regs but some of them are > not > + * writable and return an error, hence the choice of reading only those > which > + * are writable. Those are also readable! > + */ > +static int get_host_cpu_idregs(ARMCPU *cpu, int fd, ARMHostCPUFeatures > *ahcf) > +{ > + int err = 0; > + int i; > + > + for (i = 0; i < NUM_ID_IDX; i++) { > + ARM64SysReg *sysregdesc = &arm64_id_regs[i]; > + ARMSysRegs sysreg = sysregdesc->sysreg; > + uint64_t writable_mask = cpu->writable_map- > >regs[idregs_idx_to_kvm_idx(i)]; > + uint64_t *reg; > + int ret; > + > + if (!writable_mask) { > + continue; > + } > + > + reg = &ahcf->isar.idregs[i]; > + ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg)); I think we can use get_host_cpu_reg() here. > + trace_get_host_cpu_idregs(sysregdesc->name, *reg); > + if (ret) { > + error_report("%s error reading value of host %s register (%m)", > + __func__, sysregdesc->name); > + > + err = ret; > + } > + } > + return err; > +} > + > +static bool > +kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures > *ahcf, > + bool exhaustive) > { > /* Identify the feature bits corresponding to the host CPU, and > * fill out the ARMHostCPUClass fields accordingly. To do this > @@ -398,6 +465,11 @@ static bool > kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) > err |= get_host_cpu_reg(fd, ahcf, ID_DFR1_EL1_IDX); > err |= get_host_cpu_reg(fd, ahcf, ID_MMFR5_EL1_IDX); > > + /* Make sure writable ID reg values are read */ > + if (exhaustive) { > + err |= get_host_cpu_idregs(cpu, fd, ahcf); > + } Also if we do this a bit above can we avoid reading the ID registers twice if "exhaustive=true" ? Thanks, Shameer > + > /* > * DBGDIDR is a bit complicated because the kernel doesn't > * provide an accessor for it in 64-bit mode, which is what this > @@ -467,13 +539,13 @@ static bool > kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) > return true; > } > > -void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) > +void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool > exhaustive) > { > CPUARMState *env = &cpu->env; > > if (!arm_host_cpu_features.dtb_compatible) { > if (!kvm_enabled() || > - !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) { > + !kvm_arm_get_host_cpu_features(cpu, &arm_host_cpu_features, > exhaustive)) { > /* We can't report this error yet, so flag that we need to > * in arm_cpu_realizefn(). > */ > diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h > index 8d1f20ca8d89..90ba4f7d8987 100644 > --- a/target/arm/kvm_arm.h > +++ b/target/arm/kvm_arm.h > @@ -141,8 +141,12 @@ uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu); > * > * Set up the ARMCPU struct fields up to match the information probed > * from the host CPU. > + * > + * @cpu: cpu object > + * @exhaustive: if true, all the feature ID regs are queried instead of > + * a subset > */ > -void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); > +void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool > exhaustive); > > /** > * kvm_arm_add_vcpu_properties: > @@ -257,7 +261,8 @@ static inline int > kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) > /* > * These functions should never actually be called without KVM support. > */ > -static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) > +static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, > + bool exhaustive) > { > g_assert_not_reached(); > } > diff --git a/target/arm/trace-events b/target/arm/trace-events > index 4438dce7becc..17e52c0705f2 100644 > --- a/target/arm/trace-events > +++ b/target/arm/trace-events > @@ -13,3 +13,4 @@ arm_gt_update_irq(int timer, int irqstate) > "gt_update_irq: timer %d irqstate %d" > > # kvm.c > kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = > 0x%"PRIx64" is translated into 0x%"PRIx64 > +get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host > value for %s is 0x%"PRIx64 > -- > 2.49.0 >
RE: [PATCH v3 06/10] arm/kvm: Allow reading all the writable ID registers
Shameerali Kolothum Thodi via Fri, 23 May 2025 01:28:23 -0700
- Re: [PATCH v3 06/10] arm/kvm: Allow reading ... Eric Auger
- Re: [PATCH v3 06/10] arm/kvm: Allow rea... Cornelia Huck
- Re: [PATCH v3 06/10] arm/kvm: Allow rea... Cornelia Huck
- RE: [PATCH v3 06/10] arm/kvm: Allow rea... Shameerali Kolothum Thodi via