[libvirt] [PATCH v2 11/33] qemu: Store more types in qemuMonitorCPUModelInfo
John Ferlan
jferlan at redhat.com
Tue Feb 21 14:27:45 UTC 2017
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 at 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'/>
>
More information about the libvir-list
mailing list