[libvirt] [PATCHv1 4/7] qemu_capabilities: Baseline CPUModel via QEMU

Chris Venteicher cventeic at redhat.com
Sat May 5 17:48:46 UTC 2018


Spinup QEMU instance and complete QMP query-cpu-model-baseline exchanges
to determine CPUModel Baseline.

query-cpu-model-baseline only compares two CPUModels so multiple
exchanges are needed to evaluate more than two CPUModels.
---
 src/qemu/qemu_capabilities.c | 132 +++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_capabilities.h |   9 +++
 2 files changed, 141 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 097985cbe7..9ffbf91a90 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -5122,3 +5122,135 @@ virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
 {
     qemuCaps->microcodeVersion = microcodeVersion;
 }
+
+
+/* in:
+ * <host>
+ *   <cpu>
+ *     <arch>s390x</arch>
+ *     <model>z13-base</model>
+ *     <feature name='xxx'/>
+ *     ...
+ *     <feature name='yyy'/>
+ *   </cpu>
+ *   <cpu>
+ *     <arch>s390x</arch>
+ *     <model>z114-base</model>
+ *     <feature name='xxx'/>
+ *     ...
+ *     <feature name='yyy'/>
+ *   </cpu>
+ * </host>
+ *
+ * out:
+ * <cpu match='exact'>
+ *  <model>z13-base</model>
+ *  <feature policy='require' name='xxx'/>
+ *  <feature policy='require' name='yyy'/>
+ * </cpu>
+ *
+ * (ret==0) && (baseline.len == 0) if baseline not supported by QEMU
+ */
+int
+virQEMUCapsQMPBaselineCPUModel(char *exec,
+                               const char *libDir,
+                               uid_t runUid,
+                               gid_t runGid,
+                               const char **xmlCPUs,
+                               unsigned int ncpus,
+                               bool migratable,
+                               virBufferPtr baseline)
+{
+    qemuMonitorCPUModelInfoPtr  model_baseline = NULL;
+    qemuMonitorCPUModelInfoPtr  new_model_baseline = NULL;
+    qemuMonitorCPUModelInfoPtr  model_b = NULL;
+    virQEMUCapsInitQMPCommandPtr cmd = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    bool forceTCG = false;
+    int ret = -1;
+    size_t i;
+
+    VIR_DEBUG("ncpus=%i, migratable=%i", ncpus, migratable);
+
+    if (!(cmd = virQEMUCapsSpinUpQemu(exec, libDir, runUid, runGid, forceTCG)))
+        goto cleanup;
+
+    if (!(cmd->mon)) {
+        /* Not connected to QEMU (monitor) */
+        VIR_DEBUG("QEMU failed to initialize error=%s", virGetLastErrorMessage());
+        goto cleanup;
+    }
+
+    /* QEMU requires qmp_capabilities exchange first */
+    if (qemuMonitorSetCapabilities(cmd->mon) < 0) {
+        VIR_DEBUG("Failed to set monitor capabilities %s",
+                  virGetLastErrorMessage());
+        goto cleanup;
+    }
+
+    if (!xmlCPUs && ncpus != 0) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("nonzero ncpus doesn't match with NULL xmlCPUs"));
+        goto cleanup;
+    }
+
+    if (ncpus < 2) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s", _("baseline < 2 CPUs "));
+        goto cleanup;
+    }
+
+    if (virQEMUCapsLoadCPUModelInfoFromXMLString(xmlCPUs[0], "//cpu",
+                                                 &model_baseline) < 0)
+        goto cleanup;
+
+    VIR_DEBUG("xmlCPUs[0] = %s", xmlCPUs[0]);
+
+    for (i = 1; i < ncpus; i++) {
+
+        VIR_DEBUG("xmlCPUs[%lu] = %s", i, xmlCPUs[i]);
+
+        if (virQEMUCapsLoadCPUModelInfoFromXMLString(xmlCPUs[i], "//cpu", &model_b) < 0)
+            goto cleanup;
+
+        if (!model_baseline || !model_b) {
+            virReportError(VIR_ERR_INVALID_ARG, "%s", _("xmlCPU without content"));
+            goto cleanup;
+        }
+
+        if (qemuMonitorGetCPUModelBaseline(cmd->mon, model_baseline,
+                                           model_b, &new_model_baseline) < 0)
+            goto cleanup;
+
+        if (!new_model_baseline) {
+            VIR_DEBUG("QEMU didn't support baseline");
+            ret = 0;
+            goto cleanup;
+        }
+
+        qemuMonitorCPUModelInfoFree(model_baseline);
+        qemuMonitorCPUModelInfoFree(model_b);
+
+        model_b = NULL;
+
+        model_baseline = new_model_baseline;
+    }
+
+    VIR_DEBUG("model_baseline->name = %s", NULLSTR(model_baseline->name));
+
+    virQEMUCapsCPUModelInfoToXML(model_baseline, &buf);
+
+    if (virBufferUse(&buf))
+        virBufferAddBuffer(baseline, &buf);
+
+    ret = 0;
+
+ cleanup:
+    virQEMUCapsInitQMPCommandFree(cmd);
+
+    qemuMonitorCPUModelInfoFree(model_baseline);
+    qemuMonitorCPUModelInfoFree(model_b);
+
+    VIR_DEBUG("baseline = %s", virBufferCurrentContent(baseline));
+
+    return ret;
+}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 8da18a8063..2d3e8ce2ad 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -536,6 +536,15 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps,
 void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps,
                                     const char *machineType);
 
+int virQEMUCapsQMPBaselineCPUModel(char *exec,
+                                 const char *libDir,
+                                 uid_t runUid,
+                                 gid_t runGid,
+                                 const char **xmlCPUs,
+                                 unsigned int ncpus,
+                                 bool migratable,
+                                 virBufferPtr baseline);
+
 virFileCachePtr virQEMUCapsCacheNew(const char *libDir,
                                     const char *cacheDir,
                                     uid_t uid,
-- 
2.14.1




More information about the libvir-list mailing list