From: Michal Camacho Romero <michal.camacho.romero@linux.intel.com>
To: Baolu Lu <baolu.lu@linux.intel.com>, Thomas Gleixner <tglx@kernel.org>
Cc: Ning Sun <ning.sun@intel.com>,
Michal Camacho Romero <michal.camacho.romero@intel.com>,
x86@kernel.org, iommu@lists.linux.dev,
tboot-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org,
Mateusz Mowka <mateusz.mowka@intel.com>,
Adam Pawlicki <adamx.pawlicki@intel.com>,
Pawel Randzio <pawel.randzio@intel.com>,
Michal Camacho Romero <michal.camacho.romero@linux.intel.com>
Subject: [PATCH v5 2/2] iommu/vt-d: Disable PMRs and skip force-IOMMU when TXT TPRs are active
Date: Mon, 12 Oct 2026 12:22:11 +0200 [thread overview]
Message-ID: <20261012102211.1739615-1-michal.camacho.romero@linux.intel.com> (raw)
In-Reply-To: <7f637b22-110b-4e49-b083-6062bcad37c4@linux.intel.com>
When Intel TXT Protection Regions (TPRs) are present in the DTPR table,
hardware-level DMA protection is already enforced by the SINIT ACM.
In this case:
- Parse DTPR Table and count number of enabled TPRs,
by using tboot_check_tprs() function.
- Skip forcing IOMMU enablement in tboot_force_iommu(), since TPRs
already provide DMA protection.
- Tear down PMRs during intel_iommu_init() when TPRs are active,
while PMRs are redundant with TPR-based protection.
- While TPR protection is enabled, call tboot_disable_tprs()
from intel_iommu_init() to disable TPR protection, after the IOMMU
adresses translation mechanism is set up.
- Deallocate TXT heap memory using tboot_free_txt_heap_mem() when it is
no longer needed.
Link: https://uefi.org/sites/default/files/resources/633933_Intel_TXT_DMA_Protection_Ranges_rev_0p73.pdf
Link: https://cdrdv2-public.intel.com/315168/315168_TXT_MLE_DG_rev_017_7.pdf
Signed-off-by: Michal Camacho Romero <michal.camacho.romero@linux.intel.com>
---
Hi Baolu,
Thanks for the careful review, and for catching the timing problem. You
are right. In the v4 patch version the disabling of TPRs was done too early.
I've introduced both in the IOMMU and TBOOT code sections a new
improvements, which eliminate the timing problem. Summary of how
each point is handled:
Answer for Question No.1 (DMA protection gap between disabling TPRs and
IOMMU taking over):
The actual tboot_disable_tprs() call was moved to the very end
of intel_iommu_init(), after the loop that enables the DMA
remapping hardware (iommu_enable_translation() function call). Until IOMMU
address translation mechanism is set up, the TPRs remain enabled.
Answer for Question No.2 (the commit message sentence "disable TPR
regions early, allowing the kernel to manage
DMA protection prior to the OS boot"):
That sentence was wrong and I apologise for the confusion - it
described exactly the broken behaviour you pointed out. Two things
were incorrect in it:
- "disable TPR regions early" - as you noticed, by disabling the only
active DMA protection before the IOMMU is set up is precisely what created the
unprotected window. "Early" was the wrong thing to do, not a
feature.
- "allowing the kernel to manage DMA protection prior to the OS
boot" - this message was also unnecessary and misleading.
What I actually meant to describe is a hand-off: the TPRs provide the
pre-IOMMU DMA protection, and the kernel must tear them down only once
IOMMU-based DMA protection is active. The commit message has
been corrected to reflect the real flow:
Answer for Question No.3 (how can tboot_is_tpr_enabled() return true
when TPRs were already disabled):
In the Patch v4 this was indeed contradictory because the disabling happened
earlier. With the reworked flow it is consistent:
- The helper was renamed to tboot_is_tpr_protection_enabled() and
now takes num_of_enabled_tprs, the value recieved from the
tboot_check_tprs() at the start of intel_iommu_init(), before any
TPR is touched. Basing on the number of enabled TPRs, the helper can
determine whether the TPR protection is currently active.
- Because the actual tboot_disable_tprs() call is now the last step,
the TPRs are still active. They are disabled after activating the
IOMMU-based DMA protection.
I have also dropped the stale "Reviewed-by: Lu Baolu" tag as requested,
since the changes are substantial enough that the earlier review no
longer covers them.
Regards,
Michal Camacho Romero
drivers/iommu/intel/iommu.c | 42 ++++++++++++++++++++++++++++++++++---
1 file changed, 39 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 2e3b3ab216f8..ea32730701cf 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -2558,11 +2558,18 @@ static int __init probe_acpi_namespace_devices(void)
return 0;
}
-static __init void tboot_force_iommu(void)
+static __init void tboot_force_iommu(s64 num_of_enabled_tprs)
{
if (!tboot_enabled() || intel_iommu_tboot_noforce)
return;
+ /*
+ * If TPR is enabled we don't need to force IOMMU, TPR set by SINIT
+ * ACM will take care of DMA protection.
+ */
+ if (tboot_is_tpr_protection_enabled(num_of_enabled_tprs))
+ return;
+
if (!dmar_can_force_on(DMAR_FORCEON_TBOOT))
panic("tboot: Failed to force IOMMU on\n");
@@ -2584,7 +2591,15 @@ int __init intel_iommu_init(void)
* Intel IOMMU is required for a TXT/tboot launch or platform
* opt in, so enforce that.
*/
- tboot_force_iommu();
+ void __iomem *txt_heap = NULL;
+ struct acpi_table_dtpr *dtpr = tboot_get_dtpr_table(&txt_heap);
+ s64 num_of_enabled_tprs = 0;
+ if (dtpr) {
+ /* For the existing DTPR Table, verify TPRs activity status */
+ num_of_enabled_tprs = tboot_check_tprs(dtpr, &txt_heap);
+ }
+
+ tboot_force_iommu(num_of_enabled_tprs);
if (!dmar_policy_force_on())
platform_optin_force_iommu();
@@ -2623,7 +2638,8 @@ int __init intel_iommu_init(void)
* calling SENTER, but the kernel is expected to reset/tear
* down the PMRs.
*/
- if (intel_iommu_tboot_noforce) {
+ if (intel_iommu_tboot_noforce ||
+ tboot_is_tpr_protection_enabled(num_of_enabled_tprs)) {
for_each_iommu(iommu, drhd)
iommu_disable_protect_mem_regions(iommu);
}
@@ -2697,7 +2713,24 @@ int __init intel_iommu_init(void)
iommu_enable_translation(iommu);
iommu_disable_protect_mem_regions(iommu);
+
}
+
+ if (tboot_is_tpr_protection_enabled(num_of_enabled_tprs) && dtpr) {
+ /*
+ * TPRs are enabled. It is necessary to disable active TPRs
+ * to enable DMA usage by the system.
+ */
+ num_of_enabled_tprs = tboot_disable_tprs(dtpr, &txt_heap,
+ num_of_enabled_tprs);
+ if (num_of_enabled_tprs != 0)
+ panic("tboot: Failed to disable TPRs. DMA is still blocked.\n");
+ }
+
+ /* Release the TXT heap memory if it was allocated */
+ if (txt_heap)
+ tboot_free_txt_heap_mem(&txt_heap);
+
up_read(&dmar_global_lock);
pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
@@ -2707,6 +2740,9 @@ int __init intel_iommu_init(void)
return 0;
out_free_dmar:
+ if (txt_heap)
+ tboot_free_txt_heap_mem(&txt_heap);
+
intel_iommu_free_dmars();
up_write(&dmar_global_lock);
return ret;
--
2.55.0
prev parent reply other threads:[~2026-10-12 10:22 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-03 11:44 [PATCH v1 0/2] x86/tboot: Add Intel TXT Protection Regions (TPR) support Michal Camacho Romero
2026-06-03 11:44 ` [PATCH v1 1/2] x86/tboot: Add support for parsing DTPR table and disabling TPRs Michal Camacho Romero
2026-09-14 13:19 ` [PATCH v2 " Michal Camacho Romero
2026-09-15 23:23 ` Sun, Ning
2026-09-17 9:41 ` [PATCH 1/1] " Michal Camacho Romero
2026-09-18 6:45 ` kernel test robot
2026-09-18 7:35 ` kernel test robot
2026-09-17 9:43 ` [PATCH v3 1/2] " Michal Camacho Romero
2026-09-22 10:00 ` [PATCH v4 " michal.camacho.romero
2026-09-23 22:21 ` Sun, Ning
2026-09-30 12:30 ` [PATCH v5 " Michal Camacho Romero
2026-10-05 18:37 ` Sun, Ning
2026-10-12 9:35 ` [PATCH v6 " Michal Camacho Romero
2026-06-03 11:45 ` [PATCH v1 2/2] iommu/vt-d: Disable PMRs and skip force-IOMMU when TXT TPRs are active Michal Camacho Romero
2026-06-11 8:49 ` Baolu Lu
2026-08-07 9:16 ` [PATCH v2 " Michal Camacho Romero
2026-08-07 10:14 ` Michal Camacho Romero
2026-08-20 3:28 ` Baolu Lu
2026-09-03 9:33 ` [PATCH v3 " Michal Camacho Romero
2026-09-04 2:19 ` Baolu Lu
2026-10-01 12:12 ` [PATCH v4 " michal.camacho.romero
2026-10-07 7:11 ` Baolu Lu
2026-10-12 10:22 ` Michal Camacho Romero [this message]
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=20261012102211.1739615-1-michal.camacho.romero@linux.intel.com \
--to=michal.camacho.romero@linux.intel.com \
--cc=adamx.pawlicki@intel.com \
--cc=baolu.lu@linux.intel.com \
--cc=iommu@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=mateusz.mowka@intel.com \
--cc=michal.camacho.romero@intel.com \
--cc=ning.sun@intel.com \
--cc=pawel.randzio@intel.com \
--cc=tboot-devel@lists.sourceforge.net \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/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®