> 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, &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
> 

Reply via email to