From: Sandesh Patel <[email protected]>

Unlike x86 boolean CPU features, ARM CPU features are exposed by QEMU as
multi-valued properties whose accepted values depend on the host; only a
subset of the possible values are valid on any given host.

Add infra to query and hold CPU properties info.

Signed-off-by: Sandesh Patel <[email protected]>
---
 src/qemu/qemu_capabilities.c | 11 ++++++
 src/qemu/qemu_monitor.c      | 52 ++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.h      | 26 ++++++++++++++
 src/qemu/qemu_monitor_json.c | 66 ++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |  5 +++
 5 files changed, 160 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e9a97f0cf5..d79941f6bd 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -813,6 +813,7 @@ struct _virQEMUCapsAccel {
     virQEMUCapsMachineType *machineTypes;
     virQEMUCapsHostCPUData hostCPU;
     qemuMonitorCPUDefs *cpuModels;
+    qemuMonitorCPUPropsInfoList *cpuProps; /* currently only populated on ARM 
+ KVM */
 };
 
 
@@ -2094,6 +2095,7 @@ virQEMUCapsAccelCopy(virQEMUCapsAccel *dst,
     virQEMUCapsHostCPUDataCopy(&dst->hostCPU, &src->hostCPU);
 
     dst->cpuModels = qemuMonitorCPUDefsCopy(src->cpuModels);
+    dst->cpuProps = qemuMonitorCPUPropsInfoListCopy(src->cpuProps);
 }
 
 
@@ -2159,6 +2161,7 @@ virQEMUCapsAccelClear(virQEMUCapsAccel *caps)
 
     virQEMUCapsHostCPUDataClear(&caps->hostCPU);
     qemuMonitorCPUDefsFree(caps->cpuModels);
+    qemuMonitorCPUPropsInfoListFree(caps->cpuProps);
 }
 
 
@@ -3455,6 +3458,14 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCaps *qemuCaps,
     }
 
     accel->hostCPU.info = g_steal_pointer(&modelInfo);
+
+    /* Query the ARM CPU property info. Only applicable on ARM + KVM. */
+    if (ARCH_IS_ARM(qemuCaps->arch) &&
+        virQEMUCapsTypeIsAccelerated(virtType) &&
+        virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_ARM_CPU_PROPS_INFO) &&
+        qemuMonitorGetCPUPropsInfoList(mon, &accel->cpuProps) < 0)
+        return -1;
+
     return 0;
 }
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index baa78dd6fe..a770054c38 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3339,6 +3339,58 @@ qemuMonitorGetCPUModelComparison(qemuMonitor *mon,
 }
 
 
+int
+qemuMonitorGetCPUPropsInfoList(qemuMonitor *mon,
+                               qemuMonitorCPUPropsInfoList **props_list)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONGetCPUPropsInfoList(mon, props_list);
+}
+
+
+void
+qemuMonitorCPUPropsInfoListFree(qemuMonitorCPUPropsInfoList *list)
+{
+    size_t i;
+
+    if (!list)
+        return;
+
+    for (i = 0; i < list->nprops; i++) {
+        g_free(list->props[i].name);
+        g_free(list->props[i].composite);
+        g_strfreev(list->props[i].supportedValues);
+    }
+    g_free(list->props);
+    g_free(list);
+}
+
+
+qemuMonitorCPUPropsInfoList *
+qemuMonitorCPUPropsInfoListCopy(const qemuMonitorCPUPropsInfoList *orig)
+{
+    qemuMonitorCPUPropsInfoList *copy;
+    size_t i;
+
+    if (!orig)
+        return NULL;
+
+    copy = g_new0(qemuMonitorCPUPropsInfoList, 1);
+    copy->nprops = orig->nprops;
+    copy->props = g_new0(qemuMonitorCPUPropsInfo, orig->nprops);
+
+    for (i = 0; i < orig->nprops; i++) {
+        copy->props[i].name = g_strdup(orig->props[i].name);
+        copy->props[i].type = orig->props[i].type;
+        copy->props[i].supportedValues = 
g_strdupv(orig->props[i].supportedValues);
+        copy->props[i].composite = g_strdup(orig->props[i].composite);
+    }
+
+    return copy;
+}
+
+
 void
 qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfo *model_info)
 {
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c2afb580e4..1653d63722 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1455,6 +1455,20 @@ struct _qemuMonitorCPUModelInfo {
     bool migratability;
 };
 
+typedef struct _qemuMonitorCPUPropsInfo qemuMonitorCPUPropsInfo;
+struct _qemuMonitorCPUPropsInfo {
+    char *name;
+    qemuMonitorCPUPropertyType type;
+    GStrv supportedValues;
+    char *composite;
+};
+
+typedef struct _qemuMonitorCPUPropsInfoList qemuMonitorCPUPropsInfoList;
+struct _qemuMonitorCPUPropsInfoList {
+    size_t nprops;
+    qemuMonitorCPUPropsInfo *props;
+};
+
 typedef enum {
     QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC,
     QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL,
@@ -1490,6 +1504,18 @@ qemuMonitorGetCPUModelComparison(qemuMonitor *mon,
 qemuMonitorCPUModelInfo *
 qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig);
 
+int
+qemuMonitorGetCPUPropsInfoList(qemuMonitor *mon,
+                               qemuMonitorCPUPropsInfoList **props_list);
+
+void
+qemuMonitorCPUPropsInfoListFree(qemuMonitorCPUPropsInfoList *list);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorCPUPropsInfoList, 
qemuMonitorCPUPropsInfoListFree);
+
+qemuMonitorCPUPropsInfoList *
+qemuMonitorCPUPropsInfoListCopy(const qemuMonitorCPUPropsInfoList *orig);
+
 GHashTable *
 qemuMonitorGetCommandLineOptions(qemuMonitor *mon);
 
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 28f7d93834..d44a6ab270 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -5727,6 +5727,72 @@ qemuMonitorJSONGetCPUModelComparison(qemuMonitor *mon,
 }
 
 
+int
+qemuMonitorJSONGetCPUPropsInfoList(qemuMonitor *mon,
+                                   qemuMonitorCPUPropsInfoList **props_list)
+{
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(qemuMonitorCPUPropsInfoList) props_info = NULL;
+    virJSONValue *data;
+    size_t nprops;
+    size_t i;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-arm-cpu-props-info", NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    if (!(data = qemuMonitorJSONGetReply(cmd, reply, VIR_JSON_TYPE_ARRAY)))
+        return -1;
+
+    nprops = virJSONValueArraySize(data);
+
+    props_info = g_new0(qemuMonitorCPUPropsInfoList, 1);
+    props_info->nprops = nprops;
+    props_info->props = g_new0(qemuMonitorCPUPropsInfo, nprops);
+
+    for (i = 0; i < nprops; i++) {
+        virJSONValue *item = virJSONValueArrayGet(data, i);
+        virJSONValue *sv_array;
+        const char *name;
+        const char *type_str;
+        int type;
+
+        if (!(name = virJSONValueObjectGetString(item, "name"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("query-arm-cpu-props-info reply is missing 
'name'"));
+            return -1;
+        }
+
+        if (!(type_str = virJSONValueObjectGetString(item, "type"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("query-arm-cpu-props-info reply for '%1$s' is 
missing 'type'"),
+                           name);
+            return -1;
+        }
+
+        if ((type = qemuMonitorCPUPropertyTypeFromString(type_str)) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("query-arm-cpu-props-info reply for '%1$s' has 
unknown type '%2$s'"),
+                           name, type_str);
+            return -1;
+        }
+
+        props_info->props[i].name = g_strdup(name);
+        props_info->props[i].type = type;
+        props_info->props[i].composite = 
g_strdup(virJSONValueObjectGetString(item, "composite"));
+
+        if ((sv_array = virJSONValueObjectGetArray(item, "supported-values")))
+            props_info->props[i].supportedValues = 
virJSONValueArrayToStringList(sv_array);
+    }
+
+    *props_list = g_steal_pointer(&props_info);
+    return 0;
+}
+
+
 static int
 qemuMonitorJSONGetCommandLineOptionsWorker(size_t pos G_GNUC_UNUSED,
                                            virJSONValue *item,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index f4c093d717..11b07a6770 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -446,6 +446,11 @@ qemuMonitorJSONGetCPUModelComparison(qemuMonitor *mon,
                                      char **result)
     ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 
+int
+qemuMonitorJSONGetCPUPropsInfoList(qemuMonitor *mon,
+                                   qemuMonitorCPUPropsInfoList **props_list)
+    ATTRIBUTE_NONNULL(2);
+
 GHashTable *
 qemuMonitorJSONGetCommandLineOptions(qemuMonitor *mon);
 
-- 
2.43.7

Reply via email to