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

From: Edgecombe, Rick P

Date: Thu Sep 24 2026 - 19:42:04 EST


On Thu, 2026-09-24 at 12:10 +0800, Zhenzhong Duan wrote:
> 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>

We are going to need a lot more info about what this TDG call is doing. Look at
the host side seamcall wrapper commits for examples.

> ---
> 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)
> +{

offset is 0 for all callers in this series. So I'd think to drop it unless there
is some other code coming very very soon.

Can we turn some of these others into proper types? Why not pass struct
pci_tsm_mmio_entry or struct pci_dev pointers instead of raw unsigned ints?

Actually, the only caller just accepts the whole pci_tsm_mmio_entry, so you just
need:

int tdx_mcall_mmio_accept(struct pci_dev *dev, struct pci_tsm_mmio_entry *entry)

What do you think?

> + struct tdx_module_args args = {
> + .rcx = gpa | TDX_PS_4K,

Always 4KB? Needs an explanation in the log at least.

> + .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);