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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list