From: Leon Romanovsky Date: Mon, 16 Mar 2026 19:06:52 +0000 (+0200) Subject: mm/hmm: Indicate that HMM requires DMA coherency X-Git-Tag: v7.0-rc6~42^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5ebf241c407dbf629fcf515015e139fcea2c2f0;p=thirdparty%2Flinux.git mm/hmm: Indicate that HMM requires DMA coherency HMM is fundamentally about allowing a sophisticated device to perform DMA directly to a process’s memory while the CPU accesses that same memory at the same time. It is similar to SVA but does not rely on IOMMU support. Because the entire model depends on concurrent access to shared memory, it fails as a uAPI if SWIOTLB substitutes the memory or if the CPU caches are not coherent with DMA. Until now, there has been no reliable way to report this, and various approximations have been used: int hmm_dma_map_alloc(struct device *dev, struct hmm_dma_map *map, size_t nr_entries, size_t dma_entry_size) { <...> /* * The HMM API violates our normal DMA buffer ownership rules and can't * transfer buffer ownership. The dma_addressing_limited() check is a * best approximation to ensure no swiotlb buffering happens. */ dma_need_sync = !dev->dma_skip_sync; if (dma_need_sync || dma_addressing_limited(dev)) return -EOPNOTSUPP; So let's mark mapped buffers with DMA_ATTR_REQUIRE_COHERENT attribute to prevent silent data corruption if someone tries to use hmm in a system with swiotlb or incoherent DMA Reviewed-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20260316-dma-debug-overlap-v3-8-1dde90a7f08b@nvidia.com --- diff --git a/mm/hmm.c b/mm/hmm.c index f6c4ddff4bd6..5955f2f0c83d 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -778,7 +778,7 @@ dma_addr_t hmm_dma_map_pfn(struct device *dev, struct hmm_dma_map *map, struct page *page = hmm_pfn_to_page(pfns[idx]); phys_addr_t paddr = hmm_pfn_to_phys(pfns[idx]); size_t offset = idx * map->dma_entry_size; - unsigned long attrs = 0; + unsigned long attrs = DMA_ATTR_REQUIRE_COHERENT; dma_addr_t dma_addr; int ret; @@ -871,7 +871,7 @@ bool hmm_dma_unmap_pfn(struct device *dev, struct hmm_dma_map *map, size_t idx) struct dma_iova_state *state = &map->state; dma_addr_t *dma_addrs = map->dma_list; unsigned long *pfns = map->pfn_list; - unsigned long attrs = 0; + unsigned long attrs = DMA_ATTR_REQUIRE_COHERENT; if ((pfns[idx] & valid_dma) != valid_dma) return false;