.parse = qemuDomainSaveCookieParse,
.format = qemuDomainSaveCookieFormat,
};
+
+
+/**
+ * qemuDomainUpdateCPU:
+ * @vm: domain which is being started
+ * @cpu: CPU updated when the domain was running previously (before migration,
+ * snapshot, or save)
+ * @origCPU: where to store the original CPU from vm->def in case @cpu was
+ * used instead
+ *
+ * Replace the CPU definition with the updated one when QEMU is new enough to
+ * allow us to check extra features it is about to enable or disable when
+ * starting a domain. The original CPU is stored in @origCPU.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+qemuDomainUpdateCPU(virDomainObjPtr vm,
+ virCPUDefPtr cpu,
+ virCPUDefPtr *origCPU)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
+ *origCPU = NULL;
+
+ if (!cpu || !vm->def->cpu ||
+ !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION) ||
+ virCPUDefIsEqual(vm->def->cpu, cpu, false))
+ return 0;
+
+ if (!(cpu = virCPUDefCopy(cpu)))
+ return -1;
+
+ VIR_DEBUG("Replacing CPU def with the updated one");
+
+ *origCPU = vm->def->cpu;
+ vm->def->cpu = cpu;
+
+ return 0;
+}
virStorageSourcePtr qemuDomainGetStorageSourceByDevstr(const char *devstr,
virDomainDefPtr def);
+int
+qemuDomainUpdateCPU(virDomainObjPtr vm,
+ virCPUDefPtr cpu,
+ virCPUDefPtr *origCPU);
+
#endif /* __QEMU_DOMAIN_H__ */
goto cleanup;
}
- if (qemuProcessStart(conn, driver, vm, QEMU_ASYNC_JOB_START,
+ if (qemuProcessStart(conn, driver, vm, NULL, QEMU_ASYNC_JOB_START,
NULL, -1, NULL, NULL,
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
start_flags) < 0) {
}
}
- if (qemuProcessStart(conn, driver, vm, asyncJob,
- "stdio", *fd, path, NULL,
+ if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
+ asyncJob, "stdio", *fd, path, NULL,
VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
VIR_QEMU_PROCESS_START_PAUSED) == 0)
restored = true;
}
}
- ret = qemuProcessStart(conn, driver, vm, asyncJob,
+ ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
NULL, -1, NULL, NULL,
VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
virDomainAuditStart(vm, "booted", ret >= 0);
virCapsPtr caps = NULL;
bool was_running = false;
bool was_stopped = false;
+ qemuDomainSaveCookiePtr cookie;
+ virCPUDefPtr origCPU = NULL;
virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
goto endjob;
}
+ cookie = (qemuDomainSaveCookiePtr) snap->def->cookie;
+
switch ((virDomainState) snap->def->state) {
case VIR_DOMAIN_RUNNING:
case VIR_DOMAIN_PAUSED:
* to have finer control. */
if (virDomainObjIsActive(vm)) {
/* Transitions 5, 6, 8, 9 */
+ /* Replace the CPU in config and put the original one in priv
+ * once we're done.
+ */
+ if (cookie && cookie->cpu && config->cpu) {
+ origCPU = config->cpu;
+ if (!(config->cpu = virCPUDefCopy(cookie->cpu)))
+ goto endjob;
+ }
+
/* Check for ABI compatibility. We need to do this check against
* the migratable XML or it will always fail otherwise */
if (config &&
* failed loadvm attempt? */
goto endjob;
}
- if (config)
+ if (config) {
virDomainObjAssignDef(vm, config, false, NULL);
+ virCPUDefFree(priv->origCPU);
+ VIR_STEAL_PTR(priv->origCPU, origCPU);
+ }
} else {
/* Transitions 2, 3 */
load:
virDomainObjAssignDef(vm, config, false, NULL);
rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
+ cookie ? cookie->cpu : NULL,
QEMU_ASYNC_JOB_START, NULL, -1, NULL, snap,
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
VIR_QEMU_PROCESS_START_PAUSED);
start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
qemuDomainEventQueue(driver, event);
- rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
+ rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
QEMU_ASYNC_JOB_START, NULL, -1, NULL, NULL,
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
start_flags);
virObjectUnref(caps);
virObjectUnref(cfg);
virNWFilterUnlockFilterUpdates();
+ virCPUDefFree(origCPU);
return ret;
}
goto stopjob;
}
- if (qemuProcessInit(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN,
+ if (qemuProcessInit(driver, vm, mig->cpu, QEMU_ASYNC_JOB_MIGRATION_IN,
true, VIR_QEMU_PROCESS_START_AUTODESTROY) < 0)
goto stopjob;
stopProcess = true;
if (qemuProcessVerifyCPUFeatures(def, cpu) < 0)
goto cleanup;
+ /* Don't update the CPU if we already did so when starting a domain
+ * during migration, restore or snapshot revert. */
+ if (priv->origCPU) {
+ ret = 0;
+ goto cleanup;
+ }
+
if (!(orig = virCPUDefCopy(def->cpu)))
goto cleanup;
int
qemuProcessInit(virQEMUDriverPtr driver,
virDomainObjPtr vm,
+ virCPUDefPtr updatedCPU,
qemuDomainAsyncJob asyncJob,
bool migration,
unsigned int flags)
virCapsPtr caps = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
int stopFlags;
+ virCPUDefPtr origCPU = NULL;
int ret = -1;
VIR_DEBUG("vm=%p name=%s id=%d migration=%d",
vm->def->os.machine)))
goto cleanup;
+ if (qemuDomainUpdateCPU(vm, updatedCPU, &origCPU) < 0)
+ goto cleanup;
+
if (qemuProcessStartValidate(driver, vm, priv->qemuCaps, caps, flags) < 0)
goto cleanup;
if (qemuDomainSetPrivatePaths(driver, vm) < 0)
goto stop;
+
+ VIR_STEAL_PTR(priv->origCPU, origCPU);
}
ret = 0;
cleanup:
+ virCPUDefFree(origCPU);
virObjectUnref(cfg);
virObjectUnref(caps);
return ret;
qemuProcessStart(virConnectPtr conn,
virQEMUDriverPtr driver,
virDomainObjPtr vm,
+ virCPUDefPtr updatedCPU,
qemuDomainAsyncJob asyncJob,
const char *migrateFrom,
int migrateFd,
if (!migrateFrom && !snapshot)
flags |= VIR_QEMU_PROCESS_START_NEW;
- if (qemuProcessInit(driver, vm, asyncJob, !!migrateFrom, flags) < 0)
+ if (qemuProcessInit(driver, vm, updatedCPU,
+ asyncJob, !!migrateFrom, flags) < 0)
goto cleanup;
if (migrateFrom) {
flags |= VIR_QEMU_PROCESS_START_PRETEND;
flags |= VIR_QEMU_PROCESS_START_NEW;
- if (qemuProcessInit(driver, vm, QEMU_ASYNC_JOB_NONE, !!migrateURI, flags) < 0)
+ if (qemuProcessInit(driver, vm, NULL, QEMU_ASYNC_JOB_NONE,
+ !!migrateURI, flags) < 0)
goto cleanup;
if (qemuProcessPrepareDomain(conn, driver, vm, flags) < 0)
/* clean up migration data */
VIR_FREE(priv->migTLSAlias);
+ virCPUDefFree(priv->origCPU);
+ priv->origCPU = NULL;
/* clear previously used namespaces */
virBitmapFree(priv->namespaces);
int qemuProcessStart(virConnectPtr conn,
virQEMUDriverPtr driver,
virDomainObjPtr vm,
+ virCPUDefPtr updatedCPU,
qemuDomainAsyncJob asyncJob,
const char *migrateFrom,
int stdin_fd,
int qemuProcessInit(virQEMUDriverPtr driver,
virDomainObjPtr vm,
+ virCPUDefPtr updatedCPU,
qemuDomainAsyncJob asyncJob,
bool migration,
unsigned int flags);