While query-cpu-model-expansion returns only boolean features on s390,
but x86_64 reports some integer and string properties which we are
interested in.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
Notes:
Version 3:
- change the XML element to
<property name='...' type='boolean|string|number'
value='...'/>
Version 2:
- no change
src/qemu/qemu_capabilities.c | 100 +++++++++++++++++------
src/qemu/qemu_monitor.c | 25 +++++-
src/qemu/qemu_monitor.h | 27 +++++-
src/qemu/qemu_monitor_json.c | 42 ++++++++--
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 7 ++
5 files changed, 163 insertions(+), 38 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e037d5f95..0b611c323 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3076,14 +3076,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++;
}
@@ -3189,30 +3191,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 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 (virXPathULongLong("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;
+ }
}
}
@@ -3554,9 +3585,30 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
virBufferAdjustIndent(buf, 2);
for (i = 0; i < model->nprops; i++) {
- virBufferAsprintf(buf, "<property name='%s'
type='boolean' value='%s'/>\n",
- model->props[i].name,
- model->props[i].supported ? "true" :
"false");
+ qemuMonitorCPUPropertyPtr prop = model->props + i;
+
+ virBufferAsprintf(buf, "<property name='%s' type='%s'
",
+ prop->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='%llu'",
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 b15207a69..4c3f7a20f 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 8811d8501..ff8731bdd 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;
+ unsigned 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 7aa9e314c..b6a4824d6 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 (virJSONValueGetNumberUlong(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 73d1e59c8..805fee78b 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -224,11 +224,13 @@
<property name='avx512cd' type='boolean'
value='false'/>
<property name='decodeassists' type='boolean'
value='false'/>
<property name='sse4.1' type='boolean' value='true'/>
+ <property name='family' type='number' value='6'/>
<property name='avx512f' type='boolean'
value='false'/>
<property name='msr' type='boolean' value='true'/>
<property name='mce' type='boolean' value='true'/>
<property name='mca' type='boolean' value='true'/>
<property name='xcrypt' type='boolean' value='false'/>
+ <property name='min-level' type='number' value='13'/>
<property name='xgetbv1' type='boolean' value='true'/>
<property name='cid' type='boolean' value='false'/>
<property name='ds' type='boolean' value='false'/>
@@ -244,6 +246,7 @@
<property name='xcrypt-en' type='boolean'
value='false'/>
<property name='pn' type='boolean' value='false'/>
<property name='dca' type='boolean' value='false'/>
+ <property name='vendor' type='string'
value='GenuineIntel'/>
<property name='pku' type='boolean' value='false'/>
<property name='smx' type='boolean' value='false'/>
<property name='cmp-legacy' type='boolean'
value='false'/>
@@ -289,6 +292,7 @@
<property name='sse4.2' type='boolean' value='true'/>
<property name='pge' type='boolean' value='true'/>
<property name='pdcm' type='boolean' value='false'/>
+ <property name='model' type='number' value='94'/>
<property name='movbe' type='boolean' value='true'/>
<property name='nrip-save' type='boolean'
value='false'/>
<property name='ssse3' type='boolean' value='true'/>
@@ -299,6 +303,7 @@
<property name='fma' type='boolean' value='true'/>
<property name='cx16' type='boolean' value='true'/>
<property name='de' type='boolean' value='true'/>
+ <property name='stepping' type='number' value='3'/>
<property name='xsave' type='boolean' value='true'/>
<property name='clflush' type='boolean' value='true'/>
<property name='skinit' type='boolean' value='false'/>
@@ -336,6 +341,7 @@
<property name='sep' type='boolean' value='true'/>
<property name='nodeid-msr' type='boolean'
value='false'/>
<property name='misalignsse' type='boolean'
value='false'/>
+ <property name='min-xlevel' type='number'
value='2147483656'/>
<property name='bmi1' type='boolean' value='true'/>
<property name='bmi2' type='boolean' value='true'/>
<property name='kvm-pv-unhalt' type='boolean'
value='true'/>
@@ -365,6 +371,7 @@
<property name='pse36' type='boolean' value='true'/>
<property name='tbm' type='boolean' value='false'/>
<property name='wdt' type='boolean' value='false'/>
+ <property name='model-id' type='string' value='Intel(R)
Xeon(R) CPU E3-1245 v5 @ 3.50GHz'/>
<property name='sha-ni' type='boolean' value='false'/>
<property name='abm' type='boolean' value='true'/>
<property name='avx512pf' type='boolean'
value='false'/>
--
2.11.1