On 9/21/26 2:32 PM, Khushit Shah wrote:
> Implement query-cpu-props-info for ARM64/KVM by creating and finalizing
> a temporary "host" CPU object and then walking its QOM properties.
side note: the new qmp command shall be documented in
docs/system/arm/cpu-features.rst
Eric
>
> For numeric SYSREG_ properties, report the host-supported value ranges
> computed by kvm_arm_field_get_supported_values(). For boolean
> properties, report false as always supported and true as supported when
> the QOM property value is true.
>
> Signed-off-by: Khushit Shah <[email protected]>
> ---
> target/arm/arm-qmp-cmds.c | 84 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 84 insertions(+)
>
> diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
> index 0940285af1..ba488d5c01 100644
> --- a/target/arm/arm-qmp-cmds.c
> +++ b/target/arm/arm-qmp-cmds.c
> @@ -84,6 +84,90 @@ static const char *cpu_model_advertised_features[] = {
> NULL
> };
>
> +CpuPropertyInfoList *qmp_query_cpu_props_info(Error **errp)
> +{
> + CpuPropertyInfoList *head = NULL;
> + const ARMISARegisters *host_isar;
> + ObjectPropertyIterator iter;
> + ObjectProperty *prop;
> + Error *err = NULL;
> + ObjectClass *oc;
> + Object *obj;
> +
> + if (!kvm_enabled()) {
> + error_setg(errp, "query-cpu-props-info requires KVM");
> + return NULL;
> + }
> +
> + oc = cpu_class_by_name(TYPE_ARM_CPU, "host");
> + if (!oc) {
> + error_setg(errp, "The 'host' CPU type is not available");
> + return NULL;
> + }
> +
> + host_isar = kvm_arm_get_host_isar();
> +
> + /* Spin up a scratch "host" vCPU object and walk its QOM properties. */
> + obj = object_new_with_class(oc);
> + arm_cpu_finalize_features(ARM_CPU(obj), &err);
> + if (err) {
> + error_propagate(errp, err);
> + object_unref(obj);
> + return NULL;
> + }
> +
> + object_property_iter_init(&iter, obj);
> + while ((prop = object_property_iter_next(&iter))) {
> + CpuPropertyInfo *info;
> +
> + if (g_str_has_prefix(prop->name, "SYSREG_")) {
> + const ARM64SysRegField *field = prop->opaque;
> + CpuPropertyValueRangeList *ranges = NULL;
> + ArmFieldValueSet *vs = NULL;
> +
> + info = g_new0(CpuPropertyInfo, 1);
> + info->name = g_strdup(prop->name);
> + info->type = CPU_PROPERTY_TYPE_NUMBER;
> +
> + kvm_arm_field_get_supported_values(field, host_isar, &vs);
> + for (size_t k = 0; k < vs->n_ranges; k++) {
> + CpuPropertyValueRange *r = g_new0(CpuPropertyValueRange, 1);
> + r->min = vs->ranges[k].min;
> + r->max = vs->ranges[k].max;
> + QAPI_LIST_PREPEND(ranges, r);
> + }
> + info->u.number.supported_values = ranges;
> +
> + g_free(vs->ranges);
> + g_free(vs);
> + } else if (g_strv_contains(cpu_model_advertised_features,
> prop->name)) {
> + bool cur = object_property_get_bool(obj, prop->name,
> &error_abort);
> + boolList *values = NULL;
> +
> + info = g_new0(CpuPropertyInfo, 1);
> + info->name = g_strdup(prop->name);
> + info->type = CPU_PROPERTY_TYPE_BOOLEAN;
> +
> + /*
> + * "off" is always supported. "on" is only supported when the
> + * host already has the feature enabled.
> + */
> + QAPI_LIST_PREPEND(values, false);
> + if (cur) {
> + QAPI_LIST_PREPEND(values, true);
> + }
> + info->u.boolean.supported_values = values;
> + } else {
> + continue;
> + }
> +
> + QAPI_LIST_PREPEND(head, info);
> + }
> +
> + object_unref(obj);
> + return head;
> +}
> +
> CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType
> type,
> CpuModelInfo *model,
> Error **errp)