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: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>,
Dave Hansen <dave.hansen@linux.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>,
linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com>
Subject: [PATCH 3/5] iommu/vt-d: Add interfaces for trusted DMA initialization
Date: Tue, 15 Sep 2026 15:42:31 +0800 [thread overview]
Message-ID: <20260915074235.1219183-4-baolu.lu@linux.intel.com> (raw)
In-Reply-To: <20260915074235.1219183-1-baolu.lu@linux.intel.com>
Add Intel VT-d interfaces to initialize and tear down TDX Connect trusted
DMA support across active IOMMUs.
Trusted DMA depends on trusted-IOMMU hardware extensions, advertised by
the TDXCS bit in the VT-d Extended Capability Register (ECAP). When
present, the TDX module can transition an IOMMU into Secure TDX Mode via
TDH.IOMMU.SETUP, and return it to normal host operation via
TDH.IOMMU.CLEAR.
In this mode, VT-d provides TDX-managed DMA translation and invalidation
resources (trusted translation root and invalidation queue), and splits
domain ID ownership so the TDX module can use its reserved namespace
independently from host-managed DIDs.
Introduce the following interfaces:
- intel_tdxc_init(): bring up TDX Connect support on all active IOMMUs
that advertise TDXCS and have DMA translation enabled.
- intel_tdxc_exit(): tear down per-IOMMU TDX Connect state.
Initialization is best-effort at system scope: IOMMUs without required
support are skipped, while failures on attempted bring-up are treated as
errors and trigger teardown of previously initialized units.
These entry points are intended to be called by the Intel TDX Connect
platform TSM driver during module init/exit.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/Kconfig | 14 ++++++
drivers/iommu/intel/Makefile | 1 +
drivers/iommu/intel/iommu.h | 7 +++
include/linux/dmar.h | 12 ++++++
drivers/iommu/intel/iommu.c | 11 +++++
drivers/iommu/intel/tdxc.c | 82 ++++++++++++++++++++++++++++++++++++
6 files changed, 127 insertions(+)
create mode 100644 drivers/iommu/intel/tdxc.c
diff --git a/drivers/iommu/intel/Kconfig b/drivers/iommu/intel/Kconfig
index 5471f814e073..e8c0ea79a31d 100644
--- a/drivers/iommu/intel/Kconfig
+++ b/drivers/iommu/intel/Kconfig
@@ -100,4 +100,18 @@ config INTEL_IOMMU_PERF_EVENTS
to aid performance tuning and debug. These are available on modern
processors which support Intel VT-d 4.0 and later.
+config INTEL_IOMMU_TDX_CONNECT
+ bool "Intel IOMMU support for TDX Connect"
+ depends on INTEL_TDX_HOST
+ help
+ Enable Intel VT-d support required by TDX Connect on TDX host systems.
+
+ Select this if the host will run TDX Connect workloads that require
+ trusted assignment/sharing of devices with TDX guests. If enabled,
+ the Intel IOMMU driver integrates with the TDX host module so DMA
+ translation state used by those workloads is managed in the TDX trust
+ domain.
+
+ If unsure, say N.
+
endif # INTEL_IOMMU
diff --git a/drivers/iommu/intel/Makefile b/drivers/iommu/intel/Makefile
index ada651c4a01b..25bf3b970acb 100644
--- a/drivers/iommu/intel/Makefile
+++ b/drivers/iommu/intel/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_INTEL_IOMMU_DEBUGFS) += debugfs.o
obj-$(CONFIG_INTEL_IOMMU_SVM) += svm.o
obj-$(CONFIG_IRQ_REMAP) += irq_remapping.o
obj-$(CONFIG_INTEL_IOMMU_PERF_EVENTS) += perfmon.o
+obj-$(CONFIG_INTEL_IOMMU_TDX_CONNECT) += tdxc.o
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 23dbe6c24439..452a381e6a40 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -187,6 +187,7 @@
*/
#define ecap_pms(e) (((e) >> 51) & 0x1)
+#define ecap_tdxcs(e) (((e) >> 50) & 0x1)
#define ecap_rps(e) (((e) >> 49) & 0x1)
#define ecap_smpwc(e) (((e) >> 48) & 0x1)
#define ecap_flts(e) (((e) >> 47) & 0x1)
@@ -1323,6 +1324,12 @@ static inline void intel_iommu_debugfs_create_dev_pasid(struct dev_pasid_info *d
static inline void intel_iommu_debugfs_remove_dev_pasid(struct dev_pasid_info *dev_pasid) {}
#endif /* CONFIG_INTEL_IOMMU_DEBUGFS */
+#ifdef CONFIG_INTEL_IOMMU_TDX_CONNECT
+extern bool intel_tdxc_initialized;
+#else
+#define intel_tdxc_initialized (0)
+#endif /* CONFIG_INTEL_IOMMU_TDX_CONNECT */
+
extern const struct attribute_group *intel_iommu_groups[];
struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
u8 devfn, int alloc);
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 63e35df2cef4..361c0d4a45fb 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -167,6 +167,18 @@ static inline int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
}
#endif /* CONFIG_INTEL_IOMMU */
+#ifdef CONFIG_INTEL_IOMMU_TDX_CONNECT
+int intel_tdxc_init(void);
+void intel_tdxc_exit(void);
+#else
+static inline int intel_tdxc_init(void)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void intel_tdxc_exit(void) { }
+#endif /* CONFIG_INTEL_IOMMU_TDX_CONNECT */
+
#ifdef CONFIG_IRQ_REMAP
extern int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
#else /* CONFIG_IRQ_REMAP */
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 2e3b3ab216f8..e88457d96b53 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -2168,6 +2168,17 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
iommu_set_root_entry(iommu);
iommu_enable_translation(iommu);
+ /*
+ * If an IOMMU is hot-added after intel_tdxc_initialized is set, it is
+ * not enrolled into TDX secure mode. Ideally this should be integrated
+ * with dmar_iommu_hotplug() so intel_iommu_bringup_tdxc() can run on
+ * hotplug. This is currently skipped due to lack of hardware validation.
+ * Log this limitation to make it visible.
+ */
+ if (intel_tdxc_initialized && ecap_tdxcs(iommu->ecap))
+ pr_info("Trusted DMA for TEE is not enabled on hot-added IOMMU %s\n",
+ iommu->name);
+
iommu_disable_protect_mem_regions(iommu);
return 0;
diff --git a/drivers/iommu/intel/tdxc.c b/drivers/iommu/intel/tdxc.c
new file mode 100644
index 000000000000..559c752a1527
--- /dev/null
+++ b/drivers/iommu/intel/tdxc.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * tdxc.c - Intel TDX Connect Extensions support
+ *
+ * Copyright (C) 2026 Intel Corporation
+ */
+
+#define pr_fmt(fmt) "DMAR: " fmt
+
+#include <linux/pci.h>
+#include <asm/vmx.h>
+#include <asm/tdx.h>
+#include "iommu.h"
+
+bool intel_tdxc_initialized;
+
+static int intel_iommu_bringup_tdxc(struct intel_iommu *iommu, unsigned int nr_pages)
+{
+ /*
+ * Nothing to do if the iommu doesn't support TDX extension or the
+ * DMA translation has not been enabled.
+ */
+ if (!ecap_tdxcs(iommu->ecap) || !(iommu->gcmd & DMA_GCMD_TE))
+ return 0;
+
+ /* Bring-up is not complete yet; report as unsupported for now. */
+ return -EOPNOTSUPP;
+}
+
+static void intel_iommu_teardown_tdxc(struct intel_iommu *iommu)
+{
+}
+
+void intel_tdxc_exit(void)
+{
+ struct dmar_drhd_unit *drhd;
+ struct intel_iommu *iommu;
+
+ guard(rwsem_write)(&dmar_global_lock);
+ if (!intel_tdxc_initialized)
+ return;
+
+ for_each_active_iommu(iommu, drhd)
+ intel_iommu_teardown_tdxc(iommu);
+ intel_tdxc_initialized = false;
+}
+EXPORT_SYMBOL_GPL(intel_tdxc_exit);
+
+int intel_tdxc_init(void)
+{
+ const struct tdx_sys_info *tdx_sysinfo = tdx_get_sysinfo();
+ struct dmar_drhd_unit *drhd;
+ unsigned int mt_page_count;
+ struct intel_iommu *iommu;
+ int ret;
+
+ if (!intel_iommu_enabled)
+ return -EOPNOTSUPP;
+
+ if (!tdx_sysinfo ||
+ !(tdx_sysinfo->features.tdx_features0 & TDX_FEATURES0_TDXCONNECT))
+ return -EOPNOTSUPP;
+
+ mt_page_count = tdx_sysinfo->tdx_connect.iommu_mt_page_count;
+ guard(rwsem_write)(&dmar_global_lock);
+ if (intel_tdxc_initialized)
+ return 0;
+
+ for_each_active_iommu(iommu, drhd) {
+ ret = intel_iommu_bringup_tdxc(iommu, mt_page_count);
+ if (ret) {
+ for_each_active_iommu(iommu, drhd)
+ intel_iommu_teardown_tdxc(iommu);
+
+ return ret;
+ }
+ }
+ intel_tdxc_initialized = true;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(intel_tdxc_init);
--
2.43.0
next prev parent reply other threads:[~2026-09-15 7:54 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 7:42 [PATCH 0/5] iommu/vt-d: Introduce trusted DMA initialization support Lu Baolu
2026-09-15 7:42 ` [PATCH 1/5] x86/virt/tdx: Add SEAMCALL wrappers for IOMMU setup/clear Lu Baolu
2026-09-15 7:42 ` [PATCH 2/5] x86/virt/tdx: Read global metadata for trusted IOMMU Lu Baolu
2026-09-15 7:42 ` Lu Baolu [this message]
2026-09-15 7:42 ` [PATCH 4/5] iommu/vt-d: Add helpers to set up and tear down TDX extensions Lu Baolu
2026-09-15 7:42 ` [PATCH 5/5] iommu/vt-d: Reserve MSB of domain ID space for TDX module Lu Baolu
2026-09-18 2:30 ` [PATCH 0/5] iommu/vt-d: Introduce trusted DMA initialization support Tian, Kevin
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=20260915074235.1219183-4-baolu.lu@linux.intel.com \
--to=baolu.lu@linux.intel.com \
--cc=chao.gao@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--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=robin.murphy@arm.com \
--cc=will@kernel.org \
--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®