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.qi...@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.d...@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

Reply via email to