]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: domain: Drop added features from migratable CPU
authorJiri Denemark <jdenemar@redhat.com>
Mon, 11 Mar 2024 16:04:48 +0000 (17:04 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Thu, 14 Mar 2024 15:15:06 +0000 (16:15 +0100)
Features marked with added='yes' in CPU model definitions have to be
removed before migration, otherwise older libvirt would complain about
unknown CPU features. We only do this for features that were enabled for
a given CPU model even with older libvirt, which just ignored the
features. And only for features we added ourselves when updating CPU
definition during domain startup, that is we do not remove features
which were explicitly mentioned by a user.

That said, this is not the safest thing we could do, but it's
effectively the same thing we did before the affected features were
added: we ignored them completely on both sides of migration.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Tim Wiederhake <twiederh@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_migration_cookie.c

index 31a6509166d35c83ebb36b00efeae3a9ccd33b45..bc6cf133d4c5aefdc64c13be46cd326551847407 100644 (file)
@@ -66,6 +66,7 @@
 #include "backup_conf.h"
 #include "virutil.h"
 #include "virsecureerase.h"
+#include "cpu/cpu_x86.h"
 
 #include <sys/time.h>
 #include <fcntl.h>
@@ -6643,10 +6644,36 @@ qemuDomainDefCopy(virQEMUDriver *driver,
 }
 
 
+typedef struct {
+    const char * const *added;
+    GStrv keep;
+} qemuDomainDropAddedCPUFeaturesData;
+
+
+static bool
+qemuDomainDropAddedCPUFeatures(const char *name,
+                               virCPUFeaturePolicy policy G_GNUC_UNUSED,
+                               void *opaque)
+{
+    qemuDomainDropAddedCPUFeaturesData *data = opaque;
+
+    if (!g_strv_contains(data->added, name))
+        return true;
+
+    if (data->keep && g_strv_contains((const char **) data->keep, name))
+        return true;
+
+    return false;
+}
+
+
 int
 qemuDomainMakeCPUMigratable(virArch arch,
-                            virCPUDef *cpu)
+                            virCPUDef *cpu,
+                            virCPUDef *origCPU)
 {
+    qemuDomainDropAddedCPUFeaturesData data = { 0 };
+
     if (cpu->mode != VIR_CPU_MODE_CUSTOM ||
         !cpu->model ||
         !ARCH_IS_X86(arch))
@@ -6664,6 +6691,25 @@ qemuDomainMakeCPUMigratable(virArch arch,
             return -1;
     }
 
+    if (virCPUx86GetAddedFeatures(cpu->model, &data.added) < 0)
+        return -1;
+
+    /* Drop features marked as added in a cpu model, but only
+     * when they are not mentioned in origCPU, i.e., when they were not
+     * explicitly mentioned by the user.
+     */
+    if (data.added) {
+        g_auto(GStrv) keep = NULL;
+
+        if (origCPU) {
+            keep = virCPUDefListExplicitFeatures(origCPU);
+            data.keep = keep;
+        }
+
+        if (virCPUDefFilterFeatures(cpu, qemuDomainDropAddedCPUFeatures, &data) < 0)
+            return -1;
+    }
+
     return 0;
 }
 
@@ -6843,7 +6889,7 @@ qemuDomainDefFormatBufInternal(virQEMUDriver *driver,
         }
 
         if (def->cpu &&
-            qemuDomainMakeCPUMigratable(def->os.arch, def->cpu) < 0)
+            qemuDomainMakeCPUMigratable(def->os.arch, def->cpu, origCPU) < 0)
             return -1;
 
         /* Old libvirt doesn't understand <audio> elements so
index 07b031825874bf840cdb77441b9cf88c26b9fb75..626df6338f12807810fb0876f3f4b4ff9fee2f1f 100644 (file)
@@ -1049,7 +1049,8 @@ qemuDomainSupportsCheckpointsBlockjobs(virDomainObj *vm)
 
 int
 qemuDomainMakeCPUMigratable(virArch arch,
-                            virCPUDef *cpu);
+                            virCPUDef *cpu,
+                            virCPUDef *origCPU);
 
 int
 qemuDomainInitializePflashStorageSource(virDomainObj *vm,
index c53d42a01843dc549c7b88e26fcdb9169d6d8d57..90cc079c1a294caaffa0be4ab80916921a48c02f 100644 (file)
@@ -540,12 +540,15 @@ static int
 qemuMigrationCookieAddCPU(qemuMigrationCookie *mig,
                           virDomainObj *vm)
 {
+    qemuDomainObjPrivate *priv = vm->privateData;
+
     if (mig->cpu)
         return 0;
 
     mig->cpu = virCPUDefCopy(vm->def->cpu);
 
-    if (qemuDomainMakeCPUMigratable(vm->def->os.arch, mig->cpu) < 0)
+    if (qemuDomainMakeCPUMigratable(vm->def->os.arch, mig->cpu,
+                                    priv->origCPU) < 0)
         return -1;
 
     mig->flags |= QEMU_MIGRATION_COOKIE_CPU;