[PATCH v1 12/26] iommu/vt-d: Reserve the MSB domain ID bit for the TDX module

Xu Yilun
2025-11-17T02:38:39Z

From: Lu Baolu <baolu.lu@linux.intel.com>

The Intel TDX Connect Architecture Specification defines some enhancements
for the VT-d architecture to introduce IOMMU support for TEE-IO requests.
Section 2.2, 'Trusted DMA' states that:

"I/O TLB and DID Isolation – When IOMMU is enabled to support TDX
Connect, the IOMMU restricts the VMM’s DID setting, reserving the MSB bit
for the TDX module. The TDX module always sets this reserved bit on the
trusted DMA table. IOMMU tags IOTLB, PASID cache, and context entries to
indicate whether they were created from TEE-IO transactions, ensuring
isolation between TEE and non-TEE requests in translation caches."

Reserve the MSB in the domain ID for the TDX module's use if the
enhancement is required, which is detected if the ECAP.TDXCS bit in the
VT-d extended capability register is set and the TVM Usable field of the
ACPI KEYP table is set.

Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.h | 1 +
drivers/iommu/intel/dmar.c | 52 ++++++++++++++++++++++++++++++++++++-
2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 66c3aa549fd4..836777d7645d 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -192,6 +192,7 @@
*/

#define ecap_pms(e) (((e) >> 51) & 0x1)
+#define ecap_tdxc(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)
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index a54934c0536f..e9d65b26ad64 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -1033,6 +1033,56 @@ static int map_iommu(struct intel_iommu *iommu, struct dmar_drhd_unit *drhd)
return err;
}

+static int keyp_config_unit_tvm_usable(union acpi_subtable_headers *header,
+ void *arg, const unsigned long end)
+{
+ struct acpi_keyp_config_unit *acpi_cu =
+ (struct acpi_keyp_config_unit *)&header->keyp;
+ int *tvm_usable = arg;
+
+ if (acpi_cu->flags & ACPI_KEYP_F_TVM_USABLE)
+ *tvm_usable = true;
+
+ return 0;
+}
+
+static bool platform_is_tdxc_enhanced(void)
+{
+ static int tvm_usable = -1;
+ int ret;
+
+ /* only need to parse once */
+ if (tvm_usable != -1)
+ return tvm_usable;
+
+ tvm_usable = false;
+ ret = acpi_table_parse_keyp(ACPI_KEYP_TYPE_CONFIG_UNIT,
+ keyp_config_unit_tvm_usable, &tvm_usable);
+ if (ret < 0)
+ tvm_usable = false;
+
+ return tvm_usable;
+}
+
+static unsigned long iommu_max_domain_id(struct intel_iommu *iommu)
+{
+ unsigned long ndoms = cap_ndoms(iommu->cap);
+
+ /*
+ * Intel TDX Connect Architecture Specification, Section 2.2 Trusted DMA
+ *
+ * When IOMMU is enabled to support TDX Connect, the IOMMU restricts
+ * the VMM’s DID setting, reserving the MSB bit for the TDX module. The
+ * TDX module always sets this reserved bit on the trusted DMA table.
+ */
+ if (ecap_tdxc(iommu->ecap) && platform_is_tdxc_enhanced()) {
+ pr_info_once("Most Significant Bit of domain ID reserved.\n");
+ return ndoms >> 1;
+ }
+
+ return ndoms;
+}
+
static int alloc_iommu(struct dmar_drhd_unit *drhd)
{
struct intel_iommu *iommu;
@@ -1099,7 +1149,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
spin_lock_init(&iommu->lock);
ida_init(&iommu->domain_ida);
mutex_init(&iommu->did_lock);
- iommu->max_domain_id = cap_ndoms(iommu->cap);
+ iommu->max_domain_id = iommu_max_domain_id(iommu);

ver = readl(iommu->reg + DMAR_VER_REG);
pr_info("%s: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
--
2.25.1