On 9/28/26 3:34 PM, Khushit Shah wrote:
>
>> 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.
done in v10
Thanks!
Eric
>
>> 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
>>