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