Add capability to calculate hypervisor baseline using QMP message
exchanges with QEMU in addition to existing capability to calculate
baseline using libvirt utility functions.
A new utility function encapsulates the core logic for interacting with QEMU
using QMP baseline messages. The QMP messages only allow two cpu models
to be evaluated at a time so a sequence of QMP baseline messages must be
used to include all the models in the baseline when more than 2 cpu
models are input.
A QEMU process must be started prior to sending the series of QEMU
messages to compute baseline.
The QEMU process is started and maintained in the main hypervisor
baseline function and only a pointer to the QEMU process monitor is
passed to the baseline utility function.
The QEMU process is maintained in the main hypervisor baseline function
because the process will also be used for feature expansion (via QEMU)
in a later patch.
Signed-off-by: Chris Venteicher <cventeic(a)redhat.com>
---
src/qemu/qemu_driver.c | 97 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4e8a3902d3..8c6838f584 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13642,6 +13642,78 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
}
+/* in:
+ * cpus[0]->model = "z14";
+ * cpus[0]->features[0].name = "xxx";
+ * cpus[0]->features[1].name = "yyy";
+ * ***
+ * cpus[n]->model = "z13";
+ * cpus[n]->features[0].name = "xxx";
+ * cpus[n]->features[1].name = "yyy";
+ *
+ * out:
+ * *baseline->model = "z13-base";
+ * *baseline->features[0].name = "yyy";
+ */
+static int
+qemuConnectBaselineHypervisorCPUViaQEMU(qemuMonitorPtr mon,
+ virCPUDefPtr *cpus,
+ virCPUDefPtr *baseline)
+{
+ qemuMonitorCPUModelInfoPtr model_baseline = NULL;
+ qemuMonitorCPUModelInfoPtr new_model_baseline = NULL;
+ qemuMonitorCPUModelInfoPtr next_model = NULL;
+ bool migratable = true;
+ int ret = -1;
+ size_t i;
+
+ *baseline = NULL;
+
+ if (!cpus || !cpus[0]) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s", _("no cpus"));
+ goto cleanup;
+ }
+
+ for (i = 0; cpus[i]; i++) { /* cpus terminated by NULL element */
+ virCPUDefPtr cpu = cpus[i];
+
+ VIR_DEBUG("cpu[%lu]->model = %s", i, NULLSTR(cpu->model));
+
+ if (!(next_model = virQEMUCapsCPUModelInfoFromCPUDef(cpu)))
+ goto cleanup;
+
+ if (i == 0) {
+ model_baseline = next_model;
+ continue;
+ }
+
+ if (qemuMonitorGetCPUModelBaseline(mon, model_baseline,
+ next_model, &new_model_baseline) < 0)
+ goto cleanup;
+
+ qemuMonitorCPUModelInfoFree(model_baseline);
+ qemuMonitorCPUModelInfoFree(next_model);
+
+ next_model = NULL;
+
+ model_baseline = new_model_baseline;
+ }
+
+ if (!(*baseline = virQEMUCapsCPUModelInfoToCPUDef(migratable, model_baseline)))
+ goto cleanup;
+
+ VIR_DEBUG("baseline->model = %s", (*baseline)->model);
+
+ ret = 0;
+
+ cleanup:
+ qemuMonitorCPUModelInfoFree(model_baseline);
+ qemuMonitorCPUModelInfoFree(next_model);
+
+ return ret;
+}
+
+
static int
qemuConnectBaselineHypervisorCPUViaLibvirt(
virQEMUCapsPtr qemuCaps,
@@ -13710,6 +13782,11 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
virCPUDefPtr cpu = NULL;
char *cpustr = NULL;
bool useLibvirt = false;
+ bool useQemu = false;
+ bool forceTCG = false;
+ qemuMonitorCPUModelInfoPtr modelInfo = NULL;
+ qemuMonitorCPUModelInfoPtr expansion = NULL;
+ qemuProcessQmpPtr proc = NULL;
virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
@@ -13730,6 +13807,7 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
goto cleanup;
useLibvirt = ARCH_IS_X86(arch);
+ useQemu = ARCH_IS_S390(arch);
if (useLibvirt) {
migratable = !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE);
@@ -13738,6 +13816,21 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
virttype, arch,
cpus, ncpus, &cpu) < 0)
goto cleanup;
+
+ } else if (useQemu) {
+ const char *binary = virQEMUCapsGetBinary(qemuCaps);
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+
+ if (!(proc = qemuProcessQmpNew(binary, cfg->libDir,
+ cfg->user, cfg->group, forceTCG)))
+ goto cleanup;
+
+ if (qemuProcessQmpStart(proc) < 0)
+ goto cleanup;
+
+ if ((qemuConnectBaselineHypervisorCPUViaQEMU(proc->mon, cpus, &cpu) <
0) || !cpu)
+ goto cleanup;
+
} else {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("computing baseline hypervisor CPU is not supported "
@@ -13765,6 +13858,10 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
virCPUDefListFree(cpus);
virCPUDefFree(cpu);
virObjectUnref(qemuCaps);
+ qemuMonitorCPUModelInfoFree(modelInfo);
+ qemuMonitorCPUModelInfoFree(expansion);
+ qemuProcessQmpStop(proc);
+ qemuProcessQmpFree(proc);
return cpustr;
}
--
2.17.1