> 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, ¤t, 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
>