[libvirt] [PATCH 4/5] qemu-caps: Get host model directly from Qemu when available

Jason J. Herne jjherne at linux.vnet.ibm.com
Wed Nov 2 20:34:34 UTC 2016


From: "Collin L. Walling" <walling at 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 at linux.vnet.ibm.com>
Signed-off-by: Jason J. Herne <jjherne at 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




More information about the libvir-list mailing list