diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d5c5342966..d0f8176b2c 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6270,6 +6270,7 @@ qemuProcessUpdateGuestCPU(virDomainDef *def, if (def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH && def->cpu->mode != VIR_CPU_MODE_MAXIMUM) { g_autoptr(virDomainCapsCPUModels) cpuModels = NULL; + virCPUFeaturePolicy removedPolicy = VIR_CPU_FEATURE_DISABLE; if (def->cpu->check == VIR_CPU_CHECK_PARTIAL && !virQEMUCapsIsCPUUsable(qemuCaps, def->virtType, def->cpu) && @@ -6279,10 +6280,22 @@ qemuProcessUpdateGuestCPU(virDomainDef *def, def->cpu, true) < 0) return -1; + /* When starting a fresh domain we disable all features removed from + * the specified CPU model to make sure they are only used if + * explicitly requested. But when we are restoring a previously running + * domain (migration, snapshot, ...) all removed features were already + * explicitly listed in the CPU definition and if we found a removed + * feature which is missing it must have been removed later and must be + * enabled rather than disabled here match the state described by older + * libvirt. + */ + if (!(flags & VIR_QEMU_PROCESS_START_NEW)) + removedPolicy = VIR_CPU_FEATURE_REQUIRE; + if (virCPUUpdate(def->os.arch, def->cpu, virQEMUCapsGetHostModel(qemuCaps, def->virtType, VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE), - VIR_CPU_FEATURE_DISABLE) < 0) + removedPolicy) < 0) return -1; cpuModels = virQEMUCapsGetCPUModels(qemuCaps, def->virtType, NULL, NULL); @@ -8877,13 +8890,27 @@ qemuProcessRefreshCPU(virQEMUDriver *driver, g_autoptr(virCPUDef) host = NULL; g_autoptr(virCPUDef) hostmig = NULL; g_autoptr(virCPUDef) cpu = NULL; + virCPUFeaturePolicy removedPolicy; - if (!virQEMUCapsGuestIsNative(driver->hostarch, vm->def->os.arch)) - return 0; + /* When reconnecting to a running domain, we know all features marked as + * removed from a CPU model were already explicitly mentioned in the + * definition. If any removed features are missing, they must have been + * removed after the domain was started and thus they have to be enabled + * (otherwise they would be explicitly listed as disabled). + */ + removedPolicy = VIR_CPU_FEATURE_REQUIRE; if (!vm->def->cpu) return 0; + if (vm->def->cpu->mode == VIR_CPU_MODE_CUSTOM && + vm->def->cpu->model && + virCPUUpdate(vm->def->os.arch, vm->def->cpu, NULL, removedPolicy) < 0) + return -1; + + if (!virQEMUCapsGuestIsNative(driver->hostarch, vm->def->os.arch)) + return 0; + if (qemuProcessRefreshCPUMigratability(vm, VIR_ASYNC_JOB_NONE) < 0) return -1; @@ -8915,8 +8942,7 @@ qemuProcessRefreshCPU(virQEMUDriver *driver, virCPUDefCopyModelFilter(cpu, hostmig, false, virQEMUCapsCPUFilterFeatures, &host->arch); - if (virCPUUpdate(vm->def->os.arch, vm->def->cpu, cpu, - VIR_CPU_FEATURE_DISABLE) < 0) + if (virCPUUpdate(vm->def->os.arch, vm->def->cpu, cpu, removedPolicy) < 0) return -1; if (qemuProcessUpdateCPU(vm, VIR_ASYNC_JOB_NONE) < 0)