From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2AB94274FDF; Fri, 22 May 2026 04:32:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779424322; cv=none; b=FoPqVNsTtF+sok4ufME1+KEf9WaEbQrZFPz4DWNStQ1AwkQm4/e+c+gF3+fPSz6IN4UJLrIHuGXjQDpI7WrSaUMiIdRwyhouAtRUe0VfviVCAp/taWjN2VAHFJR8xZRhLuzFFRqEHD7HstGG0es98C8ypXAGZh+uaxEJME3O6SI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779424322; c=relaxed/simple; bh=1NMTpPgHDWWBijWAxwujrdNnKaXIGnJRKKqXSI9Y8oI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EUWdDKQ7Rg/uz7lOkgmVBBwFmuFqN+1WZEptm4+FpVO5p1NkV5wgzGOmqoX4+jBA5A0KZEVk/QbtlYQ4yuBsbBM/oVlrRCsoOR5SrNPx9mu4bN3kh62eN/dy3LvZ90pRZT5RHyAKrr+oms4qBiSntZsNpmM1FmG1JqMTNw6JidQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IyO1HZQd; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IyO1HZQd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4EED21F00A3D; Fri, 22 May 2026 04:31:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779424320; bh=84KfpthU62MYA6bQosKk2G8Mf+jCUzajJERZvfMNmbU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=IyO1HZQdLFeS3TxuBt5U0k1v/N+HbmfY/kfiq8WqwRYFm70y9e7LyGeFJLx162/WC fYd6tjrh8yVM4DkYYoGefgymRiqQOS69uHjcJ6qO5Xe/Z80YMT0hUwwR6kB+1A0uaS c1+TRu8jmbrHLtMtOpJ6sqFWJclIHPd3N2wNpzHBbxGl8S1ohhBLsoLGcr5bwq3HhQ S8Gnx9d+083850dr8RRDCrrAXKuJDvQ5SJwTBLcyjYcoz8UxBvIn0gnaSpOgqmIywt HRUsRglJGSPxS1ReHOeTl6Zdwgqz4roG8/9myNGeynPs7DHi6gXntfKjqWemJrYQti Py20w+Z3IuQhQ== From: "Aneesh Kumar K.V (Arm)" To: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev Cc: "Aneesh Kumar K.V (Arm)" , Robin Murphy , Marek Szyprowski , Will Deacon , Marc Zyngier , Steven Price , Suzuki K Poulose , Catalin Marinas , Jiri Pirko , Jason Gunthorpe , Mostafa Saleh , Petr Tesarik , Alexey Kardashevskiy , Dan Williams , Xu Yilun , linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Alexander Gordeev , Gerald Schaefer , Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Sven Schnelle , x86@kernel.org Subject: [PATCH v5 18/20] dma: swiotlb: handle set_memory_decrypted() failures Date: Fri, 22 May 2026 09:58:13 +0530 Message-ID: <20260522042815.370873-19-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260522042815.370873-1-aneesh.kumar@kernel.org> References: <20260522042815.370873-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-coco@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Check the return value when converting swiotlb pools between encrypted and decrypted mappings. If the default pool cannot be decrypted after early initialization, mark the pool fully used so it cannot satisfy future bounce allocations. For late initialization, return the `set_memory_decrypted()` failure. For restricted DMA pools, fail device initialization if the reserved pool cannot be decrypted. This prevents swiotlb from using pools whose encryption attributes do not match their metadata, and avoids returning pages with uncertain encryption state back to the allocator. Signed-off-by: Aneesh Kumar K.V (Arm) --- kernel/dma/swiotlb.c | 80 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index 4c56f64602ea..14d834ca298b 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -248,6 +248,23 @@ static inline unsigned long nr_slots(u64 val) return DIV_ROUND_UP(val, IO_TLB_SIZE); } +static void swiotlb_mark_pool_used(struct io_tlb_pool *pool) +{ + unsigned long i; + + for (i = 0; i < pool->nareas; i++) { + pool->areas[i].index = 0; + pool->areas[i].used = pool->area_nslabs; + } + + for (i = 0; i < pool->nslabs; i++) { + pool->slots[i].list = 0; + pool->slots[i].orig_addr = INVALID_PHYS_ADDR; + pool->slots[i].alloc_size = 0; + pool->slots[i].pad_slots = 0; + } +} + /* * Early SWIOTLB allocation may be too early to allow an architecture to * perform the desired operations. This function allows the architecture to @@ -272,8 +289,16 @@ void __init swiotlb_update_mem_attributes(void) return; bytes = PAGE_ALIGN(mem->nslabs << IO_TLB_SHIFT); - if (io_tlb_default_mem.unencrypted) - set_memory_decrypted((unsigned long)mem->vaddr, bytes >> PAGE_SHIFT); + if (io_tlb_default_mem.unencrypted) { + int ret; + + ret = set_memory_decrypted((unsigned long)mem->vaddr, + bytes >> PAGE_SHIFT); + if (ret) { + pr_warn("Failed to decrypt default memory pool, disabling it\n"); + swiotlb_mark_pool_used(mem); + } + } } static void swiotlb_init_io_tlb_pool(struct io_tlb_pool *mem, phys_addr_t start, @@ -442,9 +467,10 @@ int swiotlb_init_late(size_t size, gfp_t gfp_mask, { struct io_tlb_pool *mem = &io_tlb_default_mem.defpool; unsigned long nslabs = ALIGN(size >> IO_TLB_SHIFT, IO_TLB_SEGSIZE); + unsigned int order, area_order, slot_order; + bool leak_pages = false; unsigned int nareas; unsigned char *vstart = NULL; - unsigned int order, area_order; bool retried = false; int rc = 0; @@ -504,6 +530,7 @@ int swiotlb_init_late(size_t size, gfp_t gfp_mask, (PAGE_SIZE << order) >> 20); } + rc = -ENOMEM; nareas = limit_nareas(default_nareas, nslabs); area_order = get_order(array_size(sizeof(*mem->areas), nareas)); mem->areas = (struct io_tlb_area *) @@ -511,14 +538,20 @@ int swiotlb_init_late(size_t size, gfp_t gfp_mask, if (!mem->areas) goto error_area; + slot_order = get_order(array_size(sizeof(*mem->slots), nslabs)); mem->slots = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - get_order(array_size(sizeof(*mem->slots), nslabs))); + slot_order); if (!mem->slots) goto error_slots; - if (io_tlb_default_mem.unencrypted) - set_memory_decrypted((unsigned long)vstart, - (nslabs << IO_TLB_SHIFT) >> PAGE_SHIFT); + if (io_tlb_default_mem.unencrypted) { + rc = set_memory_decrypted((unsigned long)vstart, + (nslabs << IO_TLB_SHIFT) >> PAGE_SHIFT); + if (rc) { + leak_pages = true; + goto error_decrypt; + } + } swiotlb_init_io_tlb_pool(mem, virt_to_phys(vstart), nslabs, true, nareas); @@ -527,16 +560,20 @@ int swiotlb_init_late(size_t size, gfp_t gfp_mask, swiotlb_print_info(); return 0; +error_decrypt: + free_pages((unsigned long)mem->slots, slot_order); error_slots: free_pages((unsigned long)mem->areas, area_order); error_area: - free_pages((unsigned long)vstart, order); - return -ENOMEM; + if (!leak_pages) + free_pages((unsigned long)vstart, order); + return rc; } void __init swiotlb_exit(void) { struct io_tlb_pool *mem = &io_tlb_default_mem.defpool; + bool leak_pages = false; unsigned long tbl_vaddr; size_t tbl_size, slots_size; unsigned int area_order; @@ -552,19 +589,23 @@ void __init swiotlb_exit(void) tbl_size = PAGE_ALIGN(mem->end - mem->start); slots_size = PAGE_ALIGN(array_size(sizeof(*mem->slots), mem->nslabs)); - if (io_tlb_default_mem.unencrypted) - set_memory_encrypted(tbl_vaddr, tbl_size >> PAGE_SHIFT); + if (io_tlb_default_mem.unencrypted) { + if (set_memory_encrypted(tbl_vaddr, tbl_size >> PAGE_SHIFT)) + leak_pages = true; + } if (mem->late_alloc) { area_order = get_order(array_size(sizeof(*mem->areas), mem->nareas)); free_pages((unsigned long)mem->areas, area_order); - free_pages(tbl_vaddr, get_order(tbl_size)); + if (!leak_pages) + free_pages(tbl_vaddr, get_order(tbl_size)); free_pages((unsigned long)mem->slots, get_order(slots_size)); } else { memblock_free(mem->areas, array_size(sizeof(*mem->areas), mem->nareas)); - memblock_phys_free(mem->start, tbl_size); + if (!leak_pages) + memblock_phys_free(mem->start, tbl_size); memblock_free(mem->slots, slots_size); } @@ -1938,9 +1979,18 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem, * restricted mem pool is decrypted by default */ if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { + int ret; + mem->unencrypted = true; - set_memory_decrypted((unsigned long)phys_to_virt(rmem->base), - rmem->size >> PAGE_SHIFT); + ret = set_memory_decrypted((unsigned long)phys_to_virt(rmem->base), + rmem->size >> PAGE_SHIFT); + if (ret) { + dev_err(dev, "Failed to decrypt restricted DMA pool\n"); + kfree(pool->areas); + kfree(pool->slots); + kfree(mem); + return ret; + } } else { mem->unencrypted = false; } -- 2.43.0