diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 0e9c81b6b0..d92aa95428 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3082,14 +3082,16 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps,
cpu->nfeatures = 0;
for (i = 0; i < modelInfo->nprops; i++) {
- if (VIR_STRDUP(cpu->features[i].name, modelInfo->props[i].name) < 0)
+ virCPUFeatureDefPtr feature = cpu->features + cpu->nfeatures;
+ qemuMonitorCPUPropertyPtr prop = modelInfo->props + i;
+
+ if (prop->type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN)
+ continue;
+
+ if (VIR_STRDUP(feature->name, prop->name) < 0)
return -1;
-
- if (modelInfo->props[i].supported)
- cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
- else
- cpu->features[i].policy = VIR_CPU_FEATURE_DISABLE;
-
+ feature->policy = prop->value.boolean ? VIR_CPU_FEATURE_REQUIRE
+ : VIR_CPU_FEATURE_DISABLE;
cpu->nfeatures++;
}
@@ -3195,30 +3197,59 @@ virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
hostCPU->nprops = n;
for (i = 0; i < n; i++) {
- hostCPU->props[i].name = virXMLPropString(nodes[i], "name");
- if (!hostCPU->props[i].name) {
+ qemuMonitorCPUPropertyPtr prop = hostCPU->props + i;
+ int type;
+
+ ctxt->node = nodes[i];
+
+ if (!(prop->name = virXMLPropString(ctxt->node, "name"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing 'name' attribute for a host CPU"
" model property in QEMU capabilities cache"));
goto cleanup;
}
- if (!(str = virXMLPropString(nodes[i], "value"))) {
+ if (!(str = virXMLPropString(ctxt->node, "type")) ||
+ (type = qemuMonitorCPUPropertyTypeFromString(str)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("missing 'value' attribute for a host CPU"
- " model property in QEMU capabilities cache"));
- goto cleanup;
- }
- if (STREQ(str, "true")) {
- hostCPU->props[i].supported = true;
- } else if (STREQ(str, "false")) {
- hostCPU->props[i].supported = false;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("invalid boolean value: '%s'"), str);
+ _("missing or invalid CPU model property type "
+ "in QEMU capabilities cache"));
goto cleanup;
}
VIR_FREE(str);
+
+ prop->type = type;
+ switch (prop->type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ if (virXPathBoolean("./@value='true'", ctxt))
+ prop->value.boolean = true;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ prop->value.string = virXMLPropString(ctxt->node, "value");
+ if (!prop->value.string) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid string value for '%s' host CPU "
+ "model property in QEMU capabilities cache"),
+ prop->name);
+ goto cleanup;
+ }
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+ if (virXPathLongLong("string(./@value)", ctxt,
+ &prop->value.number) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid number value for '%s' host CPU "
+ "model property in QEMU capabilities cache"),
+ prop->name);
+ goto cleanup;
+ }
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_LAST:
+ break;
+ }
}
}
@@ -3560,9 +3591,30 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
virBufferAdjustIndent(buf, 2);
for (i = 0; i < model->nprops; i++) {
- virBufferAsprintf(buf, "\n",
- model->props[i].name,
- model->props[i].supported ? "true" : "false");
+ qemuMonitorCPUPropertyPtr prop = model->props + i;
+
+ virBufferAsprintf(buf, "name,
+ qemuMonitorCPUPropertyTypeToString(prop->type));
+
+ switch (prop->type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ virBufferAsprintf(buf, "value='%s'",
+ prop->value.boolean ? "true" : "false");
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ virBufferEscapeString(buf, "value='%s'", prop->value.string);
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+ virBufferAsprintf(buf, "value='%lld'", prop->value.number);
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_LAST:
+ break;
+ }
+ virBufferAddLit(buf, "/>\n");
}
virBufferAdjustIndent(buf, -2);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b15207a693..4c3f7a20fe 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3661,8 +3661,11 @@ qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info)
if (!model_info)
return;
- for (i = 0; i < model_info->nprops; i++)
+ for (i = 0; i < model_info->nprops; i++) {
VIR_FREE(model_info->props[i].name);
+ if (model_info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_STRING)
+ VIR_FREE(model_info->props[i].value.string);
+ }
VIR_FREE(model_info->props);
VIR_FREE(model_info->name);
@@ -3691,7 +3694,25 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig)
if (VIR_STRDUP(copy->props[i].name, orig->props[i].name) < 0)
goto error;
- copy->props[i].supported = orig->props[i].supported;
+ copy->props[i].type = orig->props[i].type;
+ switch (orig->props[i].type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ copy->props[i].value.boolean = orig->props[i].value.boolean;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ if (VIR_STRDUP(copy->props[i].value.string,
+ orig->props[i].value.string) < 0)
+ goto error;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+ copy->props[i].value.number = orig->props[i].value.number;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_LAST:
+ break;
+ }
}
return copy;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 8811d85017..20d59b052d 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -921,16 +921,35 @@ int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
qemuMonitorCPUDefInfoPtr **cpus);
void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu);
+typedef enum {
+ QEMU_MONITOR_CPU_PROPERTY_BOOLEAN,
+ QEMU_MONITOR_CPU_PROPERTY_STRING,
+ QEMU_MONITOR_CPU_PROPERTY_NUMBER,
+
+ QEMU_MONITOR_CPU_PROPERTY_LAST
+} qemuMonitorCPUPropertyType;
+
+VIR_ENUM_DECL(qemuMonitorCPUProperty)
+
+typedef struct _qemuMonitorCPUProperty qemuMonitorCPUProperty;
+typedef qemuMonitorCPUProperty *qemuMonitorCPUPropertyPtr;
+struct _qemuMonitorCPUProperty {
+ char *name;
+ qemuMonitorCPUPropertyType type;
+ union {
+ bool boolean;
+ char *string;
+ long long number;
+ } value;
+};
+
typedef struct _qemuMonitorCPUModelInfo qemuMonitorCPUModelInfo;
typedef qemuMonitorCPUModelInfo *qemuMonitorCPUModelInfoPtr;
struct _qemuMonitorCPUModelInfo {
char *name;
size_t nprops;
- struct {
- char *name;
- bool supported;
- } *props;
+ qemuMonitorCPUPropertyPtr props;
};
int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 69fe340bed..e3bef3eb64 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4977,24 +4977,50 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
return ret;
}
+
+VIR_ENUM_IMPL(qemuMonitorCPUProperty,
+ QEMU_MONITOR_CPU_PROPERTY_LAST,
+ "boolean", "string", "number")
+
static int
qemuMonitorJSONParseCPUModelProperty(const char *key,
virJSONValue *value,
void *opaque)
{
qemuMonitorCPUModelInfoPtr machine_model = opaque;
- size_t n = machine_model->nprops;
- bool supported;
+ qemuMonitorCPUPropertyPtr prop;
- if (virJSONValueGetBoolean(value, &supported) < 0)
+ prop = machine_model->props + machine_model->nprops;
+
+ switch ((virJSONType) value->type) {
+ case VIR_JSON_TYPE_STRING:
+ if (VIR_STRDUP(prop->value.string, virJSONValueGetString(value)) < 0)
+ return -1;
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_STRING;
+ break;
+
+ case VIR_JSON_TYPE_NUMBER:
+ /* Ignore numbers which cannot be parsed as unsigned long long */
+ if (virJSONValueGetNumberLong(value, &prop->value.number) < 0)
+ return 0;
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_NUMBER;
+ break;
+
+ case VIR_JSON_TYPE_BOOLEAN:
+ virJSONValueGetBoolean(value, &prop->value.boolean);
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN;
+ break;
+
+ case VIR_JSON_TYPE_OBJECT:
+ case VIR_JSON_TYPE_ARRAY:
+ case VIR_JSON_TYPE_NULL:
return 0;
-
- if (VIR_STRDUP(machine_model->props[n].name, key) < 0)
- return -1;
-
- machine_model->props[n].supported = supported;
+ }
machine_model->nprops++;
+ if (VIR_STRDUP(prop->name, key) < 0)
+ return -1;
+
return 0;
}
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
index 64da511c78..3cce40c688 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -223,11 +223,13 @@
+
+
@@ -243,6 +245,7 @@
+
@@ -288,6 +291,7 @@
+
@@ -298,6 +302,7 @@
+
@@ -335,6 +340,7 @@
+
@@ -364,6 +370,7 @@
+