]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Support domain reset command for TDX guest
authorZhenzhong Duan <zhenzhong.duan@intel.com>
Thu, 10 Jul 2025 07:21:23 +0000 (03:21 -0400)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 25 Jul 2025 10:36:11 +0000 (11:36 +0100)
TDX guest doesn't support system_reset, so have to kill the old QEMU and
start a new one to simulate the reset. This can be achieved by calling
qemuProcessFakeRebootViaRecreate().

Simiar as FakeReboot, QEMU sends SHUTDOWN event with "host-signal" reason
which can trigger another FakeReset. Check if a FakeReset is ongoing and
bypass "host-signal" processing which originally comes from FakeReset.

Domain lock is already hold in qemuDomainReset() before calling
qemuProcessFakeRebootViaRecreate(), so bypass locking in it.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_process.c
src/qemu/qemu_process.h

index b53ebcb47898e7a524b91caaa1daaa35e7336035..1afd932764147ae86a6acc976d8f2f99502851b0 100644 (file)
@@ -130,6 +130,7 @@ struct _qemuDomainObjPrivate {
     char *lockState;
 
     bool fakeReboot;
+    bool fakeReset;
     bool pausedShutdown;
     /* allowReboot:
      *
index 30c4fadeeb6f2a7c64338a6b80baa7f98111b482..8204c72d2fee57c5736162b2c1f2407c0816bbef 100644 (file)
@@ -1970,13 +1970,21 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags)
     if (virDomainResetEnsureACL(dom->conn, vm->def) < 0)
         goto cleanup;
 
+    priv = vm->privateData;
+
+    if (vm->def->sec &&
+        vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_TDX) {
+        priv->fakeReset = true;
+        ret = qemuProcessFakeRebootViaRecreate(vm, true);
+        goto cleanup;
+    }
+
     if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
         goto cleanup;
 
     if (virDomainObjCheckActive(vm) < 0)
         goto endjob;
 
-    priv = vm->privateData;
     qemuDomainObjEnterMonitor(vm);
     ret = qemuMonitorSystemReset(priv->mon);
     qemuDomainObjExitMonitor(vm);
index d726175d42d1f1e69ecd69fab177c6369f61dca9..c1fef8d5dedb1b75f365d80392b2e62e28254df5 100644 (file)
@@ -1083,6 +1083,12 @@ qemuMonitorEmitShutdown(qemuMonitor *mon, virTristateBool guest,
         if (priv->fakeReboot && STREQ_NULLABLE(reason, "host-signal"))
             return;
 
+        /* Similar as FakeReboot for FakeReset. */
+        if (priv->fakeReset && STREQ_NULLABLE(reason, "host-signal")) {
+            priv->fakeReset = false;
+            return;
+        }
+
         if ((STREQ_NULLABLE(reason, "guest-shutdown") &&
              vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART) ||
             (STREQ_NULLABLE(reason, "guest-reset") &&
index 48427b98639a24d38c0b302d6b96137eb1524d6c..313667ef9f93fa1fe5ec2543c608aff9260e967e 100644 (file)
@@ -450,8 +450,8 @@ 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)
+int
+qemuProcessFakeRebootViaRecreate(virDomainObj *vm, bool locked)
 {
     qemuDomainObjPrivate *priv = vm->privateData;
     virQEMUDriver *driver = priv->driver;
@@ -460,7 +460,9 @@ qemuProcessFakeRebootViaRecreate(virDomainObj *vm)
 
     VIR_DEBUG("Handle secure guest reboot: destroy phase");
 
-    virObjectLock(vm);
+    if (!locked)
+        virObjectLock(vm);
+
     if (qemuProcessBeginStopJob(vm, VIR_JOB_DESTROY, 0) < 0)
         goto cleanup;
 
@@ -513,7 +515,9 @@ qemuProcessFakeRebootViaRecreate(virDomainObj *vm)
     qemuDomainSetFakeReboot(vm, false);
     if (ret == -1)
         ignore_value(qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE));
-    virDomainObjEndAPI(&vm);
+    if (!locked)
+        virDomainObjEndAPI(&vm);
+    return ret;
 }
 
 
@@ -587,7 +591,7 @@ qemuProcessFakeReboot(void *opaque)
 
     if (vm->def->sec &&
         vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_TDX)
-        qemuProcessFakeRebootViaRecreate(vm);
+        ignore_value(qemuProcessFakeRebootViaRecreate(vm, false));
     else
         qemuProcessFakeRebootViaReset(vm);
 }
index b8c4af4aaf858736f2a300746a4b5cfd5b0580bb..9f783790ac757743acfaf965d9bfa4ff026d30af 100644 (file)
@@ -190,6 +190,8 @@ typedef enum {
 
 int qemuProcessKill(virDomainObj *vm, unsigned int flags);
 
+int qemuProcessFakeRebootViaRecreate(virDomainObj *vm, bool locked);
+
 void qemuProcessShutdownOrReboot(virDomainObj *vm);
 
 void qemuProcessAutoDestroy(virDomainObj *dom,