From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 72BD6F53D9B for ; Mon, 16 Mar 2026 21:13:58 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id DC0256B0388; Mon, 16 Mar 2026 17:13:57 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id D78476B038A; Mon, 16 Mar 2026 17:13:57 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BF7736B038B; Mon, 16 Mar 2026 17:13:57 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id A91146B0388 for ; Mon, 16 Mar 2026 17:13:57 -0400 (EDT) Received: from smtpin06.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 446F3BA16F for ; Mon, 16 Mar 2026 21:13:57 +0000 (UTC) X-FDA: 84553178514.06.F5EC2D3 Received: from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31]) by imf16.hostedemail.com (Postfix) with ESMTP id 7BA23180004 for ; Mon, 16 Mar 2026 21:13:55 +0000 (UTC) Authentication-Results: imf16.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="Ak/ApMNF"; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf16.hostedemail.com: domain of ljs@kernel.org designates 172.234.252.31 as permitted sender) smtp.mailfrom=ljs@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1773695635; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=f1jdT/3tyNFNbx/OggZ/Pci1Z73lkAdgILxbIelc2c8=; b=q7N+L3Ivk3WteKxZpu4b5HYULmfRv+A8I4HxRSH30E9yogYtCyneKhmVtlCzUQn9f8WFto UHlshw72jP1YlWSZl2NMXPeuYlu0CEXGxQgoyQDtY2sQYR+UrOVrkNiSpS/AGXwAdp8Pn6 NgcTb+sdClHNF4llfv/LW5LeK+bqJEU= ARC-Authentication-Results: i=1; imf16.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="Ak/ApMNF"; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf16.hostedemail.com: domain of ljs@kernel.org designates 172.234.252.31 as permitted sender) smtp.mailfrom=ljs@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1773695635; a=rsa-sha256; cv=none; b=Jkl51RNnAmsjJloZJ8CO/f+2xXpJGHH8MTJBRB5jCn57IPOIGVNzLPj4sTTOJhZG6OC+JN SdoS+mXtHh5SXOrIt2Oq8qADoXj8dCZIe+XJ1zLSkof6JJ22huHy2g/Thq+pB5l9s4+Rn6 +vVJ/Qg8R3v0VLUMYkJ5sjiKWm6+cBc= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 96E104422B; Mon, 16 Mar 2026 21:13:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4FD2C2BCAF; Mon, 16 Mar 2026 21:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773695634; bh=Yjk3yAt9EyG5UNmB6nysV8yEolQZCSnjywjZGWL+ROA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ak/ApMNFRuacQ4MUDQZjWId235ubL+k5EmWB8Vz9+P2RTPEYiEQ4Yf1PbMBTWExIs ETdhEWZyo/ZEFVnn0eVp3TClYNiFv17tukd7JWJJyGsxX/vJxM4QJ/9wMdSffP9jok 93qZvgzdpc9SlU4aEStppXtE4LBELgf3Xj9JJGozLYVqbw51Ugaf+osWqvQCbZ3xbK F5tNhgfxzhsZcXGBZPEKNUfchdbpQ9JzUTi0V5mwzHXMirsQiNiUMWKg0UQuCBvm9h O1aqIpmTopyyl4PcMYinECiIc6spih4DWUYRgSt3exe60uol23x9vx1o80YJYDOI/I 6bx27971Va+vg== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v2 06/16] mm: add mmap_action_simple_ioremap() Date: Mon, 16 Mar 2026 21:12:02 +0000 Message-ID: <1e58aaf3cdb61cc317d890c12c9a558dfc206913.1773695307.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 7BA23180004 X-Stat-Signature: q9946jxgm5s5ohepx7hkxcpwtzbrreb5 X-Rspam-User: X-HE-Tag: 1773695635-466538 X-HE-Meta: U2FsdGVkX1+fhnNxBlCZzfioEnOsp14ZmQ5lNZiuhH4MvY6kl1w4BD1zS3nderuzZD9AQ3hPaWfyZBEMiG1ZyLIVM3XJX0WNc+aGs0jzYBorWknbCn+iC5CirWmRycF9l/ZrTxse01nwkALCe1rdYjJ21VQnB2wNLrX1eFSEvXEYSHD4da0qb2uvG6vREWAkut8zXTgi+rBtESkI2qAht+7/pjem9+nKDu4Vpk+RV8hWQtCyr/xiOX4ZdgFaVRZ1eJ+Z+i6IfKA1RX5TGkTRz4EMlmbVwpcBerOcbUD4sjnnuHtwQE+yYQZCDtZUxn2nEQywynJLynJclTfs5Ts/gcADFEtV8bnch7c+cWklGCOwGZDmVyhY7atuaCXptVz5wtOv8FW7NiM+bgnWN+SP0Qydzg0zFitaS+S+ThTNoBnWLFvaq9v8AgfN7mxcqy8X0Ht+3o8xaM94RzhTkhrEItTXNpZOzM30SbgHgpNLwmh9qbRaBH2MWVWBXwUSPcKKLIwg6EUr7DZYFvoz0U6jKLvw0VGxnF3eUnLrtKOgwmHpocYVKwkyHzyPqvm9O90vF03YIGYORmca/YdZ6kQGbo3gTxtyJkFd5hDiWLGITROJV3srr3n6lDIDP9Nd/lYonyTolUAxiKVJVpxgOT8s+PeTU2pkKor+82l3/s1r4gxYP/KVEjeUYg+pOeHBC54nEMnHpZH2Z4JmYakXTAVhrzUo3QkoJ+gyuPuUCvri/ja5Ecbw0YzEljAYaMI7NSmUpK9yzsNqwyVCVTnZg/DyWXwGMkY3nt75zHr1lOv9Q17bSblEd0/tzFgFBJs60Gk4JP/KG5KcfG4Gv7YoC8zxvO4lz4IJtSJ3P0c+9OdwLqYUlIMPsO8fggSJwNE4aII54XukNP5cf40sUHV6sZNyHcqs/Roo/VcnFMkF6+qAsqCHER4OcaETGkMBL/+ibzllldYyAwmU0mMCdAooirB l+FFL0Ri 2LUSSpGP+2srt+NK2fh5J8baTLRVAlEP5+TSUOJSZGR4oEDSFXgba1CJzL4Gz7QXJVDnc9XQ9VUWdnFvUgtsfkViPp9fiyAmSvcAya6KTzL34tY+nlF7TWqUQtG6k+4LAp/tu3Vi3PiGfKKYpPpKajKjtBOtYv6RqwepiAtSc/ZBJUXaHPd0mwtOq5DoVg7kojvW3L1VEBbh2yFeX9Ts9qlKNMpS7SXLQyM1N4qRkgeQQqcL6Wn4YuFElriEvfYZyqMFg70n0O6ZVsWHrLVOzkMaQE2va7CpkR4SOgs31lTmVTBctgANs37V/72ElDXUnEpKmyftUplkSz/Rok20BWtP9l1jsRjXDMymDKTiJaK1GqpSrtVjWnpgxUy+aWuQFCtcc Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Currently drivers use vm_iomap_memory() as a simple helper function for I/O remapping memory over a range starting at a specified physical address over a specified length. In order to utilise this from mmap_prepare, separate out the core logic into __simple_ioremap_prep(), update vm_iomap_memory() to use it, and add simple_ioremap_prepare() to do the same with a VMA descriptor object. We also add MMAP_SIMPLE_IO_REMAP and relevant fields to the struct mmap_action type to permit this operation also. We use mmap_action_ioremap() to set up the actual I/O remap operation once we have checked and figured out the parameters, which makes simple_ioremap_prepare() easy to implement. We then add mmap_action_simple_ioremap() to allow drivers to make use of this mode. We update the mmap_prepare documentation to describe this mode. Finally, we update the VMA tests to reflect this change. Signed-off-by: Lorenzo Stoakes (Oracle) --- Documentation/filesystems/mmap_prepare.rst | 3 + include/linux/mm.h | 24 +++++- include/linux/mm_types.h | 6 +- mm/internal.h | 2 + mm/memory.c | 87 +++++++++++++++------- mm/util.c | 12 +++ tools/testing/vma/include/dup.h | 6 +- 7 files changed, 112 insertions(+), 28 deletions(-) diff --git a/Documentation/filesystems/mmap_prepare.rst b/Documentation/filesystems/mmap_prepare.rst index 20db474915da..be76ae475b9c 100644 --- a/Documentation/filesystems/mmap_prepare.rst +++ b/Documentation/filesystems/mmap_prepare.rst @@ -153,5 +153,8 @@ pointer. These are: * mmap_action_ioremap_full() - Same as mmap_action_ioremap(), only remaps the entire mapping from ``start_pfn`` onward. +* mmap_action_simple_ioremap() - Sets up an I/O remap from a specified + physical address and over a specified length. + **NOTE:** The ``action`` field should never normally be manipulated directly, rather you ought to use one of these helpers. diff --git a/include/linux/mm.h b/include/linux/mm.h index ad1b8c3c0cfd..df8fa6e6402b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4337,11 +4337,33 @@ static inline void mmap_action_ioremap(struct vm_area_desc *desc, * @start_pfn: The first PFN in the range to remap. */ static inline void mmap_action_ioremap_full(struct vm_area_desc *desc, - unsigned long start_pfn) + unsigned long start_pfn) { mmap_action_ioremap(desc, desc->start, start_pfn, vma_desc_size(desc)); } +/** + * mmap_action_simple_ioremap - helper for mmap_prepare hook to specify that the + * physical range in [start_phys_addr, start_phys_addr + size) should be I/O + * remapped. + * @desc: The VMA descriptor for the VMA requiring remap. + * @start_phys_addr: Start of the physical memory to be mapped. + * @size: Size of the area to map. + * + * NOTE: Some drivers might want to tweak desc->page_prot for purposes of + * write-combine or similar. + */ +static inline void mmap_action_simple_ioremap(struct vm_area_desc *desc, + phys_addr_t start_phys_addr, + unsigned long size) +{ + struct mmap_action *action = &desc->action; + + action->simple_ioremap.start_phys_addr = start_phys_addr; + action->simple_ioremap.size = size; + action->type = MMAP_SIMPLE_IO_REMAP; +} + int mmap_action_prepare(struct vm_area_desc *desc); int mmap_action_complete(struct vm_area_struct *vma, struct mmap_action *action); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 4a229cc0a06b..50685cf29792 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -814,6 +814,7 @@ enum mmap_action_type { MMAP_NOTHING, /* Mapping is complete, no further action. */ MMAP_REMAP_PFN, /* Remap PFN range. */ MMAP_IO_REMAP_PFN, /* I/O remap PFN range. */ + MMAP_SIMPLE_IO_REMAP, /* I/O remap with guardrails. */ }; /* @@ -822,13 +823,16 @@ enum mmap_action_type { */ struct mmap_action { union { - /* Remap range. */ struct { unsigned long start; unsigned long start_pfn; unsigned long size; pgprot_t pgprot; } remap; + struct { + phys_addr_t start_phys_addr; + unsigned long size; + } simple_ioremap; }; enum mmap_action_type type; diff --git a/mm/internal.h b/mm/internal.h index f5774892071e..0eaca2f0eb6a 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1804,6 +1804,8 @@ int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm); int remap_pfn_range_prepare(struct vm_area_desc *desc); int remap_pfn_range_complete(struct vm_area_struct *vma, struct mmap_action *action); +int simple_ioremap_prepare(struct vm_area_desc *desc); +/* No simple_ioremap_complete, is ultimately handled by remap complete. */ static inline int io_remap_pfn_range_prepare(struct vm_area_desc *desc) { diff --git a/mm/memory.c b/mm/memory.c index 9dec67a18116..f3f4046aee97 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3170,6 +3170,59 @@ int remap_pfn_range_complete(struct vm_area_struct *vma, return do_remap_pfn_range(vma, start, pfn, size, prot); } +static int __simple_ioremap_prep(unsigned long vm_start, unsigned long vm_end, + pgoff_t vm_pgoff, phys_addr_t start_phys, + unsigned long size, unsigned long *pfnp) +{ + const unsigned long vm_len = vm_end - vm_start; + unsigned long pfn, pages; + + /* Check that the physical memory area passed in looks valid */ + if (start_phys + size < start_phys) + return -EINVAL; + /* + * You *really* shouldn't map things that aren't page-aligned, + * but we've historically allowed it because IO memory might + * just have smaller alignment. + */ + size += start_phys & ~PAGE_MASK; + pfn = start_phys >> PAGE_SHIFT; + pages = (size + ~PAGE_MASK) >> PAGE_SHIFT; + if (pfn + pages < pfn) + return -EINVAL; + + /* We start the mapping 'vm_pgoff' pages into the area */ + if (vm_pgoff > pages) + return -EINVAL; + pfn += vm_pgoff; + pages -= vm_pgoff; + + /* Can we fit all of the mapping? */ + if ((vm_len >> PAGE_SHIFT) > pages) + return -EINVAL; + + *pfnp = pfn; + return 0; +} + +int simple_ioremap_prepare(struct vm_area_desc *desc) +{ + struct mmap_action *action = &desc->action; + const phys_addr_t start = action->simple_ioremap.start_phys_addr; + const unsigned long size = action->simple_ioremap.size; + unsigned long pfn; + int err; + + err = __simple_ioremap_prep(desc->start, desc->end, desc->pgoff, + start, size, &pfn); + if (err) + return err; + + /* The I/O remap logic does the heavy lifting. */ + mmap_action_ioremap(desc, desc->start, pfn, vma_desc_size(desc)); + return mmap_action_prepare(desc); +} + /** * vm_iomap_memory - remap memory to userspace * @vma: user vma to map to @@ -3187,32 +3240,16 @@ int remap_pfn_range_complete(struct vm_area_struct *vma, */ int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len) { - unsigned long vm_len, pfn, pages; - - /* Check that the physical memory area passed in looks valid */ - if (start + len < start) - return -EINVAL; - /* - * You *really* shouldn't map things that aren't page-aligned, - * but we've historically allowed it because IO memory might - * just have smaller alignment. - */ - len += start & ~PAGE_MASK; - pfn = start >> PAGE_SHIFT; - pages = (len + ~PAGE_MASK) >> PAGE_SHIFT; - if (pfn + pages < pfn) - return -EINVAL; - - /* We start the mapping 'vm_pgoff' pages into the area */ - if (vma->vm_pgoff > pages) - return -EINVAL; - pfn += vma->vm_pgoff; - pages -= vma->vm_pgoff; + const unsigned long vm_start = vma->vm_start; + const unsigned long vm_end = vma->vm_end; + const unsigned long vm_len = vm_end - vm_start; + unsigned long pfn; + int err; - /* Can we fit all of the mapping? */ - vm_len = vma->vm_end - vma->vm_start; - if (vm_len >> PAGE_SHIFT > pages) - return -EINVAL; + err = __simple_ioremap_prep(vm_start, vm_end, vma->vm_pgoff, start, + len, &pfn); + if (err) + return err; /* Ok, let it rip */ return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot); diff --git a/mm/util.c b/mm/util.c index cdfba09e50d7..aa92e471afe1 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1390,6 +1390,8 @@ int mmap_action_prepare(struct vm_area_desc *desc) return remap_pfn_range_prepare(desc); case MMAP_IO_REMAP_PFN: return io_remap_pfn_range_prepare(desc); + case MMAP_SIMPLE_IO_REMAP: + return simple_ioremap_prepare(desc); } WARN_ON_ONCE(1); @@ -1421,6 +1423,14 @@ int mmap_action_complete(struct vm_area_struct *vma, case MMAP_IO_REMAP_PFN: err = io_remap_pfn_range_complete(vma, action); break; + case MMAP_SIMPLE_IO_REMAP: + /* + * The simple I/O remap should have been delegated to an I/O + * remap. + */ + WARN_ON_ONCE(1); + err = -EINVAL; + break; } return mmap_action_finish(vma, action, err); @@ -1434,6 +1444,7 @@ int mmap_action_prepare(struct vm_area_desc *desc) break; case MMAP_REMAP_PFN: case MMAP_IO_REMAP_PFN: + case MMAP_SIMPLE_IO_REMAP: WARN_ON_ONCE(1); /* nommu cannot handle these. */ break; } @@ -1452,6 +1463,7 @@ int mmap_action_complete(struct vm_area_struct *vma, break; case MMAP_REMAP_PFN: case MMAP_IO_REMAP_PFN: + case MMAP_SIMPLE_IO_REMAP: WARN_ON_ONCE(1); /* nommu cannot handle this. */ err = -EINVAL; diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h index 4570ec77f153..114daaef4f73 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -453,6 +453,7 @@ enum mmap_action_type { MMAP_NOTHING, /* Mapping is complete, no further action. */ MMAP_REMAP_PFN, /* Remap PFN range. */ MMAP_IO_REMAP_PFN, /* I/O remap PFN range. */ + MMAP_SIMPLE_IO_REMAP, /* I/O remap with guardrails. */ }; /* @@ -461,13 +462,16 @@ enum mmap_action_type { */ struct mmap_action { union { - /* Remap range. */ struct { unsigned long start; unsigned long start_pfn; unsigned long size; pgprot_t pgprot; } remap; + struct { + phys_addr_t start; + unsigned long len; + } simple_ioremap; }; enum mmap_action_type type; -- 2.53.0