mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-26 23:55:23 +00:00
qemu: Use updated CPU when starting QEMU if possible
If QEMU is new enough and we have the live updated CPU definition in either save or migration cookie, we can use it to enforce ABI. The original guest CPU from domain XML will be stored in private data. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
This commit is contained in:
parent
8c19fbf452
commit
8e34f47813
@ -9240,3 +9240,43 @@ virSaveCookieCallbacks virQEMUDriverDomainSaveCookie = {
|
|||||||
.parse = qemuDomainSaveCookieParse,
|
.parse = qemuDomainSaveCookieParse,
|
||||||
.format = qemuDomainSaveCookieFormat,
|
.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;
|
||||||
|
}
|
||||||
|
@ -919,4 +919,9 @@ char *qemuDomainDiskBackingStoreGetName(virDomainDiskDefPtr disk,
|
|||||||
virStorageSourcePtr qemuDomainGetStorageSourceByDevstr(const char *devstr,
|
virStorageSourcePtr qemuDomainGetStorageSourceByDevstr(const char *devstr,
|
||||||
virDomainDefPtr def);
|
virDomainDefPtr def);
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuDomainUpdateCPU(virDomainObjPtr vm,
|
||||||
|
virCPUDefPtr cpu,
|
||||||
|
virCPUDefPtr *origCPU);
|
||||||
|
|
||||||
#endif /* __QEMU_DOMAIN_H__ */
|
#endif /* __QEMU_DOMAIN_H__ */
|
||||||
|
@ -1779,7 +1779,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
|
|||||||
goto cleanup;
|
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,
|
NULL, -1, NULL, NULL,
|
||||||
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
||||||
start_flags) < 0) {
|
start_flags) < 0) {
|
||||||
@ -6506,8 +6506,8 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemuProcessStart(conn, driver, vm, asyncJob,
|
if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
|
||||||
"stdio", *fd, path, NULL,
|
asyncJob, "stdio", *fd, path, NULL,
|
||||||
VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
|
VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
|
||||||
VIR_QEMU_PROCESS_START_PAUSED) == 0)
|
VIR_QEMU_PROCESS_START_PAUSED) == 0)
|
||||||
restored = true;
|
restored = true;
|
||||||
@ -7124,7 +7124,7 @@ qemuDomainObjStart(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qemuProcessStart(conn, driver, vm, asyncJob,
|
ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
|
||||||
NULL, -1, NULL, NULL,
|
NULL, -1, NULL, NULL,
|
||||||
VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
|
VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
|
||||||
virDomainAuditStart(vm, "booted", ret >= 0);
|
virDomainAuditStart(vm, "booted", ret >= 0);
|
||||||
@ -15294,6 +15294,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|||||||
virCapsPtr caps = NULL;
|
virCapsPtr caps = NULL;
|
||||||
bool was_running = false;
|
bool was_running = false;
|
||||||
bool was_stopped = false;
|
bool was_stopped = false;
|
||||||
|
qemuDomainSaveCookiePtr cookie;
|
||||||
|
virCPUDefPtr origCPU = NULL;
|
||||||
|
|
||||||
virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
|
virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
|
||||||
VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
|
VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
|
||||||
@ -15399,6 +15401,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cookie = (qemuDomainSaveCookiePtr) snap->def->cookie;
|
||||||
|
|
||||||
switch ((virDomainState) snap->def->state) {
|
switch ((virDomainState) snap->def->state) {
|
||||||
case VIR_DOMAIN_RUNNING:
|
case VIR_DOMAIN_RUNNING:
|
||||||
case VIR_DOMAIN_PAUSED:
|
case VIR_DOMAIN_PAUSED:
|
||||||
@ -15410,6 +15414,15 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|||||||
* to have finer control. */
|
* to have finer control. */
|
||||||
if (virDomainObjIsActive(vm)) {
|
if (virDomainObjIsActive(vm)) {
|
||||||
/* Transitions 5, 6, 8, 9 */
|
/* 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
|
/* Check for ABI compatibility. We need to do this check against
|
||||||
* the migratable XML or it will always fail otherwise */
|
* the migratable XML or it will always fail otherwise */
|
||||||
if (config &&
|
if (config &&
|
||||||
@ -15469,8 +15482,11 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|||||||
* failed loadvm attempt? */
|
* failed loadvm attempt? */
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
if (config)
|
if (config) {
|
||||||
virDomainObjAssignDef(vm, config, false, NULL);
|
virDomainObjAssignDef(vm, config, false, NULL);
|
||||||
|
virCPUDefFree(priv->origCPU);
|
||||||
|
VIR_STEAL_PTR(priv->origCPU, origCPU);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Transitions 2, 3 */
|
/* Transitions 2, 3 */
|
||||||
load:
|
load:
|
||||||
@ -15479,6 +15495,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|||||||
virDomainObjAssignDef(vm, config, false, NULL);
|
virDomainObjAssignDef(vm, config, false, NULL);
|
||||||
|
|
||||||
rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
|
rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
|
||||||
|
cookie ? cookie->cpu : NULL,
|
||||||
QEMU_ASYNC_JOB_START, NULL, -1, NULL, snap,
|
QEMU_ASYNC_JOB_START, NULL, -1, NULL, snap,
|
||||||
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
||||||
VIR_QEMU_PROCESS_START_PAUSED);
|
VIR_QEMU_PROCESS_START_PAUSED);
|
||||||
@ -15572,7 +15589,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|||||||
start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
|
start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
|
||||||
|
|
||||||
qemuDomainEventQueue(driver, event);
|
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,
|
QEMU_ASYNC_JOB_START, NULL, -1, NULL, NULL,
|
||||||
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
||||||
start_flags);
|
start_flags);
|
||||||
@ -15644,6 +15661,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
virNWFilterUnlockFilterUpdates();
|
virNWFilterUnlockFilterUpdates();
|
||||||
|
virCPUDefFree(origCPU);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2681,7 +2681,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
|
|||||||
goto stopjob;
|
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)
|
true, VIR_QEMU_PROCESS_START_AUTODESTROY) < 0)
|
||||||
goto stopjob;
|
goto stopjob;
|
||||||
stopProcess = true;
|
stopProcess = true;
|
||||||
|
@ -3946,6 +3946,13 @@ qemuProcessUpdateLiveGuestCPU(virQEMUDriverPtr driver,
|
|||||||
if (qemuProcessVerifyCPUFeatures(def, cpu) < 0)
|
if (qemuProcessVerifyCPUFeatures(def, cpu) < 0)
|
||||||
goto cleanup;
|
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)))
|
if (!(orig = virCPUDefCopy(def->cpu)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -4864,6 +4871,7 @@ qemuProcessStartValidate(virQEMUDriverPtr driver,
|
|||||||
int
|
int
|
||||||
qemuProcessInit(virQEMUDriverPtr driver,
|
qemuProcessInit(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
|
virCPUDefPtr updatedCPU,
|
||||||
qemuDomainAsyncJob asyncJob,
|
qemuDomainAsyncJob asyncJob,
|
||||||
bool migration,
|
bool migration,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
@ -4872,6 +4880,7 @@ qemuProcessInit(virQEMUDriverPtr driver,
|
|||||||
virCapsPtr caps = NULL;
|
virCapsPtr caps = NULL;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
int stopFlags;
|
int stopFlags;
|
||||||
|
virCPUDefPtr origCPU = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
VIR_DEBUG("vm=%p name=%s id=%d migration=%d",
|
VIR_DEBUG("vm=%p name=%s id=%d migration=%d",
|
||||||
@ -4896,6 +4905,9 @@ qemuProcessInit(virQEMUDriverPtr driver,
|
|||||||
vm->def->os.machine)))
|
vm->def->os.machine)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (qemuDomainUpdateCPU(vm, updatedCPU, &origCPU) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuProcessStartValidate(driver, vm, priv->qemuCaps, caps, flags) < 0)
|
if (qemuProcessStartValidate(driver, vm, priv->qemuCaps, caps, flags) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -4928,11 +4940,14 @@ qemuProcessInit(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
if (qemuDomainSetPrivatePaths(driver, vm) < 0)
|
if (qemuDomainSetPrivatePaths(driver, vm) < 0)
|
||||||
goto stop;
|
goto stop;
|
||||||
|
|
||||||
|
VIR_STEAL_PTR(priv->origCPU, origCPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
virCPUDefFree(origCPU);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
return ret;
|
return ret;
|
||||||
@ -5963,6 +5978,7 @@ int
|
|||||||
qemuProcessStart(virConnectPtr conn,
|
qemuProcessStart(virConnectPtr conn,
|
||||||
virQEMUDriverPtr driver,
|
virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
|
virCPUDefPtr updatedCPU,
|
||||||
qemuDomainAsyncJob asyncJob,
|
qemuDomainAsyncJob asyncJob,
|
||||||
const char *migrateFrom,
|
const char *migrateFrom,
|
||||||
int migrateFd,
|
int migrateFd,
|
||||||
@ -5993,7 +6009,8 @@ qemuProcessStart(virConnectPtr conn,
|
|||||||
if (!migrateFrom && !snapshot)
|
if (!migrateFrom && !snapshot)
|
||||||
flags |= VIR_QEMU_PROCESS_START_NEW;
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
if (migrateFrom) {
|
if (migrateFrom) {
|
||||||
@ -6072,7 +6089,8 @@ qemuProcessCreatePretendCmd(virConnectPtr conn,
|
|||||||
flags |= VIR_QEMU_PROCESS_START_PRETEND;
|
flags |= VIR_QEMU_PROCESS_START_PRETEND;
|
||||||
flags |= VIR_QEMU_PROCESS_START_NEW;
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuProcessPrepareDomain(conn, driver, vm, flags) < 0)
|
if (qemuProcessPrepareDomain(conn, driver, vm, flags) < 0)
|
||||||
@ -6476,6 +6494,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
/* clean up migration data */
|
/* clean up migration data */
|
||||||
VIR_FREE(priv->migTLSAlias);
|
VIR_FREE(priv->migTLSAlias);
|
||||||
|
virCPUDefFree(priv->origCPU);
|
||||||
|
priv->origCPU = NULL;
|
||||||
|
|
||||||
/* clear previously used namespaces */
|
/* clear previously used namespaces */
|
||||||
virBitmapFree(priv->namespaces);
|
virBitmapFree(priv->namespaces);
|
||||||
|
@ -75,6 +75,7 @@ typedef enum {
|
|||||||
int qemuProcessStart(virConnectPtr conn,
|
int qemuProcessStart(virConnectPtr conn,
|
||||||
virQEMUDriverPtr driver,
|
virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
|
virCPUDefPtr updatedCPU,
|
||||||
qemuDomainAsyncJob asyncJob,
|
qemuDomainAsyncJob asyncJob,
|
||||||
const char *migrateFrom,
|
const char *migrateFrom,
|
||||||
int stdin_fd,
|
int stdin_fd,
|
||||||
@ -93,6 +94,7 @@ virCommandPtr qemuProcessCreatePretendCmd(virConnectPtr conn,
|
|||||||
|
|
||||||
int qemuProcessInit(virQEMUDriverPtr driver,
|
int qemuProcessInit(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
|
virCPUDefPtr updatedCPU,
|
||||||
qemuDomainAsyncJob asyncJob,
|
qemuDomainAsyncJob asyncJob,
|
||||||
bool migration,
|
bool migration,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
Loading…
Reference in New Issue
Block a user