iommu/amd: Disable previously enabled IOMMUs at boot
Joerg Roedel
maintainercover iommu/amd: Disable previously enabled IOMMUs at boot
Hi,
here is a patch-set refactoring the AMD IOMMU init code a bit to make sure the IOMMUs get disabled at boot, even when amd_iommu=off is specified on the kernel command line.
The patch-set is tested with various combinations of kernel command-line parameters and with kexec. It applies to the x86/amd branch of the iommu-tree.
Regards,
Joerg
Joerg Roedel (7):
iommu/amd: Disable IOMMUs at boot if they are enabled iommu/amd: Rename free_on_init_error()
iommu/amd: Add new init-state IOMMU_CMDLINE_DISABLED iommu/amd: Check for error states first in iommu_go_to_state() iommu/amd: Set global pointers to NULL after freeing them iommu/amd: Free IOMMU resources when disabled on command line iommu/amd: Remove amd_iommu_disabled check from amd_iommu_detect()
drivers/iommu/amd_iommu_init.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
Signature · 1 line
2.7.4
Joerg Roedel
maintainerPATCH 1/7 iommu/amd: Disable IOMMUs at boot if they are enabled
From: Joerg Roedel <[email protected]>
When booting, make sure the IOMMUs are disabled. They could be previously enabled if we boot into a kexec or kdump kernel. So make sure they are off.
--- drivers/iommu/amd_iommu_init.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/iommu/amd_iommu_init.c +3 -0
@@ -2316,6 +2316,9 @@ static int __init early_amd_iommu_init(void)if (ret) goto out; +/* Disable any previously enabled IOMMUs */ +disable_iommus (); +if (amd_iommu_irq_remap) amd_iommu_irq_remap =check_ioapic_information ();
Signature · 1 line
2.7.4
Joerg Roedel
maintainerPATCH 2/7 iommu/amd: Rename free_on_init_error()
In reply to Joerg RoedelFrom: Joerg Roedel <[email protected]>
The function will also be used to free iommu resources when amd_iommu=off was specified on the kernel command line. So rename the function to reflect that.
--- drivers/iommu/amd_iommu_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iommu/amd_iommu_init.c +2 -2
@@ -2106,7 +2106,7 @@ static struct syscore_ops amd_iommu_syscore_ops = { .resume = amd_iommu_resume, }; -static void __init free_on_init_error (void ) +static void __init free_iommu_resources (void ) {kmemleak_free (irq_lookup_table); free_pages((unsigned long)irq_lookup_table,
@@ -2534,7 +2534,7 @@ static int __init amd_iommu_init(void)free_dma_resources ();if (!irq_remapping_enabled) {disable_iommus (); -free_on_init_error (); +free_iommu_resources (); }else {struct amd_iommu *iommu;
Signature · 1 line
2.7.4
Joerg Roedel
maintainerPATCH 3/7 iommu/amd: Add new init-state IOMMU_CMDLINE_DISABLED
In reply to Joerg RoedelFrom: Joerg Roedel <[email protected]>
This will be used when during initialization we detect that the iommu should be disabled.
--- drivers/iommu/amd_iommu_init.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/iommu/amd_iommu_init.c +5 -2
@@ -237,6 +237,7 @@ enum iommu_init_state {IOMMU_INITIALIZED ,IOMMU_NOT_FOUND ,IOMMU_INIT_ERROR , + IOMMU_CMDLINE_DISABLED, };/* Early ioapic and hpet maps from kernel command line */
@@ -2450,6 +2451,7 @@ static int __init state_next(void)break ;case IOMMU_NOT_FOUND :case IOMMU_INIT_ERROR : +case IOMMU_CMDLINE_DISABLED :/* Error states => do nothing */ ret = -EINVAL ;break ;
@@ -2467,8 +2469,9 @@ static int __init iommu_go_to_state(enum iommu_init_state state)while (init_state != state) { ret =state_next (); -if (init_state ==IOMMU_NOT_FOUND || - init_state ==IOMMU_INIT_ERROR ) +if (init_state ==IOMMU_NOT_FOUND || + init_state ==IOMMU_INIT_ERROR || + init_state ==IOMMU_CMDLINE_DISABLED )break ; }
Signature · 1 line
2.7.4
Joerg Roedel
maintainerPATCH 4/7 iommu/amd: Check for error states first in iommu_go_to_state()
In reply to Joerg RoedelFrom: Joerg Roedel <[email protected]>
Check if we are in an error state already before calling into state_next().
--- drivers/iommu/amd_iommu_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iommu/amd_iommu_init.c +2 -2
@@ -2465,14 +2465,14 @@ static int __init state_next(void)static int __init iommu_go_to_state (enum iommu_init_state state) { -int ret =0 ; +int ret = -EINVAL ;while (init_state != state) { - ret =state_next ();if (init_state ==IOMMU_NOT_FOUND || init_state ==IOMMU_INIT_ERROR || init_state ==IOMMU_CMDLINE_DISABLED )break ; + ret =state_next (); }return ret;
Signature · 1 line
2.7.4
Joerg Roedel
maintainerPATCH 5/7 iommu/amd: Set global pointers to NULL after freeing them
In reply to Joerg RoedelFrom: Joerg Roedel <[email protected]>
Avoid any tries to double-free these pointers.
--- drivers/iommu/amd_iommu_init.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/iommu/amd_iommu_init.c +5 -0
@@ -2112,18 +2112,22 @@ static void __init free_iommu_resources(void)kmemleak_free (irq_lookup_table);free_pages ((unsigned long )irq_lookup_table,get_order (rlookup_table_size)); + irq_lookup_table =NULL ;kmem_cache_destroy (amd_iommu_irq_cache); amd_iommu_irq_cache =NULL ;free_pages ((unsigned long )amd_iommu_rlookup_table,get_order (rlookup_table_size)); + amd_iommu_rlookup_table =NULL ;free_pages ((unsigned long )amd_iommu_alias_table,get_order (alias_table_size)); + amd_iommu_alias_table =NULL ;free_pages ((unsigned long )amd_iommu_dev_table,get_order (dev_table_size)); + amd_iommu_dev_table =NULL ;free_iommu_all ();
@@ -2193,6 +2197,7 @@ static void __init free_dma_resources(void) {free_pages ((unsigned long )amd_iommu_pd_alloc_bitmap,get_order (MAX_DOMAIN_ID /8 )); + amd_iommu_pd_alloc_bitmap =NULL ;free_unity_maps (); }
Signature · 1 line
2.7.4
Joerg Roedel
maintainerPATCH 6/7 iommu/amd: Free IOMMU resources when disabled on command line
In reply to Joerg RoedelFrom: Joerg Roedel <[email protected]>
After we made sure that all IOMMUs have been disabled we need to make sure that all resources we allocated are released again.
--- drivers/iommu/amd_iommu_init.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/iommu/amd_iommu_init.c +7 -0
@@ -2428,6 +2428,13 @@ static int __init state_next(void)case IOMMU_IVRS_DETECTED : ret =early_amd_iommu_init (); init_state = ret ?IOMMU_INIT_ERROR :IOMMU_ACPI_FINISHED ; +if (init_state ==IOMMU_ACPI_FINISHED && amd_iommu_disabled) { +pr_info ("AMD-Vi: AMD IOMMU disabled on kernel command-line\n" ); +free_dma_resources (); +free_iommu_resources (); + init_state =IOMMU_CMDLINE_DISABLED ; + ret = -EINVAL ; + }break ;case IOMMU_ACPI_FINISHED :early_enable_iommus ();
Signature · 1 line
2.7.4
Joerg Roedel
maintainerPATCH 7/7 iommu/amd: Remove amd_iommu_disabled check from amd_iommu_detect()
In reply to Joerg RoedelFrom: Joerg Roedel <[email protected]>
This check needs to happens later now, when all previously enabled IOMMUs have been disabled.
--- drivers/iommu/amd_iommu_init.c | 3 --- 1 file changed, 3 deletions(-)
drivers/iommu/amd_iommu_init.c +0 -3
@@ -2576,9 +2576,6 @@ int __init amd_iommu_detect(void)if (no_iommu || (iommu_detected && !gart_iommu_aperture))return -ENODEV ; -if (amd_iommu_disabled) -return -ENODEV ; - ret =iommu_go_to_state (IOMMU_IVRS_DETECTED );if (ret)return ret;
Signature · 1 line
2.7.4