From: Danish Khateeb <danishkhateeb03@gmail.com>
To: Russell King <linux@armlinux.org.uk>
Cc: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org,
Danish Khateeb <danishkhateeb03@gmail.com>
Subject: [PATCH] ARM: mm: use kmap_local_page() in copypage-v6
Date: Tue, 22 Sep 2026 13:30:54 -0500 [thread overview]
Message-ID: <20260922183054.254875-1-danishkhateeb03@gmail.com> (raw)
kmap_atomic() is deprecated in favour of kmap_local_page(), as described
in Documentation/mm/highmem.rst.
ARMv6 and ARMv7 CPUs whose data cache does not alias use
v6_copy_user_highpage_nonaliasing() and
v6_clear_user_highpage_nonaliasing() as copy_user_highpage() and
clear_user_highpage(), to copy a page on a copy-on-write fault and to
zero new anonymous pages. Both map the pages, call copy_page() or
clear_page() and unmap them again, just like the generic copy_highpage()
and clear_highpage(), which use kmap_local_page() since commit
d2c20e51e396 ("mm/highmem: remove deprecated kmap_atomic").
Neither function needs preemption or page faults disabled: they only
access the kernel mappings of the pages, and do no cache maintenance.
kmap_atomic() is __kmap_local_page_prot() with page faults and
preemption (migration on PREEMPT_RT) disabled around it, so the mappings
are made and removed as before, and a highmem page is still mapped with
migration disabled.
Convert both functions to kmap_local_page() and kunmap_local(). Apart
from dropping the deprecated calls, this lets a preemptible kernel
preempt the copy or clear of a page, as it can in the generic helpers.
The aliasing variants use their own fixed mappings and are unchanged.
Assisted-by: LLM sparse
Signed-off-by: Danish Khateeb <danishkhateeb03@gmail.com>
---
Notes:
Tested on QEMU virt (cortex-a15, 2 CPUs, 2 GB, of which 1.25 GB is
HighMem) with multi_v7_defconfig, which has HIGHMEM=y, plus PREEMPT,
DEBUG_PREEMPT, PROVE_LOCKING, DEBUG_ATOMIC_SLEEP and DEBUG_HIGHMEM, on
v7.3-rc4 with and without this patch. A test init checked every word of
every page after:
- copy-on-write of 8192 anonymous pages after fork(), written by the
child and then by the parent, and first writes to 2048 pages of a
MAP_PRIVATE file mapping (copy_user_highpage());
- write faults, and read-then-write faults, on 16384 new anonymous
pages each, right after 16384 pages were filled with a pattern and
freed; 89-98% of the new pages reused one of those frames
(clear_user_highpage()).
pagemap showed all the source pages, copies and new pages in HighMem,
and kprobes counted at least one call per page into each function.
Both kernels passed with no splats. With CPU-bound tasks on both CPUs,
a stack-trace histogram on preempt_schedule_irq() counted no
preemptions inside copy_page() or inside memset() under
v6_clear_user_highpage_nonaliasing() without the patch, and 9-54 and
40-95 with it (two runs). A control that flips a byte of each test page
in both functions made all five checks fail.
Also built with W=1 for imx_v6_v7_defconfig, which builds the aliasing
variants too.
The ARMv4/v5 copypage-*.c files also use kmap_atomic(). I've left them
alone: they do cache maintenance on VIVT caches while the pages are
mapped, and QEMU doesn't model caches, so I can't test them.
arch/arm/mm/copypage-v6.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 0710dba5c0bf..81d8471dbf00 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -32,11 +32,11 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
{
void *kto, *kfrom;
- kfrom = kmap_atomic(from);
- kto = kmap_atomic(to);
+ kfrom = kmap_local_page(from);
+ kto = kmap_local_page(to);
copy_page(kto, kfrom);
- kunmap_atomic(kto);
- kunmap_atomic(kfrom);
+ kunmap_local(kto);
+ kunmap_local(kfrom);
}
/*
@@ -45,9 +45,9 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
*/
static void v6_clear_user_highpage_nonaliasing(struct page *page, unsigned long vaddr)
{
- void *kaddr = kmap_atomic(page);
+ void *kaddr = kmap_local_page(page);
clear_page(kaddr);
- kunmap_atomic(kaddr);
+ kunmap_local(kaddr);
}
/*
base-commit: 93f51579e7df248780214094418f205253383cc5
--
2.55.0
reply other threads:[~2026-09-22 18:30 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260922183054.254875-1-danishkhateeb03@gmail.com \
--to=danishkhateeb03@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®