Re: [PATCH v8 19/23] dma-direct: select DMA address encoding from __DMA_ATTR_ALLOC_CC_SHARED
Mostafa Saleh <[email protected]> Tue, 28 Jul 2026 14:31:30 +0000
| Newsgroups | dev.linux.lists.iommu,dev.linux.lists.linux-coco,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-s390,org.ozlabs.lists.linuxppc-dev |
|---|---|
| Message-ID | <[email protected]> |
On Fri, Jul 17, 2026 at 11:34:37PM +0530, Aneesh Kumar K.V (Arm) wrote: > Make the dma-direct helpers derive the DMA address encoding from > __DMA_ATTR_ALLOC_CC_SHARED instead of implicitly relying on > force_dma_unencrypted() inside phys_to_dma_direct() > > Pass an explicit unencrypted/decrypted state into phys_to_dma_direct(), > make the alloc paths return DMA addresses that match the requested buffer > encryption state. Also only call dma_set_decrypted() when > __DMA_ATTR_ALLOC_CC_SHARED is actually set. > > Reviewed-by: Jason Gunthorpe <[email protected]> > Tested-by: Jiri Pirko <[email protected]> > Tested-by: Michael Kelley <[email protected]> > Tested-by: Mostafa Saleh <[email protected]> > Signed-off-by: Aneesh Kumar K.V (Arm) <[email protected]> Reviewed-by: Mostafa Saleh <[email protected]> Thanks, Mostafa > --- > kernel/dma/direct.c | 43 ++++++++++++++++++++++++++----------------- > 1 file changed, 26 insertions(+), 17 deletions(-) > > diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c > index f7f064323bd9..eb0ce0787885 100644 > --- a/kernel/dma/direct.c > +++ b/kernel/dma/direct.c > @@ -26,11 +26,11 @@ > u64 zone_dma_limit __ro_after_init = DMA_BIT_MASK(24); > > static inline dma_addr_t phys_to_dma_direct(struct device *dev, > - phys_addr_t phys) > + phys_addr_t phys, bool unencrypted) > { > - if (force_dma_unencrypted(dev)) > + if (unencrypted) > return phys_to_dma_unencrypted(dev, phys); > - return phys_to_dma(dev, phys); > + return phys_to_dma_encrypted(dev, phys); > } > > static inline struct page *dma_direct_to_page(struct device *dev, > @@ -41,8 +41,9 @@ static inline struct page *dma_direct_to_page(struct device *dev, > > u64 dma_direct_get_required_mask(struct device *dev) > { > + bool require_decrypted = force_dma_unencrypted(dev); > phys_addr_t phys = ((phys_addr_t)max_pfn << PAGE_SHIFT) - 1; > - u64 max_dma = phys_to_dma_direct(dev, phys); > + u64 max_dma = phys_to_dma_direct(dev, phys, require_decrypted); > > return (1ULL << (fls64(max_dma) - 1)) * 2 - 1; > } > @@ -71,7 +72,8 @@ static gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 *phys_limit) > > bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size) > { > - dma_addr_t dma_addr = phys_to_dma_direct(dev, phys); > + bool require_decrypted = force_dma_unencrypted(dev); > + dma_addr_t dma_addr = phys_to_dma_direct(dev, phys, require_decrypted); > > if (dma_addr == DMA_MAPPING_ERROR) > return false; > @@ -81,17 +83,18 @@ bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size) > > static int dma_set_decrypted(struct device *dev, void *vaddr, size_t size) > { > - if (!force_dma_unencrypted(dev)) > - return 0; > - return set_memory_decrypted((unsigned long)vaddr, PFN_UP(size)); > + int ret; > + > + ret = set_memory_decrypted((unsigned long)vaddr, PFN_UP(size)); > + if (ret) > + pr_warn_ratelimited("leaking DMA memory that can't be decrypted\n"); > + return ret; > } > > static int dma_set_encrypted(struct device *dev, void *vaddr, size_t size) > { > int ret; > > - if (!force_dma_unencrypted(dev)) > - return 0; > ret = set_memory_encrypted((unsigned long)vaddr, PFN_UP(size)); > if (ret) > pr_warn_ratelimited("leaking DMA memory that can't be re-encrypted\n"); > @@ -171,7 +174,8 @@ static struct page *dma_direct_alloc_from_pool(struct device *dev, size_t size, > dma_coherent_ok); > if (!page) > return NULL; > - *dma_handle = phys_to_dma_direct(dev, page_to_phys(page)); > + *dma_handle = phys_to_dma_direct(dev, page_to_phys(page), > + attrs & __DMA_ATTR_ALLOC_CC_SHARED); > return page; > } > > @@ -187,9 +191,11 @@ static void *dma_direct_alloc_no_mapping(struct device *dev, size_t size, > /* remove any dirty cache lines on the kernel alias */ > if (!PageHighMem(page)) > arch_dma_prep_coherent(page, size); > - > - /* return the page pointer as the opaque cookie */ > - *dma_handle = phys_to_dma_direct(dev, page_to_phys(page)); > + /* > + * return the page pointer as the opaque cookie. > + * Never used for unencrypted allocation > + */ > + *dma_handle = phys_to_dma_encrypted(dev, page_to_phys(page)); > return page; > } > > @@ -329,7 +335,8 @@ void *dma_direct_alloc(struct device *dev, size_t size, > ret = uncached_cpu_addr; > } > > - *dma_handle = phys_to_dma_direct(dev, page_to_phys(page)); > + *dma_handle = phys_to_dma_direct(dev, page_to_phys(page), > + attrs & __DMA_ATTR_ALLOC_CC_SHARED); > return ret; > > > @@ -450,11 +457,13 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size, > return NULL; > > ret = page_address(page); > - if (dma_set_decrypted(dev, ret, size)) > + if ((attrs & __DMA_ATTR_ALLOC_CC_SHARED) && > + dma_set_decrypted(dev, ret, size)) > goto out_leak_pages; > setup_page: > memset(ret, 0, size); > - *dma_handle = phys_to_dma_direct(dev, page_to_phys(page)); > + *dma_handle = phys_to_dma_direct(dev, page_to_phys(page), > + attrs & __DMA_ATTR_ALLOC_CC_SHARED); > return page; > out_leak_pages: > return NULL; > -- > 2.43.0 >