From 504981db4f69bdd28054fb98c96a3a67f7248dde Mon Sep 17 00:00:00 2001 From: Donggeun Yoo Date: Sat, 5 Sep 2026 16:47:27 +0900 Subject: [PATCH 1/4] dma-coherent: report a failed reserved memory assignment rmem_dma_device_init() drops the return value of dma_assign_coherent_memory() and always reports success. That call fails with -EBUSY when the device already has a coherent pool, and the file allows only "*one* such region of memory" per device. of_reserved_mem_device_init_by_idx() reads the zero as success. It logs "assigned reserved memory node" for a region that was not assigned and records the pairing, so of_reserved_mem_device_release() later runs rmem_dma_device_release() for it. That clears dev->dma_mem without looking at which region it was called for, dropping the pool the device did get and leaving it on ordinary memory. dma_declare_coherent_memory() checks the same call and releases the memory on failure, and rmem_swiotlb_device_init() propagates its own errors. Return the error here as well, so a device tree that assigns two pools to one device fails the probe instead of half working. Fixes: 7bfa5ab6fa1b ("drivers: dma-coherent: add initialization from device tree") Signed-off-by: Donggeun Yoo Link: https://lore.kernel.org/r/20260905074727.108029-1-donggeunyoo.kernel@gmail.com Signed-off-by: Marek Szyprowski --- kernel/dma/coherent.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c index 45bbae947f4b..4d0266893bcc 100644 --- a/kernel/dma/coherent.c +++ b/kernel/dma/coherent.c @@ -352,8 +352,7 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit)) dev_warn(dev, "reserved memory is beyond device's set DMA address range\n"); - dma_assign_coherent_memory(dev, mem); - return 0; + return dma_assign_coherent_memory(dev, mem); } static void rmem_dma_device_release(struct reserved_mem *rmem, From b7d7914a9ae3097e63d113007e4fb44d33d515b1 Mon Sep 17 00:00:00 2001 From: Donggeun Yoo Date: Sat, 5 Sep 2026 17:42:10 +0900 Subject: [PATCH 2/4] swiotlb: use the adjusted address for the highmem page lookup swiotlb_bounce() reads the page frame number from the slot's recorded orig_addr, then advances orig_addr by tlb_offset to reach the address the caller asked about. The highmem branch mixes the two: the offset within the page comes from the adjusted address, the page from the value before it. Once the adjustment crosses a page boundary the pair no longer describes one location, and the whole copy lands one page below the intended one for a positive tlb_offset, one above for a negative one. DMA_FROM_DEVICE writes the device data over the wrong page and leaves the intended one stale, DMA_TO_DEVICE feeds the device from a page the mapping may not cover. Partial syncs through dma_sync_single_range_for_*() are what make tlb_offset non-zero. The branch test is picked the same way, so a slot recorded in lowmem can be adjusted into highmem and the lowmem path then hands a highmem address to phys_to_virt(). Take both from orig_addr once it is final and keep pfn in the branch that uses it. PhysHighMem() asks the question straight from the address, as dma-debug already does. Fixes: 5f89468e2f06 ("swiotlb: manipulate orig_addr when tlb_addr has offset") Cc: stable@vger.kernel.org Signed-off-by: Donggeun Yoo Reviewed-by: Michael Kelley Link: https://lore.kernel.org/r/20260905084210.148255-1-donggeunyoo.kernel@gmail.com Signed-off-by: Marek Szyprowski --- kernel/dma/swiotlb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index ded7016a46a7..aa2f1c4588b9 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -1019,7 +1019,6 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size int index = (tlb_addr - mem->start) >> IO_TLB_SHIFT; phys_addr_t orig_addr = mem->slots[index].orig_addr; size_t alloc_size = mem->slots[index].alloc_size; - unsigned long pfn = PFN_DOWN(orig_addr); unsigned char *vaddr = mem->vaddr + tlb_addr - mem->start; int tlb_offset; @@ -1052,7 +1051,8 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size size = alloc_size; } - if (PageHighMem(pfn_to_page(pfn))) { + if (PhysHighMem(orig_addr)) { + unsigned long pfn = PFN_DOWN(orig_addr); unsigned int offset = orig_addr & ~PAGE_MASK; struct page *page; unsigned int sz = 0; From 92c6a8d6470f7e7aa86c1f144818d8fa4fcbd5aa Mon Sep 17 00:00:00 2001 From: Donggeun Yoo Date: Mon, 7 Sep 2026 21:01:24 +0900 Subject: [PATCH 3/4] dma-mapping: don't trace the DMA address when the allocation fails dma_alloc_attrs() passes *dma_handle to trace_dma_alloc() without checking whether the allocation succeeded. No backend writes it on failure: dma_direct_alloc(), iommu_dma_alloc() and the dma_map_ops instances assign it only on the path that returns a buffer. Callers usually pass an uninitialized automatic variable, so a failed allocation records whatever the stack held, next to the virt_addr=(null) that marks the record as an error: dma_alloc: dmatrace dir=BIDIRECTIONAL dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000 The device coherent pool path reaches the same call: a non-zero return from dma_alloc_from_dev_coherent() means the request was handled, not that it succeeded, so cpu_addr is NULL and dma_handle is untouched once the pool runs out. For an allocation event a NULL virt_addr already means the request failed, so the address field carries nothing. Report 0 for it in the event class rather than at each call site, which covers dma_alloc_pages() and dma_alloc_sgt_err() as well. Fixes: 038eb433dc14 ("dma-mapping: add tracing for dma-mapping API calls") Fixes: 68b6dbf1f441 ("dma-mapping: trace more error paths") Suggested-by: Marek Szyprowski Signed-off-by: Donggeun Yoo Link: https://lore.kernel.org/r/20260907120124.603373-1-donggeunyoo.kernel@gmail.com Reviewed-by: Sean Anderson Signed-off-by: Marek Szyprowski --- include/trace/events/dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h index 9df02c1511de..b06d8f99922d 100644 --- a/include/trace/events/dma.h +++ b/include/trace/events/dma.h @@ -134,7 +134,7 @@ DECLARE_EVENT_CLASS(dma_alloc_class, TP_fast_assign( __assign_str(device); __entry->virt_addr = virt_addr; - __entry->dma_addr = dma_addr; + __entry->dma_addr = virt_addr ? dma_addr : 0; __entry->size = size; __entry->flags = flags; __entry->dir = dir; From 55a8e1451869233db837a97e8f3cbf9983bc8678 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V (Arm)" Date: Tue, 8 Sep 2026 17:02:32 +0530 Subject: [PATCH 4/4] x86/mm: Don't force unencrypted DMA for IOMMU-backed devices Commit 8277a12d0d60 ("dma-pool: track decrypted atomic pools and select them via attrs") exposed an issue with force_dma_unencrypted() on systems using host memory encryption. force_dma_unencrypted() checks whether the device DMA mask can address the encryption bit and, if not, requires DMA allocations to use unencrypted memory. However, this check is not applicable when the device is using the IOMMU. In that case, the device DMA mask constrains the IOVA seen by the device, not the backing physical address, so it does not need to cover the C-bit. This currently causes dma_alloc_attrs() to set __DMA_ATTR_ALLOC_CC_SHARED for such devices. iommu_dma_alloc() does not support that attribute and rejects the allocation, causing DMA allocations to fail. Do not force DMA allocations to be unencrypted when the device is using the IOMMU. This allows the IOMMU to map the encrypted physical pages as before and avoids incorrectly requesting CC_SHARED allocations. Fixes: 8277a12d0d60 ("dma-pool: track decrypted atomic pools and select them via attrs") Reported-by: Timo Witte Closes: https://lore.kernel.org/all/CANB4YXS=Nf-co3t8eMHtqrW4sn=1BDcP6o=EoTrgZm0WYMYTyw@mail.gmail.com/ Signed-off-by: Aneesh Kumar K.V (Arm) Link: https://lore.kernel.org/r/20260908113232.247457-1-aneesh.kumar@kernel.org [mszyprow: adjusted url and changed 'link' tag to the 'closes' one] Signed-off-by: Marek Szyprowski --- arch/x86/mm/mem_encrypt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 95bae74fdab2..3aefdef5bcb0 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -30,7 +31,7 @@ bool force_dma_unencrypted(struct device *dev) * device does not support DMA to addresses that include the * encryption mask. */ - if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)) { + if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT) && !use_dma_iommu(dev)) { u64 dma_enc_mask = DMA_BIT_MASK(__ffs64(sme_me_mask)); u64 dma_dev_mask = min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit);