Re: [PATCH v8 19/23] dma-direct: select DMA address encoding from __DMA_ATTR_ALLOC_CC_SHARED
From: Mostafa Saleh
Date: Tue Jul 28 2026 - 10:51:51 EST
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 <jgg@xxxxxxxxxx>
> Tested-by: Jiri Pirko <jiri@xxxxxxxxxx>
> Tested-by: Michael Kelley <mhklinux@xxxxxxxxxxx>
> Tested-by: Mostafa Saleh <smostafa@xxxxxxxxxx>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@xxxxxxxxxx>
Reviewed-by: Mostafa Saleh <smostafa@xxxxxxxxxx>
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
>