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) &&
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);
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;
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)