Re: [PATCH v2 1/2] dma-direct: check for overflows on 32 bit DMA addresses
On Wed, 2019-10-30 at 14:41 -0700, Christoph Hellwig wrote: > On Fri, Oct 18, 2019 at 01:00:43PM +0200, Nicolas Saenz Julienne wrote: > > +#ifndef CONFIG_ARCH_DMA_ADDR_T_64BIT > > + /* Check if DMA address overflowed */ > > + if (min(addr, addr + size - 1) < > > + __phys_to_dma(dev, (phys_addr_t)(min_low_pfn << PAGE_SHIFT))) > > + return false; > > +#endif > > Would be nice to use IS_ENABLED and PFN_PHYS here, and I also think we > need to use phys_to_dma to take care of the encryption bit. If you then > also introduce an end variable we can make the whole thing actually look > nice: > > static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t > size) > { > dma_addr_t end = addr + size - 1; > > if (!dev->dma_mask) > return false; > > if (!IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && > min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn))) > return false; > > return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask); > } > > Otherwise this looks sensible to me. Thanks, noted. signature.asc Description: This is a digitally signed message part ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 1/2] dma-direct: check for overflows on 32 bit DMA addresses
On Fri, Oct 18, 2019 at 01:00:43PM +0200, Nicolas Saenz Julienne wrote: > +#ifndef CONFIG_ARCH_DMA_ADDR_T_64BIT > + /* Check if DMA address overflowed */ > + if (min(addr, addr + size - 1) < > + __phys_to_dma(dev, (phys_addr_t)(min_low_pfn << PAGE_SHIFT))) > + return false; > +#endif Would be nice to use IS_ENABLED and PFN_PHYS here, and I also think we need to use phys_to_dma to take care of the encryption bit. If you then also introduce an end variable we can make the whole thing actually look nice: static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) { dma_addr_t end = addr + size - 1; if (!dev->dma_mask) return false; if (!IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn))) return false; return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask); } Otherwise this looks sensible to me. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 1/2] dma-direct: check for overflows on 32 bit DMA addresses
As seen on the new Raspberry Pi 4 and sta2x11's DMA implementation it is possible for a device configured with 32 bit DMA addresses and a partial DMA mapping located at the end of the address space to overflow. It happens when a higher physical address, not DMAable, is translated to it's DMA counterpart. For example the Raspberry Pi 4, configurable up to 4 GB of memory, has an interconnect capable of addressing the lower 1 GB of physical memory with a DMA offset of 0xc000. It transpires that, any attempt to translate physical addresses higher than the first GB will result in an overflow which dma_capable() can't detect as it only checks for addresses bigger then the maximum allowed DMA address. Fix this by verifying in dma_capable() if the DMA address range provided is at any point lower than the minimum possible DMA address on the bus. Signed-off-by: Nicolas Saenz Julienne --- include/linux/dma-direct.h | 8 1 file changed, 8 insertions(+) diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h index adf993a3bd58..af4bb9c81ccc 100644 --- a/include/linux/dma-direct.h +++ b/include/linux/dma-direct.h @@ -3,6 +3,7 @@ #define _LINUX_DMA_DIRECT_H 1 #include +#include /* for min_low_pfn */ #include #ifdef CONFIG_ARCH_HAS_PHYS_TO_DMA @@ -27,6 +28,13 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) if (!dev->dma_mask) return false; +#ifndef CONFIG_ARCH_DMA_ADDR_T_64BIT + /* Check if DMA address overflowed */ + if (min(addr, addr + size - 1) < + __phys_to_dma(dev, (phys_addr_t)(min_low_pfn << PAGE_SHIFT))) + return false; +#endif + return addr + size - 1 <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask); } -- 2.23.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu