mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Lu Baolu <baolu.lu@linux.intel.com>
To: iommu@lists.linux.dev, x86@kernel.org,
	linux-coco@lists.linux.dev, kvm@vger.kernel.org
Cc: Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>,
	Kiryl Shutsemau <kas@kernel.org>,
	Rick Edgecombe <rick.p.edgecombe@intel.com>,
	yilun.xu@linux.intel.com, xiaoyao.li@intel.com,
	Chao Gao <chao.gao@intel.com>,
	Binbin Wu <binbin.wu@linux.intel.com>,
	linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com>
Subject: [PATCH v3 1/9] x86/virt/tdx: Add SEAMCALL wrappers for IOMMU setup/clear
Date: Thu, 12 Nov 2026 12:30:46 +0800	[thread overview]
Message-ID: <20261112043054.2664857-2-baolu.lu@linux.intel.com> (raw)
In-Reply-To: <20261112043054.2664857-1-baolu.lu@linux.intel.com>

Intel VT-d hardware gains a second set of DMA translation structures,
managed by the TDX module and used only for devices assigned to TDs.
Each IOMMU has a trusted root-table address register and a trusted
invalidation queue, both accessible only from SEAM. The existing
untrusted DMA translation path of the IOMMU stays under host control.

Before trusted DMA can be used through an IOMMU, the TDX module must
initialize these resources. TDH.IOMMU.SETUP does this: it puts the
IOMMU into Secure TDX Mode, programs the trusted root table and the
trusted invalidation queue, and protects the related I/O resources
from further untrusted host access. The host provides the memory for
this through a parameter page that lists the invalidation queue
buffers and the metadata pages the TDX module needs for the IOMMU.

TDH.IOMMU.CLEAR does the reverse. It tears down the Secure TDX Mode
state of the IOMMU, after which the host can reclaim the memory.

Add wrappers for both SEAMCALLs and export them to the tdx-host driver,
which allocates the memory and issues them.

TDH.IOMMU.SETUP and TDH.IOMMU.CLEAR are defined in the Intel TDX
Connect ABI Specification [1].

[1] https://cdrdv2.intel.com/v1/dl/getContent/858625

Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 arch/x86/include/asm/tdx.h  | 14 ++++++++++
 arch/x86/virt/vmx/tdx/tdx.h |  2 ++
 arch/x86/virt/vmx/tdx/tdx.c | 53 +++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+)

diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 89e7628796b0..d077990802b9 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -162,6 +162,17 @@ struct tdx_td {
 	int tdcx_nr_pages;
 };
 
+#define TDX_IOMMU_MT_IQ_NR	2
+#define TDX_IOMMU_MT_MAX_PAGES	(PAGE_SIZE / sizeof(u64) - TDX_IOMMU_MT_IQ_NR)
+
+/* IOMMU_MT parameter page for TDH.IOMMU.SETUP (ABI spec Table 3.35). */
+struct tdx_iommu_mt_param {
+	u64 iq[TDX_IOMMU_MT_IQ_NR];	/* HPA | number of 4K pages */
+	u64 mt[TDX_IOMMU_MT_MAX_PAGES];	/* HPA of each metadata page */
+};
+
+static_assert(sizeof(struct tdx_iommu_mt_param) == PAGE_SIZE);
+
 struct tdx_vp {
 	/* TDVP root page */
 	struct page *tdvpr_page;
@@ -202,6 +213,9 @@ u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, enum pg_level level, u64 *ex
 u64 tdh_phymem_cache_wb(bool resume);
 u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td);
 u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, kvm_pfn_t pfn);
+u64 tdh_iommu_setup(u64 reg_base, struct tdx_iommu_mt_param *param,
+		    u64 *tdx_iommu_id);
+u64 tdh_iommu_clear(u64 tdx_iommu_id);
 #else
 static inline void tdx_init(void) { }
 static inline u32 tdx_get_nr_guest_keyids(void) { return 0; }
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index cac0a5abbff1..693adda89311 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -53,6 +53,8 @@
 #define TDH_EXT_INIT			60
 #define TDH_EXT_MEM_ADD			61
 #define TDH_SYS_DISABLE			69
+#define TDH_IOMMU_SETUP			128
+#define TDH_IOMMU_CLEAR			129
 
 /* TDX page types */
 #define	PT_NDA		0x0
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 4cce77b6a31f..a1f35188a272 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -2567,3 +2567,56 @@ void tdx_sys_disable(void)
 	if (ret && (ret & TDX_SW_ERROR) != TDX_SW_ERROR)
 		pr_err("TDH.SYS.DISABLE failed: 0x%016llx\n", ret);
 }
+
+/* No cache flush is needed; hardware keeps caches coherent across KeyIDs. */
+u64 tdh_iommu_setup(u64 reg_base, struct tdx_iommu_mt_param *param,
+		    u64 *tdx_iommu_id)
+{
+	struct tdx_module_args args = {
+		.rcx = reg_base,
+		.rdx = __pa(param),
+	};
+	u64 ret;
+
+	/*
+	 * Retry only on TDX_INTERRUPTED_RESUMABLE:
+	 *
+	 *  - TDX_INTERRUPTED_RESUMABLE guarantees forward progress between
+	 *    calls.
+	 *  - On TDX_INTERRUPTED_RESUMABLE, all registers except RAX remain
+	 *    unchanged.
+	 *
+	 * The ABI spec also allows retrying on TDX_OPERAND_BUSY, but that
+	 * status doesn't guarantee forward progress, so retrying could spin
+	 * forever. The host serializes all TDH.IOMMU.SETUP and
+	 * TDH.IOMMU.CLEAR calls for an IOMMU, so the TDX module should never
+	 * report the operand as busy.
+	 */
+	do {
+		ret = seamcall_ret(TDH_IOMMU_SETUP, &args);
+	} while (ret == TDX_INTERRUPTED_RESUMABLE);
+
+	*tdx_iommu_id = args.rcx;
+
+	return ret;
+}
+EXPORT_SYMBOL_FOR_MODULES(tdh_iommu_setup, "tdx-host");
+
+u64 tdh_iommu_clear(u64 tdx_iommu_id)
+{
+	struct tdx_module_args args = {
+		.rcx = tdx_iommu_id,
+	};
+	u64 ret;
+
+	/*
+	 * Don't retry on TDX_OPERAND_BUSY. See the comment in
+	 * tdh_iommu_setup().
+	 */
+	do {
+		ret = seamcall(TDH_IOMMU_CLEAR, &args);
+	} while (ret == TDX_INTERRUPTED_RESUMABLE);
+
+	return ret;
+}
+EXPORT_SYMBOL_FOR_MODULES(tdh_iommu_clear, "tdx-host");
-- 
2.43.0


  reply	other threads:[~2026-11-12  4:43 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12  4:30 [PATCH v3 0/9] coco/tdx-host: Introduce trusted DMA initialization support Lu Baolu
2026-11-12  4:30 ` Lu Baolu [this message]
2026-11-12  4:30 ` [PATCH v3 2/9] x86/virt/tdx: Read global metadata for trusted IOMMU Lu Baolu
2026-11-12  4:30 ` [PATCH v3 3/9] x86/virt/tdx: Export Dynamic PAMT helpers to tdx-host Lu Baolu
2026-11-12  4:30 ` [PATCH v3 4/9] iommu/vt-d: Add interface for tdx-host when enabling trusted DMA Lu Baolu
2026-11-12  4:30 ` [PATCH v3 5/9] iommu/vt-d: Block GCMD and ECMD while acquired by the TDX module Lu Baolu
2026-11-12  4:30 ` [PATCH v3 6/9] iommu/vt-d: Refuse system suspend " Lu Baolu
2026-11-12  4:30 ` [PATCH v3 7/9] coco/tdx-host: Add skeleton to support PCI link encryption Lu Baolu
2026-11-12  4:30 ` [PATCH v3 8/9] coco/tdx-host: Rename tdx-host.c to main.c Lu Baolu
2026-11-12  4:30 ` [PATCH v3 9/9] coco/tdx-host: Enable trusted DMA on IOMMUs on device connect Lu Baolu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261112043054.2664857-2-baolu.lu@linux.intel.com \
    --to=baolu.lu@linux.intel.com \
    --cc=binbin.wu@linux.intel.com \
    --cc=chao.gao@intel.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=kas@kernel.org \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-coco@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rick.p.edgecombe@intel.com \
    --cc=x86@kernel.org \
    --cc=xiaoyao.li@intel.com \
    --cc=yilun.xu@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®