Blob Blame History Raw
From f05df8ca745a00a1c8bc783dcf25f648cbe5d508 Mon Sep 17 00:00:00 2001
Message-Id: <f05df8ca745a00a1c8bc783dcf25f648cbe5d508@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Fri, 6 Oct 2017 13:23:36 +0200
Subject: [PATCH] qemu: Filter CPU features when using host CPU

When reconnecting to a domain started with a host-model CPU which was
started by old libvirt that did not replace host-model with the real CPU
definition, libvirt replaces the host-model CPU with the CPU from
capabilities (because this is what the old libvirt did when it started
the domain). Without this patch libvirt could use features unknown to
QEMU in the CPU definition which replaced the original host-model CPU.
Such domain would keep running just fine, but any attempt to migrate it
will fail and once the domain is saved or snapshotted, restoring it
would fail too.

In other words whenever we want to use the CPU definition from host
capabilities as a guest CPU definition, we have to filter the unknown
features.

https://bugzilla.redhat.com/show_bug.cgi?id=1495171

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit e26cc8f82ff346c9ec90409bac06581b64e42b20)

https://bugzilla.redhat.com/show_bug.cgi?id=1508549

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 src/qemu/qemu_process.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4a8c4421a3..0bed084381 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6668,6 +6668,7 @@ qemuProcessRefreshCPU(virQEMUDriverPtr driver,
 {
     virCapsPtr caps = virQEMUDriverGetCapabilities(driver, false);
     virCPUDefPtr host = NULL;
+    virCPUDefPtr cpu = NULL;
     int ret = -1;
 
     if (!caps)
@@ -6689,7 +6690,13 @@ qemuProcessRefreshCPU(virQEMUDriverPtr driver,
         if (!(host = virCPUCopyMigratable(caps->host.cpu->arch, caps->host.cpu)))
             goto cleanup;
 
-        if (virCPUUpdate(vm->def->os.arch, vm->def->cpu, host) < 0)
+        if (!(cpu = virCPUDefCopyWithoutModel(host)) ||
+            virCPUDefCopyModelFilter(cpu, host, false,
+                                     virQEMUCapsCPUFilterFeatures,
+                                     &caps->host.cpu->arch) < 0)
+            goto cleanup;
+
+        if (virCPUUpdate(vm->def->os.arch, vm->def->cpu, cpu) < 0)
             goto cleanup;
 
         if (qemuProcessUpdateCPU(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
@@ -6699,6 +6706,7 @@ qemuProcessRefreshCPU(virQEMUDriverPtr driver,
     ret = 0;
 
  cleanup:
+    virCPUDefFree(cpu);
     virCPUDefFree(host);
     virObjectUnref(caps);
     return ret;
-- 
2.15.0