A restricted DMA pool is a firmware-described ownership boundary. Unlike a pool allocated by SWIOTLB itself, its base cannot be moved and its size cannot be rounded without claiming memory outside the reserved region.
Confidential-computing guests may require private/shared state changes to cover units larger than PAGE_SIZE. Passing a misaligned restricted region to set_memory_decrypted() can therefore fail.
Validate both the physical base and the complete reserved size with the common CoCo shared-range helper before allocating SWIOTLB metadata or performing a state transition. Perform the transition through cc_make_shared().
Signed-off-by: Aneesh Kumar K.V (Arm) aneesh.kumar@kernel.org --- kernel/dma/swiotlb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index 9928d75efc2d..cb67105b8812 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -2010,6 +2010,14 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem, return -EINVAL; }
+ if (cc_platform_has(CC_ATTR_MEM_ENCRYPT) && + !cc_shared_range_valid(rmem->base, rmem->size)) { + dev_err(dev, + "Restricted DMA pool must be aligned to %#zx bytes for memory encryption\n", + cc_shared_granule_size()); + return -EINVAL; + } + /* * Since multiple devices can share the same pool, the private data, * io_tlb_mem struct, will be initialized by the first device attached @@ -2043,8 +2051,7 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem, int ret;
mem->cc_shared = true; - ret = set_memory_decrypted((unsigned long)phys_to_virt(rmem->base), - rmem->size >> PAGE_SHIFT); + ret = cc_make_shared(phys_to_virt(rmem->base), rmem->size); if (ret) { dev_err(dev, "Failed to decrypt restricted DMA pool\n"); kfree(pool->areas);