iommu: Refactor DMA domain strictness
Subsystems (15)
Robin Murphy
maintainerv4 cover iommu: Refactor DMA domain strictness
v1: https://lore.kernel.org/linux-iommu/[email protected]/
v2: https://lore.kernel.org/linux-iommu/[email protected]/
v3: https://lore.kernel.org/linux-iommu/[email protected]/
Hi all,
I'm hoping this is good to go now. Changes from v3 are minimal, just rolling back patch #2 to the non-broken version, and tidying up the final patch as documented there.
Cheers,
Robin.
Robin Murphy (24):
iommu: Pull IOVA cookie management into the core iommu/amd: Drop IOVA cookie management iommu/arm-smmu: Drop IOVA cookie management iommu/vt-d: Drop IOVA cookie management iommu/exynos: Drop IOVA cookie management iommu/ipmmu-vmsa: Drop IOVA cookie management iommu/mtk: Drop IOVA cookie management iommu/rockchip: Drop IOVA cookie management iommu/sprd: Drop IOVA cookie management iommu/sun50i: Drop IOVA cookie management iommu/virtio: Drop IOVA cookie management iommu/dma: Unexport IOVA cookie management iommu/dma: Remove redundant "!dev" checks
iommu: Indicate queued flushes via gather data iommu/io-pgtable: Remove non-strict quirk
iommu: Introduce explicit type for non-strict DMA domains iommu/amd: Prepare for multiple DMA domain types iommu/arm-smmu: Prepare for multiple DMA domain types iommu/vt-d: Prepare for multiple DMA domain types
iommu: Express DMA strictness via the domain type
iommu: Expose DMA domain strictness via sysfs
iommu: Only log strictness for DMA domains
iommu: Merge strictness and domain type configs
iommu: Allow enabling non-strict mode dynamically
.../ABI/testing/sysfs-kernel-iommu_groups | 6 +- .../admin-guide/kernel-parameters.txt | 8 +- drivers/iommu/Kconfig | 80 +++++++++---------- drivers/iommu/amd/iommu.c | 21 +---- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 +-- drivers/iommu/arm/arm-smmu/arm-smmu.c | 19 ++--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 9 --- drivers/iommu/dma-iommu.c | 58 ++++++++------ drivers/iommu/exynos-iommu.c | 19 +---- drivers/iommu/intel/iommu.c | 23 ++---- drivers/iommu/io-pgtable-arm-v7s.c | 12 +-- drivers/iommu/io-pgtable-arm.c | 12 +-- drivers/iommu/iommu.c | 56 ++++++++----- drivers/iommu/iova.c | 14 +++- drivers/iommu/ipmmu-vmsa.c | 28 +------ drivers/iommu/mtk_iommu.c | 7 -- drivers/iommu/mtk_iommu_v1.c | 1 - drivers/iommu/rockchip-iommu.c | 12 +-- drivers/iommu/sprd-iommu.c | 7 -- drivers/iommu/sun50i-iommu.c | 13 +-- drivers/iommu/virtio-iommu.c | 8 -- include/linux/dma-iommu.h | 6 ++ include/linux/io-pgtable.h | 5 -- include/linux/iommu.h | 23 +++++- 24 files changed, 184 insertions(+), 274 deletions(-)
Signature · 1 line
2.25.1
Robin Murphy
maintainerPATCH v4 1/24 iommu: Pull IOVA cookie management into the core
Now that everyone has converged on iommu-dma for IOMMU_DOMAIN_DMA support, we can abandon the notion of drivers being responsible for the cookie type, and consolidate all the management into the core code.
---
v3: Use a simpler temporary check instead of trying to be clever with
the error code
--- drivers/iommu/iommu.c | 7 +++++++ include/linux/iommu.h | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-)
drivers/iommu/iommu.c +7 -0
@@ -7,6 +7,7 @@#define pr_fmt (fmt) "iommu: " fmt#include <linux/device.h> +#include <linux/dma-iommu.h> #include <linux/kernel.h> #include <linux/bits.h> #include <linux/bug.h>
@@ -1946,6 +1947,11 @@ static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,/* Assume all sizes by default; the driver may override this later */ domain->pgsize_bitmap = bus->iommu_ops->pgsize_bitmap; +/* Temporarily avoid -EEXIST while drivers still get their own cookies */ +if (type ==IOMMU_DOMAIN_DMA && !domain->iova_cookie &&iommu_get_dma_cookie (domain)) { +iommu_domain_free (domain); + domain =NULL ; + }return domain; }
@@ -1957,6 +1963,7 @@ EXPORT_SYMBOL_GPL(iommu_domain_alloc);void iommu_domain_free (struct iommu_domain *domain) { +iommu_put_dma_cookie (domain); domain->ops->domain_free (domain); }EXPORT_SYMBOL_GPL (iommu_domain_free);
include/linux/iommu.h +2 -1
@@ -40,6 +40,7 @@ struct iommu_domain;struct notifier_block ;struct iommu_sva ;struct iommu_fault_event ; +struct iommu_dma_cookie ;/* iommu fault flags */ #define IOMMU_FAULT_READ 0x0
@@ -86,7 +87,7 @@ struct iommu_domain {iommu_fault_handler_t handler;void *handler_token;struct iommu_domain_geometry geometry; -void *iova_cookie; +struct iommu_dma_cookie *iova_cookie; };enum iommu_cap {
Signature · 1 line
2.25.1
Robin Murphy
maintainerPATCH v4 2/24 iommu/amd: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
--- drivers/iommu/amd/iommu.c | 12 ------------ 1 file changed, 12 deletions(-)
drivers/iommu/amd/iommu.c +0 -12
@@ -1918,16 +1918,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type) domain->domain.geometry.aperture_end = ~0ULL ; domain->domain.geometry.force_aperture = true; -if (type ==IOMMU_DOMAIN_DMA && -iommu_get_dma_cookie (&domain->domain) == -ENOMEM ) - goto free_domain; -return &domain->domain; - -free_domain: -protection_domain_free (domain); - -return NULL ; }static void amd_iommu_domain_free (struct iommu_domain *dom)
@@ -1944,9 +1935,6 @@ static void amd_iommu_domain_free(struct iommu_domain *dom)if (!dom)return ; -if (dom->type ==IOMMU_DOMAIN_DMA ) -iommu_put_dma_cookie (&domain->domain); -if (domain->flags &PD_IOMMUV2_MASK )free_gcr3_table (domain);
Signature · 1 line
2.25.1
Robin Murphy
maintainerPATCH v4 3/24 iommu/arm-smmu: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 7 ------- drivers/iommu/arm/arm-smmu/arm-smmu.c | 15 ++++----------- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 9 --------- 3 files changed, 4 insertions(+), 27 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +0 -7
@@ -1984,12 +1984,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)if (!smmu_domain)return NULL ; -if (type ==IOMMU_DOMAIN_DMA && -iommu_get_dma_cookie (&smmu_domain->domain)) { -kfree (smmu_domain); -return NULL ; - } -mutex_init (&smmu_domain->init_mutex);INIT_LIST_HEAD (&smmu_domain->devices);spin_lock_init (&smmu_domain->devices_lock);
@@ -2021,7 +2015,6 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)struct arm_smmu_domain *smmu_domain =to_smmu_domain (domain);struct arm_smmu_device *smmu = smmu_domain->smmu; -iommu_put_dma_cookie (domain);free_io_pgtable_ops (smmu_domain->pgtbl_ops);/* Free the CD and ASID, if we allocated them */
drivers/iommu/arm/arm-smmu/arm-smmu.c +4 -11
@@ -868,10 +868,10 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) {struct arm_smmu_domain *smmu_domain; -if (type !=IOMMU_DOMAIN_UNMANAGED && - type !=IOMMU_DOMAIN_DMA && - type !=IOMMU_DOMAIN_IDENTITY ) -return NULL ; +if (type !=IOMMU_DOMAIN_UNMANAGED && type !=IOMMU_DOMAIN_IDENTITY ) { +if (using_legacy_binding || type !=IOMMU_DOMAIN_DMA ) +return NULL ; + }/* * Allocate the domain and initialise some of its data structures. * We can't really do anything meaningful until we've added a
@@ -881,12 +881,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)if (!smmu_domain)return NULL ; -if (type ==IOMMU_DOMAIN_DMA && (using_legacy_binding || -iommu_get_dma_cookie (&smmu_domain->domain))) { -kfree (smmu_domain); -return NULL ; - } -mutex_init (&smmu_domain->init_mutex);spin_lock_init (&smmu_domain->cb_lock);
@@ -901,7 +895,6 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)* Free the domain resources. We assume that all devices have * already been detached. */ -iommu_put_dma_cookie (domain);arm_smmu_destroy_domain_context (domain);kfree (smmu_domain); }
drivers/iommu/arm/arm-smmu/qcom_iommu.c +0 -9
@@ -10,7 +10,6 @@#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/delay.h> -#include <linux/dma-iommu.h> #include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/interrupt.h>
@@ -335,12 +334,6 @@ static struct iommu_domain *qcom_iommu_domain_alloc(unsigned type)if (!qcom_domain)return NULL ; -if (type ==IOMMU_DOMAIN_DMA && -iommu_get_dma_cookie (&qcom_domain->domain)) { -kfree (qcom_domain); -return NULL ; - } -mutex_init (&qcom_domain->init_mutex);spin_lock_init (&qcom_domain->pgtbl_lock);
@@ -351,8 +344,6 @@ static void qcom_iommu_domain_free(struct iommu_domain *domain) {struct qcom_iommu_domain *qcom_domain =to_qcom_iommu_domain (domain); -iommu_put_dma_cookie (domain); -if (qcom_domain->iommu) {/* * NOTE: unmap can be called after client device is powered
Signature · 1 line
2.25.1
Robin Murphy
maintainerPATCH v4 4/24 iommu/vt-d: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
--- drivers/iommu/intel/iommu.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/iommu/intel/iommu.c +0 -8
@@ -1979,10 +1979,6 @@ static void domain_exit(struct dmar_domain *domain)/* Remove associated devices and clear attached or cached domains */ domain_remove_dev_info (domain); -/* destroy iovas */ -if (domain->domain.type ==IOMMU_DOMAIN_DMA ) -iommu_put_dma_cookie (&domain->domain); -if (domain->pgd) {struct page *freelist;
@@ -4544,10 +4540,6 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)return NULL ; } -if (type ==IOMMU_DOMAIN_DMA && -iommu_get_dma_cookie (&dmar_domain->domain)) -return NULL ; - domain = &dmar_domain->domain; domain->geometry.aperture_start =0 ; domain->geometry.aperture_end =
Signature · 1 line
2.25.1
Robin Murphy
maintainerPATCH v4 5/24 iommu/exynos: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
---
v3: Also remove unneeded include
--- drivers/iommu/exynos-iommu.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-)
drivers/iommu/exynos-iommu.c +4 -15
@@ -21,7 +21,6 @@#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/slab.h> -#include <linux/dma-iommu.h> typedef u32 sysmmu_iova_t ;typedef u32 sysmmu_pte_t ;
@@ -735,20 +734,16 @@ static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)/* Check if correct PTE offsets are initialized */ BUG_ON (PG_ENT_SHIFT <0 || !dma_dev); +if (type !=IOMMU_DOMAIN_DMA && type !=IOMMU_DOMAIN_UNMANAGED ) +return NULL ; + domain =kzalloc (sizeof (*domain),GFP_KERNEL );if (!domain)return NULL ; -if (type ==IOMMU_DOMAIN_DMA ) { -if (iommu_get_dma_cookie (&domain->domain) !=0 ) - goto err_pgtable; - }else if (type !=IOMMU_DOMAIN_UNMANAGED ) { - goto err_pgtable; - } - domain->pgtable = (sysmmu_pte_t *)__get_free_pages (GFP_KERNEL ,2 );if (!domain->pgtable) - goto err_dma_cookie; + goto err_pgtable; domain->lv2entcnt = (short *)__get_free_pages (GFP_KERNEL | __GFP_ZERO,1 );if (!domain->lv2entcnt)
@@ -779,9 +774,6 @@ static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)free_pages ((unsigned long )domain->lv2entcnt,1 ); err_counter:free_pages ((unsigned long )domain->pgtable,2 ); -err_dma_cookie: -if (type ==IOMMU_DOMAIN_DMA ) -iommu_put_dma_cookie (&domain->domain); err_pgtable:kfree (domain);return NULL ;
@@ -809,9 +801,6 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)spin_unlock_irqrestore (&domain->lock, flags); -if (iommu_domain->type ==IOMMU_DOMAIN_DMA ) -iommu_put_dma_cookie (iommu_domain); -dma_unmap_single (dma_dev,virt_to_phys (domain->pgtable),LV1TABLE_SIZE ,DMA_TO_DEVICE );
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 6/24 iommu/ipmmu-vmsa: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
---
v3: Also remove unneeded include
--- drivers/iommu/ipmmu-vmsa.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-)
drivers/iommu/ipmmu-vmsa.c +4 -24
@@ -8,7 +8,6 @@#include <linux/bitmap.h> #include <linux/delay.h> -#include <linux/dma-iommu.h> #include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/export.h>
@@ -564,10 +563,13 @@ static irqreturn_t ipmmu_irq(int irq, void *dev)* IOMMU Operations */ -static struct iommu_domain *__ipmmu_domain_alloc (unsigned type) +static struct iommu_domain *ipmmu_domain_alloc (unsigned type) {struct ipmmu_vmsa_domain *domain; +if (type !=IOMMU_DOMAIN_UNMANAGED && type !=IOMMU_DOMAIN_DMA ) +return NULL ; + domain =kzalloc (sizeof (*domain),GFP_KERNEL );if (!domain)return NULL ;
@@ -577,27 +579,6 @@ static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)return &domain->io_domain; } -static struct iommu_domain *ipmmu_domain_alloc (unsigned type) -{ -struct iommu_domain *io_domain =NULL ; - -switch (type) { -case IOMMU_DOMAIN_UNMANAGED : - io_domain =__ipmmu_domain_alloc (type); -break ; - -case IOMMU_DOMAIN_DMA : - io_domain =__ipmmu_domain_alloc (type); -if (io_domain &&iommu_get_dma_cookie (io_domain)) { -kfree (io_domain); - io_domain =NULL ; - } -break ; - } - -return io_domain; -} -static void ipmmu_domain_free (struct iommu_domain *io_domain) {struct ipmmu_vmsa_domain *domain =to_vmsa_domain (io_domain);
@@ -606,7 +587,6 @@ static void ipmmu_domain_free(struct iommu_domain *io_domain)* Free the domain resources. We assume that all devices have already * been detached. */ -iommu_put_dma_cookie (io_domain);ipmmu_domain_destroy_context (domain);free_io_pgtable_ops (domain->iop);kfree (domain);
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 7/24 iommu/mtk: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
---
v3: Also remove unneeded includes
--- drivers/iommu/mtk_iommu.c | 7 ------- drivers/iommu/mtk_iommu_v1.c | 1 - 2 files changed, 8 deletions(-)
drivers/iommu/mtk_iommu.c +0 -7
@@ -9,7 +9,6 @@#include <linux/component.h> #include <linux/device.h> #include <linux/dma-direct.h> -#include <linux/dma-iommu.h> #include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h>
@@ -441,17 +440,11 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)if (!dom)return NULL ; -if (iommu_get_dma_cookie (&dom->domain)) { -kfree (dom); -return NULL ; - } -return &dom->domain; }static void mtk_iommu_domain_free (struct iommu_domain *domain) { -iommu_put_dma_cookie (domain);kfree (to_mtk_domain (domain)); }
drivers/iommu/mtk_iommu_v1.c +0 -1
@@ -13,7 +13,6 @@#include <linux/component.h> #include <linux/device.h> #include <linux/dma-mapping.h> -#include <linux/dma-iommu.h> #include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h>
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 8/24 iommu/rockchip: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
---
v3: Also remove unneeded include
--- drivers/iommu/rockchip-iommu.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-)
drivers/iommu/rockchip-iommu.c +1 -11
@@ -10,7 +10,6 @@#include <linux/compiler.h> #include <linux/delay.h> #include <linux/device.h> -#include <linux/dma-iommu.h> #include <linux/dma-mapping.h> #include <linux/errno.h> #include <linux/interrupt.h>
@@ -1074,10 +1073,6 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)if (!rk_domain)return NULL ; -if (type ==IOMMU_DOMAIN_DMA && -iommu_get_dma_cookie (&rk_domain->domain)) - goto err_free_domain; -/* * rk32xx iommus use a 2 level pagetable. * Each level1 (dt) and level2 (pt) table has 1024 4-byte entries.
@@ -1085,7 +1080,7 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)*/ rk_domain->dt = (u32 *)get_zeroed_page (GFP_KERNEL |GFP_DMA32 );if (!rk_domain->dt) - goto err_put_cookie; + goto err_free_domain; rk_domain->dt_dma =dma_map_single (dma_dev, rk_domain->dt,SPAGE_SIZE ,DMA_TO_DEVICE );
@@ -1106,9 +1101,6 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type) err_free_dt:free_page ((unsigned long )rk_domain->dt); -err_put_cookie: -if (type ==IOMMU_DOMAIN_DMA ) -iommu_put_dma_cookie (&rk_domain->domain); err_free_domain:kfree (rk_domain);
@@ -1137,8 +1129,6 @@ static void rk_iommu_domain_free(struct iommu_domain *domain) SPAGE_SIZE, DMA_TO_DEVICE);free_page ((unsigned long )rk_domain->dt); -if (domain->type ==IOMMU_DOMAIN_DMA ) -iommu_put_dma_cookie (&rk_domain->domain);kfree (rk_domain); }
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 9/24 iommu/sprd: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
---
v3: Also remove unneeded include
--- drivers/iommu/sprd-iommu.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/iommu/sprd-iommu.c +0 -7
@@ -8,7 +8,6 @@#include <linux/clk.h> #include <linux/device.h> -#include <linux/dma-iommu.h> #include <linux/dma-mapping.h> #include <linux/errno.h> #include <linux/iommu.h>
@@ -144,11 +143,6 @@ static struct iommu_domain *sprd_iommu_domain_alloc(unsigned int domain_type)if (!dom)return NULL ; -if (iommu_get_dma_cookie (&dom->domain)) { -kfree (dom); -return NULL ; - } -spin_lock_init (&dom->pgtlock); dom->domain.geometry.aperture_start =0 ;
@@ -161,7 +155,6 @@ static void sprd_iommu_domain_free(struct iommu_domain *domain) {struct sprd_iommu_domain *dom =to_sprd_domain (domain); -iommu_put_dma_cookie (domain);kfree (dom); }
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 10/24 iommu/sun50i: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
---
v3: Also remove unneeded include
--- drivers/iommu/sun50i-iommu.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-)
drivers/iommu/sun50i-iommu.c +1 -12
@@ -7,7 +7,6 @@#include <linux/clk.h> #include <linux/device.h> #include <linux/dma-direction.h> -#include <linux/dma-iommu.h> #include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/errno.h>
@@ -610,14 +609,10 @@ static struct iommu_domain *sun50i_iommu_domain_alloc(unsigned type)if (!sun50i_domain)return NULL ; -if (type ==IOMMU_DOMAIN_DMA && -iommu_get_dma_cookie (&sun50i_domain->domain)) - goto err_free_domain; - sun50i_domain->dt = (u32 *)__get_free_pages (GFP_KERNEL | __GFP_ZERO,get_order (DT_SIZE ));if (!sun50i_domain->dt) - goto err_put_cookie; + goto err_free_domain;refcount_set (&sun50i_domain->refcnt,1 );
@@ -627,10 +622,6 @@ static struct iommu_domain *sun50i_iommu_domain_alloc(unsigned type)return &sun50i_domain->domain; -err_put_cookie: -if (type ==IOMMU_DOMAIN_DMA ) -iommu_put_dma_cookie (&sun50i_domain->domain); - err_free_domain:kfree (sun50i_domain);
@@ -644,8 +635,6 @@ static void sun50i_iommu_domain_free(struct iommu_domain *domain)free_pages ((unsigned long )sun50i_domain->dt,get_order (DT_SIZE )); sun50i_domain->dt =NULL ; -iommu_put_dma_cookie (domain); -kfree (sun50i_domain); }
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 11/24 iommu/virtio: Drop IOVA cookie management
In reply to Robin MurphyThe core code bakes its own cookies now.
--- drivers/iommu/virtio-iommu.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/iommu/virtio-iommu.c +0 -8
@@ -598,12 +598,6 @@ static struct iommu_domain *viommu_domain_alloc(unsigned type)spin_lock_init (&vdomain->mappings_lock); vdomain->mappings =RB_ROOT_CACHED ; -if (type ==IOMMU_DOMAIN_DMA && -iommu_get_dma_cookie (&vdomain->domain)) { -kfree (vdomain); -return NULL ; - } -return &vdomain->domain; }
@@ -643,8 +637,6 @@ static void viommu_domain_free(struct iommu_domain *domain) {struct viommu_domain *vdomain =to_viommu_domain (domain); -iommu_put_dma_cookie (domain); -/* Free all remaining mappings (size 2^64) */ viommu_del_mappings (vdomain,0 ,0 );
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 12/24 iommu/dma: Unexport IOVA cookie management
In reply to Robin MurphyIOVA cookies are now got and put by core code, so we no longer need to export these to modular drivers. The export for getting MSI cookies stays, since VFIO can still be a module, but it was already relying on someone else putting them, so that aspect is unaffected.
--- drivers/iommu/dma-iommu.c | 7 ------- drivers/iommu/iommu.c | 3 +-- 2 files changed, 1 insertion(+), 9 deletions(-)
drivers/iommu/dma-iommu.c +0 -7
@@ -98,9 +98,6 @@ static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)/** * iommu_get_dma_cookie - Acquire DMA-API resources for a domain * @domain: IOMMU domain to prepare for DMA-API usage -* -* IOMMU drivers should normally call this from their domain_alloc -* callback when domain->type == IOMMU_DOMAIN_DMA. */ int iommu_get_dma_cookie (struct iommu_domain *domain) {
@@ -113,7 +110,6 @@ int iommu_get_dma_cookie(struct iommu_domain *domain)return 0 ; } -EXPORT_SYMBOL (iommu_get_dma_cookie);/** * iommu_get_msi_cookie - Acquire just MSI remapping resources
@@ -151,8 +147,6 @@ EXPORT_SYMBOL(iommu_get_msi_cookie);* iommu_put_dma_cookie - Release a domain's DMA mapping resources * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie() or * iommu_get_msi_cookie() -* -* IOMMU drivers should normally call this from their domain_free callback. */ void iommu_put_dma_cookie (struct iommu_domain *domain) {
@@ -172,7 +166,6 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)kfree (cookie); domain->iova_cookie =NULL ; } -EXPORT_SYMBOL (iommu_put_dma_cookie);/** * iommu_dma_get_resv_regions - Reserved region driver helper
drivers/iommu/iommu.c +1 -2
@@ -1947,8 +1947,7 @@ static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,/* Assume all sizes by default; the driver may override this later */ domain->pgsize_bitmap = bus->iommu_ops->pgsize_bitmap; -/* Temporarily avoid -EEXIST while drivers still get their own cookies */ -if (type ==IOMMU_DOMAIN_DMA && !domain->iova_cookie &&iommu_get_dma_cookie (domain)) { +if (type ==IOMMU_DOMAIN_DMA &&iommu_get_dma_cookie (domain)) {iommu_domain_free (domain); domain =NULL ; }
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 13/24 iommu/dma: Remove redundant "!dev" checks
In reply to Robin Murphyiommu_dma_init_domain() is now only called from iommu_setup_dma_ops(), which has already assumed dev to be non-NULL.
--- drivers/iommu/dma-iommu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/iommu/dma-iommu.c +1 -4
@@ -363,7 +363,7 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,init_iova_domain (iovad,1UL << order, base_pfn); -if (!cookie->fq_domain && (!dev || !dev_is_untrusted (dev)) && +if (!cookie->fq_domain && !dev_is_untrusted (dev) && domain->ops->flush_iotlb_all && !iommu_get_dma_strict (domain)) {if (init_iova_flush_queue (iovad, iommu_dma_flush_iotlb_all, iommu_dma_entry_dtor))
@@ -372,9 +372,6 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, cookie->fq_domain = domain; } -if (!dev) -return 0 ; -return iova_reserve_iommu_regions (dev, domain); }
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 14/24 iommu: Indicate queued flushes via gather data
In reply to Robin MurphySince iommu_iotlb_gather exists to help drivers optimise flushing for a given unmap request, it is also the logical place to indicate whether the unmap is strict or not, and thus help them further optimise for whether to expect a sync or a flush_all subsequently. As part of that, it also seems fair to make the flush queue code take responsibility for enforcing the really subtle ordering requirement it brings, so that we don't need to worry about forgetting that if new drivers want to add flush queue support, and can consolidate the existing versions.
While we're adding to the kerneldoc, also fill in some info for @freelist which was overlooked previously.
---
v3: New
--- drivers/iommu/dma-iommu.c | 1 + drivers/iommu/iova.c | 7 +++++++ include/linux/iommu.h | 8 +++++++- 3 files changed, 15 insertions(+), 1 deletion(-)
drivers/iommu/dma-iommu.c +1 -0
@@ -474,6 +474,7 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr, dma_addr -= iova_off; size =iova_align (iovad, size + iova_off);iommu_iotlb_gather_init (&iotlb_gather); + iotlb_gather.queued = cookie->fq_domain; unmapped =iommu_unmap_fast (domain, dma_addr, size, &iotlb_gather);WARN_ON (unmapped != size);
drivers/iommu/iova.c +7 -0
@@ -637,6 +637,13 @@ void queue_iova(struct iova_domain *iovad,unsigned long flags;unsigned idx; +/* +* Order against the IOMMU driver's pagetable update from unmapping +* @pte, to guarantee that iova_domain_flush() observes that if called +* from a different CPU before we release the lock below. +*/ +smp_wmb (); +spin_lock_irqsave (&fq->lock, flags);/*
include/linux/iommu.h +7 -1
@@ -161,16 +161,22 @@ enum iommu_dev_features {* @start: IOVA representing the start of the range to be flushed * @end: IOVA representing the end of the range to be flushed (inclusive) * @pgsize: The interval at which to perform the flush +* @freelist: Removed pages to free after sync +* @queued: Indicates that the flush will be queued * * This structure is intended to be updated by multiple calls to the * ->unmap() function in struct iommu_ops before eventually being passed -* into ->iotlb_sync(). +* into ->iotlb_sync(). Drivers can add pages to @freelist to be freed after +* ->iotlb_sync() or ->iotlb_flush_all() have cleared all cached references to +* them. @queued is set to indicate when ->iotlb_flush_all() will be called +* later instead of ->iotlb_sync(), so drivers may optimise accordingly. */ struct iommu_iotlb_gather {unsigned long start;unsigned long end;size_t pgsize;struct page *freelist; +bool queued; };/**
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 15/24 iommu/io-pgtable: Remove non-strict quirk
In reply to Robin MurphyIO_PGTABLE_QUIRK_NON_STRICT was never a very comfortable fit, since it's not a quirk of the pagetable format itself. Now that we have a more appropriate way to convey non-strict unmaps, though, this last of the non-quirk quirks can also go, and with the flush queue code also now enforcing its own ordering we can have a lovely cleanup all round.
---
v3: New
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 --- drivers/iommu/io-pgtable-arm-v7s.c | 12 ++---------- drivers/iommu/io-pgtable-arm.c | 12 ++---------- include/linux/io-pgtable.h | 5 ----- 5 files changed, 4 insertions(+), 31 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +0 -3
@@ -2174,9 +2174,6 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain, .iommu_dev = smmu->dev, }; -if (!iommu_get_dma_strict (domain)) - pgtbl_cfg.quirks |=IO_PGTABLE_QUIRK_NON_STRICT ; - pgtbl_ops =alloc_io_pgtable_ops (fmt, &pgtbl_cfg, smmu_domain);if (!pgtbl_ops)return -ENOMEM ;
drivers/iommu/arm/arm-smmu/arm-smmu.c +0 -3
@@ -765,9 +765,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, .iommu_dev = smmu->dev, }; -if (!iommu_get_dma_strict (domain)) - pgtbl_cfg.quirks |=IO_PGTABLE_QUIRK_NON_STRICT ; -if (smmu->impl && smmu->impl->init_context) { ret = smmu->impl->init_context (smmu_domain, &pgtbl_cfg, dev);if (ret)
drivers/iommu/io-pgtable-arm-v7s.c +2 -10
@@ -700,14 +700,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, ARM_V7S_BLOCK_SIZE(lvl + 1)); ptep =iopte_deref (pte[i], lvl, data);__arm_v7s_free_table (ptep, lvl +1 , data); - }else if (iop->cfg.quirks &IO_PGTABLE_QUIRK_NON_STRICT ) { -/* -* Order the PTE update against queueing the IOVA, to -* guarantee that a flush callback from a different CPU -* has observed it before the TLBIALL can be issued. -*/ -smp_wmb (); - }else { + }else if (!gather->queued) {io_pgtable_tlb_add_page (iop, gather, iova, blk_size); } iova += blk_size;
@@ -791,8 +784,7 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |IO_PGTABLE_QUIRK_NO_PERMS | -IO_PGTABLE_QUIRK_ARM_MTK_EXT | -IO_PGTABLE_QUIRK_NON_STRICT )) +IO_PGTABLE_QUIRK_ARM_MTK_EXT ))return NULL ;/* If ARM_MTK_4GB is enabled, the NO_PERMS is also expected. */
drivers/iommu/io-pgtable-arm.c +2 -10
@@ -638,14 +638,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,io_pgtable_tlb_flush_walk (iop, iova + i * size, size,ARM_LPAE_GRANULE (data));__arm_lpae_free_pgtable (data, lvl +1 ,iopte_deref (pte, data)); - }else if (iop->cfg.quirks &IO_PGTABLE_QUIRK_NON_STRICT ) { -/* -* Order the PTE update against queueing the IOVA, to -* guarantee that a flush callback from a different CPU -* has observed it before the TLBIALL can be issued. -*/ -smp_wmb (); - }else { + }else if (!gather->queued) {io_pgtable_tlb_add_page (iop, gather, iova + i * size, size); }
@@ -825,7 +818,6 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)bool tg1;if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS | -IO_PGTABLE_QUIRK_NON_STRICT |IO_PGTABLE_QUIRK_ARM_TTBR1 |IO_PGTABLE_QUIRK_ARM_OUTER_WBWA ))return NULL ;
@@ -929,7 +921,7 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie) typeof(&cfg->arm_lpae_s2_cfg.vtcr) vtcr = &cfg->arm_lpae_s2_cfg.vtcr;/* The NS quirk doesn't apply at stage 2 */ -if (cfg->quirks & ~(IO_PGTABLE_QUIRK_NON_STRICT )) +if (cfg->quirks)return NULL ; data =arm_lpae_alloc_pgtable (cfg);
include/linux/io-pgtable.h +0 -5
@@ -73,10 +73,6 @@ struct io_pgtable_cfg {* to support up to 35 bits PA where the bit32, bit33 and bit34 are * encoded in the bit9, bit4 and bit5 of the PTE respectively. * -* IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs -* on unmap, for DMA domains using the flush queue mechanism for -* delayed invalidation. -* * IO_PGTABLE_QUIRK_ARM_TTBR1: (ARM LPAE format) Configure the table * for use in the upper half of a split address space. *
@@ -86,7 +82,6 @@ struct io_pgtable_cfg {#define IO_PGTABLE_QUIRK_ARM_NS BIT(0)#define IO_PGTABLE_QUIRK_NO_PERMS BIT(1)#define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3) -#define IO_PGTABLE_QUIRK_NON_STRICT BIT(4)#define IO_PGTABLE_QUIRK_ARM_TTBR1 BIT(5)#define IO_PGTABLE_QUIRK_ARM_OUTER_WBWA BIT(6)unsigned long quirks;
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v4 15/24] iommu/io-pgtable: Remove non-strict quirk
Hi Robin,
Quoted 7 lines · Robin Murphy
IO_PGTABLE_QUIRK_NON_STRICTwas never a very comfortable fit, since it's not a quirk of the pagetable format itself. Now that we have a more appropriate way to convey non-strict unmaps, though, this last of the non-quirk quirks can also go, and with the flush queue code also now enforcing its own ordering we can have a lovely cleanup all round.Signed-off-by Robin Murphy <[email protected]>
Thanks for your patch, which is now commit a8e5f04458c4e496 ("iommu/io-pgtable: Remove non-strict quirk") in iommu/next.
Quoted 5 lines
drivers/iommu/io-pgtable-arm-v7s.c +0
-0@@ -700,14 +700,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, ARM_V7S_BLOCK_SIZE(lvl + 1)); ptep =iopte_deref (pte[i], lvl, data);
drivers/iommu/io-pgtable-arm-v7s.c static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, · line 703
Quoted 10 lines
drivers/iommu/io-pgtable-arm-v7s.c +1
-8__arm_v7s_free_table (ptep, lvl +1 , data); - }else if (iop->cfg.quirks &IO_PGTABLE_QUIRK_NON_STRICT ) { -/* -* Order the PTE update against queueing the IOVA, to -* guarantee that a flush callback from a different CPU -* has observed it before the TLBIALL can be issued. -*/ -smp_wmb (); - }else { + }else if (!gather->queued) {
If CONFIG_IOMMU_API=n:
error: ‘struct iommu_iotlb_gather’ has no member named ‘queued’
This can be reproduced using e.g. shmobile_defconfig with
CONFIG_IOMMU_SUPPORT=y CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y
Quoted 9 lines
drivers/iommu/io-pgtable-arm-v7s.c +0
-0io_pgtable_tlb_add_page (iop, gather, iova, blk_size); } iova += blk_size;drivers/iommu/io-pgtable-arm.c +0
-0@@ -638,14 +638,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,io_pgtable_tlb_flush_walk (iop, iova + i * size, size,ARM_LPAE_GRANULE (data));
drivers/iommu/io-pgtable-arm.c static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, · line 641
Quoted 10 lines
drivers/iommu/io-pgtable-arm.c +1
-8__arm_lpae_free_pgtable (data, lvl +1 ,iopte_deref (pte, data)); - }else if (iop->cfg.quirks &IO_PGTABLE_QUIRK_NON_STRICT ) { -/* -* Order the PTE update against queueing the IOVA, to -* guarantee that a flush callback from a different CPU -* has observed it before the TLBIALL can be issued. -*/ -smp_wmb (); - }else { + }else if (!gather->queued) {
If CONFIG_IOMMU_API=n:
error: ‘struct iommu_iotlb_gather’ has no member named ‘queued’
This can be reproduced using e.g. shmobile_defconfig with
CONFIG_IOMMU_SUPPORT=y CONFIG_IOMMU_IO_PGTABLE_LPAE=y
drivers/iommu/io-pgtable-arm.c static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, · line 644
Quoted 3 lines
drivers/iommu/io-pgtable-arm.c +0
-0io_pgtable_tlb_add_page (iop, gather, iova + i * size, size); }
Perhaps "select IOMMU_API" should be added (moved from individual drivers) to both IOMMU_IO_PGTABLE_ARMV7S and IOMMU_IO_PGTABLE_LPAE? Or iommu_iotlb_gather.queued should not be accessed here, or the access wrapped into a static inline helper function with a dummy for the CONFIG_IOMMU_API=n case?
Gr{oetje,eeting}s,
Geert
Signature · 5 lines
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected] In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Robin Murphy
maintainerRe: [PATCH v4 15/24] iommu/io-pgtable: Remove non-strict quirk
Hi Geert,
Quoted 71 lines · Geert Uytterhoeven
Hi Robin,
Quoted 7 lines · Robin Murphy
IO_PGTABLE_QUIRK_NON_STRICTwas never a very comfortable fit, since it's not a quirk of the pagetable format itself. Now that we have a more appropriate way to convey non-strict unmaps, though, this last of the non-quirk quirks can also go, and with the flush queue code also now enforcing its own ordering we can have a lovely cleanup all round.Signed-off-by Robin Murphy <[email protected]>Thanks for your patch, which is now commit
a8e5f04458c4e496("iommu/io-pgtable: Remove non-strict quirk") in iommu/next.Quoted 5 lines
drivers/iommu/io-pgtable-arm-v7s.c +0
-0@@ -700,14 +700,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, ARM_V7S_BLOCK_SIZE(lvl + 1)); ptep =iopte_deref (pte[i], lvl, data);drivers/iommu/io-pgtable-arm-v7s.c static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data, · line 703
Quoted 10 lines
drivers/iommu/io-pgtable-arm-v7s.c +1
-8__arm_v7s_free_table (ptep, lvl +1 , data); - }else if (iop->cfg.quirks &IO_PGTABLE_QUIRK_NON_STRICT ) { -/* -* Order the PTE update against queueing the IOVA, to -* guarantee that a flush callback from a different CPU -* has observed it before the TLBIALL can be issued. -*/ -smp_wmb (); - }else { + }else if (!gather->queued) {If
CONFIG_IOMMU_API=n:error: ‘struct iommu_iotlb_gather’ has no member named ‘queued’
This can be reproduced using e.g.
shmobile_defconfigwith
CONFIG_IOMMU_SUPPORT=yCONFIG_IOMMU_IO_PGTABLE_ARMV7S=yQuoted 9 lines
drivers/iommu/io-pgtable-arm-v7s.c +0
-0io_pgtable_tlb_add_page (iop, gather, iova, blk_size); } iova += blk_size;drivers/iommu/io-pgtable-arm.c +0
-0@@ -638,14 +638,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,io_pgtable_tlb_flush_walk (iop, iova + i * size, size,ARM_LPAE_GRANULE (data));drivers/iommu/io-pgtable-arm.c static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, · line 641
Quoted 10 lines
drivers/iommu/io-pgtable-arm.c +1
-8__arm_lpae_free_pgtable (data, lvl +1 ,iopte_deref (pte, data)); - }else if (iop->cfg.quirks &IO_PGTABLE_QUIRK_NON_STRICT ) { -/* -* Order the PTE update against queueing the IOVA, to -* guarantee that a flush callback from a different CPU -* has observed it before the TLBIALL can be issued. -*/ -smp_wmb (); - }else { + }else if (!gather->queued) {If
CONFIG_IOMMU_API=n:error: ‘struct iommu_iotlb_gather’ has no member named ‘queued’
This can be reproduced using e.g.
shmobile_defconfigwith
CONFIG_IOMMU_SUPPORT=yCONFIG_IOMMU_IO_PGTABLE_LPAE=ydrivers/iommu/io-pgtable-arm.c static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, · line 644
Quoted 3 lines
drivers/iommu/io-pgtable-arm.c +0
-0io_pgtable_tlb_add_page (iop, gather, iova + i * size, size); }
Quoted 5 lines
Perhaps "select
IOMMU_API" should be added (moved from individual drivers) to bothIOMMU_IO_PGTABLE_ARMV7SandIOMMU_IO_PGTABLE_LPAE? Or iommu_iotlb_gather.queued should not be accessed here, or the access wrapped into a static inline helper function with a dummy for theCONFIG_IOMMU_API=ncase?
Those (and worse) should be fixed by this patch:
which apparently hasn't made it to -next yet.
Thanks,
Robin.
Quoted 5 lines
Gr{oetje,eeting}s,
Geert
Robin Murphy
maintainerPATCH v4 16/24 iommu: Introduce explicit type for non-strict DMA domains
In reply to Robin MurphyPromote the difference between strict and non-strict DMA domains from an internal detail to a distinct domain feature and type, to pave the road for exposing it through the sysfs default domain interface.
--- drivers/iommu/dma-iommu.c | 2 +- drivers/iommu/iommu.c | 8 ++++++-- include/linux/iommu.h | 11 +++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-)
drivers/iommu/dma-iommu.c +1 -1
@@ -1312,7 +1312,7 @@ void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 dma_limit)* The IOMMU core code allocates the default DMA domain, which the * underlying IOMMU driver needs to support via the dma-iommu layer. */ -if (domain->type ==IOMMU_DOMAIN_DMA ) { +if (iommu_is_dma_domain (domain)) {if (iommu_dma_init_domain (domain, dma_base, dma_limit, dev)) goto out_err; dev->dma_ops = &iommu_dma_ops;
drivers/iommu/iommu.c +6 -2
@@ -115,6 +115,7 @@ static const char *iommu_domain_type_str(unsigned int t)case IOMMU_DOMAIN_UNMANAGED :return "Unmanaged" ;case IOMMU_DOMAIN_DMA : +case IOMMU_DOMAIN_DMA_FQ :return "Translated" ;default :return "Unknown" ;
@@ -552,6 +553,9 @@ static ssize_t iommu_group_show_type(struct iommu_group *group,case IOMMU_DOMAIN_DMA : type ="DMA\n" ;break ; +case IOMMU_DOMAIN_DMA_FQ : + type ="DMA-FQ\n" ; +break ; } }mutex_unlock (&group->mutex);
@@ -765,7 +769,7 @@ static int iommu_create_device_direct_mappings(struct iommu_group *group,unsigned long pg_size;int ret =0 ; -if (!domain || domain->type !=IOMMU_DOMAIN_DMA ) +if (!domain || !iommu_is_dma_domain (domain))return 0 ;BUG_ON (!domain->pgsize_bitmap);
@@ -1947,7 +1951,7 @@ static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,/* Assume all sizes by default; the driver may override this later */ domain->pgsize_bitmap = bus->iommu_ops->pgsize_bitmap; -if (type ==IOMMU_DOMAIN_DMA &&iommu_get_dma_cookie (domain)) { +if (iommu_is_dma_domain (domain) &&iommu_get_dma_cookie (domain)) {iommu_domain_free (domain); domain =NULL ; }
include/linux/iommu.h +11 -0
@@ -61,6 +61,7 @@ struct iommu_domain_geometry {#define __IOMMU_DOMAIN_DMA_API (1U << 1)/* Domain for use in DMA-API implementation */ #define __IOMMU_DOMAIN_PT (1U << 2)/* Domain is identity mapped */ +#define __IOMMU_DOMAIN_DMA_FQ (1U << 3)/* DMA-API uses flush queue */ /* * This are the possible domain-types
@@ -73,12 +74,17 @@ struct iommu_domain_geometry {* IOMMU_DOMAIN_DMA - Internally used for DMA-API implementations. * This flag allows IOMMU drivers to implement * certain optimizations for these domains +* IOMMU_DOMAIN_DMA_FQ - As above, but definitely using batched TLB +* invalidation. */ #define IOMMU_DOMAIN_BLOCKED (0U)#define IOMMU_DOMAIN_IDENTITY (__IOMMU_DOMAIN_PT)#define IOMMU_DOMAIN_UNMANAGED (__IOMMU_DOMAIN_PAGING)#define IOMMU_DOMAIN_DMA (__IOMMU_DOMAIN_PAGING | \ __IOMMU_DOMAIN_DMA_API) +#define IOMMU_DOMAIN_DMA_FQ (__IOMMU_DOMAIN_PAGING | \ + __IOMMU_DOMAIN_DMA_API | \ + __IOMMU_DOMAIN_DMA_FQ)struct iommu_domain {unsigned type;
@@ -90,6 +96,11 @@ struct iommu_domain {struct iommu_dma_cookie *iova_cookie; }; +static inline bool iommu_is_dma_domain (struct iommu_domain *domain) +{ +return domain->type & __IOMMU_DOMAIN_DMA_API; +} +enum iommu_cap {IOMMU_CAP_CACHE_COHERENCY ,/* IOMMU can enforce cache coherent DMA transactions */
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 17/24 iommu/amd: Prepare for multiple DMA domain types
In reply to Robin MurphyThe DMA ops reset/setup can simply be unconditional, since iommu-dma already knows only to touch DMA domains.
--- drivers/iommu/amd/iommu.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/iommu/amd/iommu.c +2 -7
@@ -1707,14 +1707,9 @@ static struct iommu_device *amd_iommu_probe_device(struct device *dev)static void amd_iommu_probe_finalize (struct device *dev) { -struct iommu_domain *domain; -/* Domains are initialized for this device - have a look what we ended up with */ - domain =iommu_get_domain_for_dev (dev); -if (domain->type ==IOMMU_DOMAIN_DMA ) -iommu_setup_dma_ops (dev,0 ,U64_MAX ); -else -set_dma_ops (dev,NULL ); +set_dma_ops (dev,NULL ); +iommu_setup_dma_ops (dev,0 ,U64_MAX ); }static void amd_iommu_release_device (struct device *dev)
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 18/24 iommu/arm-smmu: Prepare for multiple DMA domain types
In reply to Robin MurphyIn preparation for the strict vs. non-strict decision for DMA domains to be expressed in the domain type, make sure we expose our flush queue awareness by accepting the new domain type.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 1 + drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +1 -0
@@ -1972,6 +1972,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)if (type !=IOMMU_DOMAIN_UNMANAGED && type !=IOMMU_DOMAIN_DMA && + type !=IOMMU_DOMAIN_DMA_FQ && type !=IOMMU_DOMAIN_IDENTITY )return NULL ;
drivers/iommu/arm/arm-smmu/arm-smmu.c +2 -1
@@ -866,7 +866,8 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)struct arm_smmu_domain *smmu_domain;if (type !=IOMMU_DOMAIN_UNMANAGED && type !=IOMMU_DOMAIN_IDENTITY ) { -if (using_legacy_binding || type !=IOMMU_DOMAIN_DMA ) +if (using_legacy_binding || + (type !=IOMMU_DOMAIN_DMA && type !=IOMMU_DOMAIN_DMA_FQ ))return NULL ; }/*
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 19/24 iommu/vt-d: Prepare for multiple DMA domain types
In reply to Robin MurphyIn preparation for the strict vs. non-strict decision for DMA domains to be expressed in the domain type, make sure we expose our flush queue awareness by accepting the new domain type, and test the specific feature flag where we want to identify DMA domains in general. The DMA ops reset/setup can simply be made unconditional, since iommu-dma already knows only to touch DMA domains.
--- drivers/iommu/intel/iommu.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
drivers/iommu/intel/iommu.c +6 -9
@@ -582,7 +582,7 @@ struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)int iommu_id;/* si_domain and vm domain should not get here. */ -if (WARN_ON (domain->domain.type !=IOMMU_DOMAIN_DMA )) +if (WARN_ON (!iommu_is_dma_domain (&domain->domain)))return NULL ;for_each_domain_iommu (iommu_id, domain)
@@ -1034,7 +1034,7 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, pteval = ((uint64_t )virt_to_dma_pfn (tmp_page) <<VTD_PAGE_SHIFT ) |DMA_PTE_READ |DMA_PTE_WRITE ;if (domain_use_first_level (domain)) { pteval |=DMA_FL_PTE_XD |DMA_FL_PTE_US ; -if (domain->domain.type ==IOMMU_DOMAIN_DMA ) +if (iommu_is_dma_domain (&domain->domain)) pteval |=DMA_FL_PTE_ACCESS ; }if (cmpxchg64 (&pte->val,0ULL , pteval))
@@ -2345,7 +2345,7 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,if (domain_use_first_level (domain)) { attr |=DMA_FL_PTE_XD |DMA_FL_PTE_US ; -if (domain->domain.type ==IOMMU_DOMAIN_DMA ) { +if (iommu_is_dma_domain (&domain->domain)) { attr |=DMA_FL_PTE_ACCESS ;if (prot &DMA_PTE_WRITE ) attr |=DMA_FL_PTE_DIRTY ;
@@ -4528,6 +4528,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)switch (type) {case IOMMU_DOMAIN_DMA : +case IOMMU_DOMAIN_DMA_FQ :case IOMMU_DOMAIN_UNMANAGED : dmar_domain =alloc_domain (0 );if (!dmar_domain) {
@@ -5197,12 +5198,8 @@ static void intel_iommu_release_device(struct device *dev)static void intel_iommu_probe_finalize (struct device *dev) { -struct iommu_domain *domain =iommu_get_domain_for_dev (dev); - -if (domain && domain->type ==IOMMU_DOMAIN_DMA ) -iommu_setup_dma_ops (dev,0 ,U64_MAX ); -else -set_dma_ops (dev,NULL ); +set_dma_ops (dev,NULL ); +iommu_setup_dma_ops (dev,0 ,U64_MAX ); } static void intel_iommu_get_resv_regions(struct device *device,
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 20/24 iommu: Express DMA strictness via the domain type
In reply to Robin MurphyEliminate the iommu_get_dma_strict() indirection and pipe the information through the domain type from the beginning. Besides the flow simplification this also has several nice side-effects:
- Automatically implies strict mode for untrusted devices by virtue of their IOMMU_DOMAIN_DMA override.
- Ensures that we only end up using flush queues for drivers which are aware of them and can actually benefit.
- Allows us to handle flush queue init failure by falling back to strict mode instead of leaving it to possibly blow up later.
---
v3: Remember to update iommu_def_domain_type accordingly from
iommu_set_dma_strict() too
--- drivers/iommu/dma-iommu.c | 10 ++++++---- drivers/iommu/iommu.c | 14 +++++--------- include/linux/iommu.h | 1 - 3 files changed, 11 insertions(+), 14 deletions(-)
drivers/iommu/dma-iommu.c +6 -4
@@ -363,13 +363,15 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,init_iova_domain (iovad,1UL << order, base_pfn); -if (!cookie->fq_domain && !dev_is_untrusted (dev) && - domain->ops->flush_iotlb_all && !iommu_get_dma_strict (domain)) { +/* If the FQ fails we can simply fall back to strict mode */ +if (domain->type ==IOMMU_DOMAIN_DMA_FQ && !cookie->fq_domain) {if (init_iova_flush_queue (iovad, iommu_dma_flush_iotlb_all, - iommu_dma_entry_dtor)) + iommu_dma_entry_dtor)) {pr_warn ("iova flush queue initialization failed\n" ); -else + domain->type =IOMMU_DOMAIN_DMA ; + }else { cookie->fq_domain = domain; + } }return iova_reserve_iommu_regions (dev, domain);
drivers/iommu/iommu.c +5 -9
@@ -136,6 +136,9 @@ static int __init iommu_subsys_init(void) } } +if (!iommu_default_passthrough () && !iommu_dma_strict) + iommu_def_domain_type =IOMMU_DOMAIN_DMA_FQ ; + pr_info("Default domain type: %s %s\n", iommu_domain_type_str(iommu_def_domain_type), (iommu_cmd_line & IOMMU_CMD_LINE_DMA_API) ?
@@ -355,17 +358,10 @@ early_param("iommu.strict", iommu_dma_setup);void iommu_set_dma_strict (void ) { iommu_dma_strict = true; +if (iommu_def_domain_type ==IOMMU_DOMAIN_DMA_FQ ) + iommu_def_domain_type =IOMMU_DOMAIN_DMA ; } -bool iommu_get_dma_strict (struct iommu_domain *domain) -{ -/* only allow lazy flushing for DMA domains */ -if (domain->type ==IOMMU_DOMAIN_DMA ) -return iommu_dma_strict; -return true; -} -EXPORT_SYMBOL_GPL (iommu_get_dma_strict); -static ssize_t iommu_group_attr_show (struct kobject *kobj,struct attribute *__attr,char *buf) {
include/linux/iommu.h +0 -1
@@ -504,7 +504,6 @@ int iommu_set_pgtable_quirks(struct iommu_domain *domain, unsigned long quirks);void iommu_set_dma_strict (void ); -bool iommu_get_dma_strict (struct iommu_domain *domain);extern int report_iommu_fault (struct iommu_domain *domain,struct device *dev,unsigned long iova,int flags);
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 21/24 iommu: Expose DMA domain strictness via sysfs
In reply to Robin MurphyThe sysfs interface for default domain types exists primarily so users can choose the performance/security tradeoff relevant to their own workload. As such, the choice between the policies for DMA domains fits perfectly as an additional point on that scale - downgrading a particular device from a strict default to non-strict may be enough to let it reach the desired level of performance, while still retaining more peace of mind than with a wide-open identity domain. Now that we've abstracted non-strict mode as a distinct type of DMA domain, allow it to be chosen through the user interface as well.
---
v3: Summarise the implications in the documentation for completeness
--- Documentation/ABI/testing/sysfs-kernel-iommu_groups | 6 +++++- drivers/iommu/iommu.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-)
Documentation/ABI/testing/sysfs-kernel-iommu_groups +5 -1
@@ -42,8 +42,12 @@ Description: /sys/kernel/iommu_groups/<grp_id>/type shows the type of default ======== ====================================================== DMA All the DMA transactions from the device in this group are translated by the iommu. + DMA-FQ As above, but using batched invalidation to lazily + remove translations after use. This may offer reduced + overhead at the cost of reduced memory protection. identity All the DMA transactions from the device in this group - are not translated by the iommu. + are not translated by the iommu. Maximum performance + but zero protection. auto Change to the type the device was booted with. ======== ======================================================
drivers/iommu/iommu.c +2 -0
@@ -3267,6 +3267,8 @@ static ssize_t iommu_group_store_type(struct iommu_group *group, req_type =IOMMU_DOMAIN_IDENTITY ; else if (sysfs_streq(buf, "DMA")) req_type =IOMMU_DOMAIN_DMA ; + else if (sysfs_streq(buf, "DMA-FQ")) + req_type =IOMMU_DOMAIN_DMA_FQ ; else if (sysfs_streq(buf, "auto")) req_type =0 ; else
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 22/24 iommu: Only log strictness for DMA domains
In reply to Robin MurphyWhen passthrough is enabled, the default strictness policy becomes irrelevant, since any subsequent runtime override to a DMA domain type now embodies an explicit choice of strictness as well. Save on noise by only logging the default policy when it is meaningfully in effect.
--- drivers/iommu/iommu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/iommu/iommu.c +5 -4
@@ -144,10 +144,11 @@ static int __init iommu_subsys_init(void) (iommu_cmd_line &IOMMU_CMD_LINE_DMA_API ) ? "(set via kernel command line)" : ""); -pr_info ("DMA domain TLB invalidation policy: %s mode %s\n" , - iommu_dma_strict ?"strict" :"lazy" , - (iommu_cmd_line &IOMMU_CMD_LINE_STRICT ) ? -"(set via kernel command line)" :"" ); +if (!iommu_default_passthrough ()) +pr_info ("DMA domain TLB invalidation policy: %s mode %s\n" , + iommu_dma_strict ?"strict" :"lazy" , + (iommu_cmd_line &IOMMU_CMD_LINE_STRICT ) ? +"(set via kernel command line)" :"" );return 0 ; }
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 23/24 iommu: Merge strictness and domain type configs
In reply to Robin MurphyTo parallel the sysfs behaviour, merge the new build-time option for DMA domain strictness into the default domain type choice.
---
v3: Remember to update parameter documentation as well
--- .../admin-guide/kernel-parameters.txt | 8 +- drivers/iommu/Kconfig | 80 +++++++++---------- drivers/iommu/iommu.c | 2 +- 3 files changed, 44 insertions(+), 46 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +3 -5
@@ -2045,11 +2045,9 @@ 1 - Strict mode. DMA unmap operations invalidate IOMMU hardware TLBs synchronously. - unset - Use value of CONFIG_IOMMU_DEFAULT_{LAZY,STRICT}. - Note: on x86, the default behaviour depends on the - equivalent driver-specific parameters, but a strict - mode explicitly specified by either method takes - precedence. + unset - Use value of CONFIG_IOMMU_DEFAULT_DMA_{LAZY,STRICT}. + Note: on x86, strict mode specified via one of the + legacy driver-specific options takes precedence. iommu.passthrough= [ARM64, X86] Configure DMA to bypass the IOMMU by default.
drivers/iommu/Kconfig +40 -40
95 lines not on this page · raw message
drivers/iommu/iommu.c +1 -1
@@ -31,7 +31,7 @@ static struct kset *iommu_group_kset;static DEFINE_IDA (iommu_group_ida);static unsigned int iommu_def_domain_type__read_mostly ; -static bool iommu_dma_strict__read_mostly =IS_ENABLED (CONFIG_IOMMU_DEFAULT_STRICT ); +static bool iommu_dma_strict__read_mostly =IS_ENABLED (CONFIG_IOMMU_DEFAULT_DMA_STRICT );static u32 iommu_cmd_line__read_mostly ;struct iommu_group {
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
maintainerPATCH v4 24/24 iommu: Allow enabling non-strict mode dynamically
In reply to Robin MurphyAllocating and enabling a flush queue is in fact something we can reasonably do while a DMA domain is active, without having to rebuild it from scratch. Thus we can allow a strict -> non-strict transition from sysfs without requiring to unbind the device's driver, which is of particular interest to users who want to make selective relaxations to critical devices like the one serving their root filesystem.
Disabling and draining a queue also seems technically possible to achieve without rebuilding the whole domain, but would certainly be more involved. Furthermore there's not such a clear use-case for tightening up security *after* the device may already have done whatever it is that you don't trust it not to do, so we only consider the relaxation case.
---
v3: Actually think about concurrency, rework most of the fq data
accesses to be (hopefully) safe and comment it all
v4: Squash in simplified iommu_dma_init_fq() refactor, clean up previous
barrier from init_iova_flush_queue(), drop rogue header change (turns out there's a whole other rabbit hole of iova_fq cleanup to venture down after this...)
--- drivers/iommu/dma-iommu.c | 47 ++++++++++++++++++++++++++------------- drivers/iommu/iommu.c | 17 ++++++++++---- drivers/iommu/iova.c | 11 ++++----- include/linux/dma-iommu.h | 6 +++++ 4 files changed, 57 insertions(+), 24 deletions(-)
drivers/iommu/dma-iommu.c +32 -15
@@ -310,6 +310,30 @@ static bool dev_is_untrusted(struct device *dev)return dev_is_pci (dev) &&to_pci_dev (dev)->untrusted; } +/* sysfs updates are serialised by the mutex of the group owning @domain */ +int iommu_dma_init_fq (struct iommu_domain *domain) +{ +struct iommu_dma_cookie *cookie = domain->iova_cookie; +int ret; + +if (cookie->fq_domain) +return 0 ; + + ret =init_iova_flush_queue (&cookie->iovad, iommu_dma_flush_iotlb_all, + iommu_dma_entry_dtor); +if (ret) { +pr_warn ("iova flush queue initialization failed\n" ); +return ret; + } +/* +* Prevent incomplete iovad->fq being observable. Pairs with path from +* __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova() +*/ +smp_wmb (); +WRITE_ONCE (cookie->fq_domain, domain); +return 0 ; +} +/** * iommu_dma_init_domain - Initialise a DMA mapping domain * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
@@ -364,15 +388,8 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,init_iova_domain (iovad,1UL << order, base_pfn);/* If the FQ fails we can simply fall back to strict mode */ -if (domain->type ==IOMMU_DOMAIN_DMA_FQ && !cookie->fq_domain) { -if (init_iova_flush_queue (iovad, iommu_dma_flush_iotlb_all, - iommu_dma_entry_dtor)) { -pr_warn ("iova flush queue initialization failed\n" ); - domain->type =IOMMU_DOMAIN_DMA ; - }else { - cookie->fq_domain = domain; - } - } +if (domain->type ==IOMMU_DOMAIN_DMA_FQ &&iommu_dma_init_fq (domain)) + domain->type =IOMMU_DOMAIN_DMA ;return iova_reserve_iommu_regions (dev, domain); }
@@ -447,17 +464,17 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain, }static void iommu_dma_free_iova (struct iommu_dma_cookie *cookie, -dma_addr_t iova,size_t size,struct page *freelist) +dma_addr_t iova,size_t size,struct iommu_iotlb_gather *gather) {struct iova_domain *iovad = &cookie->iovad;/* The MSI case is only ever cleaning up its most recent allocation */ if (cookie->type ==IOMMU_DMA_MSI_COOKIE ) cookie->msi_iova -= size; -else if (cookie->fq_domain)/* non-strict mode */ +else if (gather && gather->queued)queue_iova (iovad,iova_pfn (iovad, iova), size >>iova_shift (iovad), - (unsigned long )freelist); + (unsigned long )gather->freelist);else free_iova_fast (iovad,iova_pfn (iovad, iova), size >>iova_shift (iovad));
@@ -476,14 +493,14 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr, dma_addr -= iova_off; size =iova_align (iovad, size + iova_off);iommu_iotlb_gather_init (&iotlb_gather); - iotlb_gather.queued = cookie->fq_domain; + iotlb_gather.queued =READ_ONCE (cookie->fq_domain); unmapped =iommu_unmap_fast (domain, dma_addr, size, &iotlb_gather);WARN_ON (unmapped != size); -if (!cookie->fq_domain) +if (!iotlb_gather.queued)iommu_iotlb_sync (domain, &iotlb_gather); -iommu_dma_free_iova (cookie, dma_addr, size, iotlb_gather.freelist); +iommu_dma_free_iova (cookie, dma_addr, size, &iotlb_gather); } static void __iommu_dma_unmap_swiotlb(struct device *dev, dma_addr_t dma_addr,
drivers/iommu/iommu.c +13 -4
@@ -3203,6 +3203,14 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, goto out; } +/* We can bring up a flush queue without tearing down the domain */ +if (type ==IOMMU_DOMAIN_DMA_FQ && prev_dom->type ==IOMMU_DOMAIN_DMA ) { + ret =iommu_dma_init_fq (prev_dom); +if (!ret) + prev_dom->type =IOMMU_DOMAIN_DMA_FQ ; + goto out; + } +/* Sets group->default_domain to the newly allocated domain */ ret =iommu_group_alloc_default_domain (dev->bus, group, type);if (ret)
@@ -3243,9 +3251,9 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, }/* -* Changing the default domain through sysfs requires the users to ubind the -* drivers from the devices in the iommu group. Return failure if this doesn't -* meet. +* Changing the default domain through sysfs requires the users to unbind the +* drivers from the devices in the iommu group, except for a DMA -> DMA-FQ +* transition. Return failure if this isn't met. * * We need to consider the race between this and the device release path. * device_lock(dev) is used here to guarantee that the device release path
@@ -3321,7 +3329,8 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,/* Check if the device in the group still has a driver bound to it */ device_lock (dev); -if (device_is_bound (dev)) { +if (device_is_bound (dev) && !(req_type ==IOMMU_DOMAIN_DMA_FQ && + group->default_domain->type ==IOMMU_DOMAIN_DMA )) {pr_err_ratelimited ("Device is still bound to driver\n" ); ret = -EBUSY ; goto out;
drivers/iommu/iova.c +6 -5
@@ -121,8 +121,6 @@ int init_iova_flush_queue(struct iova_domain *iovad,spin_lock_init (&fq->lock); } -smp_wmb (); - iovad->fq = queue;timer_setup (&iovad->fq_timer, fq_flush_timeout,0 );
@@ -633,17 +631,20 @@ void queue_iova(struct iova_domain *iovad, unsigned long pfn, unsigned long pages, unsigned long data) { - struct iova_fq *fq = raw_cpu_ptr(iovad->fq); + struct iova_fq *fq;unsigned long flags;unsigned idx;/* * Order against the IOMMU driver's pagetable update from unmapping * @pte, to guarantee that iova_domain_flush() observes that if called -* from a different CPU before we release the lock below. +* from a different CPU before we release the lock below. Full barrier +* so it also pairs with iommu_dma_init_fq() to avoid seeing partially +* written fq state here. */ -smp_wmb (); +smp_mb (); + fq =raw_cpu_ptr (iovad->fq);spin_lock_irqsave (&fq->lock, flags);/*
include/linux/dma-iommu.h +6 -0
@@ -20,6 +20,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain);/* Setup call for arch DMA mapping code */ void iommu_setup_dma_ops (struct device *dev,u64 dma_base,u64 dma_limit); +int iommu_dma_init_fq (struct iommu_domain *domain);/* The DMA API isn't _quite_ the whole story, though... */ /*
@@ -54,6 +55,11 @@ static inline void iommu_setup_dma_ops(struct device *dev, u64 dma_base, { } +static inline int iommu_dma_init_fq (struct iommu_domain *domain) +{ +return -EINVAL ; +} +static inline int iommu_get_dma_cookie (struct iommu_domain *domain) {return -ENODEV ;
Signature · 6 lines
2.25.1 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Joerg Roedel
maintainerQuoted 17 lines · Robin Murphy
Robin Murphy (24):
iommu: Pull IOVA cookie management into the core iommu/amd: Drop IOVA cookie management iommu/arm-smmu: Drop IOVA cookie management iommu/vt-d: Drop IOVA cookie management iommu/exynos: Drop IOVA cookie management iommu/ipmmu-vmsa: Drop IOVA cookie management iommu/mtk: Drop IOVA cookie management iommu/rockchip: Drop IOVA cookie management iommu/sprd: Drop IOVA cookie management iommu/sun50i: Drop IOVA cookie management iommu/virtio: Drop IOVA cookie management iommu/dma: Unexport IOVA cookie management iommu/dma: Remove redundant "!dev" checks
iommu: Indicate queued flushes via gather data iommu/io-pgtable: Remove non-strict quirk
iommu: Introduce explicit type for non-strict DMA domains
Quoted 8 lines
iommu/amd: Prepare for multiple DMA domain types iommu/arm-smmu: Prepare for multiple DMA domain types iommu/vt-d: Prepare for multiple DMA domain types
iommu: Express DMA strictness via the domain type
iommu: Expose DMA domain strictness via sysfs
iommu: Only log strictness for DMA domains
iommu: Merge strictness and domain type configs
iommu: Allow enabling non-strict mode dynamically
Applied all except patch 12. Please re-submit patch 12 together with the APPLE DART fixups after v5.15-rc1 is out.
Thanks,
Joerg
Robin Murphy
maintainerQuoted 27 lines · Joerg Roedel
Quoted 17 lines · Robin Murphy
Robin Murphy (24):
iommu: Pull IOVA cookie management into the core iommu/amd: Drop IOVA cookie management iommu/arm-smmu: Drop IOVA cookie management iommu/vt-d: Drop IOVA cookie management iommu/exynos: Drop IOVA cookie management iommu/ipmmu-vmsa: Drop IOVA cookie management iommu/mtk: Drop IOVA cookie management iommu/rockchip: Drop IOVA cookie management iommu/sprd: Drop IOVA cookie management iommu/sun50i: Drop IOVA cookie management iommu/virtio: Drop IOVA cookie management iommu/dma: Unexport IOVA cookie management iommu/dma: Remove redundant "!dev" checks
iommu: Indicate queued flushes via gather data iommu/io-pgtable: Remove non-strict quirk
iommu: Introduce explicit type for non-strict DMA domainsQuoted 8 lines
iommu/amd: Prepare for multiple DMA domain types iommu/arm-smmu: Prepare for multiple DMA domain types iommu/vt-d: Prepare for multiple DMA domain types
iommu: Express DMA strictness via the domain type
iommu: Expose DMA domain strictness via sysfs
iommu: Only log strictness for DMA domains
iommu: Merge strictness and domain type configs
iommu: Allow enabling non-strict mode dynamically
Quoted 2 lines
Applied all except patch 12. Please re-submit patch 12 together with the APPLE DART fixups after v5.15-rc1 is out.
Brilliant, thanks for fixing that up!
Sven - I've prepared the follow-up patches already[1], so consider yourself off the hook (I see no point in trying to fix the nominal DART cookie bugs between now and then) :)
Cheers,
Robin.
[1] https://gitlab.arm.com/linux-arm/linux-rm/-/commits/iommu/fq-fixes
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Quoted 4 lines · Robin Murphy
Sven - I've prepared the follow-up patches already[1], so consider yourself off the hook (I see no point in trying to fix the nominal DART cookie bugs between now and then) :)
Great, thanks for taking care of that! :)
Just tested your branch and everything works. Feel free to add
Best,
Sven