> On 16 Sep 2026, at 8:15 PM, Eric Auger <[email protected]> wrote: > > !-------------------------------------------------------------------| > CAUTION: External Email > > |-------------------------------------------------------------------! > > Add kvm_idreg_write_scratch_vcpu helper that will be used > by qmp_query_cpu_model_expansion code to test SYSREG settings > against a scratch vcpu. Indeed when the expansion code is called > the actual vcpu has not been initialized so we use a scratch vcpu. > This latter has been initialized with features taken from > legacy compositive options (EL2, SVE, ...). So the trial is > very close to the final setup. > > Signed-off-by: Eric Auger <[email protected]> > --- > target/arm/kvm_arm.h | 4 ++++ > target/arm/kvm-stub.c | 7 ++++++ > target/arm/kvm.c | 51 +++++++++++++++++++++++++++++++++++++++++ > target/arm/trace-events | 1 + > 4 files changed, 63 insertions(+) > > diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h > index 2b3474cc36..bace69efed 100644 > --- a/target/arm/kvm_arm.h > +++ b/target/arm/kvm_arm.h > @@ -14,6 +14,7 @@ > #include "qapi/qapi-types-misc-arm.h" > #include "system/kvm.h" > #include "target/arm/cpu-qom.h" > +#include "cpu-idregs.h" > > #define KVM_ARM_VGIC_V2 (1 << 0) > #define KVM_ARM_VGIC_V3 (1 << 1) > @@ -250,4 +251,7 @@ void arm_gic_cap_kvm_probe(GICCapability *v2, > GICCapability *v3); > */ > char *kvm_print_register_name(uint64_t regidx); > > +bool kvm_idreg_write_scratch_vcpu(ARMCPU *cpu, int cpufd, > + ARM64SysRegField *field, uint64_t newfv, > + Error **errp); > #endif > diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c > index 88cbe8d85c..8e6fae0a4d 100644 > --- a/target/arm/kvm-stub.c > +++ b/target/arm/kvm-stub.c > @@ -119,3 +119,10 @@ char *kvm_print_register_name(uint64_t regidx) > { > g_assert_not_reached(); > } > + > +bool kvm_idreg_write_scratch_vcpu(ARMCPU *cpu, int cpufd, > + ARM64SysRegField *field, uint64_t newfv, > + Error **errp) > +{ > + g_assert_not_reached(); > +} > diff --git a/target/arm/kvm.c b/target/arm/kvm.c > index 537673177a..f7ca0e0250 100644 > --- a/target/arm/kvm.c > +++ b/target/arm/kvm.c > @@ -447,6 +447,57 @@ static bool kvm_arm_vcpu_validate_sysreg(ARMCPU *cpu, > ARM64SysRegField *field, > #define KEY_TO_REG_IDX(key) ((uint32_t)(((uint64_t)(key)) >> 8)) > #define KEY_TO_SHIFT(key) ((uint8_t)(((uint64_t)(key)) & 0xFF)) > > +bool kvm_idreg_write_scratch_vcpu(ARMCPU *cpu, int cpufd, > + ARM64SysRegField *field, uint64_t newfv, > + Error **errp) > +{ > + uint64_t mask, old_reg_val, new_reg_val, oldfv; > + struct kvm_one_reg reg; > + int lower = field->shift; > + int length = field->length; > + int index = field->index; > + uint64_t kidx; > + int ret; > + > + mask = MAKE_64BIT_MASK(lower, length); > + > + if (!kvm_arm_vcpu_validate_sysreg(cpu, field, newfv, errp)) { > + return false; > + }; > + > + kidx = idregs_sysreg_to_kvm_reg(id_register_sysreg[index]); > + ret = read_sys_reg64(cpufd, &old_reg_val, kidx); > + if (ret) { > + error_setg(errp, "failed to read the scratch vcpu value for field %s > %m", > + field->name); > + return false; > + } > + oldfv = (old_reg_val & mask) >> lower; > + > + new_reg_val = old_reg_val & ~mask; > + new_reg_val |= newfv << lower; > + > + reg.id = kidx; > + reg.addr = (uintptr_t)&new_reg_val; > + ret = ioctl(cpufd, KVM_SET_ONE_REG, ®); > + if (ret) { > + error_setg(errp, "failed to apply new value 0x%"PRIx64" for field %s > " > + "(previous is 0x%"PRIx64"): %m", newfv, field->name, > oldfv); > + return false; > + } else { > + uint64_t check_val, actualfv; > + > + ret = read_sys_reg64(cpufd, &check_val, kidx); > + if (ret) { > + error_setg(errp, "failed to read the new reg value: %m"); > + return false; > + } > + actualfv = (check_val & mask) >> lower; > + trace_kvm_idreg_write_scratch_vcpu(field->name, oldfv, newfv, > actualfv); > + } > + return true; > +} > +
Hi Eric, This looks similar to kvm_arm_apply_sysreg_props(), we maybe be able to abstract out kvm_arm_apply_sysreg_prop(), which can then be used by both these functions. > static void set_sysreg_prop(Object *obj, Visitor *v, > const char *name, void *opaque, > Error **errp) > diff --git a/target/arm/trace-events b/target/arm/trace-events > index 2a9cc67035..7a3f499a0e 100644 > --- a/target/arm/trace-events > +++ b/target/arm/trace-events > @@ -21,6 +21,7 @@ set_sysreg_prop(const char *name, uint64_t old, uint64_t > mask, uint64_t field_va > apply_sysreg_prop(const char *reg_name, const char *field_name, uint64_t old, > uint64_t current, uint64_t mask, uint64_t field_value, uint64_t new) "%s.%s > old=0x%"PRIx64" current=0x%"PRIx64" mask=0x%"PRIx64" new field > value=0x%"PRIx64" new=0x%"PRIx64 > nb_sysreg_props(const char *name, int count) "%s: %d SYSREG properties" > unexpected_writable_reserved_field(const char *reg_name, const char > *field_name, int lower, int upper) "Unexpected writable reserved field: %s.%s > [%d,%d], skip it ..." > +kvm_idreg_write_scratch_vcpu(const char *name, uint64_t oldfv, uint64_t > newfv, uint64_t actualfv) "successful dry-run for %s old=0x%"PRIx64" > new=0x%"PRIx64" actual=0x%"PRIx64 > > # cpu.c > arm_cpu_reset(uint64_t mp_aff) "cpu %" PRIu64 > -- > 2.53.0 >
