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


Reply via email to