* [PATCH 1/9] iommu/vt-d: Fix no_iommu to disable platform optin
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-04 5:15 ` [PATCH 2/9] iommu/vt-d: Force requesting ACS when tboot is enabled Kevin Tian
` (7 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel,
stable
If user explicitly requests to disable iommu (via "iommu=off" or
"intel_iommu=off"), there is no reason to force enabling it due
to platform optin (for external-facing devices). User should be
aware of any security implication of doing so.
"intel_iommu=off" implements this policy by setting no_platform_optin
to skip platform optin in platform_optin_force_iommu().
However, "iommu=off" (no_iommu=1) doesn't set no_platform_optin
hence is broken in this aspect:
- detect_intel_iommu() doesn't request ACS if no_iommu=1
- platform_optin_force_iommu() forces iommu on if external-facing
devices exist and no_platform_optin is not set
This leads to a bad configuration with ACS disabled while DMA
remapping is enabled.
Instead of setting no_platform_optin (will soon be removed) for
no_iommu=1, directly check no_iommu in platform_optin_force_iommu().
Fixes: 89a6079df791 ("iommu/vt-d: Force IOMMU on for platform opt in hint")
Cc: stable@vger.kernel.org
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/iommu.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 4d0e65bc131d..9584ac0ed02f 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -2479,10 +2479,11 @@ static bool has_external_pci(void)
static int __init platform_optin_force_iommu(void)
{
- if (!dmar_platform_optin() || no_platform_optin || !has_external_pci())
+ if (no_iommu || !dmar_platform_optin() || no_platform_optin ||
+ !has_external_pci())
return 0;
- if (no_iommu || dmar_disabled)
+ if (dmar_disabled)
pr_info("Intel-IOMMU force enabled due to platform opt in\n");
/*
@@ -2493,7 +2494,6 @@ static int __init platform_optin_force_iommu(void)
iommu_set_default_passthrough(false);
dmar_disabled = 0;
- no_iommu = 0;
return 1;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 2/9] iommu/vt-d: Force requesting ACS when tboot is enabled
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
2026-06-04 5:15 ` [PATCH 1/9] iommu/vt-d: Fix no_iommu to disable platform optin Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-04 5:15 ` [PATCH 3/9] iommu/vt-d: Remove dead code when CONFIG_INTEL_IOMMU is not set Kevin Tian
` (6 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel,
stable
Currently the conditions of requesting ACS in detect_intel_iommu()
don't include tboot, leading to a possible misconfiguration with ACS
disabled (e.g. due to user opts) while iommu is later forced on by
tboot_force_iommu().
Fix it by checking tboot in detect_intel_iommu().
Fixes: 5d990b627537 ("PCI: add pci_request_acs")
Cc: stable@vger.kernel.org
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/dmar.c | 15 +++++++++++++--
drivers/iommu/intel/iommu.c | 2 +-
drivers/iommu/intel/iommu.h | 2 ++
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index d33c119a935e..e8f01e56cf46 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -915,6 +915,18 @@ dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
return 0;
}
+static bool dmar_required(void)
+{
+ /* tboot supersedes any user/platform opt */
+ if (!intel_iommu_tboot_noforce && tboot_enabled())
+ return true;
+
+ if (!no_iommu && (!dmar_disabled || dmar_platform_optin()))
+ return true;
+
+ return false;
+}
+
void __init detect_intel_iommu(void)
{
int ret;
@@ -928,8 +940,7 @@ void __init detect_intel_iommu(void)
if (!ret)
ret = dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
&validate_drhd_cb);
- if (!ret && !no_iommu && !iommu_detected &&
- (!dmar_disabled || dmar_platform_optin())) {
+ if (!ret && !iommu_detected && dmar_required()) {
iommu_detected = 1;
/* Make sure ACS will be enabled */
pci_request_acs();
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 9584ac0ed02f..0365ff4e5092 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -57,7 +57,7 @@ static int rwbf_quirk;
* (used when kernel is launched w/ TXT)
*/
static int force_on = 0;
-static int intel_iommu_tboot_noforce;
+int intel_iommu_tboot_noforce;
static int no_platform_optin;
#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index ef145560aa98..e0ac9efa1aa9 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1343,6 +1343,7 @@ static inline bool ecmd_has_pmu_essential(struct intel_iommu *iommu)
extern int dmar_disabled;
extern int intel_iommu_enabled;
+extern int intel_iommu_tboot_noforce;
#else
static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
{
@@ -1355,6 +1356,7 @@ static inline int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
#define dmar_disabled (1)
#define intel_iommu_enabled (0)
#define intel_iommu_sm (0)
+#define intel_iommu_tboot_noforce (0)
#endif
static inline const char *decode_prq_descriptor(char *str, size_t size,
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 3/9] iommu/vt-d: Remove dead code when CONFIG_INTEL_IOMMU is not set
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
2026-06-04 5:15 ` [PATCH 1/9] iommu/vt-d: Fix no_iommu to disable platform optin Kevin Tian
2026-06-04 5:15 ` [PATCH 2/9] iommu/vt-d: Force requesting ACS when tboot is enabled Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-04 5:15 ` [PATCH 4/9] iommu/vt-d: Consolidate dmar state management and force_on logic Kevin Tian
` (5 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel
Those are leftovers and unreachable now: the entire intel directory
is built only when CONFIG_INTEL_IOMMU is set.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/iommu.h | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index e0ac9efa1aa9..bb8b973476f6 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1329,7 +1329,6 @@ static inline bool intel_domain_is_ss_paging(struct dmar_domain *domain)
return domain->domain.ops == &intel_ss_paging_domain_ops;
}
-#ifdef CONFIG_INTEL_IOMMU
extern int intel_iommu_sm;
int iommu_calculate_agaw(struct intel_iommu *iommu);
int iommu_calculate_max_sagaw(struct intel_iommu *iommu);
@@ -1344,20 +1343,6 @@ static inline bool ecmd_has_pmu_essential(struct intel_iommu *iommu)
extern int dmar_disabled;
extern int intel_iommu_enabled;
extern int intel_iommu_tboot_noforce;
-#else
-static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
-{
- return 0;
-}
-static inline int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
-{
- return 0;
-}
-#define dmar_disabled (1)
-#define intel_iommu_enabled (0)
-#define intel_iommu_sm (0)
-#define intel_iommu_tboot_noforce (0)
-#endif
static inline const char *decode_prq_descriptor(char *str, size_t size,
u64 dw0, u64 dw1, u64 dw2, u64 dw3)
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 4/9] iommu/vt-d: Consolidate dmar state management and force_on logic
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
` (2 preceding siblings ...)
2026-06-04 5:15 ` [PATCH 3/9] iommu/vt-d: Remove dead code when CONFIG_INTEL_IOMMU is not set Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-12 11:08 ` Baolu Lu
2026-06-04 5:15 ` [PATCH 5/9] iommu/vt-d: Use dmar_can_force_on() for platform optin Kevin Tian
` (4 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel
Currently the dmar state is carried by multiple variables (no_iommu,
dmar_disabled, no_platform_optin, etc.) with error-prone force_on logic
scattered in multiple places.
Unify the state management and centralize the policy/priority for
various force_on scenarios.
No functional impact except one case - "intel_iommu=off" sets
no_platform_optin which is checked in platform_optin_force_iommu()
but not in detect_intel_iommu(), leading to ACS unnecessarily requested
when iommu could not be forced on later. Now with the unified logic
this becomes more consistent.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/dmar.c | 57 ++++++++++++++++++++++++++++++++++---
drivers/iommu/intel/iommu.c | 7 +++++
drivers/iommu/intel/iommu.h | 45 +++++++++++++++++++++++++++++
3 files changed, 105 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index e8f01e56cf46..791b91a7be29 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -915,14 +915,60 @@ dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
return 0;
}
+/*
+ * Centralized helper for deciding the force_on policy
+ *
+ * dmar disabled states (for DMA Remapping) are defined from stronger
+ * disables (more negative values) to weaker disables (less negative
+ * values).
+ *
+ * When a force_on type is passed in, it is associated to a reference
+ * level for comparison. force_on is permitted when dmar is in a
+ * disabled state less negative than the reference level (if dmar is
+ * enabled then the check is always true).
+ *
+ * For supported force_on types:
+ *
+ * - DMAR_FORCEON_TBOOT: tboot strictly requires DMA remapping for secure
+ * boot hence supersedes any user opts ("iommu=off" or "intel_iommu=off")
+ * and weaker disables.
+ *
+ * - DMAR_FORCEON_PLATFORM: external-facing devices requires DMA
+ * remapping to prevent malicious downstream external devices from
+ * composing DMA attacks. force_on is permitted only if dmar is disabled
+ * by build configurations (CONFIG_INTEL_IOMMU_DEFAULT_ON=off).
+ */
+bool dmar_can_force_on(enum dmar_force_on force_on)
+{
+ int level;
+
+ switch (force_on) {
+ case DMAR_FORCEON_TBOOT:
+ level = DMAR_DISABLED_USER;
+ break;
+ case DMAR_FORCEON_PLATFORM:
+ level = DMAR_DISABLED_AUTO;
+ break;
+ default:
+ pr_warn("Unsupported force_on type (%d)\n", force_on);
+ /* '0' means returning true only when dmar is enabled */
+ level = 0;
+ break;
+ }
+
+ return dmar_state >= level;
+}
+
static bool dmar_required(void)
{
- /* tboot supersedes any user/platform opt */
- if (!intel_iommu_tboot_noforce && tboot_enabled())
+ if (dmar_is_enabled())
return true;
- if (!no_iommu && (!dmar_disabled || dmar_platform_optin()))
- return true;
+ if (!intel_iommu_tboot_noforce && tboot_enabled())
+ return dmar_can_force_on(DMAR_FORCEON_TBOOT);
+
+ if (dmar_platform_optin())
+ return dmar_can_force_on(DMAR_FORCEON_PLATFORM);
return false;
}
@@ -936,6 +982,9 @@ void __init detect_intel_iommu(void)
};
down_write(&dmar_global_lock);
+ if (no_iommu)
+ dmar_state = DMAR_DISABLED_USER;
+
ret = dmar_table_detect();
if (!ret)
ret = dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 0365ff4e5092..0fc131a34963 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -196,6 +196,11 @@ static LIST_HEAD(dmar_satc_units);
static void intel_iommu_domain_free(struct iommu_domain *domain);
+#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
+int dmar_state = DMAR_ENABLED;
+#else
+int dmar_state = DMAR_DISABLED_AUTO;
+#endif
int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
@@ -237,9 +242,11 @@ static int __init intel_iommu_setup(char *str)
while (*str) {
if (!strncmp(str, "on", 2)) {
+ dmar_state = DMAR_ENABLED;
dmar_disabled = 0;
pr_info("IOMMU enabled\n");
} else if (!strncmp(str, "off", 3)) {
+ dmar_state = DMAR_DISABLED_USER;
dmar_disabled = 1;
no_platform_optin = 1;
pr_info("IOMMU disabled\n");
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index bb8b973476f6..1acc393dafce 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1340,6 +1340,51 @@ static inline bool ecmd_has_pmu_essential(struct intel_iommu *iommu)
DMA_ECMD_ECCAP3_ESSENTIAL;
}
+enum dmar_force_on {
+ DMAR_FORCEON_PLATFORM,
+ DMAR_FORCEON_TBOOT
+};
+
+/*
+ * Enabled states are positive, with more positive value being stronger.
+ * Disabled states are negative, with more negative value being stronger.
+ *
+ * 'dmar' here refers to DMA remapping instead of the dmar/iommu unit.
+ *
+ * - DMAR_ENABLED_FORCE:
+ * force enabled (e.g. by tboot or platform optin).
+ *
+ * - DMAR_ENABLED:
+ * enabled by build configuration (CONFIG_INTEL_IOMMU_DEFAULT_ON=on)
+ * or user opts ("intel_iommu=on").
+ *
+ * - DMAR_DISABLED_AUTO
+ * disabled by build configuration (CONFIG_INTEL_IOMMU_DEFAULT_ON=off).
+ *
+ * - DMAR_DISABLED_USER
+ * disabled by user opts ("intel_iommu=off" or "iommu=off").
+ *
+ * - '0' is invalid, compared to decide dmar enabled vs. disabled
+ *
+ */
+#define DMAR_ENABLED_FORCE 2
+#define DMAR_ENABLED 1
+#define DMAR_DISABLED_AUTO -1
+#define DMAR_DISABLED_USER -2
+extern int dmar_state;
+
+static inline bool dmar_is_enabled(void)
+{
+ return dmar_state > 0;
+}
+
+static inline bool dmar_is_disabled(void)
+{
+ return dmar_state < 0;
+}
+
+bool dmar_can_force_on(enum dmar_force_on force_on);
+
extern int dmar_disabled;
extern int intel_iommu_enabled;
extern int intel_iommu_tboot_noforce;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 4/9] iommu/vt-d: Consolidate dmar state management and force_on logic
2026-06-04 5:15 ` [PATCH 4/9] iommu/vt-d: Consolidate dmar state management and force_on logic Kevin Tian
@ 2026-06-12 11:08 ` Baolu Lu
0 siblings, 0 replies; 15+ messages in thread
From: Baolu Lu @ 2026-06-12 11:08 UTC (permalink / raw)
To: Kevin Tian, Joerg Roedel, Will Deacon, Robin Murphy
Cc: baolu.lu, Joerg Roedel, Mika Westerberg, Ashok Raj, Chris Wright,
Jesse Barnes, Asit Mallick, iommu, linux-kernel
On 6/4/2026 1:15 PM, Kevin Tian wrote:
> Currently the dmar state is carried by multiple variables (no_iommu,
> dmar_disabled, no_platform_optin, etc.) with error-prone force_on logic
> scattered in multiple places.
>
> Unify the state management and centralize the policy/priority for
> various force_on scenarios.
>
> No functional impact except one case - "intel_iommu=off" sets
> no_platform_optin which is checked in platform_optin_force_iommu()
> but not in detect_intel_iommu(), leading to ACS unnecessarily requested
> when iommu could not be forced on later. Now with the unified logic
> this becomes more consistent.
>
> Signed-off-by: Kevin Tian<kevin.tian@intel.com>
> ---
> drivers/iommu/intel/dmar.c | 57 ++++++++++++++++++++++++++++++++++---
> drivers/iommu/intel/iommu.c | 7 +++++
> drivers/iommu/intel/iommu.h | 45 +++++++++++++++++++++++++++++
> 3 files changed, 105 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index e8f01e56cf46..791b91a7be29 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -915,14 +915,60 @@ dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
> return 0;
> }
>
> +/*
> + * Centralized helper for deciding the force_on policy
> + *
> + * dmar disabled states (for DMA Remapping) are defined from stronger
> + * disables (more negative values) to weaker disables (less negative
> + * values).
> + *
> + * When a force_on type is passed in, it is associated to a reference
> + * level for comparison. force_on is permitted when dmar is in a
> + * disabled state less negative than the reference level (if dmar is
> + * enabled then the check is always true).
> + *
> + * For supported force_on types:
> + *
> + * - DMAR_FORCEON_TBOOT: tboot strictly requires DMA remapping for secure
> + * boot hence supersedes any user opts ("iommu=off" or "intel_iommu=off")
> + * and weaker disables.
> + *
> + * - DMAR_FORCEON_PLATFORM: external-facing devices requires DMA
> + * remapping to prevent malicious downstream external devices from
> + * composing DMA attacks. force_on is permitted only if dmar is disabled
> + * by build configurations (CONFIG_INTEL_IOMMU_DEFAULT_ON=off).
> + */
It reads like tboot successfully overrides the user's choices, whereas
the platform opt-in cannot. Could you shed more light on this? My
understanding is that "trusted boot environment" is considered stronger
than "user choices", which in turn is stronger than a "platform opt-in
hint".
If this is indeed the core design philosophy, would you mind spelling it
out explicitly in this comment? Making the exact precedence clear
will help future development follow the same philosophy.
> +bool dmar_can_force_on(enum dmar_force_on force_on)
> +{
> + int level;
> +
> + switch (force_on) {
> + case DMAR_FORCEON_TBOOT:
> + level = DMAR_DISABLED_USER;
> + break;
> + case DMAR_FORCEON_PLATFORM:
> + level = DMAR_DISABLED_AUTO;
> + break;
> + default:
> + pr_warn("Unsupported force_on type (%d)\n", force_on);
> + /* '0' means returning true only when dmar is enabled */
> + level = 0;
> + break;
> + }
> +
> + return dmar_state >= level;
> +}
If this helper returns false (meaning a requested force_on type cannot
be enforced), would it be better to notify the user via a clear pr_info/
pr_warn in the kernel log?
Normally, a failure to enforce a requested "force_on" condition might
mean security or trust implications that the administrator should be
aware of.
The rest of the patch looks good to me. Thanks!
Thanks,
baolu
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/9] iommu/vt-d: Use dmar_can_force_on() for platform optin
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
` (3 preceding siblings ...)
2026-06-04 5:15 ` [PATCH 4/9] iommu/vt-d: Consolidate dmar state management and force_on logic Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-12 13:16 ` Baolu Lu
2026-06-04 5:15 ` [PATCH 6/9] iommu/vt-d: Call dmar_can_force_on() for tboot optin Kevin Tian
` (3 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel
So the policy of requesting ACS in detect_intel_iommu() is consistent
with that in platform_optin_force_iommu().
While at it, remove no_platform_optin which is unnecessary now.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/iommu.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 0fc131a34963..edf01261a41d 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -58,7 +58,6 @@ static int rwbf_quirk;
*/
static int force_on = 0;
int intel_iommu_tboot_noforce;
-static int no_platform_optin;
#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
@@ -248,7 +247,6 @@ static int __init intel_iommu_setup(char *str)
} else if (!strncmp(str, "off", 3)) {
dmar_state = DMAR_DISABLED_USER;
dmar_disabled = 1;
- no_platform_optin = 1;
pr_info("IOMMU disabled\n");
} else if (!strncmp(str, "igfx_off", 8)) {
disable_igfx_iommu = 1;
@@ -2486,20 +2484,22 @@ static bool has_external_pci(void)
static int __init platform_optin_force_iommu(void)
{
- if (no_iommu || !dmar_platform_optin() || no_platform_optin ||
- !has_external_pci())
+ if (!dmar_platform_optin() || !dmar_can_force_on(DMAR_FORCEON_PLATFORM))
return 0;
- if (dmar_disabled)
- pr_info("Intel-IOMMU force enabled due to platform opt in\n");
+ if (!has_external_pci())
+ return 0;
/*
* If Intel-IOMMU is disabled by default, we will apply identity
* map for all devices except those marked as being untrusted.
*/
- if (dmar_disabled)
+ if (dmar_is_disabled()) {
+ pr_info("Intel-IOMMU force enabled due to platform opt in\n");
iommu_set_default_passthrough(false);
+ }
+ dmar_state = DMAR_ENABLED_FORCE;
dmar_disabled = 0;
return 1;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 5/9] iommu/vt-d: Use dmar_can_force_on() for platform optin
2026-06-04 5:15 ` [PATCH 5/9] iommu/vt-d: Use dmar_can_force_on() for platform optin Kevin Tian
@ 2026-06-12 13:16 ` Baolu Lu
0 siblings, 0 replies; 15+ messages in thread
From: Baolu Lu @ 2026-06-12 13:16 UTC (permalink / raw)
To: Kevin Tian, Joerg Roedel, Will Deacon, Robin Murphy
Cc: baolu.lu, Joerg Roedel, Mika Westerberg, Ashok Raj, Chris Wright,
Jesse Barnes, Asit Mallick, iommu, linux-kernel
On 6/4/2026 1:15 PM, Kevin Tian wrote:
> So the policy of requesting ACS in detect_intel_iommu() is consistent
> with that in platform_optin_force_iommu().
>
> While at it, remove no_platform_optin which is unnecessary now.
>
> Signed-off-by: Kevin Tian <kevin.tian@intel.com>
> ---
> drivers/iommu/intel/iommu.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index 0fc131a34963..edf01261a41d 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -58,7 +58,6 @@ static int rwbf_quirk;
> */
> static int force_on = 0;
> int intel_iommu_tboot_noforce;
> -static int no_platform_optin;
>
> #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
>
> @@ -248,7 +247,6 @@ static int __init intel_iommu_setup(char *str)
> } else if (!strncmp(str, "off", 3)) {
> dmar_state = DMAR_DISABLED_USER;
> dmar_disabled = 1;
> - no_platform_optin = 1;
> pr_info("IOMMU disabled\n");
> } else if (!strncmp(str, "igfx_off", 8)) {
> disable_igfx_iommu = 1;
> @@ -2486,20 +2484,22 @@ static bool has_external_pci(void)
>
> static int __init platform_optin_force_iommu(void)
> {
> - if (no_iommu || !dmar_platform_optin() || no_platform_optin ||
> - !has_external_pci())
> + if (!dmar_platform_optin() || !dmar_can_force_on(DMAR_FORCEON_PLATFORM))
> return 0;
>
> - if (dmar_disabled)
> - pr_info("Intel-IOMMU force enabled due to platform opt in\n");
> + if (!has_external_pci())
> + return 0;
Moving has_external_pci() down here seems to be an optimization. :-)
Scanning the PCI fabric for external-facing ports can be costly, and now
we could skip it entirely if platform force-on is unnecessary.
>
> /*
> * If Intel-IOMMU is disabled by default, we will apply identity
> * map for all devices except those marked as being untrusted.
> */
> - if (dmar_disabled)
> + if (dmar_is_disabled()) {
> + pr_info("Intel-IOMMU force enabled due to platform opt in\n");
> iommu_set_default_passthrough(false);
> + }
>
> + dmar_state = DMAR_ENABLED_FORCE;
I was initially wondering if we needed a lock to protect dmar_state
here, but since this runs during early boot in a single-threaded
environment (indicated by the __init prefix), concurrent access isn't a
concern.
However, changing dmar_state here does mean that any logic calling
dmar_is_enabled() before this point will see a "disabled" state, while
subsequent calls will see an "enabled" state.
While I don't see a real problem right now, this state volatility is
something we should document. Could we add a brief comment here to
clarify this intentional state upgrade?
> dmar_disabled = 0;
>
> return 1;
The rest looks good to me.
Thanks,
baolu
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 6/9] iommu/vt-d: Call dmar_can_force_on() for tboot optin
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
` (4 preceding siblings ...)
2026-06-04 5:15 ` [PATCH 5/9] iommu/vt-d: Use dmar_can_force_on() for platform optin Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-12 13:57 ` Baolu Lu
2026-06-04 5:15 ` [PATCH 7/9] iommu/vt-d: Remove the 'force_on' variable Kevin Tian
` (2 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel
So the policy of requesting ACS in detect_intel_iommu() is consistent
with that in tboot_force_iommu().
Though tboot is the strongest override so far, add a panic() in case
dmar_can_force_on() may return false due to future extensions.
No functional impact at this point.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/iommu.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index edf01261a41d..ed227de6d0ba 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -2544,12 +2544,16 @@ static int __init probe_acpi_namespace_devices(void)
static __init int tboot_force_iommu(void)
{
- if (!tboot_enabled())
+ if (!tboot_enabled() || intel_iommu_tboot_noforce)
return 0;
- if (no_iommu || dmar_disabled)
+ if (!dmar_can_force_on(DMAR_FORCEON_TBOOT))
+ panic("tboot: Failed to force IOMMU on\n");
+
+ if (dmar_is_disabled())
pr_warn("Forcing Intel-IOMMU to enabled\n");
+ dmar_state = DMAR_ENABLED_FORCE;
dmar_disabled = 0;
no_iommu = 0;
@@ -2566,8 +2570,7 @@ int __init intel_iommu_init(void)
* Intel IOMMU is required for a TXT/tboot launch or platform
* opt in, so enforce that.
*/
- force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) ||
- platform_optin_force_iommu();
+ force_on = tboot_force_iommu() || platform_optin_force_iommu();
down_write(&dmar_global_lock);
if (dmar_table_init()) {
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 6/9] iommu/vt-d: Call dmar_can_force_on() for tboot optin
2026-06-04 5:15 ` [PATCH 6/9] iommu/vt-d: Call dmar_can_force_on() for tboot optin Kevin Tian
@ 2026-06-12 13:57 ` Baolu Lu
0 siblings, 0 replies; 15+ messages in thread
From: Baolu Lu @ 2026-06-12 13:57 UTC (permalink / raw)
To: Kevin Tian, Joerg Roedel, Will Deacon, Robin Murphy
Cc: baolu.lu, Joerg Roedel, Mika Westerberg, Ashok Raj, Chris Wright,
Jesse Barnes, Asit Mallick, iommu, linux-kernel
On 6/4/2026 1:15 PM, Kevin Tian wrote:
> So the policy of requesting ACS in detect_intel_iommu() is consistent
> with that in tboot_force_iommu().
>
> Though tboot is the strongest override so far, add a panic() in case
> dmar_can_force_on() may return false due to future extensions.
>
> No functional impact at this point.
>
> Signed-off-by: Kevin Tian <kevin.tian@intel.com>
> ---
> drivers/iommu/intel/iommu.c | 11 +++++++----
> 1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index edf01261a41d..ed227de6d0ba 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -2544,12 +2544,16 @@ static int __init probe_acpi_namespace_devices(void)
>
> static __init int tboot_force_iommu(void)
> {
> - if (!tboot_enabled())
> + if (!tboot_enabled() || intel_iommu_tboot_noforce)
Hmm, it looks a bit strange here. The core design philosophy is that the
trusted boot environment takes priority over user options. However,
checking intel_iommu_tboot_noforce at the very top means a user
option (intel_iommu=tboot_noforce) is successfully overriding tboot.
Is this an exception? If so, it might be worth adding a brief comment
clarifying why `tboot_noforce` is allowed to bypass the priority?
> return 0;
>
> - if (no_iommu || dmar_disabled)
> + if (!dmar_can_force_on(DMAR_FORCEON_TBOOT))
> + panic("tboot: Failed to force IOMMU on\n");
> +
> + if (dmar_is_disabled())
> pr_warn("Forcing Intel-IOMMU to enabled\n");
>
> + dmar_state = DMAR_ENABLED_FORCE;
> dmar_disabled = 0;
> no_iommu = 0;
>
> @@ -2566,8 +2570,7 @@ int __init intel_iommu_init(void)
> * Intel IOMMU is required for a TXT/tboot launch or platform
> * opt in, so enforce that.
> */
> - force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) ||
> - platform_optin_force_iommu();
> + force_on = tboot_force_iommu() || platform_optin_force_iommu();
>
> down_write(&dmar_global_lock);
> if (dmar_table_init()) {
Thanks,
baolu
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 7/9] iommu/vt-d: Remove the 'force_on' variable
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
` (5 preceding siblings ...)
2026-06-04 5:15 ` [PATCH 6/9] iommu/vt-d: Call dmar_can_force_on() for tboot optin Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-12 14:16 ` Baolu Lu
2026-06-04 5:15 ` [PATCH 8/9] iommu/vt-d: Remove dmar_disabled Kevin Tian
2026-06-04 5:15 ` [PATCH 9/9] iommu/vt-d: Support the new DMA_REMAP_OPT_OUT flag bit Kevin Tian
8 siblings, 1 reply; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel
The force_on variable is now redundant - same information captured
by "dmar_state == DMAR_ENABLED_FORCE". Replace all force_on checks
with dmar_is_force_on().
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/iommu.c | 34 +++++++++++++++-------------------
drivers/iommu/intel/iommu.h | 5 +++++
2 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index ed227de6d0ba..d05ae36eda70 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -53,10 +53,9 @@ static int rwbf_quirk;
#define rwbf_required(iommu) (rwbf_quirk || cap_rwbf((iommu)->cap))
/*
- * set to 1 to panic kernel if can't successfully enable VT-d
+ * set to 1 to avoid kernel panic if can't successfully enable VT-d
* (used when kernel is launched w/ TXT)
*/
-static int force_on = 0;
int intel_iommu_tboot_noforce;
#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
@@ -1708,7 +1707,7 @@ static int __init init_dmars(void)
* we always have to disable PMRs or DMA may fail on
* this device
*/
- if (force_on)
+ if (dmar_is_force_on())
iommu_disable_protect_mem_regions(iommu);
continue;
}
@@ -1800,7 +1799,7 @@ static int init_iommu_hw(void)
* we always have to disable PMRs or DMA may fail on
* this device
*/
- if (force_on)
+ if (dmar_is_force_on())
iommu_disable_protect_mem_regions(iommu);
continue;
}
@@ -1861,7 +1860,7 @@ static void iommu_resume(void *data)
unsigned long flag;
if (init_iommu_hw()) {
- if (force_on)
+ if (dmar_is_force_on())
panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
else
WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
@@ -2129,7 +2128,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
/*
* we always have to disable PMRs or DMA may fail on this device
*/
- if (force_on)
+ if (dmar_is_force_on())
iommu_disable_protect_mem_regions(iommu);
return 0;
}
@@ -2482,13 +2481,13 @@ static bool has_external_pci(void)
return false;
}
-static int __init platform_optin_force_iommu(void)
+static void __init platform_optin_force_iommu(void)
{
if (!dmar_platform_optin() || !dmar_can_force_on(DMAR_FORCEON_PLATFORM))
- return 0;
+ return;
if (!has_external_pci())
- return 0;
+ return;
/*
* If Intel-IOMMU is disabled by default, we will apply identity
@@ -2501,8 +2500,6 @@ static int __init platform_optin_force_iommu(void)
dmar_state = DMAR_ENABLED_FORCE;
dmar_disabled = 0;
-
- return 1;
}
static int __init probe_acpi_namespace_devices(void)
@@ -2542,10 +2539,10 @@ static int __init probe_acpi_namespace_devices(void)
return 0;
}
-static __init int tboot_force_iommu(void)
+static __init void tboot_force_iommu(void)
{
if (!tboot_enabled() || intel_iommu_tboot_noforce)
- return 0;
+ return;
if (!dmar_can_force_on(DMAR_FORCEON_TBOOT))
panic("tboot: Failed to force IOMMU on\n");
@@ -2556,8 +2553,6 @@ static __init int tboot_force_iommu(void)
dmar_state = DMAR_ENABLED_FORCE;
dmar_disabled = 0;
no_iommu = 0;
-
- return 1;
}
int __init intel_iommu_init(void)
@@ -2570,17 +2565,18 @@ int __init intel_iommu_init(void)
* Intel IOMMU is required for a TXT/tboot launch or platform
* opt in, so enforce that.
*/
- force_on = tboot_force_iommu() || platform_optin_force_iommu();
+ tboot_force_iommu();
+ platform_optin_force_iommu();
down_write(&dmar_global_lock);
if (dmar_table_init()) {
- if (force_on)
+ if (dmar_is_force_on())
panic("tboot: Failed to initialize DMAR table\n");
goto out_free_dmar;
}
if (dmar_dev_scope_init() < 0) {
- if (force_on)
+ if (dmar_is_force_on())
panic("tboot: Failed to initialize DMAR device scope\n");
goto out_free_dmar;
}
@@ -2634,7 +2630,7 @@ int __init intel_iommu_init(void)
ret = init_dmars();
if (ret) {
- if (force_on)
+ if (dmar_is_force_on())
panic("tboot: Failed to initialize DMARs\n");
pr_err("Initialization failed\n");
goto out_free_dmar;
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 1acc393dafce..6b4e47f2f245 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1383,6 +1383,11 @@ static inline bool dmar_is_disabled(void)
return dmar_state < 0;
}
+static inline bool dmar_is_force_on(void)
+{
+ return dmar_state == DMAR_ENABLED_FORCE;
+}
+
bool dmar_can_force_on(enum dmar_force_on force_on);
extern int dmar_disabled;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 7/9] iommu/vt-d: Remove the 'force_on' variable
2026-06-04 5:15 ` [PATCH 7/9] iommu/vt-d: Remove the 'force_on' variable Kevin Tian
@ 2026-06-12 14:16 ` Baolu Lu
0 siblings, 0 replies; 15+ messages in thread
From: Baolu Lu @ 2026-06-12 14:16 UTC (permalink / raw)
To: Kevin Tian, Joerg Roedel, Will Deacon, Robin Murphy
Cc: baolu.lu, Joerg Roedel, Mika Westerberg, Ashok Raj, Chris Wright,
Jesse Barnes, Asit Mallick, iommu, linux-kernel
On 6/4/2026 1:15 PM, Kevin Tian wrote:
> The force_on variable is now redundant - same information captured
> by "dmar_state == DMAR_ENABLED_FORCE". Replace all force_on checks
> with dmar_is_force_on().
>
> Signed-off-by: Kevin Tian <kevin.tian@intel.com>
> ---
> drivers/iommu/intel/iommu.c | 34 +++++++++++++++-------------------
> drivers/iommu/intel/iommu.h | 5 +++++
> 2 files changed, 20 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index ed227de6d0ba..d05ae36eda70 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -53,10 +53,9 @@ static int rwbf_quirk;
> #define rwbf_required(iommu) (rwbf_quirk || cap_rwbf((iommu)->cap))
>
> /*
> - * set to 1 to panic kernel if can't successfully enable VT-d
> + * set to 1 to avoid kernel panic if can't successfully enable VT-d
> * (used when kernel is launched w/ TXT)
> */
It might be cleaner to replace it entirely with a new comment. For
example:
/*
* Skip forcing iommu enablement and avoid tboot-related kernel panics
* during initialization when set to 1 (via intel_iommu=tboot_noforce).
*/
int intel_iommu_tboot_noforce;
> -static int force_on = 0;
> int intel_iommu_tboot_noforce;
>
> #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
> @@ -1708,7 +1707,7 @@ static int __init init_dmars(void)
> * we always have to disable PMRs or DMA may fail on
> * this device
> */
> - if (force_on)
> + if (dmar_is_force_on())
> iommu_disable_protect_mem_regions(iommu);
> continue;
> }
> @@ -1800,7 +1799,7 @@ static int init_iommu_hw(void)
> * we always have to disable PMRs or DMA may fail on
> * this device
> */
> - if (force_on)
> + if (dmar_is_force_on())
> iommu_disable_protect_mem_regions(iommu);
> continue;
> }
> @@ -1861,7 +1860,7 @@ static void iommu_resume(void *data)
> unsigned long flag;
>
> if (init_iommu_hw()) {
> - if (force_on)
> + if (dmar_is_force_on())
> panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
> else
> WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
> @@ -2129,7 +2128,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
> /*
> * we always have to disable PMRs or DMA may fail on this device
> */
> - if (force_on)
> + if (dmar_is_force_on())
> iommu_disable_protect_mem_regions(iommu);
> return 0;
> }
> @@ -2482,13 +2481,13 @@ static bool has_external_pci(void)
> return false;
> }
>
> -static int __init platform_optin_force_iommu(void)
> +static void __init platform_optin_force_iommu(void)
> {
> if (!dmar_platform_optin() || !dmar_can_force_on(DMAR_FORCEON_PLATFORM))
> - return 0;
> + return;
>
> if (!has_external_pci())
> - return 0;
> + return;
>
> /*
> * If Intel-IOMMU is disabled by default, we will apply identity
> @@ -2501,8 +2500,6 @@ static int __init platform_optin_force_iommu(void)
>
> dmar_state = DMAR_ENABLED_FORCE;
> dmar_disabled = 0;
> -
> - return 1;
> }
>
> static int __init probe_acpi_namespace_devices(void)
> @@ -2542,10 +2539,10 @@ static int __init probe_acpi_namespace_devices(void)
> return 0;
> }
>
> -static __init int tboot_force_iommu(void)
> +static __init void tboot_force_iommu(void)
> {
> if (!tboot_enabled() || intel_iommu_tboot_noforce)
> - return 0;
> + return;
>
> if (!dmar_can_force_on(DMAR_FORCEON_TBOOT))
> panic("tboot: Failed to force IOMMU on\n");
> @@ -2556,8 +2553,6 @@ static __init int tboot_force_iommu(void)
> dmar_state = DMAR_ENABLED_FORCE;
> dmar_disabled = 0;
> no_iommu = 0;
> -
> - return 1;
> }
>
> int __init intel_iommu_init(void)
> @@ -2570,17 +2565,18 @@ int __init intel_iommu_init(void)
> * Intel IOMMU is required for a TXT/tboot launch or platform
> * opt in, so enforce that.
> */
> - force_on = tboot_force_iommu() || platform_optin_force_iommu();
> + tboot_force_iommu();
> + platform_optin_force_iommu();
>
> down_write(&dmar_global_lock);
> if (dmar_table_init()) {
> - if (force_on)
> + if (dmar_is_force_on())
> panic("tboot: Failed to initialize DMAR table\n");
> goto out_free_dmar;
> }
>
> if (dmar_dev_scope_init() < 0) {
> - if (force_on)
> + if (dmar_is_force_on())
> panic("tboot: Failed to initialize DMAR device scope\n");
> goto out_free_dmar;
> }
> @@ -2634,7 +2630,7 @@ int __init intel_iommu_init(void)
>
> ret = init_dmars();
> if (ret) {
> - if (force_on)
> + if (dmar_is_force_on())
> panic("tboot: Failed to initialize DMARs\n");
> pr_err("Initialization failed\n");
> goto out_free_dmar;
> diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
> index 1acc393dafce..6b4e47f2f245 100644
> --- a/drivers/iommu/intel/iommu.h
> +++ b/drivers/iommu/intel/iommu.h
> @@ -1383,6 +1383,11 @@ static inline bool dmar_is_disabled(void)
> return dmar_state < 0;
> }
>
> +static inline bool dmar_is_force_on(void)
> +{
> + return dmar_state == DMAR_ENABLED_FORCE;
> +}
This helper is only meaningful after
tboot_force_iommu();
platform_optin_force_iommu();
have been called. It would be better to add a brief comment about this?
> +
> bool dmar_can_force_on(enum dmar_force_on force_on);
>
> extern int dmar_disabled;
Thanks,
baolu
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 8/9] iommu/vt-d: Remove dmar_disabled
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
` (6 preceding siblings ...)
2026-06-04 5:15 ` [PATCH 7/9] iommu/vt-d: Remove the 'force_on' variable Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
2026-06-12 14:26 ` Baolu Lu
2026-06-04 5:15 ` [PATCH 9/9] iommu/vt-d: Support the new DMA_REMAP_OPT_OUT flag bit Kevin Tian
8 siblings, 1 reply; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel
It's replaced by dmar_is_disabled() now, covering both "iommu=off"
and "intel_iommu=off". Also remove unnecessary checks on no_iommu,
leaving only one exception in intel_iommu_init() which skips debugfs
init for "iommu=off" but not "intel_iommu=off". Keep it to avoid
surprise for now.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/iommu.c | 9 ++-------
drivers/iommu/intel/iommu.h | 1 -
drivers/iommu/intel/svm.c | 2 +-
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index d05ae36eda70..78498dafa60a 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -199,7 +199,6 @@ int dmar_state = DMAR_ENABLED;
#else
int dmar_state = DMAR_DISABLED_AUTO;
#endif
-int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
int intel_iommu_enabled = 0;
@@ -241,11 +240,9 @@ static int __init intel_iommu_setup(char *str)
while (*str) {
if (!strncmp(str, "on", 2)) {
dmar_state = DMAR_ENABLED;
- dmar_disabled = 0;
pr_info("IOMMU enabled\n");
} else if (!strncmp(str, "off", 3)) {
dmar_state = DMAR_DISABLED_USER;
- dmar_disabled = 1;
pr_info("IOMMU disabled\n");
} else if (!strncmp(str, "igfx_off", 8)) {
disable_igfx_iommu = 1;
@@ -2366,7 +2363,7 @@ void intel_iommu_shutdown(void)
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu = NULL;
- if (no_iommu || dmar_disabled)
+ if (dmar_is_disabled())
return;
/*
@@ -2499,7 +2496,6 @@ static void __init platform_optin_force_iommu(void)
}
dmar_state = DMAR_ENABLED_FORCE;
- dmar_disabled = 0;
}
static int __init probe_acpi_namespace_devices(void)
@@ -2551,7 +2547,6 @@ static __init void tboot_force_iommu(void)
pr_warn("Forcing Intel-IOMMU to enabled\n");
dmar_state = DMAR_ENABLED_FORCE;
- dmar_disabled = 0;
no_iommu = 0;
}
@@ -2594,7 +2589,7 @@ int __init intel_iommu_init(void)
if (!no_iommu)
intel_iommu_debugfs_init();
- if (no_iommu || dmar_disabled) {
+ if (dmar_is_disabled()) {
/*
* We exit the function here to ensure IOMMU's remapping and
* mempool aren't setup, which means that the IOMMU's PMRs
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 6b4e47f2f245..1832debf4982 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1390,7 +1390,6 @@ static inline bool dmar_is_force_on(void)
bool dmar_can_force_on(enum dmar_force_on force_on);
-extern int dmar_disabled;
extern int intel_iommu_enabled;
extern int intel_iommu_tboot_noforce;
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 57cd1db7207a..971dddaba48e 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -115,7 +115,7 @@ static int intel_iommu_sva_supported(struct device *dev)
struct device_domain_info *info = dev_iommu_priv_get(dev);
struct intel_iommu *iommu;
- if (!info || dmar_disabled)
+ if (!info || dmar_is_disabled())
return -EINVAL;
iommu = info->iommu;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 8/9] iommu/vt-d: Remove dmar_disabled
2026-06-04 5:15 ` [PATCH 8/9] iommu/vt-d: Remove dmar_disabled Kevin Tian
@ 2026-06-12 14:26 ` Baolu Lu
0 siblings, 0 replies; 15+ messages in thread
From: Baolu Lu @ 2026-06-12 14:26 UTC (permalink / raw)
To: Kevin Tian, Joerg Roedel, Will Deacon, Robin Murphy
Cc: baolu.lu, Joerg Roedel, Mika Westerberg, Ashok Raj, Chris Wright,
Jesse Barnes, Asit Mallick, iommu, linux-kernel
On 6/4/2026 1:15 PM, Kevin Tian wrote:
> It's replaced by dmar_is_disabled() now, covering both "iommu=off"
> and "intel_iommu=off". Also remove unnecessary checks on no_iommu,
> leaving only one exception in intel_iommu_init() which skips debugfs
> init for "iommu=off" but not "intel_iommu=off". Keep it to avoid
> surprise for now.
As mentioned in the previous patch, dmar_is_disabled() only becomes
meaningful for wider usage after the force_on logic has been executed,
right? Would it be better to add a check to make it safe?
>
> Signed-off-by: Kevin Tian <kevin.tian@intel.com>
> ---
> drivers/iommu/intel/iommu.c | 9 ++-------
> drivers/iommu/intel/iommu.h | 1 -
> drivers/iommu/intel/svm.c | 2 +-
> 3 files changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index d05ae36eda70..78498dafa60a 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -199,7 +199,6 @@ int dmar_state = DMAR_ENABLED;
> #else
> int dmar_state = DMAR_DISABLED_AUTO;
> #endif
> -int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
> int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
>
> int intel_iommu_enabled = 0;
> @@ -241,11 +240,9 @@ static int __init intel_iommu_setup(char *str)
> while (*str) {
> if (!strncmp(str, "on", 2)) {
> dmar_state = DMAR_ENABLED;
> - dmar_disabled = 0;
> pr_info("IOMMU enabled\n");
> } else if (!strncmp(str, "off", 3)) {
> dmar_state = DMAR_DISABLED_USER;
> - dmar_disabled = 1;
> pr_info("IOMMU disabled\n");
> } else if (!strncmp(str, "igfx_off", 8)) {
> disable_igfx_iommu = 1;
> @@ -2366,7 +2363,7 @@ void intel_iommu_shutdown(void)
> struct dmar_drhd_unit *drhd;
> struct intel_iommu *iommu = NULL;
>
> - if (no_iommu || dmar_disabled)
> + if (dmar_is_disabled())
> return;
>
> /*
> @@ -2499,7 +2496,6 @@ static void __init platform_optin_force_iommu(void)
> }
>
> dmar_state = DMAR_ENABLED_FORCE;
> - dmar_disabled = 0;
> }
>
> static int __init probe_acpi_namespace_devices(void)
> @@ -2551,7 +2547,6 @@ static __init void tboot_force_iommu(void)
> pr_warn("Forcing Intel-IOMMU to enabled\n");
>
> dmar_state = DMAR_ENABLED_FORCE;
> - dmar_disabled = 0;
> no_iommu = 0;
> }
>
> @@ -2594,7 +2589,7 @@ int __init intel_iommu_init(void)
> if (!no_iommu)
> intel_iommu_debugfs_init();
>
> - if (no_iommu || dmar_disabled) {
> + if (dmar_is_disabled()) {
> /*
> * We exit the function here to ensure IOMMU's remapping and
> * mempool aren't setup, which means that the IOMMU's PMRs
> diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
> index 6b4e47f2f245..1832debf4982 100644
> --- a/drivers/iommu/intel/iommu.h
> +++ b/drivers/iommu/intel/iommu.h
> @@ -1390,7 +1390,6 @@ static inline bool dmar_is_force_on(void)
>
> bool dmar_can_force_on(enum dmar_force_on force_on);
>
> -extern int dmar_disabled;
> extern int intel_iommu_enabled;
> extern int intel_iommu_tboot_noforce;
>
> diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
> index 57cd1db7207a..971dddaba48e 100644
> --- a/drivers/iommu/intel/svm.c
> +++ b/drivers/iommu/intel/svm.c
> @@ -115,7 +115,7 @@ static int intel_iommu_sva_supported(struct device *dev)
> struct device_domain_info *info = dev_iommu_priv_get(dev);
> struct intel_iommu *iommu;
>
> - if (!info || dmar_disabled)
> + if (!info || dmar_is_disabled())
> return -EINVAL;
>
> iommu = info->iommu;
Thanks,
baolu
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 9/9] iommu/vt-d: Support the new DMA_REMAP_OPT_OUT flag bit
2026-06-04 5:15 [PATCH 0/9] iommu/vt-d: Support a new DMAR flag Kevin Tian
` (7 preceding siblings ...)
2026-06-04 5:15 ` [PATCH 8/9] iommu/vt-d: Remove dmar_disabled Kevin Tian
@ 2026-06-04 5:15 ` Kevin Tian
8 siblings, 0 replies; 15+ messages in thread
From: Kevin Tian @ 2026-06-04 5:15 UTC (permalink / raw)
To: Lu Baolu, Joerg Roedel, Will Deacon, Robin Murphy
Cc: Kevin Tian, Joerg Roedel, Mika Westerberg, Ashok Raj,
Chris Wright, Jesse Barnes, Asit Mallick, iommu, linux-kernel
Some BIOS already provides config options to expose/hide VT-d units
as a whole to/from system software. A new demand is to allow exposing
VT-d units but requesting system software to disable DMA remapping
while sustaining interrupt remapping. This can be communicated now by
setting the new DMA_REMAP_OPT_OUT flag bit in the DMAR table, as
introduced in VT-d spec v5.2 (section 8.1, DMA Remapping Reporting
Structure).
Introduce a new disabled state (DMAR_DISABLED_FW) for DMA_REMAP_OPT_OUT.
As the strongest disabled state, it cannot be overridden by user opts
or any force_on types. If tboot is enabled in the meantime, kernel will
panic. It is user responsibility to configure BIOS properly.
One cleanup is left for future - the DMAR flag is parsed multiple
times, in detect_intel_iommu(), dmar_platform_optin() (which can be
called at run-time), etc. Caching it is a cleaner way.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
---
drivers/iommu/intel/dmar.c | 32 ++++++++++++++++++++++----------
drivers/iommu/intel/iommu.h | 4 ++++
include/linux/dmar.h | 1 +
3 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 791b91a7be29..24b173d33afd 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -931,7 +931,9 @@ dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
*
* - DMAR_FORCEON_TBOOT: tboot strictly requires DMA remapping for secure
* boot hence supersedes any user opts ("iommu=off" or "intel_iommu=off")
- * and weaker disables.
+ * and weaker disables. But if firmware forces DMA remapping off (by
+ * setting DMAR_REMAP_OPT_OUT in the DMAR table), no force_on is allowed.
+ * Firmware settings must be changed to unblock tboot.
*
* - DMAR_FORCEON_PLATFORM: external-facing devices requires DMA
* remapping to prevent malicious downstream external devices from
@@ -975,31 +977,41 @@ static bool dmar_required(void)
void __init detect_intel_iommu(void)
{
- int ret;
struct dmar_res_callback validate_drhd_cb = {
.cb[ACPI_DMAR_TYPE_HARDWARE_UNIT] = &dmar_validate_one_drhd,
.ignore_unhandled = true,
};
+ struct acpi_table_dmar *dmar;
+ int ret;
down_write(&dmar_global_lock);
if (no_iommu)
dmar_state = DMAR_DISABLED_USER;
ret = dmar_table_detect();
- if (!ret)
- ret = dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
- &validate_drhd_cb);
- if (!ret && !iommu_detected && dmar_required()) {
+ if (!ret) {
+ dmar = (struct acpi_table_dmar *)dmar_tbl;
+ ret = dmar_walk_dmar_table(dmar, &validate_drhd_cb);
+ }
+
+ if (ret)
+ goto out;
+
+ if (dmar->flags & DMAR_REMAP_OPT_OUT) {
+ dmar_state = DMAR_DISABLED_FW;
+ pr_info("Firmware forces DMA remapping off\n");
+ }
+
+ if (!iommu_detected && dmar_required()) {
iommu_detected = 1;
/* Make sure ACS will be enabled */
pci_request_acs();
}
- if (!ret) {
- x86_init.iommu.iommu_init = intel_iommu_init;
- x86_platform.iommu_shutdown = intel_iommu_shutdown;
- }
+ x86_init.iommu.iommu_init = intel_iommu_init;
+ x86_platform.iommu_shutdown = intel_iommu_shutdown;
+out:
if (dmar_tbl) {
acpi_put_table(dmar_tbl);
dmar_tbl = NULL;
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 1832debf4982..67ecf3521fd4 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1364,6 +1364,9 @@ enum dmar_force_on {
* - DMAR_DISABLED_USER
* disabled by user opts ("intel_iommu=off" or "iommu=off").
*
+ * - DMAR_DISABLED_FW
+ * disabled due to firmware opt-out (DMAR_REMAP_OPT_OUT)
+ *
* - '0' is invalid, compared to decide dmar enabled vs. disabled
*
*/
@@ -1371,6 +1374,7 @@ enum dmar_force_on {
#define DMAR_ENABLED 1
#define DMAR_DISABLED_AUTO -1
#define DMAR_DISABLED_USER -2
+#define DMAR_DISABLED_FW -3
extern int dmar_state;
static inline bool dmar_is_enabled(void)
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 692b2b445761..63e35df2cef4 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -24,6 +24,7 @@ struct acpi_dmar_header;
#define DMAR_INTR_REMAP 0x1
#define DMAR_X2APIC_OPT_OUT 0x2
#define DMAR_PLATFORM_OPT_IN 0x4
+#define DMAR_REMAP_OPT_OUT 0x8
struct intel_iommu;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread