[PATCH v1 13/28] i386/tdx: finalize TDX guest state upon reset

Ani Sinha posted 28 patches 1 month, 4 weeks ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>, "Michael S. Tsirkin" <mst@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Richard Henderson <richard.henderson@linaro.org>, Eduardo Habkost <eduardo@habkost.net>, David Woodhouse <dwmw2@infradead.org>, Paul Durrant <paul@xen.org>, Bernhard Beschow <shentey@gmail.com>, Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Peter Xu <peterx@redhat.com>, David Hildenbrand <david@kernel.org>, Peter Maydell <peter.maydell@linaro.org>, Marcelo Tosatti <mtosatti@redhat.com>, Zhao Liu <zhao1.liu@intel.com>, Song Gao <gaosong@loongson.cn>, Huacai Chen <chenhuacai@kernel.org>, Aurelien Jarno <aurelien@aurel32.net>, Jiaxun Yang <jiaxun.yang@flygoat.com>, Aleksandar Rikalo <arikalo@gmail.com>, Nicholas Piggin <npiggin@gmail.com>, Harsh Prateek Bora <harshpb@linux.ibm.com>, Chinmay Rath <rathc@linux.ibm.com>, Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <dbarboza@ventanamicro.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Halil Pasic <pasic@linux.ibm.com>, Christian Borntraeger <borntraeger@linux.ibm.com>, Eric Farman <farman@linux.ibm.com>, Matthew Rosato <mjrosato@linux.ibm.com>, Ilya Leoshkevich <iii@linux.ibm.com>, Thomas Huth <thuth@redhat.com>
There is a newer version of this series
[PATCH v1 13/28] i386/tdx: finalize TDX guest state upon reset
Posted by Ani Sinha 1 month, 4 weeks ago
When the confidential virtual machine KVM file descriptor changes due to the
guest reset, some TDX specific setup steps needs to be done again. This
includes finalizing the inital guest launch state again. This change
re-executes some parts of the TDX setup during the device reset phaze using a
resettable interface. This finalizes the guest launch state again and locks
it in. Also care has been taken so that notifiers are installed only once.

Signed-off-by: Ani Sinha <anisinha@redhat.com>
---
 target/i386/kvm/tdx.c | 39 +++++++++++++++++++++++++++++++++++++--
 target/i386/kvm/tdx.h |  1 +
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c
index bafaf62cdb..1903cc2132 100644
--- a/target/i386/kvm/tdx.c
+++ b/target/i386/kvm/tdx.c
@@ -19,6 +19,7 @@
 #include "crypto/hash.h"
 #include "system/kvm_int.h"
 #include "system/runstate.h"
+#include "system/reset.h"
 #include "system/system.h"
 #include "system/ramblock.h"
 #include "system/address-spaces.h"
@@ -389,6 +390,19 @@ static void tdx_finalize_vm(Notifier *notifier, void *unused)
     CONFIDENTIAL_GUEST_SUPPORT(tdx_guest)->ready = true;
 }
 
+static void tdx_handle_reset(Object *obj, ResetType type)
+{
+    if (!runstate_is_running()) {
+        return;
+    }
+
+    if (!kvm_enable_hypercall(BIT_ULL(KVM_HC_MAP_GPA_RANGE))) {
+        error_setg(&error_fatal, "KVM_HC_MAP_GPA_RANGE not enabled for guest");
+    }
+
+    tdx_finalize_vm(NULL, NULL);
+}
+
 static Notifier tdx_machine_done_notify = {
     .notify = tdx_finalize_vm,
 };
@@ -689,6 +703,7 @@ static int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
     X86MachineState *x86ms = X86_MACHINE(ms);
     TdxGuest *tdx = TDX_GUEST(cgs);
     int r = 0;
+    static bool notifier_added;
 
     kvm_mark_guest_state_protected();
 
@@ -736,8 +751,10 @@ static int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
      */
     kvm_readonly_mem_allowed = false;
 
-    qemu_add_machine_init_done_notifier(&tdx_machine_done_notify);
-
+    if (!notifier_added) {
+        qemu_add_machine_init_done_notifier(&tdx_machine_done_notify);
+        notifier_added = true;
+    }
     tdx_guest = tdx;
     return 0;
 }
@@ -1503,6 +1520,7 @@ OBJECT_DEFINE_TYPE_WITH_INTERFACES(TdxGuest,
                                    TDX_GUEST,
                                    X86_CONFIDENTIAL_GUEST,
                                    { TYPE_USER_CREATABLE },
+                                   { TYPE_RESETTABLE_INTERFACE },
                                    { NULL })
 
 static void tdx_guest_init(Object *obj)
@@ -1536,20 +1554,37 @@ static void tdx_guest_init(Object *obj)
 
     tdx->event_notify_vector = -1;
     tdx->event_notify_apicid = -1;
+    qemu_register_resettable(obj);
 }
 
 static void tdx_guest_finalize(Object *obj)
 {
 }
 
+static ResettableState *tdx_reset_state(Object *obj)
+{
+    TdxGuest *tdx = TDX_GUEST(obj);
+    return &tdx->reset_state;
+}
+
 static void tdx_guest_class_init(ObjectClass *oc, const void *data)
 {
     ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
     X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
+    ResettableClass *rc = RESETTABLE_CLASS(oc);
 
     klass->kvm_init = tdx_kvm_init;
     x86_klass->kvm_type = tdx_kvm_type;
     x86_klass->cpu_instance_init = tdx_cpu_instance_init;
     x86_klass->adjust_cpuid_features = tdx_adjust_cpuid_features;
     x86_klass->check_features = tdx_check_features;
+
+    /*
+     * the exit phase makes sure sev handles reset after all legacy resets
+     * have taken place (in the hold phase) and IGVM has also properly
+     * set up the boot state.
+     */
+    rc->phases.exit = tdx_handle_reset;
+    rc->get_state = tdx_reset_state;
+
 }
diff --git a/target/i386/kvm/tdx.h b/target/i386/kvm/tdx.h
index 1c38faf983..264fbe530c 100644
--- a/target/i386/kvm/tdx.h
+++ b/target/i386/kvm/tdx.h
@@ -70,6 +70,7 @@ typedef struct TdxGuest {
 
     uint32_t event_notify_vector;
     uint32_t event_notify_apicid;
+    ResettableState reset_state;
 } TdxGuest;
 
 #ifdef CONFIG_TDX
-- 
2.42.0
Re: [PATCH v1 13/28] i386/tdx: finalize TDX guest state upon reset
Posted by Gerd Hoffmann 1 month, 3 weeks ago
On Fri, Dec 12, 2025 at 08:33:41PM +0530, Ani Sinha wrote:
> When the confidential virtual machine KVM file descriptor changes due to the
> guest reset, some TDX specific setup steps needs to be done again. This
> includes finalizing the inital guest launch state again. This change
> re-executes some parts of the TDX setup during the device reset phaze using a
> resettable interface. This finalizes the guest launch state again and locks
> it in. Also care has been taken so that notifiers are installed only once.

> +    if (!notifier_added) {
> +        qemu_add_machine_init_done_notifier(&tdx_machine_done_notify);
> +        notifier_added = true;
> +    }

Is this notifier needed still if you finalize the initial guest state in
the reset handler?

take care,
  Gerd
Re: [PATCH v1 13/28] i386/tdx: finalize TDX guest state upon reset
Posted by Ani Sinha 1 month, 3 weeks ago

On Wed, 17 Dec 2025, Gerd Hoffmann wrote:

> On Fri, Dec 12, 2025 at 08:33:41PM +0530, Ani Sinha wrote:
> > When the confidential virtual machine KVM file descriptor changes due to the
> > guest reset, some TDX specific setup steps needs to be done again. This
> > includes finalizing the inital guest launch state again. This change
> > re-executes some parts of the TDX setup during the device reset phaze using a
> > resettable interface. This finalizes the guest launch state again and locks
> > it in. Also care has been taken so that notifiers are installed only once.
>
> > +    if (!notifier_added) {
> > +        qemu_add_machine_init_done_notifier(&tdx_machine_done_notify);
> > +        notifier_added = true;
> > +    }
>
> Is this notifier needed still if you finalize the initial guest state in
> the reset handler?
>

Yes good point. Following small change will be needed.

From 59e1df5f3c64a75a14139c498106a225bf3b42b2 Mon Sep 17 00:00:00 2001
From: Ani Sinha <anisinha@redhat.com>
Date: Thu, 18 Dec 2025 14:11:40 +0530
Subject: [PATCH] i386/tdx: remove notifier that is not needed

Take Gerd's suggestion.

Signed-off-by: Ani Sinha <anisinha@redhat.com>
---
 target/i386/kvm/tdx.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c
index 20f9d63eff..144020e378 100644
--- a/target/i386/kvm/tdx.c
+++ b/target/i386/kvm/tdx.c
@@ -392,7 +392,7 @@ static void tdx_finalize_vm(Notifier *notifier, void *unused)

 static void tdx_handle_reset(Object *obj, ResetType type)
 {
-    if (!runstate_is_running()) {
+    if (!runstate_is_running() && !phase_check(PHASE_MACHINE_READY)) {
         return;
     }

@@ -429,9 +429,6 @@ static NotifierWithReturn tdx_vmfd_pre_change_notifier = {
     .notify = set_tdx_vm_uninitialized,
 };

-static Notifier tdx_machine_done_notify = {
-    .notify = tdx_finalize_vm,
-};

 /*
  * Some CPUID bits change from fixed1 to configurable bits when TDX module
@@ -778,7 +775,6 @@ static int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
     kvm_readonly_mem_allowed = false;

     if (!notifier_added) {
-        qemu_add_machine_init_done_notifier(&tdx_machine_done_notify);
         kvm_vmfd_add_pre_change_notifier(&tdx_vmfd_pre_change_notifier);
         notifier_added = true;
     }
-- 
2.42.0