drivers/iommu/amd/init.c | 9 +++++++++ drivers/iommu/iommu.c | 6 ++++++ include/linux/iommu.h | 1 + 3 files changed, 16 insertions(+)
From: Li RongQing <lirongqing@baidu.com>
On x86 platforms, AMD IOMMU is typically enabled by default. When the
kernel is compiled with CONFIG_IOMMU_DEFAULT_DMA_LAZY, the IOMMU
operates in translated mode with deferred TLB flushing. While this
provides a security layer, it introduces measurable performance
overhead compared to Intel systems where the IOMMU often defaults
to a disabled state.
To optimize out-of-the-box performance for AMD users, shift the
default to passthrough mode when the following conditions are met:
1. No explicit IOMMU mode was requested via the command line.
2. The kernel was configured to use 'lazy' DMA remapping by default.
3. Memory encryption (SME/SEV) is not active, as these features
require translation for security.
This change allows standard DMA operations to bypass remapping
overhead while maintaining the ability for users to explicitly
enable translation if required.
To support this, export iommu_dma_is_user_configured() from the
IOMMU core to allow vendor drivers to check if the DMA API
configuration was overridden by the user.
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
drivers/iommu/amd/init.c | 9 +++++++++
drivers/iommu/iommu.c | 6 ++++++
include/linux/iommu.h | 1 +
3 files changed, 16 insertions(+)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index f3fd7f3..e89a5ce 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -3619,6 +3619,15 @@ void __init amd_iommu_detect(void)
amd_iommu_detected = true;
iommu_detected = 1;
x86_init.iommu.iommu_init = amd_iommu_init;
+
+ if (!iommu_dma_is_user_configured()) {
+ if (!cc_platform_has(CC_ATTR_MEM_ENCRYPT) &&
+ IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_LAZY)) {
+ pr_info("Defaulting to Passthrough mode for performance\n");
+ iommu_set_default_passthrough(false);
+ }
+ }
+
return;
disable_snp:
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 50718ab..a950dbb 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -4091,3 +4091,9 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
return ret;
}
#endif /* CONFIG_IRQ_MSI_IOMMU */
+
+bool iommu_dma_is_user_configured(void)
+{
+ return !!(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API);
+}
+EXPORT_SYMBOL_GPL(iommu_dma_is_user_configured);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 54b8b48..c3ff8a9 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -967,6 +967,7 @@ int iommu_set_pgtable_quirks(struct iommu_domain *domain,
unsigned long quirks);
void iommu_set_dma_strict(void);
+bool iommu_dma_is_user_configured(void);
extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
unsigned long iova, int flags);
--
2.9.4
On 2026-03-26 9:38 am, lirongqing wrote:
> From: Li RongQing <lirongqing@baidu.com>
>
> On x86 platforms, AMD IOMMU is typically enabled by default. When the
> kernel is compiled with CONFIG_IOMMU_DEFAULT_DMA_LAZY, the IOMMU
> operates in translated mode with deferred TLB flushing. While this
> provides a security layer, it introduces measurable performance
> overhead compared to Intel systems where the IOMMU often defaults
> to a disabled state.
>
> To optimize out-of-the-box performance for AMD users, shift the
> default to passthrough mode when the following conditions are met:
> 1. No explicit IOMMU mode was requested via the command line.
> 2. The kernel was configured to use 'lazy' DMA remapping by default.
> 3. Memory encryption (SME/SEV) is not active, as these features
> require translation for security.
>
> This change allows standard DMA operations to bypass remapping
> overhead while maintaining the ability for users to explicitly
> enable translation if required.
>
> To support this, export iommu_dma_is_user_configured() from the
> IOMMU core to allow vendor drivers to check if the DMA API
> configuration was overridden by the user.
Frankly, no. CONFIG_IOMMU_DEFAULT_PASSTHROUGH already exists for users
who want that behaviour. IF you want an equivalent of
CONFIG_INTEL_IOMMU_DEFAULT_ON which prevents the IOMMU being used at all
then implement that (however I imagine a lot of VFIO users would be
unhappy about changing the default of that at this point). You can't
just completely break CONFIG_IOMMU_DEFAULT_DMA_LAZY for all the users
who do want its particular behaviour.
Note that "lazy" mode does still represent nearly all of the
security/memory safety functionality offered by the IOMMU, so it does
have significant value - strict mode only adds protection for
use-after-free of memory which _was_ already a legitimate DMA buffer for
the given device at one point. A better title for this patch would be
"Silently make AMD systems less secure unless users go out of their way
to add command-line arguments to work around this change"...
There may well also still be some performance difference between the
IOMMU being enabled in passthrough, and being truly disabled - I seem to
recall the Intel GPU folks saying that was significant enough to care
about at least on some older Intel systems.
Thansk,
Robin.
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> ---
> drivers/iommu/amd/init.c | 9 +++++++++
> drivers/iommu/iommu.c | 6 ++++++
> include/linux/iommu.h | 1 +
> 3 files changed, 16 insertions(+)
>
> diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
> index f3fd7f3..e89a5ce 100644
> --- a/drivers/iommu/amd/init.c
> +++ b/drivers/iommu/amd/init.c
> @@ -3619,6 +3619,15 @@ void __init amd_iommu_detect(void)
> amd_iommu_detected = true;
> iommu_detected = 1;
> x86_init.iommu.iommu_init = amd_iommu_init;
> +
> + if (!iommu_dma_is_user_configured()) {
> + if (!cc_platform_has(CC_ATTR_MEM_ENCRYPT) &&
> + IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_LAZY)) {
> + pr_info("Defaulting to Passthrough mode for performance\n");
> + iommu_set_default_passthrough(false);
> + }
> + }
> +
> return;
>
> disable_snp:
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 50718ab..a950dbb 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -4091,3 +4091,9 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
> return ret;
> }
> #endif /* CONFIG_IRQ_MSI_IOMMU */
> +
> +bool iommu_dma_is_user_configured(void)
> +{
> + return !!(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API);
> +}
> +EXPORT_SYMBOL_GPL(iommu_dma_is_user_configured);
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index 54b8b48..c3ff8a9 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -967,6 +967,7 @@ int iommu_set_pgtable_quirks(struct iommu_domain *domain,
> unsigned long quirks);
>
> void iommu_set_dma_strict(void);
> +bool iommu_dma_is_user_configured(void);
>
> extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
> unsigned long iova, int flags);
> > On x86 platforms, AMD IOMMU is typically enabled by default. When the
> > kernel is compiled with CONFIG_IOMMU_DEFAULT_DMA_LAZY, the IOMMU
> > operates in translated mode with deferred TLB flushing. While this
> > provides a security layer, it introduces measurable performance
> > overhead compared to Intel systems where the IOMMU often defaults to a
> > disabled state.
> >
> > To optimize out-of-the-box performance for AMD users, shift the
> > default to passthrough mode when the following conditions are met:
> > 1. No explicit IOMMU mode was requested via the command line.
> > 2. The kernel was configured to use 'lazy' DMA remapping by default.
> > 3. Memory encryption (SME/SEV) is not active, as these features
> > require translation for security.
> >
> > This change allows standard DMA operations to bypass remapping
> > overhead while maintaining the ability for users to explicitly enable
> > translation if required.
> >
> > To support this, export iommu_dma_is_user_configured() from the IOMMU
> > core to allow vendor drivers to check if the DMA API configuration was
> > overridden by the user.
>
> Frankly, no. CONFIG_IOMMU_DEFAULT_PASSTHROUGH already exists for
> users who want that behaviour. IF you want an equivalent of
> CONFIG_INTEL_IOMMU_DEFAULT_ON which prevents the IOMMU being used
> at all then implement that (however I imagine a lot of VFIO users would be
> unhappy about changing the default of that at this point). You can't just
> completely break CONFIG_IOMMU_DEFAULT_DMA_LAZY for all the users
> who do want its particular behaviour.
>
However, CONFIG_IOMMU_DEFAULT_DMA_LAZY is a kernel default. On AMD CPUs, this causes a drop in networking and I/O performance, and many manuals to recommend setting iommu=pt. Why can't passthrough be the default? and IOMMU is disabled by default on Intel CPUs, why is security considered a non-issue for Intel but a concern for AMD?"
And I understand that setting iommu to PT should not affect the usage of VFIO.
[Li,Rongqing]
> Note that "lazy" mode does still represent nearly all of the security/memory
> safety functionality offered by the IOMMU, so it does have significant value -
> strict mode only adds protection for use-after-free of memory which _was_
> already a legitimate DMA buffer for the given device at one point. A better
> title for this patch would be "Silently make AMD systems less secure unless
> users go out of their way to add command-line arguments to work around
> this change"...
>
> There may well also still be some performance difference between the
> IOMMU being enabled in passthrough, and being truly disabled - I seem to
> recall the Intel GPU folks saying that was significant enough to care about at
> least on some older Intel systems.
>
> Thansk,
> Robin.
>
> > Signed-off-by: Li RongQing <lirongqing@baidu.com>
> > ---
> > drivers/iommu/amd/init.c | 9 +++++++++
> > drivers/iommu/iommu.c | 6 ++++++
> > include/linux/iommu.h | 1 +
> > 3 files changed, 16 insertions(+)
> >
> > diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index
> > f3fd7f3..e89a5ce 100644
> > --- a/drivers/iommu/amd/init.c
> > +++ b/drivers/iommu/amd/init.c
> > @@ -3619,6 +3619,15 @@ void __init amd_iommu_detect(void)
> > amd_iommu_detected = true;
> > iommu_detected = 1;
> > x86_init.iommu.iommu_init = amd_iommu_init;
> > +
> > + if (!iommu_dma_is_user_configured()) {
> > + if (!cc_platform_has(CC_ATTR_MEM_ENCRYPT) &&
> > + IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_LAZY)) {
> > + pr_info("Defaulting to Passthrough mode for performance\n");
> > + iommu_set_default_passthrough(false);
> > + }
> > + }
> > +
> > return;
> >
> > disable_snp:
> > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
> > 50718ab..a950dbb 100644
> > --- a/drivers/iommu/iommu.c
> > +++ b/drivers/iommu/iommu.c
> > @@ -4091,3 +4091,9 @@ int iommu_dma_prepare_msi(struct msi_desc
> *desc, phys_addr_t msi_addr)
> > return ret;
> > }
> > #endif /* CONFIG_IRQ_MSI_IOMMU */
> > +
> > +bool iommu_dma_is_user_configured(void)
> > +{
> > + return !!(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API); }
> > +EXPORT_SYMBOL_GPL(iommu_dma_is_user_configured);
> > diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
> > 54b8b48..c3ff8a9 100644
> > --- a/include/linux/iommu.h
> > +++ b/include/linux/iommu.h
> > @@ -967,6 +967,7 @@ int iommu_set_pgtable_quirks(struct
> iommu_domain *domain,
> > unsigned long quirks);
> >
> > void iommu_set_dma_strict(void);
> > +bool iommu_dma_is_user_configured(void);
> >
> > extern int report_iommu_fault(struct iommu_domain *domain, struct
> device *dev,
> > unsigned long iova, int flags);
On 2026-03-27 9:25 am, Li,Rongqing(ACG CCN) wrote:
>
>
>>> On x86 platforms, AMD IOMMU is typically enabled by default. When the
>>> kernel is compiled with CONFIG_IOMMU_DEFAULT_DMA_LAZY, the IOMMU
>>> operates in translated mode with deferred TLB flushing. While this
>>> provides a security layer, it introduces measurable performance
>>> overhead compared to Intel systems where the IOMMU often defaults to a
>>> disabled state.
>>>
>>> To optimize out-of-the-box performance for AMD users, shift the
>>> default to passthrough mode when the following conditions are met:
>>> 1. No explicit IOMMU mode was requested via the command line.
>>> 2. The kernel was configured to use 'lazy' DMA remapping by default.
>>> 3. Memory encryption (SME/SEV) is not active, as these features
>>> require translation for security.
>>>
>>> This change allows standard DMA operations to bypass remapping
>>> overhead while maintaining the ability for users to explicitly enable
>>> translation if required.
>>>
>>> To support this, export iommu_dma_is_user_configured() from the IOMMU
>>> core to allow vendor drivers to check if the DMA API configuration was
>>> overridden by the user.
>>
>> Frankly, no. CONFIG_IOMMU_DEFAULT_PASSTHROUGH already exists for
>> users who want that behaviour. IF you want an equivalent of
>> CONFIG_INTEL_IOMMU_DEFAULT_ON which prevents the IOMMU being used
>> at all then implement that (however I imagine a lot of VFIO users would be
>> unhappy about changing the default of that at this point). You can't just
>> completely break CONFIG_IOMMU_DEFAULT_DMA_LAZY for all the users
>> who do want its particular behaviour.
>>
>
> However, CONFIG_IOMMU_DEFAULT_DMA_LAZY is a kernel default.
Sure, it's what x86 defconfig sets, so if you want to change the default
x86 behaviour to passthrough, send a patch to x86 defconfig to make it
select IOMMU_DEFAULT_DMA_PASSTHROUGH instead (and I guess also move
IOMMU_DEFAULT_DMA_LAZY to hardening.config to preserve expectations
there). Don't just vandalise one driver such that IOMMU_DEFAULT_DMA_LAZY
cannot even work properly at all.
> On AMD CPUs, this causes a drop in networking and I/O performance, and many manuals to recommend setting iommu=pt. Why can't passthrough be the default? and IOMMU is disabled by default on Intel CPUs, why is security considered a non-issue for Intel but a concern for AMD?"
>
> And I understand that setting iommu to PT should not affect the usage of VFIO.
Indeed it wouldn't, but if you're trying to argue for parity with
INTEL_IOMMU_DEFAULT_ON=n, then what that would actually be is applying
the "amd_iommu=off" behaviour by default, not passthrough.
Thanks,
Robin.
>
> [Li,Rongqing]
>
>
>
>> Note that "lazy" mode does still represent nearly all of the security/memory
>> safety functionality offered by the IOMMU, so it does have significant value -
>> strict mode only adds protection for use-after-free of memory which _was_
>> already a legitimate DMA buffer for the given device at one point. A better
>> title for this patch would be "Silently make AMD systems less secure unless
>> users go out of their way to add command-line arguments to work around
>> this change"...
>>
>> There may well also still be some performance difference between the
>> IOMMU being enabled in passthrough, and being truly disabled - I seem to
>> recall the Intel GPU folks saying that was significant enough to care about at
>> least on some older Intel systems.
>>
>> Thansk,
>> Robin.
>>
>>> Signed-off-by: Li RongQing <lirongqing@baidu.com>
>>> ---
>>> drivers/iommu/amd/init.c | 9 +++++++++
>>> drivers/iommu/iommu.c | 6 ++++++
>>> include/linux/iommu.h | 1 +
>>> 3 files changed, 16 insertions(+)
>>>
>>> diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index
>>> f3fd7f3..e89a5ce 100644
>>> --- a/drivers/iommu/amd/init.c
>>> +++ b/drivers/iommu/amd/init.c
>>> @@ -3619,6 +3619,15 @@ void __init amd_iommu_detect(void)
>>> amd_iommu_detected = true;
>>> iommu_detected = 1;
>>> x86_init.iommu.iommu_init = amd_iommu_init;
>>> +
>>> + if (!iommu_dma_is_user_configured()) {
>>> + if (!cc_platform_has(CC_ATTR_MEM_ENCRYPT) &&
>>> + IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_LAZY)) {
>>> + pr_info("Defaulting to Passthrough mode for performance\n");
>>> + iommu_set_default_passthrough(false);
>>> + }
>>> + }
>>> +
>>> return;
>>>
>>> disable_snp:
>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>> 50718ab..a950dbb 100644
>>> --- a/drivers/iommu/iommu.c
>>> +++ b/drivers/iommu/iommu.c
>>> @@ -4091,3 +4091,9 @@ int iommu_dma_prepare_msi(struct msi_desc
>> *desc, phys_addr_t msi_addr)
>>> return ret;
>>> }
>>> #endif /* CONFIG_IRQ_MSI_IOMMU */
>>> +
>>> +bool iommu_dma_is_user_configured(void)
>>> +{
>>> + return !!(iommu_cmd_line & IOMMU_CMD_LINE_DMA_API); }
>>> +EXPORT_SYMBOL_GPL(iommu_dma_is_user_configured);
>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>> 54b8b48..c3ff8a9 100644
>>> --- a/include/linux/iommu.h
>>> +++ b/include/linux/iommu.h
>>> @@ -967,6 +967,7 @@ int iommu_set_pgtable_quirks(struct
>> iommu_domain *domain,
>>> unsigned long quirks);
>>>
>>> void iommu_set_dma_strict(void);
>>> +bool iommu_dma_is_user_configured(void);
>>>
>>> extern int report_iommu_fault(struct iommu_domain *domain, struct
>> device *dev,
>>> unsigned long iova, int flags);
>
© 2016 - 2026 Red Hat, Inc.