Re: [PATCH v7 11/22] dma-pool: track decrypted atomic pools and select them via attrs
Aneesh Kumar K.V <[email protected]>
| Newsgroups | dev.linux.lists.linux-coco,dev.linux.lists.iommu,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]> |
Jason Gunthorpe <[email protected]> writes: > On Wed, Jul 01, 2026 at 11:19:15AM +0530, Aneesh Kumar K.V (Arm) wrote: >> @@ -114,14 +120,17 @@ static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size, >> * Memory in the atomic DMA pools must be unencrypted, the pools do not >> * shrink so no re-encryption occurs in dma_direct_free(). >> */ >> - ret = set_memory_decrypted((unsigned long)page_to_virt(page), >> - 1 << order); >> - if (ret) { >> - leak_pages = true; >> - goto remove_mapping; >> + if (dma_pool->cc_shared) { >> + ret = set_memory_decrypted((unsigned long)page_to_virt(page), >> + 1 << order); >> + if (ret) { >> + leak_pages = true; >> + goto remove_mapping; >> + } >> } > > This makes the memory_decrypted conditional, but it doesn't change > the lines a few above: > > addr = dma_common_contiguous_remap(page, pool_size, > pgprot_decrypted(pgprot_dmacoherent(PAGE_KERNEL)), > ^^^^^^^^^^^^ > __builtin_return_address(0)); > if (!addr) > goto free_page; > > It is wrong to pass pgprot_decrypted() to the arch code if > set_memory_decrypted() was not called. > > Also it looks at some point the nature of the atomic pool has become > confused. Originally it was just to allocate atomic memory that had > been vmap'd outside the atomic context (to set the non-coherent > pgprot), so every caller was expecting non-cached memory. > > Then it was reused to also allocate CC shared memory outside the > atomic context. That was fine for x86 that doesn't use DMA_REMAP but > on ARM64 it now means all atomic pool CC memory is uncached? That > doesn't seem to make any sense... > > I suppose along the lines of this patch the solution is to add a > noncoherent property to the pool so we can select the correct > combination: > > noncoherent !SHARED = vmap pgprot_noncached > !noncoherent SHARED= vmap pgprot_decrypted + set_memory_decrypted > noncoherent SHARED = (probably unrealistic in real systems) > !noncoherent !SHARED = normal __dma_direct_alloc_pages() > > But I don't view this as that important, the CC hypervisor is probably > going to use the S2 page table to force cachable on all system memory > so the non-cached pgprot is a NOP, but the extra vmap is wasteful and > it is confusing.. So maybe a little fixme is all that is needed here. > Something like? modified kernel/dma/direct.c @@ -260,6 +260,9 @@ void *dma_direct_alloc(struct device *dev, size_t size, /* * Remapping or decrypting memory may block, allocate the memory from * the atomic pools instead if we aren't allowed block. + * FIXME!! With CONFIG_DMA_DIRECT_REMAP, the pool is also mapped as + * DMA-coherent (non-cacheable). We may want to create a separate pool + * dedicated to CC_SHARED atomic allocations. */ if ((remap || (attrs & __DMA_ATTR_ALLOC_CC_SHARED)) && dma_direct_use_pool(dev, gfp)) { modified kernel/dma/pool.c @@ -88,6 +88,7 @@ static int atomic_pool_expand(struct dma_gen_pool *dma_pool, size_t pool_size, unsigned int order; struct page *page = NULL; bool leak_pages = false; + pgprot_t prot; void *addr; int ret = -ENOMEM; unsigned int min_encrypt_order = get_order(mem_cc_shared_granule_size()); @@ -110,8 +111,12 @@ static int atomic_pool_expand(struct dma_gen_pool *dma_pool, size_t pool_size, arch_dma_prep_coherent(page, pool_size); #ifdef CONFIG_DMA_DIRECT_REMAP - addr = dma_common_contiguous_remap(page, pool_size, - pgprot_decrypted(pgprot_dmacoherent(PAGE_KERNEL)), + if (dma_pool->cc_shared) + prot = pgprot_decrypted(pgprot_dmacoherent(PAGE_KERNEL)); + else + prot = pgprot_dmacoherent(PAGE_KERNEL); + + addr = dma_common_contiguous_remap(page, pool_size, prot, __builtin_return_address(0)); if (!addr) goto free_page;