From: Justinien Bouron <jbouron@amazon.com>
To: Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
David Hildenbrand <david@kernel.org>,
Ryan Roberts <ryan.roberts@arm.com>,
Andrew Morton <akpm@linux-foundation.org>,
Huang Ying <ying.huang@linux.alibaba.com>,
Quentin Perret <qperret@google.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>
Cc: Justinien Bouron <jbouron@amazon.com>,
Gunnar Kudrjavets <gunnarku@amazon.com>
Subject: [PATCH v2] arm64: Add user and kernel page-fault tracepoints
Date: Fri, 21 Aug 2026 15:28:56 -0700 [thread overview]
Message-ID: <20260821222858.12476-1-jbouron@amazon.com> (raw)
Those tracepoints were made generic in commit 06aa9378df01
("x86/tracing, x86/mm: Move page fault tracepoints to generic"), call
them from arm64's page fault handling routine.
Signed-off-by: Justinien Bouron <jbouron@amazon.com>
Reviewed-by: Gunnar Kudrjavets <gunnarku@amazon.com>
---
Link to v1: https://lore.kernel.org/lkml/20260520045524.75670-1-jbouron@amazon.com/
Diff with v1:
* Moved the tracepoint after kprobe_page_fault(), as recommended by Leo Yan.
---
Benchmarking
============
Since the added code sits in the page-fault handling hot-path, I've also ran
some benchmarks to make sure this change is not accidentally introducing a
regression. All testing below was done on a c6g.metal EC2 instance (i.e.
bare-metal) which is an ARM64 CPU with 64 cores and 128GiB of RAM.
First, a microbenchmark that maps anonymous memory and write to the first four
bytes of each page, thus running into page-fault for each one:
#include <stdio.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
int main(int argc, char **argv) {
int npages = atoi(argv[1]);
size_t size = npages * 4096;
printf("pid = %d\n", getpid());
char *p = mmap((void*)0xcafe0000,
size,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
assert(p != MAP_FAILED);
for (int i = 0; i < npages; i++)
*(uint32_t *)(p + i * 4096) = 0xdeadbeef;
munmap(p, size);
}
Compiled with: `gcc microbench.c -no-pie -o microbench` (GCC 15.2.0)
Before the change:
$ hyperfine --runs 50 './microbench 100000'
Benchmark 1: ./microbench 100000
Time (mean ± σ): 148.9 ms ± 0.9 ms [User: 6.0 ms, System: 142.9 ms]
Range (min … max): 147.5 ms … 151.5 ms 50 runs
After the change:
$ hyperfine --runs 50 './microbench 100000'
Benchmark 1: ./microbench 100000
Time (mean ± σ): 151.0 ms ± 0.6 ms [User: 5.6 ms, System: 145.4 ms]
Range (min … max): 150.0 ms … 152.4 ms 50 runs
Second benchmark, linux kernel compilation benchmark with defconfig (on commit
bd5f485f3f02):
Before the change:
$ hyperfine --runs 5 --prepare 'make clean && sync && echo 3 | sudo tee /proc/sys/vm/drop_caches' 'make -j65'
Benchmark 1: make -j65
Time (mean ± σ): 157.298 s ± 2.593 s [User: 6993.534 s, System: 1213.435 s]
Range (min … max): 155.881 s … 161.870 s 5 runs
After the change:
$ hyperfine --runs 3 --prepare 'make clean && sync && echo 3 | sudo tee /proc/sys/vm/drop_caches' 'make -j65'
Benchmark 1: make -j65
Time (mean ± σ): 156.723 s ± 0.496 s [User: 6987.524 s, System: 1236.200 s]
Range (min … max): 156.316 s … 157.275 s 3 runs
Testing
=======
Re-using the microbenchmark above, we can see the page-faults generated by
writing to each mmap'ed page (mmap'ed region starts at address 0xcafe0000):
$ sudo perf record -e exceptions:page_fault_user -- ./microbench 16
pid = 1284962
[ perf record: Woken up 2 times to write data ]
[ perf record: Captured and wrote 0.015 MB perf.data (63 samples) ]
$ sudo perf script
microbench 1284962 [020] 123047.716213: exceptions:page_fault_user: address=0xf25f095c3640 ip=0xf25f095c3640 error_code=0x82000007
microbench 1284962 [020] 123047.716221: exceptions:page_fault_user: address=0xf25f095e8066 ip=0xf25f095bf0c4 error_code=0x92000007
microbench 1284962 [020] 123047.716222: exceptions:page_fault_user: address=0xf25f095e8066 ip=0xf25f095bf0cc error_code=0x9200004f
microbench 1284962 [020] 123047.716227: exceptions:page_fault_user: address=0xf25f095e6e28 ip=0xf25f095bf0d0 error_code=0x92000007
microbench 1284962 [020] 123047.716229: exceptions:page_fault_user: address=0xf25f095e6e70 ip=0xf25f095bf19c error_code=0x9200004f
microbench 1284962 [020] 123047.716233: exceptions:page_fault_user: address=0xf25f095a7b38 ip=0xf25f095bf304 error_code=0x92000007
microbench 1284962 [020] 123047.716237: exceptions:page_fault_user: address=0xf25f095e5d28 ip=0xf25f095bf2f8 error_code=0x9200004f
microbench 1284962 [020] 123047.716241: exceptions:page_fault_user: address=0xfffff7aa5f10 ip=0xf25f095bdd64 error_code=0x92000047
microbench 1284962 [020] 123047.716256: exceptions:page_fault_user: address=0x400040 ip=0xf25f095c0160 error_code=0x92000007
microbench 1284962 [020] 123047.716258: exceptions:page_fault_user: address=0x41fdf8 ip=0xf25f095c02f0 error_code=0x92000007
microbench 1284962 [020] 123047.716260: exceptions:page_fault_user: address=0xf25f095e3020 ip=0xf25f095c0548 error_code=0x92000007
microbench 1284962 [020] 123047.716263: exceptions:page_fault_user: address=0xf25f095e4000 ip=0xf25f095c0640 error_code=0x92000007
microbench 1284962 [020] 123047.716270: exceptions:page_fault_user: address=0xf25f095dd008 ip=0xf25f095ad848 error_code=0x92000047
microbench 1284962 [020] 123047.716273: exceptions:page_fault_user: address=0x41fec0 ip=0xf25f095c0cd0 error_code=0x9200004f
microbench 1284962 [020] 123047.716293: exceptions:page_fault_user: address=0xf25f095d6000 ip=0xf25f095ba1c4 error_code=0x92000007
microbench 1284962 [020] 123047.716305: exceptions:page_fault_user: address=0xfffff7aa4e30 ip=0xf25f095addec error_code=0x92000047
microbench 1284962 [020] 123047.716335: exceptions:page_fault_user: address=0xf25f095914d8 ip=0xf25f095c5be0 error_code=0x92000047
microbench 1284962 [020] 123047.716342: exceptions:page_fault_user: address=0xf25f0958fa88 ip=0xf25f095ae4c0 error_code=0x92000007
microbench 1284962 [020] 123047.716345: exceptions:page_fault_user: address=0xf25f0958fb20 ip=0xf25f095ae534 error_code=0x9200004f
microbench 1284962 [020] 123047.716349: exceptions:page_fault_user: address=0xf25f093d02e0 ip=0xf25f095ae704 error_code=0x92000006
microbench 1284962 [020] 123047.716354: exceptions:page_fault_user: address=0xf25f09578788 ip=0xf25f095adbb0 error_code=0x92000007
microbench 1284962 [020] 123047.716357: exceptions:page_fault_user: address=0xf25f093efcef ip=0xf25f095c5358 error_code=0x92000007
microbench 1284962 [020] 123047.716361: exceptions:page_fault_user: address=0xf25f093f1650 ip=0xf25f095b927c error_code=0x92000007
microbench 1284962 [020] 123047.716366: exceptions:page_fault_user: address=0xf25f095de610 ip=0xf25f095c5c10 error_code=0x92000047
microbench 1284962 [020] 123047.716370: exceptions:page_fault_user: address=0xf25f0958d080 ip=0xf25f095b46a4 error_code=0x9200004f
microbench 1284962 [020] 123047.716375: exceptions:page_fault_user: address=0xf25f0958e000 ip=0xf25f095b46fc error_code=0x9200004f
microbench 1284962 [020] 123047.716380: exceptions:page_fault_user: address=0xf25f095902d8 ip=0xf25f095b46a4 error_code=0x9200004f
microbench 1284962 [020] 123047.716412: exceptions:page_fault_user: address=0xf25f09472180 ip=0xf25f09472180 error_code=0x82000007
microbench 1284962 [020] 123047.716431: exceptions:page_fault_user: address=0xf25f095d4000 ip=0xf25f095aaa40 error_code=0x92000047
microbench 1284962 [020] 123047.716443: exceptions:page_fault_user: address=0xf25f0951b1a0 ip=0xf25f0951b1a0 error_code=0x82000007
microbench 1284962 [020] 123047.716445: exceptions:page_fault_user: address=0xf25f0940188c ip=0xf25f0940188c error_code=0x82000007
microbench 1284962 [020] 123047.716446: exceptions:page_fault_user: address=0xf25f09597458 ip=0xf25f0951b1dc error_code=0x92000047
microbench 1284962 [020] 123047.716449: exceptions:page_fault_user: address=0xf25f0959de39 ip=0xf25f0951b1e4 error_code=0x92000047
microbench 1284962 [020] 123047.716451: exceptions:page_fault_user: address=0xf25f094bdce0 ip=0xf25f094bdce0 error_code=0x82000007
microbench 1284962 [020] 123047.716453: exceptions:page_fault_user: address=0xf25f09596518 ip=0xf25f0951b260 error_code=0x92000047
microbench 1284962 [020] 123047.716455: exceptions:page_fault_user: address=0xf25f0945ec10 ip=0xf25f0945ec10 error_code=0x82000007
microbench 1284962 [020] 123047.716457: exceptions:page_fault_user: address=0xf25f09592180 ip=0xf25f0940c918 error_code=0x92000047
microbench 1284962 [020] 123047.716459: exceptions:page_fault_user: address=0xf25f0946da88 ip=0xf25f0946da88 error_code=0x82000007
microbench 1284962 [020] 123047.716475: exceptions:page_fault_user: address=0xf25f094c66e0 ip=0xf25f094c66e0 error_code=0x82000007
microbench 1284962 [020] 123047.716478: exceptions:page_fault_user: address=0xf25f09418220 ip=0xf25f09418220 error_code=0x82000007
microbench 1284962 [020] 123047.716480: exceptions:page_fault_user: address=0xf25f095249a2 ip=0xf25f094182b8 error_code=0x92000007
microbench 1284962 [020] 123047.716482: exceptions:page_fault_user: address=0xf25f0949d180 ip=0xf25f0949d180 error_code=0x82000007
microbench 1284962 [020] 123047.716484: exceptions:page_fault_user: address=0xf25f09429e40 ip=0xf25f09429e40 error_code=0x82000007
microbench 1284962 [020] 123047.716486: exceptions:page_fault_user: address=0xf25f09535384 ip=0xf25f09427c58 error_code=0x92000007
microbench 1284962 [020] 123047.716488: exceptions:page_fault_user: address=0xf25f095433d2 ip=0xf25f0941e788 error_code=0x92000007
microbench 1284962 [020] 123047.716490: exceptions:page_fault_user: address=0xf25f09443b80 ip=0xf25f09443b80 error_code=0x82000007
microbench 1284962 [020] 123047.716497: exceptions:page_fault_user: address=0x18072008 ip=0xf25f0946bb88 error_code=0x92000046
microbench 1284962 [020] 123047.716517: exceptions:page_fault_user: address=0xcafe0000 ip=0x4008e4 error_code=0x92000045
microbench 1284962 [020] 123047.716522: exceptions:page_fault_user: address=0xcafe1000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716524: exceptions:page_fault_user: address=0xcafe2000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716530: exceptions:page_fault_user: address=0xcafe3000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716532: exceptions:page_fault_user: address=0xcafe4000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716533: exceptions:page_fault_user: address=0xcafe5000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716535: exceptions:page_fault_user: address=0xcafe6000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716537: exceptions:page_fault_user: address=0xcafe7000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716538: exceptions:page_fault_user: address=0xcafe8000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716540: exceptions:page_fault_user: address=0xcafe9000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716542: exceptions:page_fault_user: address=0xcafea000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716553: exceptions:page_fault_user: address=0xcafeb000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716555: exceptions:page_fault_user: address=0xcafec000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716557: exceptions:page_fault_user: address=0xcafed000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716559: exceptions:page_fault_user: address=0xcafee000 ip=0x4008e4 error_code=0x92000047
microbench 1284962 [020] 123047.716561: exceptions:page_fault_user: address=0xcafef000 ip=0x4008e4 error_code=0x92000047
IP 0x4008e4 corresponds to the instruction where the write to each page is
performed:
$ objdump --disassemble=main ./microbench | grep 4008e4 -C7
4008c8: b9402be0 ldr w0, [sp, #40]
4008cc: 53144c00 lsl w0, w0, #12
4008d0: 93407c00 sxtw x0, w0
4008d4: f9401fe1 ldr x1, [sp, #56]
4008d8: 8b000020 add x0, x1, x0
4008dc: 5297dde1 mov w1, #0xbeef // #48879
4008e0: 72bbd5a1 movk w1, #0xdead, lsl #16
=>4008e4: b9000001 str w1, [x0]
4008e8: b9402be0 ldr w0, [sp, #40]
4008ec: 11000400 add w0, w0, #0x1
4008f0: b9002be0 str w0, [sp, #40]
4008f4: b9402be1 ldr w1, [sp, #40]
4008f8: b9402fe0 ldr w0, [sp, #44]
4008fc: 6b00003f cmp w1, w0
400900: 54fffe4b b.lt 4008c8 <main+0x9c> // b.tstop
First error_code when writing to the mmap'ed region is 0x92000045 which, as
expected, corresponds to user-mode, write fault, at page-table level 1 (see
https://esr.arm64.dev/#0x92000045). Following faults have similar error_code but
for page-table level 3 fault (https://esr.arm64.dev/#0x92000047).
For kernel page-faults, tested using tracepoints directly:
# echo 1 > events/exceptions/page_fault_kernel/enable
# cat trace_pipe
bash-1285046 [022] ..... 123669.960098: page_fault_kernel: address=0xeb76fd8ce0f0 ip=schedule_tail error_code=0x9600004f
bash-1285046 [022] ..... 123669.960196: page_fault_kernel: address=0xeb76fd7e3088 ip=__arch_copy_from_user error_code=0x96000007
bash-1285046 [022] ..... 123669.960535: page_fault_kernel: address=0xc434acd45e08 ip=__arch_clear_user error_code=0x96000044
bash-1285046 [022] ..... 123669.960553: page_fault_kernel: address=0xe4a5638f98e4 ip=__arch_clear_user error_code=0x96000044
<...>-1285047 [056] ..... 123673.423617: page_fault_kernel: address=0xb4b46cea0010 ip=__arch_clear_user error_code=0x96000044
<...>-1285047 [056] ..... 123673.423644: page_fault_kernel: address=0xf1a30e2c28e4 ip=__arch_clear_user error_code=0x96000044
---
arch/arm64/mm/fault.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0b52557652be..2a4a3e9089ad 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -46,6 +46,9 @@
#include <asm/traps.h>
#include <asm/virt.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/exceptions.h>
+
struct fault_info {
int (*fn)(unsigned long far, unsigned long esr,
struct pt_regs *regs);
@@ -614,6 +617,11 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
if (kprobe_page_fault(regs, esr))
return 0;
+ if (user_mode(regs))
+ trace_page_fault_user(addr, regs, esr);
+ else
+ trace_page_fault_kernel(addr, regs, esr);
+
/*
* If we're in an interrupt or have no user context, we must not take
* the fault.
--
2.53.0
reply other threads:[~2026-08-21 22:29 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=20260821222858.12476-1-jbouron@amazon.com \
--to=jbouron@amazon.com \
--cc=akpm@linux-foundation.org \
--cc=catalin.marinas@arm.com \
--cc=david@kernel.org \
--cc=gunnarku@amazon.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=memxor@gmail.com \
--cc=qperret@google.com \
--cc=ryan.roberts@arm.com \
--cc=will@kernel.org \
--cc=ying.huang@linux.alibaba.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.