> On 16 Oct 2026, at 7:24 PM, Eric Auger <[email protected]> wrote:
> 
> !-------------------------------------------------------------------|
>  CAUTION: External Email
> 
> |-------------------------------------------------------------------!
> 
> Hi,
> 
> On 9/21/26 2:32 PM, Khushit Shah wrote:
>> Report blockers for named CPU models in query-cpu-definitions.
>> 
>> Efficiently do this by validating the realized ID register values
>> against the host values. sveNNNN properties need special handling
>> because they are not stored in ID registers.
>> 
>> This way, we need not instantiate each model to check if it can be
>> realized on the host, and we also get granular information about the ID
>> register fields blocking realization.
>> 
>> Introduce arm_cpu_class_check_missing_features() and
>> kvm_arm_idregs_get_blockers() to achieve this.
> 
> I would recommend to show an excerpt of the output
Cover letter already has one… Will add to commit message.

Thanks,
Khushit
>> 
>> Signed-off-by: Khushit Shah <[email protected]>
>> ---
>> target/arm/arm-qmp-cmds.c    | 12 +++++++++
>> target/arm/cpu-models-stub.c |  5 ++++
>> target/arm/cpu-models.c      | 35 +++++++++++++++++++++++++
>> target/arm/cpu-models.h      |  2 ++
>> target/arm/kvm.c             | 50 ++++++++++++++++++++++++++++++++++++
>> target/arm/kvm_arm.h         | 13 ++++++++++
>> 6 files changed, 117 insertions(+)
>> 
>> diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
>> index ba488d5c01..d837ec6653 100644
>> --- a/target/arm/arm-qmp-cmds.c
>> +++ b/target/arm/arm-qmp-cmds.c
>> @@ -379,6 +379,18 @@ static void arm_cpu_add_definition(gpointer data, 
>> gpointer user_data)
>>     info->name = cpu_model_from_type(typename);
>>     info->q_typename = g_strdup(typename);
>> 
>> +    /* calculate blockers */
>> +    if (kvm_enabled()
>> +            && !g_str_equal(info->name, "host")
>> +            && !g_str_equal(info->name, "max")
>> +            && arm_find_model(info->name) != NULL) {
>> +        arm_cpu_class_check_missing_features(ARM_CPU_CLASS(oc),
>> +                                    &info->unavailable_features);
>> +        if (info->unavailable_features) {
>> +            info->has_unavailable_features = true;
>> +        }
>> +    }
>> +
>>     QAPI_LIST_PREPEND(*cpu_list, info);
>> }
>> 
>> diff --git a/target/arm/cpu-models-stub.c b/target/arm/cpu-models-stub.c
>> index 48f712d648..2d1be49e0a 100644
>> --- a/target/arm/cpu-models-stub.c
>> +++ b/target/arm/cpu-models-stub.c
>> @@ -11,3 +11,8 @@ const ArmNamedCpuModel *arm_find_model(const char *name)
>> {
>>     return NULL;
>> }
>> +
>> +void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList 
>> **blockers)
>> +{
>> +    return;
>> +}
>> diff --git a/target/arm/cpu-models.c b/target/arm/cpu-models.c
>> index 855eb5ee6b..9591b6dbfc 100644
>> --- a/target/arm/cpu-models.c
>> +++ b/target/arm/cpu-models.c
>> @@ -477,6 +477,41 @@ static void arm_named_cpu_initfn(Object *obj)
>>     arm_named_cpu_zero_unknown_feature_ids(cpu, &error_abort);
>> }
>> 
>> +void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList 
>> **blockers)
>> +{
>> +    Error *err = NULL;
>> +    Object *obj = object_new_with_class(OBJECT_CLASS(acc));
>> +    ARMCPU *cpu = ARM_CPU(obj);
>> +
>> +    if (!kvm_enabled() || !arm_find_model(acc->info->name)) {
>> +        goto out;
>> +    }
>> +
>> +    if (cpu_isar_feature(aa64_sve, cpu)) {
>> +        aarch64_cpu_sve_finalize(cpu, &err);
>> +        if (err) {
>> +            error_free(err);
>> +            err = NULL;
>> +            uint32_t host_vq_map = cpu->sve_vq.supported;
>> +            uint32_t model_vq_map = cpu->sve_vq.map;
>> +
>> +            if ((model_vq_map & host_vq_map) != model_vq_map) {
>> +                for (int vq = 1; vq <= ARM_MAX_VQ; vq++) {
>> +                    uint32_t vq_bit = (1 << (vq - 1));
>> +                    if ((model_vq_map & vq_bit) && !(host_vq_map & vq_bit)) 
>> {
>> +                        QAPI_LIST_PREPEND(*blockers,
>> +                            g_strdup_printf("sve%d", vq * 128));
>> +                    }
>> +                }
>> +            }
>> +        }
>> +    }
>> +
>> +    kvm_arm_idregs_get_blockers(cpu, kvm_arm_get_host_isar(), blockers);
>> +out:
>> +    object_unref(obj);
>> +}
>> +
>> void arm_register_named_cpu_models(void)
>> {
>>     static ARMCPUInfo *arm_named_cpu_infos;
>> diff --git a/target/arm/cpu-models.h b/target/arm/cpu-models.h
>> index 144778744e..41bb15d928 100644
>> --- a/target/arm/cpu-models.h
>> +++ b/target/arm/cpu-models.h
>> @@ -4,6 +4,7 @@
>> 
>> #include "qapi/error.h"
>> #include "qom/object.h"
>> +#include "cpu.h"
>> 
>> typedef enum ArmModelPropType {
>>     ARM_MODEL_PROP_BOOL,
>> @@ -32,5 +33,6 @@ void arm_apply_model_props(Object *obj, const 
>> ArmModelPropValue *props,
>>                            Error **errp);
>> void arm_realize_model_chain(Object *obj, const ArmNamedCpuModel *model,
>>                              Error **errp);
>> +void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList 
>> **blockers);
>> 
>> #endif /* ARM_CPU_MODELS_H */
>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>> index bb74f8c274..ca3da80262 100644
>> --- a/target/arm/kvm.c
>> +++ b/target/arm/kvm.c
>> @@ -1485,6 +1485,56 @@ arm_field_skip_writeback_if_not_writable(const 
>> ARM64SysRegField *field)
>>     return field_matches(field, ID_DFR0_EL1_IDX, "PerfMon");
>> }
>> 
>> +void kvm_arm_idregs_get_blockers(ARMCPU *cpu,
>> +                                 const ARMISARegisters *host_isar,
>> +                                 strList **blockers)
>> +{
>> +    for (int i = 0; i < NUM_ID_IDX; i++) {
>> +        ARM64SysReg *reg = &arm64_id_regs[i];
>> +
>> +        if (!reg->name) {
>> +            continue;
>> +        }
>> +
>> +        for (uint32_t j = 0; j < reg->fields_count; j++) {
>> +            const ARM64SysRegField *field = &reg->fields[j];
>> +            ArmFieldValueSet *vs = NULL;
>> +            bool supported = false;
>> +            uint64_t model_val;
>> +
>> +            /* Not a blocker if the field is never written back to KVM. */
>> +            if (arm_field_skip_writeback_always(field) ||
>> +                (!arm_field_is_writable(field) &&
>> +                 arm_field_skip_writeback_if_not_writable(field))) {
>> +                continue;
>> +            }
>> +
>> +            model_val = extract64(cpu->isar.idregs[field->index],
>> +                                  field->shift, field->length);
> nit I see you use that several times, you could introduce a helper
>> +
>> +            /*
>> +             * If the field is written back, make sure a "supported" value
>> +             * is requested.
>> +             */
>> +            kvm_arm_field_get_supported_values(field, host_isar, &vs);
>> +            for (size_t k = 0; k < vs->n_ranges; k++) {
>> +                if (model_val >= vs->ranges[k].min &&
>> +                    model_val <= vs->ranges[k].max) {
>> +                    supported = true;
>> +                    break;
>> +                }
>> +            }
>> +            g_free(vs->ranges);
>> +            g_free(vs);
>> +
>> +            if (!supported) {
>> +                QAPI_LIST_PREPEND(*blockers,
>> +                    g_strdup_printf("SYSREG_%s_%s", reg->name, 
>> field->name));
>> +            }
>> +        }
>> +    }
>> +}
>> +
>> /*
>>  * Copy writable ID reg fields from isar.idregs[] into the KVM cpreg list,
>>  * so the subsequent write_list_to_kvmstate() pushes them to KVM.
>> diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
>> index ab01ce8665..59832d8063 100644
>> --- a/target/arm/kvm_arm.h
>> +++ b/target/arm/kvm_arm.h
>> @@ -205,6 +205,19 @@ void kvm_arm_field_get_supported_values(const 
>> ARM64SysRegField *field,
>>                                         const ARMISARegisters *host_isar,
>>                                         ArmFieldValueSet **value_set);
>> 
>> +/**
>> + * kvm_arm_idregs_get_blockers:
>> + * @cpu: ARMCPU
>> + * @host_isar: The host ISAR registers
>> + * @blockers: The list of blockers
>> + *
>> + * Get the list of "blockers" in @cpu's idregs state for the given
>> + * @host_isar.
>> + */
>> +void kvm_arm_idregs_get_blockers(ARMCPU *cpu,
>> +                                 const ARMISARegisters *host_isar,
>> +                                 strList **blockers);
>> +
>> /**
>>  * kvm_arm_steal_time_finalize:
>>  * @cpu: ARMCPU for which to finalize kvm-steal-time
> Thanks
> 
> Eric


Reply via email to