> On 16 Sep 2026, at 8:15 PM, Eric Auger <[email protected]> wrote:
> 
> !-------------------------------------------------------------------|
>  CAUTION: External Email
> 
> |-------------------------------------------------------------------!
> 
> SYSREG prop settings were recorded in a hashtable but they
> are not yet injected on guest. Iterate over all set fields and
> apply the new value through KVM_SET_ONE_REG. The new field
> value overrides the current observable vcpu register value.
> 
> Signed-off-by: Eric Auger <[email protected]>

With this, I suppose, what named models will do is directly write to
ID register state, As it also defines state which affects vCPU init flags also.

> ---
> target/arm/kvm.c        | 65 +++++++++++++++++++++++++++++++++++++++++
> target/arm/trace-events |  1 +
> 2 files changed, 66 insertions(+)
> 
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 3ec2618cc1..ddf320d0e6 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -343,6 +343,9 @@ static ARM64SysRegField *get_field(int i, ARM64SysReg 
> *reg)
> #define MAKE_IDREG_KEY(reg_idx, field_shift) \
>     (((uint64_t)(reg_idx) << 8) | ((uint64_t)(field_shift) & 0xFF))
> 
> +#define KEY_TO_REG_IDX(key)     ((uint32_t)(((uint64_t)(key)) >> 8))
> +#define KEY_TO_SHIFT(key)       ((uint8_t)(((uint64_t)(key)) & 0xFF))
> +
> static void set_sysreg_prop(Object *obj, Visitor *v,
>                             const char *name, void *opaque,
>                             Error **errp)
> @@ -2215,6 +2218,63 @@ int kvm_arch_pre_create_vcpu(CPUState *cpu, Error 
> **errp)
>     return 0;
> }
> 
> +static int kvm_arm_apply_sysreg_props(ARMCPU *cpu, Error **errp)
> +{
> +    uint64_t *idregs = cpu->isar.idregs;
> +    gpointer key_ptr, value_ptr;
> +    CPUState *cs = CPU(cpu);
> +    GHashTableIter iter;
> +
> +    g_hash_table_iter_init(&iter, cpu->sysreg_props);
> +
> +    while (g_hash_table_iter_next(&iter, &key_ptr, &value_ptr)) {
> +        uint64_t key = (uint64_t)key_ptr;
> +        uint64_t value = (uint64_t)value_ptr;
> +        uint32_t reg_idx = KEY_TO_REG_IDX(key);
> +        uint8_t lower    = KEY_TO_SHIFT(key);
> +        ARM64SysReg *reg = &arm64_id_regs[reg_idx];
> +        struct kvm_one_reg kvm_reg;
> +        uint64_t current, old, mask;
> +        uint64_t kvm_idx;
> +        ARM64SysRegField *field = get_field(lower, reg);
> +        int length = field->length;
> +        uint64_t oldfv;
> +        int ret;
> +
> +        mask = MAKE_64BIT_MASK(lower, length);
> +        value = value << lower;
> +
> +        old = idregs[reg_idx];
> +
> +        kvm_idx = idregs_sysreg_to_kvm_reg(id_register_sysreg[reg_idx]);
> +        ret = read_sys_reg64(cs->kvm_fd, &current, kvm_idx);
> +        if (ret) {
> +            error_setg(errp, "failed to read the current value of %s",
> +                       reg->name);
> +            return ret;
> +        }
> +        oldfv = (current & mask) >> lower;
> +
> +        idregs[reg_idx] = current & ~mask;
> +        idregs[reg_idx] |= value;
> +        kvm_reg.id = kvm_idx;
> +        kvm_reg.addr = (uintptr_t)&idregs[reg_idx];
> +
We can ignore this if value == old value

> +        ret = ioctl(cs->kvm_fd, KVM_SET_ONE_REG, &kvm_reg);
> +        if (ret) {
> +            error_setg(errp, "failed to apply new value 0x%"PRIx64" for 
> field %s.%s "
> +                       "(previous is 0x%"PRIx64"): %m", idregs[reg_idx],
> +                       reg->name, field->name, oldfv);
> +            return ret;
> +        }
> +
> +        trace_apply_sysreg_prop(reg->name, field->name, old, current,
> +                                mask, value, idregs[reg_idx]);
> +    }
> +    return 0;
> +}
> +
> int kvm_arch_init_vcpu(CPUState *cs, Error **errp)
> {
>     int ret;
> @@ -2315,6 +2375,11 @@ int kvm_arch_init_vcpu(CPUState *cs, Error **errp)
>     }
>     cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
> 
> +    ret = kvm_arm_apply_sysreg_props(cpu, errp);
> +    if (ret) {
> +        return ret;
> +    }
> +
This should also happen on vCPU reset.

Overall, I like this approach as if the user does not provide any property 
overrides, it should behave the same as older builds.

Warm Regards,
Khushit
>     return kvm_arm_init_cpreg_list(cpu);
> }
> 
> diff --git a/target/arm/trace-events b/target/arm/trace-events
> index d72ad6b671..b4d2b45a7d 100644
> --- a/target/arm/trace-events
> +++ b/target/arm/trace-events
> @@ -18,6 +18,7 @@ kvm_arm_writable_idregs_to_cpreg_list(const char *name, 
> uint64_t previous, uint6
> decode_idreg_writemap(const char* name, int lower, int upper, char 
> *prop_name) "%s [%d:%d] is writable (prop %s)"
> get_sysreg_prop(const char *name, uint64_t value) "%s 0x%"PRIx64
> set_sysreg_prop(const char *name, uint64_t old, uint64_t mask, uint64_t 
> field_value, uint64_t new) "%s old reg value=0x%"PRIx64" mask=0x%"PRIx64" new 
> field value=0x%"PRIx64" new reg value=0x%"PRIx64
> +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"
> 
> # cpu.c
> -- 
> 2.53.0
> 

Reply via email to