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(a)intel.com>
Reviewed-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 10 +++++++++-
src/qemu/qemu_monitor.c | 6 ++++++
src/qemu/qemu_process.c | 14 +++++++++-----
src/qemu/qemu_process.h | 2 ++
5 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 49f83613e3..c704cb2114 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -130,6 +130,7 @@ struct _qemuDomainObjPrivate {
char *lockState;
bool fakeReboot;
+ bool fakeReset;
bool pausedShutdown;
/* allowReboot:
*
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 206f6504df..37b16f56b0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -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);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index d726175d42..c1fef8d5de 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -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") &&
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 68c0a5b64d..e7fcace9e2 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -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);
}
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index b8c4af4aaf..9f783790ac 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -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,
--
2.47.1