From: Sandesh Patel <sandesh.patel@nutanix.com>
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 <sandesh.patel@nutanix.com>
---
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
© 2016 - 2026 Red Hat, Inc.