When qmp query-cpu-model-expansion is available probe Qemu for its view of the
host model. In kvm environments this can provide a more complete view of the
host model because features supported by Qemu and Kvm can be considered.
Signed-off-by: Collin L. Walling <walling(a)linux.vnet.ibm.com>
Signed-off-by: Jason J. Herne <jjherne(a)linux.vnet.ibm.com>
# Conflicts:
# tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies
Signed-off-by: Jason J. Herne <jjherne(a)linux.vnet.ibm.com>
---
src/qemu/qemu_capabilities.c | 185 ++++++++++++++++++++-
tests/domaincapsschemadata/qemu_2.7.0.s390x.xml | 4 +-
tests/domaincapsschemadata/qemu_2.8.0.s390x.xml | 17 +-
.../qemucapabilitiesdata/caps_2.8.0.s390x.replies | 26 +++
tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml | 17 ++
5 files changed, 239 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index bff30ed..7d33b19 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -399,6 +399,8 @@ struct _virQEMUCaps {
size_t ngicCapabilities;
virGICCapability *gicCapabilities;
+ qemuMonitorCPUModelInfoPtr hostCPUModelInfo;
+
/* Anything below is not stored in the cache since the values are
* re-computed from the other fields or external data sources every
* time we probe QEMU or load the results from the cache.
@@ -2163,6 +2165,10 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
!(ret->hostCPUModel = virCPUDefCopy(qemuCaps->hostCPUModel)))
goto error;
+ if (qemuCaps->hostCPUModelInfo &&
+ !(ret->hostCPUModelInfo =
qemuMonitorCPUModelInfoCopy(qemuCaps->hostCPUModelInfo)))
+ goto error;
+
if (VIR_ALLOC_N(ret->machineTypes, qemuCaps->nmachineTypes) < 0)
goto error;
ret->nmachineTypes = qemuCaps->nmachineTypes;
@@ -2811,6 +2817,18 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
return ret;
}
+static int
+virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
+ qemuMonitorPtr mon)
+{
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION) ||
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
+ return 0;
+
+ return qemuMonitorGetCPUModelExpansion(mon, "static", "host",
+ &qemuCaps->hostCPUModelInfo);
+}
+
struct tpmTypeToCaps {
int type;
virQEMUCapsFlags caps;
@@ -3020,18 +3038,62 @@ virQEMUCapsCPUFilterFeatures(const char *name,
}
-void
-virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
- virCapsPtr caps)
+static void
+virQEMUCapsCopyCPUModelFromQEMU(virQEMUCapsPtr qemuCaps)
{
virCPUDefPtr cpu = NULL;
+ qemuMonitorCPUModelInfoPtr modelInfo = NULL;
+ size_t i;
- if (!caps)
- return;
+ if (!(modelInfo = qemuCaps->hostCPUModelInfo)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("missing host CPU model info from QEMU capabilities"
+ " for binary %s"), qemuCaps->binary);
+ goto error;
+ }
- if (!virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
+ if (VIR_ALLOC(cpu) < 0)
goto error;
+ if (VIR_STRDUP(cpu->model, modelInfo->name) < 0 ||
+ VIR_ALLOC_N(cpu->features, modelInfo->nprops) < 0)
+ goto error;
+
+ cpu->nfeatures_max = modelInfo->nprops;
+ cpu->nfeatures = 0;
+ cpu->sockets = cpu->cores = cpu->threads = 0;
+ cpu->type = VIR_CPU_TYPE_GUEST;
+ cpu->mode = VIR_CPU_MODE_CUSTOM;
+ cpu->match = VIR_CPU_MATCH_EXACT;
+
+ for (i = 0; i < modelInfo->nprops; i++) {
+ if (VIR_STRDUP(cpu->features[i].name, modelInfo->props[i].name) < 0)
+ goto error;
+
+ if (modelInfo->props[i].supported)
+ cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
+ else
+ cpu->features[i].policy = VIR_CPU_FEATURE_DISABLE;
+
+ cpu->nfeatures++;
+ }
+
+ qemuCaps->hostCPUModel = cpu;
+ return;
+
+ error:
+ virCPUDefFree(cpu);
+ qemuCaps->hostCPUModel = NULL;
+ virResetLastError();
+}
+
+
+static void
+virQEMUCapsCopyCPUModelFromHost(virQEMUCapsPtr qemuCaps,
+ virCapsPtr caps)
+{
+ virCPUDefPtr cpu = NULL;
+
if (caps->host.cpu && caps->host.cpu->model) {
if (VIR_ALLOC(cpu) < 0)
goto error;
@@ -3055,6 +3117,98 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
virResetLastError();
}
+void
+virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
+ virCapsPtr caps)
+{
+ if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
+ return;
+
+ switch (qemuCaps->arch) {
+ case VIR_ARCH_S390:
+ case VIR_ARCH_S390X:
+ virQEMUCapsCopyCPUModelFromQEMU(qemuCaps);
+ break;
+ default: virQEMUCapsCopyCPUModelFromHost(qemuCaps, caps);
+ }
+}
+
+
+static int
+virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
+ xmlXPathContextPtr ctxt)
+{
+ char *str = NULL;
+ xmlNodePtr hostCPUNode;
+ xmlNodePtr *featureNodes = NULL;
+ xmlNodePtr oldnode = ctxt->node;
+ qemuMonitorCPUModelInfoPtr hostCPU = NULL;
+ int ret = -1;
+ size_t i;
+ int n;
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ if (!(hostCPUNode = virXPathNode("./hostCPU", ctxt)) ||
+ VIR_ALLOC(hostCPU) < 0)
+ goto cleanup;
+
+ if ((str = virXMLPropString(hostCPUNode, "model"))) {
+ if (VIR_STRDUP(hostCPU->name, str) < 0)
+ goto cleanup;
+ }
+
+ ctxt->node = hostCPUNode;
+
+ if ((n = virXPathNodeSet("./feature", ctxt, &featureNodes)) > 0) {
+ if (VIR_ALLOC_N(hostCPU->props, n) < 0)
+ goto cleanup;
+
+ hostCPU->nprops = n;
+
+ for (i = 0; i < n; i++) {
+ if (!(str = virXMLPropString(featureNodes[i], "name"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing 'name' element for a host CPU
model"
+ " feature in QEMU capabilities cache"));
+ goto cleanup;
+ }
+ if (VIR_STRDUP(hostCPU->props[i].name, str) < 0)
+ goto cleanup;
+ if (!(str = virXMLPropString(featureNodes[i], "supported"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing 'supported' element for a host
CPU"
+ " model feature 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;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed supported value: expected
'yes'"
+ " or 'no'"));
+ goto cleanup;
+ }
+ }
+ }
+
+ qemuCaps->hostCPUModelInfo = hostCPU;
+ hostCPU = NULL;
+ ret = 0;
+
+ cleanup:
+ ctxt->node = oldnode;
+ VIR_FREE(str);
+ VIR_FREE(featureNodes);
+ qemuMonitorCPUModelInfoFree(hostCPU);
+ return ret;
+}
+
static int
virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps,
@@ -3250,6 +3404,9 @@ virQEMUCapsLoadCache(virCapsPtr caps,
}
VIR_FREE(str);
+ if (virQEMUCapsLoadHostCPUModelInfo(qemuCaps, ctxt) < 0)
+ goto cleanup;
+
if (virQEMUCapsLoadCPUModels(qemuCaps, ctxt, VIR_DOMAIN_VIRT_KVM) < 0 ||
virQEMUCapsLoadCPUModels(qemuCaps, ctxt, VIR_DOMAIN_VIRT_QEMU) < 0)
goto cleanup;
@@ -3443,6 +3600,20 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps,
virBufferAsprintf(&buf, "<arch>%s</arch>\n",
virArchToString(qemuCaps->arch));
+ if (qemuCaps->hostCPUModelInfo) {
+ virBufferAsprintf(&buf, "<hostCPU model='%s'>\n",
+ qemuCaps->hostCPUModelInfo->name);
+ virBufferAdjustIndent(&buf, 2);
+ for (i = 0; i < qemuCaps->hostCPUModelInfo->nprops; i++) {
+ virBufferAsprintf(&buf, "<feature name='%s'
supported='%s'/>\n",
+ qemuCaps->hostCPUModelInfo->props[i].name,
+ qemuCaps->hostCPUModelInfo->props[i].supported ?
+ "yes" : "no");
+ }
+ virBufferAdjustIndent(&buf, -2);
+ virBufferAddLit(&buf, "</hostCPU>\n");
+ }
+
virQEMUCapsFormatCPUModels(qemuCaps, &buf, VIR_DOMAIN_VIRT_KVM);
virQEMUCapsFormatCPUModels(qemuCaps, &buf, VIR_DOMAIN_VIRT_QEMU);
@@ -4135,6 +4306,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_QMP_SCHEMA) &&
virQEMUCapsProbeQMPSchemaCapabilities(qemuCaps, mon) < 0)
goto cleanup;
+ if (virQEMUCapsProbeQMPHostCPU(qemuCaps, mon) < 0)
+ goto cleanup;
/* 'intel-iommu' shows up as a device since 2.2.0, but can
* not be used with -device until 2.7.0. Before that it
diff --git a/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml
b/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml
index 9f181d3..999e279 100644
--- a/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml
+++ b/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml
@@ -20,9 +20,7 @@
</os>
<cpu>
<mode name='host-passthrough' supported='yes'/>
- <mode name='host-model' supported='yes'>
- <model fallback='allow'></model>
- </mode>
+ <mode name='host-model' supported='no'/>
<mode name='custom' supported='no'/>
</cpu>
<devices>
diff --git a/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml
b/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml
index 0b792b2..efe3459 100644
--- a/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml
+++ b/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml
@@ -21,7 +21,22 @@
<cpu>
<mode name='host-passthrough' supported='yes'/>
<mode name='host-model' supported='yes'>
- <model fallback='allow'></model>
+ <model fallback='allow'>zEC12.2-base</model>
+ <feature policy='require' name='aefsi'/>
+ <feature policy='require' name='msa5'/>
+ <feature policy='require' name='msa4'/>
+ <feature policy='require' name='msa3'/>
+ <feature policy='require' name='msa2'/>
+ <feature policy='require' name='msa1'/>
+ <feature policy='require' name='sthyi'/>
+ <feature policy='require' name='edat'/>
+ <feature policy='require' name='ri'/>
+ <feature policy='require' name='edat2'/>
+ <feature policy='require' name='ipter'/>
+ <feature policy='require' name='esop'/>
+ <feature policy='require' name='cte'/>
+ <feature policy='require' name='te'/>
+ <feature policy='require' name='cmm'/>
</mode>
<mode name='custom' supported='yes'>
<model usable='unknown'>z10EC-base</model>
diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies
b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies
index 3ccad4f..0405d5d 100644
--- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies
+++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies
@@ -13023,6 +13023,32 @@
{
"return": {
+ "model": {
+ "name": "zEC12.2-base",
+ "props": {
+ "aefsi": true,
+ "msa5": true,
+ "msa4": true,
+ "msa3": true,
+ "msa2": true,
+ "msa1": true,
+ "sthyi": true,
+ "edat": true,
+ "ri": true,
+ "edat2": true,
+ "ipter": true,
+ "esop": true,
+ "cte": true,
+ "te": true,
+ "cmm": true
+ }
+ }
+ },
+ "id": "libvirt-48"
+}
+
+{
+ "return": {
},
"id": "libvirt-1"
}
diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
index 1b955cf..c4c9bf9 100644
--- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
@@ -133,6 +133,23 @@
<kvmVersion>0</kvmVersion>
<package></package>
<arch>s390x</arch>
+ <hostCPU model='zEC12.2-base'>
+ <feature name='aefsi' supported='yes'/>
+ <feature name='msa5' supported='yes'/>
+ <feature name='msa4' supported='yes'/>
+ <feature name='msa3' supported='yes'/>
+ <feature name='msa2' supported='yes'/>
+ <feature name='msa1' supported='yes'/>
+ <feature name='sthyi' supported='yes'/>
+ <feature name='edat' supported='yes'/>
+ <feature name='ri' supported='yes'/>
+ <feature name='edat2' supported='yes'/>
+ <feature name='ipter' supported='yes'/>
+ <feature name='esop' supported='yes'/>
+ <feature name='cte' supported='yes'/>
+ <feature name='te' supported='yes'/>
+ <feature name='cmm' supported='yes'/>
+ </hostCPU>
<cpu type='kvm' name='z10EC-base'/>
<cpu type='kvm' name='z9EC-base'/>
<cpu type='kvm' name='z196.2-base'/>
--
2.7.4