|
|
3e5111 |
From b2196db320485b642d6654279ebb6b75eeafd3e9 Mon Sep 17 00:00:00 2001
|
|
|
3e5111 |
Message-Id: <b2196db320485b642d6654279ebb6b75eeafd3e9@dist-git>
|
|
|
3e5111 |
From: Jiri Denemark <jdenemar@redhat.com>
|
|
|
3e5111 |
Date: Tue, 11 Apr 2017 20:46:05 +0200
|
|
|
3e5111 |
Subject: [PATCH] qemu: Use more data for comparing CPUs
|
|
|
3e5111 |
|
|
|
3e5111 |
With QEMU older than 2.9.0 libvirt uses CPUID instruction to determine
|
|
|
3e5111 |
what CPU features are supported on the host. This was later used when
|
|
|
3e5111 |
checking compatibility of guest CPUs. Since QEMU 2.9.0 we ask QEMU for
|
|
|
3e5111 |
the host CPU data. But the two methods we use usually provide disjoint
|
|
|
3e5111 |
sets of CPU features because QEMU/KVM does not support all features
|
|
|
3e5111 |
provided by the host CPU and on the other hand it can enable some
|
|
|
3e5111 |
feature even if the host CPU does not support them.
|
|
|
3e5111 |
|
|
|
3e5111 |
So if there is a domain which requires a CPU features disabled by
|
|
|
3e5111 |
QEMU/KVM, libvirt will refuse to start it with QEMU > 2.9.0 as its guest
|
|
|
3e5111 |
CPU is incompatible with the host CPU data we got from QEMU. But such
|
|
|
3e5111 |
domain would happily start on older QEMU (of course, the features would
|
|
|
3e5111 |
be missing the guest CPU). To fix this regression, we need to combine
|
|
|
3e5111 |
both CPU feature sets when checking guest CPU compatibility.
|
|
|
3e5111 |
|
|
|
3e5111 |
https://bugzilla.redhat.com/show_bug.cgi?id=1439933
|
|
|
3e5111 |
|
|
|
3e5111 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
3e5111 |
(cherry picked from commit 5b4a6adb5ca24a6cb91cdc55c31506fb278d3a91)
|
|
|
3e5111 |
|
|
|
3e5111 |
https://bugzilla.redhat.com/show_bug.cgi?id=1444421
|
|
|
3e5111 |
|
|
|
3e5111 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
3e5111 |
---
|
|
|
3e5111 |
src/qemu/qemu_capabilities.c | 35 +++++++++++++++++++++++++++++++++--
|
|
|
3e5111 |
src/qemu/qemu_capabilities.h | 4 ++++
|
|
|
3e5111 |
src/qemu/qemu_process.c | 2 +-
|
|
|
3e5111 |
3 files changed, 38 insertions(+), 3 deletions(-)
|
|
|
3e5111 |
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
|
|
|
3e5111 |
index ec773971e..49de506ed 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_capabilities.c
|
|
|
3e5111 |
+++ b/src/qemu/qemu_capabilities.c
|
|
|
3e5111 |
@@ -387,6 +387,10 @@ struct _virQEMUCapsHostCPUData {
|
|
|
3e5111 |
virCPUDefPtr reported;
|
|
|
3e5111 |
/* Migratable host CPU definition used for updating guest CPU. */
|
|
|
3e5111 |
virCPUDefPtr migratable;
|
|
|
3e5111 |
+ /* CPU definition with features detected by libvirt using virCPUGetHost
|
|
|
3e5111 |
+ * combined with features reported by QEMU. This is used for backward
|
|
|
3e5111 |
+ * compatible comparison between a guest CPU and a host CPU. */
|
|
|
3e5111 |
+ virCPUDefPtr full;
|
|
|
3e5111 |
};
|
|
|
3e5111 |
|
|
|
3e5111 |
/*
|
|
|
3e5111 |
@@ -2112,6 +2116,10 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsHostCPUDataPtr dst,
|
|
|
3e5111 |
!(dst->migratable = virCPUDefCopy(src->migratable)))
|
|
|
3e5111 |
return -1;
|
|
|
3e5111 |
|
|
|
3e5111 |
+ if (src->full &&
|
|
|
3e5111 |
+ !(dst->full = virCPUDefCopy(src->full)))
|
|
|
3e5111 |
+ return -1;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
return 0;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
@@ -2122,6 +2130,7 @@ virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUDataPtr cpuData)
|
|
|
3e5111 |
qemuMonitorCPUModelInfoFree(cpuData->info);
|
|
|
3e5111 |
virCPUDefFree(cpuData->reported);
|
|
|
3e5111 |
virCPUDefFree(cpuData->migratable);
|
|
|
3e5111 |
+ virCPUDefFree(cpuData->full);
|
|
|
3e5111 |
|
|
|
3e5111 |
memset(cpuData, 0, sizeof(*cpuData));
|
|
|
3e5111 |
}
|
|
|
3e5111 |
@@ -2463,6 +2472,11 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
|
|
|
3e5111 |
|
|
|
3e5111 |
case VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE:
|
|
|
3e5111 |
return cpuData->migratable;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ case VIR_QEMU_CAPS_HOST_CPU_FULL:
|
|
|
3e5111 |
+ /* 'full' is non-NULL only if we have data from both QEMU and
|
|
|
3e5111 |
+ * virCPUGetHost */
|
|
|
3e5111 |
+ return cpuData->full ? cpuData->full : cpuData->reported;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
return NULL;
|
|
|
3e5111 |
@@ -2473,12 +2487,14 @@ static void
|
|
|
3e5111 |
virQEMUCapsSetHostModel(virQEMUCapsPtr qemuCaps,
|
|
|
3e5111 |
virDomainVirtType type,
|
|
|
3e5111 |
virCPUDefPtr reported,
|
|
|
3e5111 |
- virCPUDefPtr migratable)
|
|
|
3e5111 |
+ virCPUDefPtr migratable,
|
|
|
3e5111 |
+ virCPUDefPtr full)
|
|
|
3e5111 |
{
|
|
|
3e5111 |
virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type);
|
|
|
3e5111 |
|
|
|
3e5111 |
cpuData->reported = reported;
|
|
|
3e5111 |
cpuData->migratable = migratable;
|
|
|
3e5111 |
+ cpuData->full = full;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
|
|
|
3e5111 |
@@ -3350,6 +3366,8 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
|
|
|
3e5111 |
virCPUDefPtr cpu = NULL;
|
|
|
3e5111 |
virCPUDefPtr migCPU = NULL;
|
|
|
3e5111 |
virCPUDefPtr hostCPU = NULL;
|
|
|
3e5111 |
+ virCPUDefPtr fullCPU = NULL;
|
|
|
3e5111 |
+ size_t i;
|
|
|
3e5111 |
int rc;
|
|
|
3e5111 |
|
|
|
3e5111 |
if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
|
|
|
3e5111 |
@@ -3369,6 +3387,18 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
|
|
|
3e5111 |
virQEMUCapsCPUFilterFeatures,
|
|
|
3e5111 |
qemuCaps) < 0)
|
|
|
3e5111 |
goto error;
|
|
|
3e5111 |
+ } else if (type == VIR_DOMAIN_VIRT_KVM &&
|
|
|
3e5111 |
+ virCPUGetHostIsSupported(qemuCaps->arch)) {
|
|
|
3e5111 |
+ if (!(fullCPU = virCPUGetHost(qemuCaps->arch, VIR_CPU_TYPE_GUEST,
|
|
|
3e5111 |
+ NULL, NULL, 0)))
|
|
|
3e5111 |
+ goto error;
|
|
|
3e5111 |
+
|
|
|
3e5111 |
+ for (i = 0; i < cpu->nfeatures; i++) {
|
|
|
3e5111 |
+ if (cpu->features[i].policy == VIR_CPU_FEATURE_REQUIRE &&
|
|
|
3e5111 |
+ virCPUDefUpdateFeature(fullCPU, cpu->features[i].name,
|
|
|
3e5111 |
+ VIR_CPU_FEATURE_REQUIRE) < 0)
|
|
|
3e5111 |
+ goto error;
|
|
|
3e5111 |
+ }
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
if (!(migCPU = virQEMUCapsNewHostCPUModel()))
|
|
|
3e5111 |
@@ -3384,7 +3414,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
|
|
|
3e5111 |
goto error;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
|
|
|
3e5111 |
- virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU);
|
|
|
3e5111 |
+ virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU, fullCPU);
|
|
|
3e5111 |
|
|
|
3e5111 |
cleanup:
|
|
|
3e5111 |
virCPUDefFree(hostCPU);
|
|
|
3e5111 |
@@ -3393,6 +3423,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
|
|
|
3e5111 |
error:
|
|
|
3e5111 |
virCPUDefFree(cpu);
|
|
|
3e5111 |
virCPUDefFree(migCPU);
|
|
|
3e5111 |
+ virCPUDefFree(fullCPU);
|
|
|
3e5111 |
virResetLastError();
|
|
|
3e5111 |
goto cleanup;
|
|
|
3e5111 |
}
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
|
|
|
3e5111 |
index 16fe044cc..644b8e27b 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_capabilities.h
|
|
|
3e5111 |
+++ b/src/qemu/qemu_capabilities.h
|
|
|
3e5111 |
@@ -456,6 +456,10 @@ typedef enum {
|
|
|
3e5111 |
VIR_QEMU_CAPS_HOST_CPU_REPORTED,
|
|
|
3e5111 |
/* Migratable host CPU definition used for updating guest CPU. */
|
|
|
3e5111 |
VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE,
|
|
|
3e5111 |
+ /* CPU definition with features detected by libvirt using virCPUGetHost
|
|
|
3e5111 |
+ * combined with features reported by QEMU. This is used for backward
|
|
|
3e5111 |
+ * compatible comparison between a guest CPU and a host CPU. */
|
|
|
3e5111 |
+ VIR_QEMU_CAPS_HOST_CPU_FULL,
|
|
|
3e5111 |
} virQEMUCapsHostCPUType;
|
|
|
3e5111 |
|
|
|
3e5111 |
virCPUDefPtr virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
|
|
|
3e5111 |
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
|
3e5111 |
index c81389ef2..a33ec87e6 100644
|
|
|
3e5111 |
--- a/src/qemu/qemu_process.c
|
|
|
3e5111 |
+++ b/src/qemu/qemu_process.c
|
|
|
3e5111 |
@@ -5307,7 +5307,7 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def,
|
|
|
3e5111 |
if (def->cpu->check == VIR_CPU_CHECK_PARTIAL &&
|
|
|
3e5111 |
virCPUCompare(caps->host.arch,
|
|
|
3e5111 |
virQEMUCapsGetHostModel(qemuCaps, def->virtType,
|
|
|
3e5111 |
- VIR_QEMU_CAPS_HOST_CPU_REPORTED),
|
|
|
3e5111 |
+ VIR_QEMU_CAPS_HOST_CPU_FULL),
|
|
|
3e5111 |
def->cpu, true) < 0)
|
|
|
3e5111 |
return -1;
|
|
|
3e5111 |
|
|
|
3e5111 |
--
|
|
|
3e5111 |
2.12.2
|
|
|
3e5111 |
|