Register a callback to handle memory acceptance after memory plugging in
TDX guests. When memory is added by virtio-mem or other memory hotplug
drivers, the TDX guest must accept the memory pages using
TDG.MEM.PAGE.ACCEPT TDCALL before they can be safely accessed.

The callback uses the existing tdx_accept_memory() function to accept all
pages in the newly plugged memory range. Without this callback, newly
added memory would remain in "unaccepted" state, and any access to these
pages would trigger VM exits and potentially cause guest crashes. The
callback is registered during TDX setup and remains active for the
lifetime of the guest, ensuring all dynamically added memory is properly
accepted before being made available to the kernel's memory management
subsystem.

Signed-off-by: Zhenzhong Duan <[email protected]>
---
 arch/x86/coco/tdx/tdx.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 186915a17c50..d93ba092d311 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -326,6 +326,25 @@ static void reduce_unnecessary_ve(void)
        enable_cpu_topology_enumeration();
 }
 
+static int tdx_memory_post_plug(u64 addr, u64 size)
+{
+       u64 end;
+
+       if (!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(size))
+               return -EINVAL;
+
+       if (check_add_overflow(addr, size, &end))
+               return -EINVAL;
+
+       if (tdx_accept_memory(addr, end))
+               return 0;
+
+       pr_err("Failed to accept memory [0x%llx, 0x%llx)\n",
+              (unsigned long long)addr, (unsigned long long)end);
+
+       return -EINVAL;
+}
+
 static void tdx_setup(u64 *cc_mask)
 {
        struct tdx_module_args args = {};
@@ -359,6 +378,8 @@ static void tdx_setup(u64 *cc_mask)
        disable_sept_ve(td_attr);
 
        reduce_unnecessary_ve();
+
+       set_memory_post_plug_callback(tdx_memory_post_plug);
 }
 
 /*
-- 
2.52.0


Reply via email to