This command is hooked into the virsh hypervisor-cpu-baseline command.
As such, the CPU models provided in the XML sent to the command will be
baselined with the CPU contained in the QEMU capabilities file for the
appropriate QEMU binary (for s390x, this CPU definition can be observed
via virsh domcapabilities).
Signed-off-by: Collin Walling <walling(a)linux.ibm.com>
Reviewed-by: Daniel Henrique Barboza <danielh413(a)gmail.com>
---
src/qemu/qemu_capabilities.c | 84 ++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_capabilities.h | 7 ++++
src/qemu/qemu_driver.c | 27 ++++++++++++++
3 files changed, 118 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5cbcf64..71f4f4e 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -5446,3 +5446,87 @@ virQEMUCapsStripMachineAliases(virQEMUCapsPtr qemuCaps)
for (i = 0; i < qemuCaps->nmachineTypes; i++)
VIR_FREE(qemuCaps->machineTypes[i].alias);
}
+
+
+static int
+virQEMUCapsStealCPUModelFromInfo(virCPUDefPtr dst,
+ qemuMonitorCPUModelInfoPtr *src)
+{
+ qemuMonitorCPUModelInfoPtr info = *src;
+ size_t i;
+
+ virCPUDefFreeModel(dst);
+
+ VIR_STEAL_PTR(dst->model, info->name);
+
+ for (i = 0; i < info->nprops; i++) {
+ char *name = info->props[i].name;
+ int policy = VIR_CPU_FEATURE_REQUIRE;
+
+ if (info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_BOOLEAN &&
+ !info->props[i].value.boolean)
+ policy = VIR_CPU_FEATURE_DISABLE;
+
+ if (virCPUDefAddFeature(dst, name, policy) < 0)
+ goto error;
+ }
+
+ qemuMonitorCPUModelInfoFree(info);
+ *src = NULL;
+ return 0;
+
+ error:
+ virCPUDefFree(dst);
+ return -1;
+}
+
+
+virCPUDefPtr
+virQEMUCapsCPUModelBaseline(virQEMUCapsPtr qemuCaps,
+ const char *libDir,
+ uid_t runUid,
+ gid_t runGid,
+ int ncpus,
+ virCPUDefPtr *cpus)
+{
+ qemuMonitorCPUModelInfoPtr result = NULL;
+ qemuProcessQMPPtr proc = NULL;
+ virCPUDefPtr cpu = NULL;
+ virCPUDefPtr baseline = NULL;
+ size_t i;
+
+ if (VIR_ALLOC(cpu) < 0)
+ goto cleanup;
+
+ if (virCPUDefCopyModel(cpu, cpus[0], false))
+ goto cleanup;
+
+ if (!(proc = qemuProcessQMPNew(qemuCaps->binary, libDir,
+ runUid, runGid, false)))
+ goto cleanup;
+
+ if (qemuProcessQMPStart(proc) < 0)
+ goto cleanup;
+
+ for (i = 1; i < ncpus; i++) {
+ if (qemuMonitorGetCPUModelBaseline(proc->mon, cpu->model,
+ cpu->nfeatures, cpu->features,
+ cpus[i]->model, cpus[i]->nfeatures,
+ cpus[i]->features, &result) < 0)
+ goto cleanup;
+
+ if (virQEMUCapsStealCPUModelFromInfo(cpu, &result) < 0)
+ goto cleanup;
+ }
+
+ VIR_STEAL_PTR(baseline, cpu);
+
+ cleanup:
+ if (!baseline)
+ virQEMUCapsLogProbeFailure(qemuCaps->binary);
+
+ qemuMonitorCPUModelInfoFree(result);
+ qemuProcessQMPFree(proc);
+ virCPUDefFree(cpu);
+ return baseline;
+}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 102f259..08fd555 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -648,4 +648,11 @@ virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps);
virArch virQEMUCapsArchFromString(const char *arch);
const char *virQEMUCapsArchToString(virArch arch);
+virCPUDefPtr virQEMUCapsCPUModelBaseline(virQEMUCapsPtr qemuCaps,
+ const char *libDir,
+ uid_t runUid,
+ gid_t runGid,
+ int ncpus,
+ virCPUDefPtr *cpus);
+
#endif /* LIBVIRT_QEMU_CAPABILITIES_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 42b1ce2..9750962 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13573,6 +13573,7 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
unsigned int flags)
{
virQEMUDriverPtr driver = conn->privateData;
+ virQEMUDriverConfigPtr config = driver->config;
virCPUDefPtr *cpus = NULL;
virQEMUCapsPtr qemuCaps = NULL;
virArch arch;
@@ -13627,6 +13628,32 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
if (!(cpu = virCPUBaseline(arch, cpus, ncpus, cpuModels,
(const char **)features, migratable)))
goto cleanup;
+ } else if (ARCH_IS_S390(arch) &&
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_BASELINE)) {
+ /* Add a copy of the hypervisor CPU to the list */
+ virCPUDefPtr hvCPU, tmp;
+ size_t allocated = ncpus + 1;
+
+ hvCPU = virQEMUCapsGetHostModel(qemuCaps, virttype,
+ VIR_QEMU_CAPS_HOST_CPU_REPORTED);
+ if (VIR_ALLOC(tmp) < 0)
+ goto cleanup;
+
+ if (virCPUDefCopyModel(tmp, hvCPU, false))
+ goto cleanup;
+
+ if (VIR_INSERT_ELEMENT(cpus, ncpus, allocated, tmp) < 0)
+ goto cleanup;
+
+ ncpus++;
+
+ if (!(cpu = virQEMUCapsCPUModelBaseline(qemuCaps, config->libDir,
+ config->user, config->group,
+ ncpus, cpus)))
+ goto cleanup;
+
+ if (!(flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES))
+ virCPUDefFreeFeatures(cpu);
} else {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("computing baseline hypervisor CPU is not supported "
--
2.7.4