Implement query-cpu-props-info for ARM64/KVM by creating and finalizing a temporary "host" CPU object and then walking its QOM properties.
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) -- 2.52.0
