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 EC8B24A99D6; Mon, 21 Sep 2026 14:50:53 +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=1790002255; cv=none; b=WcV0LJkcGtyy1BQNqfJm51jLvDaeJCElrcUjrZ9YVZaG/KKlchxFlm/HzQ546gdBCiRGjdYZF5FO4PrMcWDKYFY+HQOOZEXs0H5+lteV/sV04jlvjd72idJ/jQ4I/JauzfIfcVNFtJgd3PqxlcPWxWPDq7JXYbSy5SEVUB48WjI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790002255; c=relaxed/simple; bh=0nxO8GAQTby2dzIN+fHvmidM+eXHnBKAqX9CYKt9hSY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p/qm9Kh+XUxVQTFCQCsgBudBabK0vaZEGJ4uU+/HNUW3cwnf6xPcB8roowsAniF72zwo7M5jnWuZVhORzP9RzbYOkJZYHkWssi6CcSpc1rmoKM/1L4quPvqkODiBaad8Gscf7Hy0iQVkIJaVA8bMedZc/lf4i3jyuuTbQsLSsf4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ck3o087i; 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="ck3o087i" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B14E11F000FF; Mon, 21 Sep 2026 14:50:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790002253; bh=8DvGDN8B0fy3MEMDtp1UmGcUak3xg58IFiLeBCZo6/s=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ck3o087iBTLP7bnheoTSKrQKTTXclUbW2E1CiIgXY+3mdFm01bdkgut73uwzE6lIL 2/XR+olitu0IQTYInC0J5i0aMJD6w4/EDRujKFVYQPApzNKARiAGFeW5mrMvVmRmb7 2PteYvQDRNHihMaerqOzcRzfADlFMW5jlIKe+5ZoTKEpBjQNdr6SPOM+9u8BtTKpv1 ka1eYnY1zSi/jv3PQugkhsJddm8+icaUWp6VGnHNLpfq6qsGSbqxp77oReEVHjdAAv Ou64udbe8N3tWZhe/8Fv/R2AnEjkcfneRo5XIFwQhu0mj1hVCHmeHn22+hNCJxuzVY h9lKR+t9FlBLw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, iommu@lists.linux.dev Cc: "Aneesh Kumar K.V (Arm)" , Andrew Morton , Catalin Marinas , christian.koenig@amd.com, Jason Gunthorpe , Joerg Roedel , Marc Zyngier , Marek Szyprowski , Robin Murphy , Steven Price , Sumit Semwal , Suzuki K Poulose , Thomas Gleixner , Will Deacon , dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, linux-media@vger.kernel.org, linux-mm@kvack.org Subject: [RFC PATCH v7 12/13] dma-buf: system_heap: Allocate shared buffers using CoCo shared memory allocator Date: Mon, 21 Sep 2026 20:18:46 +0530 Message-ID: <20260921144847.501151-13-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260921144847.501151-1-aneesh.kumar@kernel.org> References: <20260921144847.501151-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The system_cc_shared heap currently allocates its backing pages using the normal system-heap order policy and changes each resulting compound page to shared state. That is unsafe when an architecture requires state changes in units larger than PAGE_SIZE: an order-0 tail is neither sufficiently aligned nor large enough to transition independently. Use the common CoCo shared-page allocator for every backing allocation of the shared heap. Preserve the existing preferred-order search and its GFP policy: each candidate order is passed to the common allocator as a byte request, and that allocator rounds it up when the architecture shared granule is larger. Add __GFP_COMP for shared allocations because an order-0 candidate can be rounded into a high-order allocation. The system heap uses compound_order() and page_size() for accounting and release, so the returned allocation must retain compound-page semantics. Calculate a rounded internal backing length but retain the original length in dma_buf::size. The preceding scatterlist-length change ensures that the rounded tail is not included in DMA mappings or other operations. This permits a 4 KiB request on a 64 KiB shared-granule system without exposing the extra 60 KiB to an importer. Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/dma-buf/heaps/system_heap.c | 119 ++++++++++++---------------- 1 file changed, 51 insertions(+), 68 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index b5b8cdf65f23..35ac029dc41b 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -11,14 +11,13 @@ */ #include +#include #include #include #include #include #include -#include #include -#include #include #include #include @@ -65,34 +64,6 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP}; static const unsigned int orders[] = {8, 4, 0}; #define NUM_ORDERS ARRAY_SIZE(orders) -static int system_heap_set_page_decrypted(struct page *page) -{ - unsigned long addr = (unsigned long)page_address(page); - unsigned int nr_pages = 1 << compound_order(page); - int ret; - - ret = set_memory_decrypted(addr, nr_pages); - if (ret) - pr_warn_ratelimited("dma-buf system heap: failed to decrypt page at %p\n", - page_address(page)); - - return ret; -} - -static int system_heap_set_page_encrypted(struct page *page) -{ - unsigned long addr = (unsigned long)page_address(page); - unsigned int nr_pages = 1 << compound_order(page); - int ret; - - ret = set_memory_encrypted(addr, nr_pages); - if (ret) - pr_warn_ratelimited("dma-buf system heap: failed to re-encrypt page at %p, leaking memory\n", - page_address(page)); - - return ret; -} - static int dup_sg_table(struct sg_table *from, struct sg_table *to) { struct scatterlist *sg, *new_sg; @@ -337,6 +308,20 @@ static void system_heap_vunmap(struct dma_buf *dmabuf, struct iosys_map *map) iosys_map_clear(map); } +static void system_heap_free_page(struct page *page, bool cc_shared) +{ + struct cc_shared_pages mem; + + if (!cc_shared) { + __free_pages(page, compound_order(page)); + return; + } + + mem.page = page; + mem.shared_size = page_size(page); + free_cc_shared_pages(&mem); +} + static void system_heap_dma_buf_release(struct dma_buf *dmabuf) { struct system_heap_buffer *buffer = dmabuf->priv; @@ -345,19 +330,8 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf) int i; table = &buffer->sg_table; - for_each_sgtable_sg(table, sg, i) { - struct page *page = sg_page(sg); - - /* - * Intentionally leak pages that cannot be re-encrypted - * to prevent shared memory from being reused. - */ - if (cc_shared_buffer(buffer) && - system_heap_set_page_encrypted(page)) - continue; - - __free_pages(page, compound_order(page)); - } + for_each_sgtable_sg(table, sg, i) + system_heap_free_page(sg_page(sg), cc_shared_buffer(buffer)); sg_free_table(table); kfree(buffer); } @@ -375,22 +349,39 @@ static const struct dma_buf_ops system_heap_buf_ops = { .release = system_heap_dma_buf_release, }; +static struct page *system_heap_alloc_order(unsigned int order, + gfp_t flags, bool cc_shared) +{ + struct cc_shared_pages mem; + + if (!cc_shared) + return alloc_pages(flags, order); + + /* The shared granule can raise the actual allocation order. */ + flags |= __GFP_COMP; + if (alloc_cc_shared_pages(flags, PAGE_SIZE << order, &mem)) + return NULL; + + return mem.page; +} + static struct page *alloc_largest_available(unsigned long size, - unsigned int max_order) + unsigned int max_order, bool cc_shared) { struct page *page; - int i; gfp_t flags; + int i; for (i = 0; i < NUM_ORDERS; i++) { if (size < (PAGE_SIZE << orders[i])) continue; if (max_order < orders[i]) continue; + flags = order_flags[i]; if (mem_accounting) flags |= __GFP_ACCOUNT; - page = alloc_pages(flags, orders[i]); + page = system_heap_alloc_order(orders[i], flags, cc_shared); if (!page) continue; return page; @@ -405,6 +396,7 @@ static struct dma_buf *system_heap_allocate(struct dma_heap *heap, { struct system_heap_buffer *buffer; DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct cc_shared_layout layout; unsigned long size_remaining = len; unsigned long sg_remaining = len; unsigned int max_order = orders[0]; @@ -417,6 +409,14 @@ static struct dma_buf *system_heap_allocate(struct dma_heap *heap, struct page *page, *tmp_page; int i, ret = -ENOMEM; + if (cc_shared) { + ret = cc_shared_calc_layout(len, &layout); + if (ret) + return ERR_PTR(ret); + + size_remaining = layout.shared_size; + } + buffer = kzalloc_obj(*buffer); if (!buffer) return ERR_PTR(-ENOMEM); @@ -439,7 +439,8 @@ static struct dma_buf *system_heap_allocate(struct dma_heap *heap, goto free_buffer; } - page = alloc_largest_available(size_remaining, max_order); + page = alloc_largest_available(size_remaining, max_order, + cc_shared); if (!page) goto free_buffer; @@ -464,14 +465,6 @@ static struct dma_buf *system_heap_allocate(struct dma_heap *heap, list_del(&page->lru); } - if (cc_shared_buffer(buffer)) { - for_each_sgtable_sg(table, sg, i) { - ret = system_heap_set_page_decrypted(sg_page(sg)); - if (ret) - goto free_pages; - } - } - /* create the dmabuf */ exp_info.exp_name = dma_heap_get_name(heap); exp_info.ops = &system_heap_buf_ops; @@ -486,22 +479,12 @@ static struct dma_buf *system_heap_allocate(struct dma_heap *heap, return dmabuf; free_pages: - for_each_sgtable_sg(table, sg, i) { - struct page *p = sg_page(sg); - - /* - * Intentionally leak pages that cannot be re-encrypted - * to prevent shared memory from being reused. - */ - if (cc_shared_buffer(buffer) && - system_heap_set_page_encrypted(p)) - continue; - __free_pages(p, compound_order(p)); - } + for_each_sgtable_sg(table, sg, i) + system_heap_free_page(sg_page(sg), cc_shared); sg_free_table(table); free_buffer: list_for_each_entry_safe(page, tmp_page, &pages, lru) - __free_pages(page, compound_order(page)); + system_heap_free_page(page, cc_shared); kfree(buffer); return ERR_PTR(ret); -- 2.43.0