Certain peripherals may be bestowed with knowledge of the physical memory map of the system in which they live, and refuse to handle addresses that they do not think are memory, which causes issues when remapping to arbitrary IOVAs. Sidestep the issue by restricting IOVA domains to only allocate addresses within ranges which match the physical memory layout.
Signed-off-by: Robin Murphy <[email protected]> --- Posting this as an RFC because it's something I've been having to use on Juno for all the PCI IOMMU development - it's pretty horrible, but I can't easily think of a nicer solution... drivers/iommu/dma-iommu.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index ea5a9ebf0f78..2385fab382d8 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -25,6 +25,7 @@ #include <linux/huge_mm.h> #include <linux/iommu.h> #include <linux/iova.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/scatterlist.h> #include <linux/vmalloc.h> @@ -74,6 +75,23 @@ void iommu_put_dma_cookie(struct iommu_domain *domain) } EXPORT_SYMBOL(iommu_put_dma_cookie); +static void iova_match_mem(struct iova_domain *iovad) +{ + struct memblock_region *reg; + unsigned long blk, base = iovad->start_pfn; + unsigned long shift = iova_shift(iovad); + + for_each_memblock(memory, reg) { + blk = (reg->base + iova_mask(iovad)) >> shift; + if (blk > base) + reserve_iova(iovad, base, blk - 1); + base = (reg->base + reg->size) >> shift; + } + blk = -1UL >> shift; + if (blk > base) + reserve_iova(iovad, base, blk); +} + /** * iommu_dma_init_domain - Initialise a DMA mapping domain * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie() @@ -123,6 +141,7 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, u64 size iovad->dma_32bit_pfn = end_pfn; } else { init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn); + iova_match_mem(iovad); } return 0; } -- 2.8.1.dirty _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
