On 02/15/2017 11:44 AM, Jiri Denemark wrote:
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 2:
- no change
src/qemu/qemu_capabilities.c | 84 ++++++++++++++++--------
src/qemu/qemu_monitor.c | 22 ++++++-
src/qemu/qemu_monitor.h | 23 +++++--
src/qemu/qemu_monitor_json.c | 37 ++++++++---
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 7 ++
5 files changed, 133 insertions(+), 40 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index aab336954..466852d13 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3074,14 +3074,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;
So s390 only supports "boolean" or "default" types?
+
+ 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++;
}
@@ -3154,7 +3156,6 @@ static int
virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
xmlXPathContextPtr ctxt)
{
- char *str = NULL;
xmlNodePtr hostCPUNode;
xmlNodePtr *featureNodes = NULL;
xmlNodePtr oldnode = ctxt->node;
@@ -3187,30 +3188,47 @@ virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
hostCPU->nprops = n;
for (i = 0; i < n; i++) {
- hostCPU->props[i].name = virXMLPropString(featureNodes[i],
"name");
- if (!hostCPU->props[i].name) {
+ qemuMonitorCPUPropertyPtr prop = hostCPU->props + i;
+ ctxt->node = featureNodes[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 you follow the suggestion I have in the previous patch, then if you
don't find the property named "type", then you know the 'value' is
either "yes" or "no"
If there is a type then the "value" property is either "string" or
"number"
- if (!(str = virXMLPropString(featureNodes[i], "boolean"))) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("missing 'boolean' attribute for a host
CPU"
- " model property in QEMU capabilities
cache"));
- goto cleanup;
- }
- if (STREQ(str, "yes")) {
- hostCPU->props[i].supported = true;
- } else if (STREQ(str, "no")) {
- hostCPU->props[i].supported = false;
+ if (virXPathBoolean("boolean(./@boolean)", ctxt)) {
+ if (virXPathBoolean("./@boolean='yes'", ctxt))
+ prop->value.boolean = true;
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN;
+ } else if (virXPathBoolean("boolean(./@string)", ctxt)) {
+ prop->value.string = virXMLPropString(ctxt->node,
"string");
+ 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;
+ }
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_STRING;
+ } else if (virXPathBoolean("boolean(./@ull)", ctxt)) {
ull is just an implementation detail. I think it should be number
+ if (virXPathULongLong("string(./@ull)",
ctxt,
+ &prop->value.ull) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid integer value for '%s' host
CPU "
in this context 'integer' isn't necessarily correct since the desire is
an unsigned long long
+ "model property in QEMU
capabilities cache"),
+ prop->name);
+ goto cleanup;
+ }
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_ULL;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("invalid boolean value: '%s'"),
str);
+ _("missing value for '%s' host CPU model
"
+ "property in QEMU capabilities cache"),
+ prop->name);
One would think that if you use 'type=%s', then this would be simplified
to be if the "value" property doesn't exist, then you have a failure.
What that value property eventually gets "read" as matters only for what
the 'type' is (or the default of boolean)
goto cleanup;
}
- VIR_FREE(str);
}
}
@@ -3220,7 +3238,6 @@ virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
cleanup:
ctxt->node = oldnode;
- VIR_FREE(str);
VIR_FREE(featureNodes);
qemuMonitorCPUModelInfoFree(hostCPU);
return ret;
@@ -3552,9 +3569,24 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
virBufferAdjustIndent(buf, 2);
for (i = 0; i < model->nprops; i++) {
- virBufferAsprintf(buf, "<property name='%s'
boolean='%s'/>\n",
- model->props[i].name,
- model->props[i].supported ? "yes" :
"no");
+ qemuMonitorCPUPropertyPtr prop = model->props + i;
+
+ switch (prop->type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ virBufferAsprintf(buf, "<property name='%s'
boolean='%s'/>\n",
+ prop->name, prop->value.boolean ? "yes" :
"no");
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ virBufferAsprintf(buf, "<property name='%s' ",
prop->name);
+ virBufferEscapeString(buf, "string='%s'/>\n",
prop->value.string);
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_ULL:
+ virBufferAsprintf(buf, "<property name='%s'
ull='%llu'/>\n",
+ prop->name, prop->value.ull);
+ break;
+ }
obviously easy adjustments here especially if there's a VIR_ENUM_IMPL
for qemuMonitorCPUPropertyType that only writes out the "type" if
'string' or 'number'
}
virBufferAdjustIndent(buf, -2);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b15207a69..a434b234b 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,22 @@ 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_ULL:
+ copy->props[i].value.ull = orig->props[i].value.ull;
+ break;
+ }
}
return copy;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 8811d8501..112f041f1 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -921,16 +921,31 @@ int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
qemuMonitorCPUDefInfoPtr **cpus);
void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu);
+typedef enum {
+ QEMU_MONITOR_CPU_PROPERTY_BOOLEAN,
As stated in previous patch, I think should should be "DEFAULT"
+ QEMU_MONITOR_CPU_PROPERTY_STRING,
+ QEMU_MONITOR_CPU_PROPERTY_ULL,
likewise, "NUMBER" not "ULL"
John
+} qemuMonitorCPUPropertyType;
+
+typedef struct _qemuMonitorCPUProperty qemuMonitorCPUProperty;
+typedef qemuMonitorCPUProperty *qemuMonitorCPUPropertyPtr;
+struct _qemuMonitorCPUProperty {
+ char *name;
+ qemuMonitorCPUPropertyType type;
+ union {
+ bool boolean;
+ char *string;
+ unsigned long long ull;
+ } 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 1d281af48..415761525 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4983,18 +4983,39 @@ qemuMonitorJSONParseCPUModelProperty(const char *key,
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.ull) < 0)
+ return 0;
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_ULL;
+ 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 c13e8318f..32368e648 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -222,11 +222,13 @@
<property name='avx512cd' boolean='no'/>
<property name='decodeassists' boolean='no'/>
<property name='sse4.1' boolean='yes'/>
+ <property name='family' ull='6'/>
<property name='avx512f' boolean='no'/>
<property name='msr' boolean='yes'/>
<property name='mce' boolean='yes'/>
<property name='mca' boolean='yes'/>
<property name='xcrypt' boolean='no'/>
+ <property name='min-level' ull='13'/>
<property name='xgetbv1' boolean='yes'/>
<property name='cid' boolean='no'/>
<property name='ds' boolean='no'/>
@@ -242,6 +244,7 @@
<property name='xcrypt-en' boolean='no'/>
<property name='pn' boolean='no'/>
<property name='dca' boolean='no'/>
+ <property name='vendor' string='GenuineIntel'/>
<property name='pku' boolean='no'/>
<property name='smx' boolean='no'/>
<property name='cmp-legacy' boolean='no'/>
@@ -287,6 +290,7 @@
<property name='sse4.2' boolean='yes'/>
<property name='pge' boolean='yes'/>
<property name='pdcm' boolean='no'/>
+ <property name='model' ull='94'/>
<property name='movbe' boolean='yes'/>
<property name='nrip-save' boolean='no'/>
<property name='ssse3' boolean='yes'/>
@@ -297,6 +301,7 @@
<property name='fma' boolean='yes'/>
<property name='cx16' boolean='yes'/>
<property name='de' boolean='yes'/>
+ <property name='stepping' ull='3'/>
<property name='xsave' boolean='yes'/>
<property name='clflush' boolean='yes'/>
<property name='skinit' boolean='no'/>
@@ -334,6 +339,7 @@
<property name='sep' boolean='yes'/>
<property name='nodeid-msr' boolean='no'/>
<property name='misalignsse' boolean='no'/>
+ <property name='min-xlevel' ull='2147483656'/>
<property name='bmi1' boolean='yes'/>
<property name='bmi2' boolean='yes'/>
<property name='kvm-pv-unhalt' boolean='yes'/>
@@ -363,6 +369,7 @@
<property name='pse36' boolean='yes'/>
<property name='tbm' boolean='no'/>
<property name='wdt' boolean='no'/>
+ <property name='model-id' string='Intel(R) Xeon(R) CPU E3-1245 v5 @
3.50GHz'/>
<property name='sha-ni' boolean='no'/>
<property name='abm' boolean='yes'/>
<property name='avx512pf' boolean='no'/>