[RFC PATCH 08/15] x86/tdx: Add TDG.MMIO.ACCEPT module call wrapper for TDX Connect

From: Zhenzhong Duan

Date: Thu Sep 24 2026 - 00:11:55 EST


TDG.MMIO.ACCEPT verifies and accepts a pending private MMIO range for
a trusted device.

The MMIO range to be accepted can be a sub-range of the MMIO ranges
originally defined in the Device Interface Report. Because the TDX
module caches these ranges from the Device Interface Report, the guest
does not need to pass the explicit physical start and end addresses of
the MMIO range. Instead, it only needs to provide the target MMIO
range index, the offset within that range, and the size to be accepted.

Translate TDX module return codes into Linux errno values.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>
---
arch/x86/coco/tdx/tdx_connect.c | 38 +++++++++++++++++++++++++++++++
arch/x86/include/asm/shared/tdx.h | 1 +
arch/x86/include/asm/tdx.h | 1 +
3 files changed, 40 insertions(+)

diff --git a/arch/x86/coco/tdx/tdx_connect.c b/arch/x86/coco/tdx/tdx_connect.c
index 1409b1a30cc6..09a92fe23357 100644
--- a/arch/x86/coco/tdx/tdx_connect.c
+++ b/arch/x86/coco/tdx/tdx_connect.c
@@ -71,3 +71,41 @@ int tdx_mcall_tdi_read(u64 func_id, u64 field, u64 *value)
return tdx_mcall_tdi_to_errno(ret);
}
EXPORT_SYMBOL_FOR_MODULES(tdx_mcall_tdi_read, "tdx-guest");
+
+/**
+ * tdx_mcall_mmio_accept() - Accept a pending private MMIO mapping of a
+ * Trust Device Interface (TDI) instance
+ * @func_id: Function identifier specifying the TDI instance
+ * @index: MMIO range index from the Device Interface Report
+ * @pg_offset: Range offset to start accepting the subrange from, in pages
+ * @page_cnt: Count of pages to accept
+ * @gpa: GPA base address the subrange mapped to
+ *
+ * Verify and accept a pending private MMIO mapping. Upon success, the MMIO
+ * pages are set as mapped in the TDX module.
+ *
+ * Return 0 on success, -EINVAL for unaligned GPA, -ENXIO for invalid operands,
+ * -EBUSY for busy operation, -ENODEV for TDI not present or invalid metadata,
+ * or -EIO on other TDCALL failures.
+ *
+ */
+int tdx_mcall_mmio_accept(u64 func_id, u64 index, u32 pg_offset, u32 page_cnt, phys_addr_t gpa)
+{
+ struct tdx_module_args args = {
+ .rcx = gpa | TDX_PS_4K,
+ .rdx = index,
+ .r8 = func_id,
+ .r9 = (u64)pg_offset << 32 | page_cnt,
+ };
+ u64 ret;
+
+ if (!IS_ALIGNED(gpa, PAGE_SIZE))
+ return -EINVAL;
+
+ ret = __tdcall_ret(TDG_MMIO_ACCEPT, &args);
+ if (!ret)
+ return 0;
+
+ return tdx_mcall_tdi_to_errno(ret);
+}
+EXPORT_SYMBOL_FOR_MODULES(tdx_mcall_mmio_accept, "tdx-guest");
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index 499103f7a01b..ce80fb2116fb 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -21,6 +21,7 @@
#define TDG_VM_RD 7
#define TDG_VM_WR 8
#define TDG_TDI_READ 67
+#define TDG_MMIO_ACCEPT 71

/* TDX TD attributes */
#define TDX_TD_ATTR_DEBUG_BIT 0
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 71cd701d346f..e6493f3bc0d1 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -155,6 +155,7 @@ struct tdcm_rsp_check_teeio_supp {

u64 tdx_hcall_tdcm(u16 devid, void *buf, size_t size, u8 vector);
int tdx_mcall_tdi_read(u64 func_id, u64 field, u64 *value);
+int tdx_mcall_mmio_accept(u64 func_id, u64 index, u32 pg_offset, u32 page_cnt, phys_addr_t gpa);
#endif

void __init tdx_dump_attributes(u64 td_attr);
--
2.52.0