From: "Collin L. Walling" <walling(a)linux.vnet.ibm.com>
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>
---
src/qemu/qemu_capabilities.c | 88 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 87 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 7a8202a..4a6ae07 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -389,6 +389,8 @@ struct _virQEMUCaps {
size_t ngicCapabilities;
virGICCapability *gicCapabilities;
+ virCPUDefPtr hostCPUModelFromQemu;
+
/* 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.
@@ -2118,6 +2120,10 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
!(ret->hostCPUModel = virCPUDefCopy(qemuCaps->hostCPUModel)))
goto error;
+ if (qemuCaps->hostCPUModelFromQemu &&
+ !(ret->hostCPUModelFromQemu =
virCPUDefCopy(qemuCaps->hostCPUModelFromQemu)))
+ goto error;
+
if (VIR_ALLOC_N(ret->machineTypes, qemuCaps->nmachineTypes) < 0)
goto error;
ret->nmachineTypes = qemuCaps->nmachineTypes;
@@ -2728,6 +2734,51 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
return ret;
}
+static int
+virQEMUCapsProbeQMPCPUModelExpansion(virQEMUCapsPtr qemuCaps,
+ qemuMonitorPtr mon)
+{
+ qemuMonitorCPUModelInfoPtr model_info;
+ virCPUDefPtr hostcpumodel;
+ int nfeatures;
+ int ret = -1;
+ size_t i;
+
+ if (qemuMonitorGetCPUModelExpansion(mon, "static", "host",
&model_info) < 0)
+ goto cleanup;
+
+ if (model_info == NULL) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC(hostcpumodel) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(hostcpumodel->model, model_info->name) < 0)
+ goto cleanup;
+
+ nfeatures = hostcpumodel->nfeatures = model_info->nprops;
+
+ if (VIR_ALLOC_N(hostcpumodel->features, nfeatures) < 0)
+ goto cleanup;
+
+ for (i = 0; i < nfeatures; i++) {
+ if (VIR_STRDUP(hostcpumodel->features[i].name, model_info->props[i].name)
< 0)
+ goto cleanup;
+
+ hostcpumodel->features[i].policy = -1;
+ }
+
+ hostcpumodel->arch = qemuCaps->arch;
+ qemuCaps->hostCPUModelFromQemu = virCPUDefCopy(hostcpumodel);
+ ret = 0;
+
+ cleanup:
+ virCPUDefFree(hostcpumodel);
+ return ret;
+}
+
struct tpmTypeToCaps {
int type;
virQEMUCapsFlags caps;
@@ -2958,6 +3009,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
virCapsPtr caps)
{
virCPUDefPtr cpu = NULL;
+ virCPUDefPtr src = NULL;
if (!caps)
return;
@@ -2974,7 +3026,10 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
cpu->mode = VIR_CPU_MODE_CUSTOM;
cpu->match = VIR_CPU_MATCH_EXACT;
- if (virCPUDefCopyModelFilter(cpu, caps->host.cpu, true,
+ if (!(src = qemuCaps->hostCPUModelFromQemu))
+ src = caps->host.cpu;
+
+ if (virCPUDefCopyModelFilter(cpu, src, true,
virQEMUCapsCPUFilterFeatures, NULL) < 0)
goto error;
}
@@ -3118,6 +3173,21 @@ virQEMUCapsLoadCache(virCapsPtr caps,
}
VIR_FREE(str);
+ xmlNodePtr node;
+ if ((node = virXPathNode("./host/cpu[1]", ctxt))) {
+ xmlNodePtr oldNode = ctxt->node;
+ ctxt->node = node;
+ if (!(qemuCaps->hostCPUModelFromQemu = virCPUDefParseXML(node,
+ ctxt,
+ VIR_CPU_TYPE_HOST))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing host cpu data in QEMU capabilities
cache"));
+ goto cleanup;
+ }
+ ctxt->node = oldNode;
+ node = NULL;
+ }
+
if ((n = virXPathNodeSet("./cpu", ctxt, &nodes)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to parse qemu capabilities cpus"));
@@ -3298,6 +3368,20 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps,
virBufferAsprintf(&buf, "<arch>%s</arch>\n",
virArchToString(qemuCaps->arch));
+ if (qemuCaps->hostCPUModelFromQemu) {
+ virBufferAddLit(&buf, "<host>\n");
+ virBufferAdjustIndent(&buf, 2);
+ virBufferAddLit(&buf, "<cpu>\n");
+ virBufferAdjustIndent(&buf, 2);
+ virBufferEscapeString(&buf, "<arch>%s</arch>\n",
+
virArchToString(qemuCaps->hostCPUModelFromQemu->arch));
+ virCPUDefFormatBuf(&buf, qemuCaps->hostCPUModelFromQemu, true);
+ virBufferAdjustIndent(&buf, -2);
+ virBufferAddLit(&buf, "</cpu>\n");
+ virBufferAdjustIndent(&buf, -2);
+ virBufferAddLit(&buf, "</host>\n");
+ }
+
if (qemuCaps->cpuDefinitions) {
for (i = 0; i < qemuCaps->cpuDefinitions->nmodels; i++) {
virDomainCapsCPUModelPtr cpu = qemuCaps->cpuDefinitions->models + i;
@@ -3790,6 +3874,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
goto cleanup;
if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, mon) < 0)
goto cleanup;
+ if (virQEMUCapsProbeQMPCPUModelExpansion(qemuCaps, mon) < 0)
+ goto cleanup;
if (virQEMUCapsProbeQMPKVMState(qemuCaps, mon) < 0)
goto cleanup;
if (virQEMUCapsProbeQMPTPM(qemuCaps, mon) < 0)
--
1.9.1