i386/tdx: finalize TDX guest state upon reset
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 initial 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. Machine done notifier which was previously used is no longer needed as the same code is now executed as a part of VM reset. Signed-off-by: Ani Sinha <anisinha@redhat.com> Link: https://lore.kernel.org/r/20260225035000.385950-18-anisinha@redhat.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Ani Sinha committed
Feb 25, 2026 at 09:19 UTC
05caf2690e5a29a25928c6717c4204ea3c0bfee3
3 files changed
+37
-5
target/i386/kvm/tdx.c
+33
-5
@@ -19,6 +19,7 @@
19
#include "crypto/hash.h"
20
#include "system/kvm_int.h"
21
#include "system/runstate.h"
22
+#include "system/reset.h"
23
#include "system/system.h"
24
#include "system/ramblock.h"
25
#include "system/address-spaces.h"
@@ -38,6 +39,7 @@
39
#include "kvm_i386.h"
40
#include "tdx.h"
41
#include "tdx-quote-generator.h"
42
+#include "trace.h"
43
44
#include "standard-headers/asm-x86/kvm_para.h"
45
@@ -389,9 +391,19 @@ static void tdx_finalize_vm(Notifier *notifier, void *unused)
391
CONFIDENTIAL_GUEST_SUPPORT(tdx_guest)->ready = true;
392
}
393
392
-static Notifier tdx_machine_done_notify = {
393
- .notify = tdx_finalize_vm,
394
-};
394
+static void tdx_handle_reset(Object *obj, ResetType type)
395
+{
396
+ if (!runstate_is_running() && !phase_check(PHASE_MACHINE_READY)) {
397
+ return;
398
+ }
399
+
400
+ if (!kvm_enable_hypercall(BIT_ULL(KVM_HC_MAP_GPA_RANGE))) {
401
+ error_setg(&error_fatal, "KVM_HC_MAP_GPA_RANGE not enabled for guest");
402
+ }
403
+
404
+ tdx_finalize_vm(NULL, NULL);
405
+ trace_tdx_handle_reset();
406
+}
407
408
/*
409
* Some CPUID bits change from fixed1 to configurable bits when TDX module
@@ -738,8 +750,6 @@ static int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
750
*/
751
kvm_readonly_mem_allowed = false;
752
741
- qemu_add_machine_init_done_notifier(&tdx_machine_done_notify);
742
-
753
tdx_guest = tdx;
754
return 0;
755
}
@@ -1505,6 +1515,7 @@ OBJECT_DEFINE_TYPE_WITH_INTERFACES(TdxGuest,
1515
TDX_GUEST,
1516
X86_CONFIDENTIAL_GUEST,
1517
{ TYPE_USER_CREATABLE },
1518
+ { TYPE_RESETTABLE_INTERFACE },
1519
{ NULL })
1520
1521
static void tdx_guest_init(Object *obj)
@@ -1538,16 +1549,24 @@ static void tdx_guest_init(Object *obj)
1549
1550
tdx->event_notify_vector = -1;
1551
tdx->event_notify_apicid = -1;
1552
+ qemu_register_resettable(obj);
1553
}
1554
1555
static void tdx_guest_finalize(Object *obj)
1556
{
1557
}
1558
1559
+static ResettableState *tdx_reset_state(Object *obj)
1560
+{
1561
+ TdxGuest *tdx = TDX_GUEST(obj);
1562
+ return &tdx->reset_state;
1563
+}
1564
+
1565
static void tdx_guest_class_init(ObjectClass *oc, const void *data)
1566
{
1567
ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
1568
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
1569
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
1570
1571
klass->kvm_init = tdx_kvm_init;
1572
klass->can_rebuild_guest_state = true;
@@ -1555,4 +1574,13 @@ static void tdx_guest_class_init(ObjectClass *oc, const void *data)
1574
x86_klass->cpu_instance_init = tdx_cpu_instance_init;
1575
x86_klass->adjust_cpuid_features = tdx_adjust_cpuid_features;
1576
x86_klass->check_features = tdx_check_features;
1577
+
1578
+ /*
1579
+ * the exit phase makes sure sev handles reset after all legacy resets
1580
+ * have taken place (in the hold phase) and IGVM has also properly
1581
+ * set up the boot state.
1582
+ */
1583
+ rc->phases.exit = tdx_handle_reset;
1584
+ rc->get_state = tdx_reset_state;
1585
+
1586
}
target/i386/kvm/tdx.h
+1
@@ -70,6 +70,7 @@ typedef struct TdxGuest {
70
71
uint32_t event_notify_vector;
72
uint32_t event_notify_apicid;
73
+ ResettableState reset_state;
74
} TdxGuest;
75
76
#ifdef CONFIG_TDX
target/i386/kvm/trace-events
+3
@@ -14,3 +14,6 @@ kvm_xen_soft_reset(void) ""
14
kvm_xen_set_shared_info(uint64_t gfn) "shared info at gfn 0x%" PRIx64
15
kvm_xen_set_vcpu_attr(int cpu, int type, uint64_t gpa) "vcpu attr cpu %d type %d gpa 0x%" PRIx64
16
kvm_xen_set_vcpu_callback(int cpu, int vector) "callback vcpu %d vector %d"
17
+
18
+# tdx.c
19
+tdx_handle_reset(void) ""