[libvirt] [PATCH v3 8/8] qemu_driver: hook up query-cpu-model-comparison

Collin Walling walling at linux.ibm.com
Thu May 30 14:23:37 UTC 2019


This command is hooked into the virsh hypervisor-cpu-compare command.
As such, the CPU model XML provided to the command will be compared
to the hypervisor CPU contained in the QEMU capabilities file for the
appropriate QEMU binary (for s390x, this CPU definition can be observed
via virsh domcapabilities).

s390x can report that the first model (A) is a subset of the second
(B). If A is the hypervisor CPU and a subset of B (the CPU contained
in the XML), then B would not be able to run on this machine and thus
we will report that CPU model B is incompatible.

Signed-off-by: Collin Walling <walling at linux.ibm.com>
Reviewed-by: Daniel Henrique Barboza <danielh413 at gmail.com>
---
 src/qemu/qemu_capabilities.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_capabilities.h |  9 +++++++++
 src/qemu/qemu_driver.c       | 11 ++++++++++
 3 files changed, 68 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 8efc6d6..4970a1e 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -5534,3 +5534,51 @@ virQEMUCapsCPUModelBaseline(virQEMUCapsPtr qemuCaps,
     virCPUDefFree(cpu);
     return baseline;
 }
+
+virCPUCompareResult
+virQEMUCapsCPUModelComparison(virQEMUCapsPtr qemuCaps,
+                              const char *libDir,
+                              uid_t runUid,
+                              gid_t runGid,
+                              virCPUDefPtr cpu_a,
+                              virCPUDefPtr cpu_b,
+                              bool failIncompatible)
+{
+    qemuProcessQMPPtr proc = NULL;
+    qemuMonitorCPUModelInfoPtr result = NULL;
+    int ret = -1;
+
+    if (!(proc = qemuProcessQMPNew(qemuCaps->binary, libDir,
+                                   runUid, runGid, false)))
+        goto cleanup;
+
+    if (qemuProcessQMPStart(proc) < 0)
+        goto cleanup;
+
+    if (qemuMonitorGetCPUModelComparison(proc->mon, cpu_a->model,
+                                         cpu_a->nfeatures, cpu_a->features,
+                                         cpu_b->model, cpu_b->nfeatures,
+                                         cpu_b->features, &result) < 0)
+        goto cleanup;
+
+    if (STREQ(result->name, "incompatible") ||
+        STREQ(result->name, "subset"))
+        ret = VIR_CPU_COMPARE_INCOMPATIBLE;
+    else if (STREQ(result->name, "identical"))
+        ret = VIR_CPU_COMPARE_IDENTICAL;
+    else if (STREQ(result->name, "superset"))
+        ret = VIR_CPU_COMPARE_SUPERSET;
+
+    if (failIncompatible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) {
+        ret = VIR_CPU_COMPARE_ERROR;
+        virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL);
+    }
+
+ cleanup:
+    if (ret < 0)
+        virQEMUCapsLogProbeFailure(qemuCaps->binary);
+
+    qemuMonitorCPUModelInfoFree(result);
+    qemuProcessQMPFree(proc);
+    return ret;
+}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 47612e9..01aecc0 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -658,4 +658,13 @@ virCPUDefPtr virQEMUCapsCPUModelBaseline(virQEMUCapsPtr qemuCaps,
                                         int ncpus,
                                         virCPUDefPtr *cpus);
 
+virCPUCompareResult
+virQEMUCapsCPUModelComparison(virQEMUCapsPtr qemuCaps,
+                              const char *libDir,
+                              uid_t runUid,
+                              gid_t runGid,
+                              virCPUDefPtr cpu_a,
+                              virCPUDefPtr cpu_b,
+                              bool failIncompatible);
+
 #endif /* LIBVIRT_QEMU_CAPABILITIES_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9750962..a33648f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13466,9 +13466,11 @@ qemuConnectCompareHypervisorCPU(virConnectPtr conn,
 {
     int ret = VIR_CPU_COMPARE_ERROR;
     virQEMUDriverPtr driver = conn->privateData;
+    virQEMUDriverConfigPtr config = driver->config;
     virQEMUCapsPtr qemuCaps = NULL;
     bool failIncompatible;
     virCPUDefPtr hvCPU;
+    virCPUDefPtr cpu;
     virArch arch;
     virDomainVirtType virttype;
 
@@ -13503,6 +13505,14 @@ qemuConnectCompareHypervisorCPU(virConnectPtr conn,
 
     if (ARCH_IS_X86(arch)) {
         ret = virCPUCompareXML(arch, hvCPU, xmlCPU, failIncompatible);
+    } else if (ARCH_IS_S390(arch) &&
+               virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_COMPARISON)) {
+        if (virCPUDefParseXMLHelper(xmlCPU, NULL, VIR_CPU_TYPE_AUTO, &cpu) < 0)
+            goto cleanup;
+
+        ret = virQEMUCapsCPUModelComparison(qemuCaps, config->libDir,
+                                            config->user, config->group,
+                                            hvCPU, cpu, failIncompatible);
     } else {
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("comparing with the hypervisor CPU is not supported "
@@ -13510,6 +13520,7 @@ qemuConnectCompareHypervisorCPU(virConnectPtr conn,
     }
 
  cleanup:
+    virCPUDefFree(cpu);
     virObjectUnref(qemuCaps);
     return ret;
 }
-- 
2.7.4




More information about the libvir-list mailing list