[PATCH] dma-buf: try to catch swiotlb bounce buffers

Daniel Vetter daniel.vetter at ffwll.ch
Wed Feb 7 18:02:01 UTC 2024


They rather fundamentally break the entire concept of zero copy, so if
an exporter manages to hand these out things will break all over.

Luckily there's not too many case that use
swiotlb_sync_single_for_device/cpu():

- The generic iommu dma-api code in drivers/iommu/dma-iommu.c. We can
  catch that with sg_dma_is_swiotlb() reliably.

- The generic direct dma code in kernel/dma/direct.c. We can mostly
  catch that with looking for a NULL dma_ops, except for some powerpc
  special cases.

- Xen, which I don't bother to catch here.

Implement these checks in dma_buf_map_attachment when
CONFIG_DMA_API_DEBUG is enabled.

Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
Cc: Sumit Semwal <sumit.semwal at linaro.org>
Cc: "Christian König" <christian.koenig at amd.com>
Cc: linux-media at vger.kernel.org
Cc: linaro-mm-sig at lists.linaro.org
Cc: Paul Cercueil <paul at crapouillou.net>
---
Entirely untested, but since I sent the mail with the idea I figured I
might as well type it up after I realized there's a lot fewer cases to
check. That is, if I haven't completely misread the dma-api and swiotlb
code.
-Sima
---
 drivers/dma-buf/dma-buf.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d1e7f823fbdb..d6f95523f995 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -28,6 +28,12 @@
 #include <linux/mount.h>
 #include <linux/pseudo_fs.h>
 
+#ifdef CONFIG_DMA_API_DEBUG
+#include <linux/dma-direct.h>
+#include <linux/dma-map-ops.h>
+#include <linux/swiotlb.h>
+#endif
+
 #include <uapi/linux/dma-buf.h>
 #include <uapi/linux/magic.h>
 
@@ -1149,10 +1155,13 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 #ifdef CONFIG_DMA_API_DEBUG
 	if (!IS_ERR(sg_table)) {
 		struct scatterlist *sg;
+		struct device *dev = attach->dev;
 		u64 addr;
 		int len;
 		int i;
 
+		bool is_direct_dma = !get_dma_ops(dev);
+
 		for_each_sgtable_dma_sg(sg_table, sg, i) {
 			addr = sg_dma_address(sg);
 			len = sg_dma_len(sg);
@@ -1160,7 +1169,15 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 				pr_debug("%s: addr %llx or len %x is not page aligned!\n",
 					 __func__, addr, len);
 			}
+
+			if (is_direct_dma) {
+				phys_addr_t paddr = dma_to_phys(dev, addr);
+
+				WARN_ON_ONCE(is_swiotlb_buffer(dev, paddr));
+			}
 		}
+
+		WARN_ON_ONCE(sg_dma_is_swiotlb(sg));
 	}
 #endif /* CONFIG_DMA_API_DEBUG */
 	return sg_table;
-- 
2.43.0



More information about the dri-devel mailing list