Utilize the existing fake reboot mechanism to do reboot for TDX guest.
Different from normal guest, TDX guest doesn't support system_reset,
so have to kill the old guest and start a new one to simulate the reboot.
Co-developed-by: Chenyi Qiang <chenyi.qiang(a)intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan(a)intel.com>
---
src/qemu/qemu_process.c | 81 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 78 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 870b089024..cb9deecb22 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -446,6 +446,68 @@ qemuProcessHandleReset(qemuMonitor *mon G_GNUC_UNUSED,
}
+/*
+ * Secure guest doesn't support fake reboot via machine CPU reset.
+ * We thus fake reboot via QEMU re-creation.
+ */
+static void
+qemuProcessFakeRebootViaRecreate(virDomainObj *vm)
+{
+ qemuDomainObjPrivate *priv = vm->privateData;
+ virQEMUDriver *driver = priv->driver;
+ int ret = -1;
+
+ VIR_DEBUG("Handle secure guest reboot: destroy phase");
+
+ virObjectLock(vm);
+ if (qemuProcessBeginStopJob(vm, VIR_JOB_DESTROY, 0) < 0)
+ goto cleanup;
+
+ if (virDomainObjCheckActive(vm) < 0) {
+ qemuProcessEndStopJob(vm);
+ goto cleanup;
+ }
+
+ qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED,
+ VIR_ASYNC_JOB_NONE, 0);
+ virDomainAuditStop(vm, "destroyed");
+
+ /* skip remove inactive domain from active list */
+ qemuProcessEndStopJob(vm);
+
+ VIR_DEBUG("Handle secure guest reboot: boot phase");
+
+ if (qemuProcessBeginJob(vm, VIR_DOMAIN_JOB_OPERATION_START, 0) < 0) {
+ qemuDomainRemoveInactive(driver, vm, 0, false);
+ goto cleanup;
+ }
+
+ if (qemuProcessStart(NULL, driver, vm, NULL, VIR_ASYNC_JOB_START,
+ NULL, -1, NULL, NULL, NULL,
+ VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
+ 0) < 0) {
+ virDomainAuditStart(vm, "booted", false);
+ qemuDomainRemoveInactive(driver, vm, 0, false);
+ goto endjob;
+ }
+
+ virDomainAuditStart(vm, "booted", true);
+
+ qemuDomainSaveStatus(vm);
+ ret = 0;
+
+ endjob:
+ qemuProcessEndJob(vm);
+
+ cleanup:
+ priv->pausedShutdown = false;
+ qemuDomainSetFakeReboot(vm, false);
+ if (ret == -1)
+ ignore_value(qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE));
+ virDomainObjEndAPI(&vm);
+}
+
+
/*
* Since we have the '-no-shutdown' flag set, the
* QEMU process will currently have guest OS shutdown
@@ -455,15 +517,13 @@ qemuProcessHandleReset(qemuMonitor *mon G_GNUC_UNUSED,
* guest OS booting up again
*/
static void
-qemuProcessFakeReboot(void *opaque)
+qemuProcessFakeRebootViaReset(virDomainObj *vm)
{
- virDomainObj *vm = opaque;
qemuDomainObjPrivate *priv = vm->privateData;
virQEMUDriver *driver = priv->driver;
virDomainRunningReason reason = VIR_DOMAIN_RUNNING_BOOTED;
int ret = -1, rc;
- VIR_DEBUG("vm=%p", vm);
virObjectLock(vm);
if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
goto cleanup;
@@ -509,6 +569,21 @@ qemuProcessFakeReboot(void *opaque)
}
+static void
+qemuProcessFakeReboot(void *opaque)
+{
+ virDomainObj *vm = opaque;
+
+ VIR_DEBUG("vm=%p", vm);
+
+ if (vm->def->sec &&
+ vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_TDX)
+ qemuProcessFakeRebootViaRecreate(vm);
+ else
+ qemuProcessFakeRebootViaReset(vm);
+}
+
+
void
qemuProcessShutdownOrReboot(virDomainObj *vm)
{
--
2.34.1