On Wed, Jul 17, 2019 at 10:03:25 -0400, Collin Walling wrote:
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).
This is not how the baseline API works. If a user wants the current host
CPU model to be taken in the baseline computation, they need to provide
it in the array of input CPUs by themselves.
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 b898113..ab337fa 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -5574,3 +5574,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)
This function does not belong to qemu_capabilities.c, it should be in
qemu_driver.c and with a different prefix, of course. And this applies
to the helper above too.
+{
+ 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)
See my comment to 2/8. Wouldn't this be much better as
if (qemuMonitorGetCPUModelBaseline(proc->mon, cpu, cpus[i],
&result) < 0)
+ goto cleanup;
+
+ if (virQEMUCapsStealCPUModelFromInfo(cpu, &result) < 0)
+ goto cleanup;
+ }
+
+ VIR_STEAL_PTR(baseline, cpu);
+
+ cleanup:
+ if (!baseline)
+ virQEMUCapsLogProbeFailure(qemuCaps->binary);
There's no probing here. It's just an implementation of the API invoked
by libvirt client. No need to log anything here.
+
+ qemuMonitorCPUModelInfoFree(result);
As Boris already noticed, result cannot be non-NULL here. In fact, you
could even make the result variable local to the for loop.
+ qemuProcessQMPFree(proc);
+ virCPUDefFree(cpu);
+ return baseline;
+}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 8dde759..b49c0b9 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -665,3 +665,10 @@ 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);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d3a144a..37b9c75 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13553,6 +13553,7 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
unsigned int flags)
{
virQEMUDriverPtr driver = conn->privateData;
+ virQEMUDriverConfigPtr config = driver->config;
You should use
VIR_AUTOUNREF(virQEMUDriverConfigPtr) cfg = virQEMUDriverGetConfig(driver);
instead.
virCPUDefPtr *cpus = NULL;
virQEMUCapsPtr qemuCaps = NULL;
virArch arch;
@@ -13607,6 +13608,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++;
All the code in this if statement down to here should go away.
+
+ if (!(cpu = virQEMUCapsCPUModelBaseline(qemuCaps, config->libDir,
+ config->user, config->group,
+ ncpus, cpus)))
+ goto cleanup;
+
+ if (!(flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES))
+ virCPUDefFreeFeatures(cpu);
This seems to be wrong.
} else {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("computing baseline hypervisor CPU is not supported "
Jirka