Running `dwatch -X read` on a cubieboard (Cortex-A8) results in the following panic: Fatal kernel mode data abort: 'Translation Fault (L2)' on read trapframe: 0xd40b3948 FSR=00000007, FAR=20f49780, spsr=200000d3 r0 =20f49780, r1 =dba75010, r2 =00008000, r3 =bfc00000 r4 =d9596098, r5 =00000000, r6 =d40b3b10, r7 =00000001 r8 =d768281c, r9 =d9596098, r10=00000003, r11=d40b3a50 r12=d95e01a8, ssp=d40b39d8, slr=d95bde84, pc =d95ce09c panic: Fatal abort cpuid = 0 time = 1787862210 KDB: stack backtrace: db_trace_self() at db_trace_self pc = 0xc06df164 lr = 0xc0089bc0 (db_trace_self_wrapper+0x40) sp = 0xd40b3720 fp = 0xd40b3838 db_trace_self_wrapper() at db_trace_self_wrapper+0x40 pc = 0xc0089bc0 lr = 0xc0361940 (vpanic+0x15c) sp = 0xd40b3840 fp = 0xd40b3860 r4 = 0x00000100 r5 = 0xc07e3bb2 r6 = 0xc0c09d24 r7 = 0x00000000 vpanic() at vpanic+0x15c pc = 0xc0361940 lr = 0xc03617e4 (vpanic) sp = 0xd40b3868 fp = 0xd40b386c r4 = 0xd40b3948 r5 = 0x00000013 r6 = 0x20f49780 r7 = 0x00000007 r8 = 0x00000007 r9 = 0x00000013 r10 = 0x20f49780 vpanic() at vpanic pc = 0xc03617e4 lr = 0xc0705cb4 (abort_align) sp = 0xd40b3874 fp = 0xd40b38a0 r4 = 0x00000007 r5 = 0x00000007 r6 = 0x00000013 r7 = 0x20f49780 r8 = 0xd40b386c r9 = 0xc03617e4 r10 = 0xd40b3874 abort_align() at abort_align pc = 0xc0705cb4 lr = 0xc070592c (abort_handler+0x4d0) sp = 0xd40b38a8 fp = 0xd40b3940 r4 = 0xc4d9a400 r10 = 0x20f49780 abort_handler() at abort_handler+0x4d0 pc = 0xc070592c lr = 0xc06e1ae4 (exception_exit) sp = 0xd40b3948 fp = 0xd40b3a50 r4 = 0xd9596098 r5 = 0x00000000 r6 = 0xd40b3b10 r7 = 0x00000001 r8 = 0xd768281c r9 = 0xd9596098 r10 = 0x00000003 exception_exit() at exception_exit pc = 0xc06e1ae4 lr = 0xd95bde84 ($a+0xe98) sp = 0xd40b39d8 fp = 0xd40b3a50 r0 = 0x20f49780 r1 = 0xdba75010 r2 = 0x00008000 r3 = 0xbfc00000 r4 = 0xd9596098 r5 = 0x00000000 r6 = 0xd40b3b10 r7 = 0x00000001 r8 = 0xd768281c r9 = 0xd9596098 r10 = 0x00000003 r12 = 0xd95e01a8 dtrace_copy() at dtrace_copy+0x10 pc = 0xd95ce09c lr = 0xd95bde84 ($a+0xe98) sp = 0xd40b39d8 fp = 0xd40b3a50 $a() at $a+0xe98 pc = 0xd95bde84 lr = 0xd95b488c ($a+0xa8) sp = 0xd40b3a58 fp = 0xd40b3bc8 r4 = 0x00000011 r5 = 0xd95b39e4 r6 = 0x00000000 r7 = 0x00000001 r8 = 0x00000014 r9 = 0x00000013 r10 = 0xd40b3c90 $a() at $a+0xa8 pc = 0xd95b488c lr = 0xd95b19ec (dtrace_probe+0x8e4) sp = 0xd40b3bd0 fp = 0xd40b3d40 r4 = 0xdba75010 r5 = 0x000013fe r6 = 0xdba6c2c0 r7 = 0xdba71340 r8 = 0x00000000 r9 = 0xdba71240 r10 = 0xdba71380 dtrace_probe() at dtrace_probe+0x8e4 pc = 0xd95b19ec lr = 0xdafa0f08 ($a+0xec) sp = 0xd40b3d48 fp = 0xd40b3db8 r4 = 0x00008a47 r5 = 0x00000000 r6 = 0xd40b3d60 r7 = 0xdafa4cf0 r8 = 0x20f49780 r9 = 0x00000003 r10 = 0xc4d98000 $a() at $a+0xec pc = 0xdafa0f08 lr = 0xc07053fc (swi_handler+0x8a0) sp = 0xd40b3dc0 fp = 0xd40b3e38 r4 = 0xc4d9a400 r5 = 0x00000000 r6 = 0xc09d64ac r7 = 0x00000001 r8 = 0xc4d9a6dc r9 = 0x00000000 swi_handler() at swi_handler+0x8a0 pc = 0xc07053fc lr = 0xc06e1a78 (swi_exit) sp = 0xd40b3e40 fp = 0xbfbfea58 r4 = 0x20b05fa0 r5 = 0x00000000 r6 = 0x000001fe r7 = 0x00000003 r8 = 0x20f46000 r9 = 0x20b05fa0 r10 = 0x20f46000 swi_exit() at swi_exit pc = 0xc06e1a78 lr = 0xc06e1a78 (swi_exit) sp = 0xd40b3e40 fp = 0xbfbfea58 KDB: enter: panic [ thread pid 2638 tid 100091 ] Stopped at kdb_enter+0x54: ldrb r15, [r15, r15, ror r15]! After investigation I've found 3 issues which, once fixed, solve this problem. Firstly, reading user memory from dtrace_copy (DIR-copyinto) should be done using the unprivileged ARM instructions. Secondly, the call into the DTrace hook is passing the value of the FAR instead of the fault type identifier, preventing the hook from executing the correct code-path and to, ultimately, recover from the fault. (BTW, there is another typo which would have de-facto prevented the handling of translation faults, so this doesn't seem to be a regression from 2014 when there seems to have been some back-and-forth w.r.t. the passing or not of the fault number as direct argument to the dtrace_trap function) At last, the call into the DTrace hook happens fairly late in the flow of the abort handler. This is likely wrong because this is not how all the other architectures do, nor how the 2005 DTrace paper describes the handling of unmapped memory: DTrace is expected to simply bypass the fault handler over fault induced by DTrace and to advance the instruction pointer over to the next instruction. No mapping should be attempted. With these issues fixed, the DIR copyinto function successfully reports the invalid access instead of crashing the kernel and the dwatch read/write/rw profiles work as expected! Still, the faulting addresses are reported as NULL, but fixing this requires adding the FAR to the ARM trapframe. This seems to be quite easy and low risk to do: the tf_pad field could potentially be recycled w/o having to change the assembler entry and exit points. But I'm unsure how useful it is for DTrace to have this information. Given my understanding of AArch64 and RISC-V, both reporting the last faulting address (instead of the first, on amd64), the usefulness of having a precise address reported is likely to be pretty low. The easter-egg of this investigation is that both AArch64 and RISC-V suffer from the same pessimization in dtrace_copy: they keep faulting on the successive bytes. In my test, it was not unusual to see 32768-bytes long copies to be attempted*. I've rewritten the ARM32 dtrace_copy to detect the trap and abort the copy early. AArch64 and RISC-V could likely be de-pessimized in a similar way. Otherwise, it is just an useless and a wasteful usage of cycles. Hopefully, the previous paragraph will reinforce the interest in keeping the armv7 architecture alive. It is a low-overhead, affordable, accessible, easily understandable and hackable architecture, ideal for learning and that results in bringing improvements to the benefit of all. I'll add a link towards a review with my fixes to this PR, to tie-in the circular reference. Cheers, Benjamin *: A funny anecdote is that I mistook the successive faulting for a forever trap-loop. I pulled my hair, lost more sleep, asked existential questions before finally realizing that there were no bugs anymore to be found (or not there, at least...).
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=3e6bc5c3b5632ac9f55633b7d4e2e1a42b96a78b commit 3e6bc5c3b5632ac9f55633b7d4e2e1a42b96a78b Author: Benjamin Jacobs <freebsd@dev.thsi.be> AuthorDate: 2026-09-03 13:52:19 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-09-03 15:05:03 +0000 sys/arm: Fix DTrace trap hook Move the dtrace_trap hook at the start of the abort handler to exit early when a trap is handled by DTrace. Fix the type argument to be the actual fault type instead of the value of the FAR. The latter will need to be added to the trapframe, until then DTrace will report unmapped addresses as the null address. Correct the comment of the PUSHFRAMEINSVC assembler macro to reflect that coming from SVC32 mode is expected for DTrace traps. PR: 298064 MFC after: 1 month Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D59279 sys/arm/arm/exception.S | 6 +++--- sys/arm/arm/trap-v6.c | 15 ++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-)
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=00678f5e5c08ec7949e2f57d78faeaf266a0f17a commit 00678f5e5c08ec7949e2f57d78faeaf266a0f17a Author: Benjamin Jacobs <freebsd@dev.thsi.be> AuthorDate: 2026-09-03 13:52:24 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-09-03 15:05:03 +0000 dtrace/arm: Really trap translation faults Fix the constant case label to properly handle translation faults caused by DTrace probes. Alignment errors are not expected to be generated, so stop handling them. While at it, correct an amd64-specific comment and add a comment regarding the missing faulting address which could be addressed by a later improvement. PR: 298064 MFC after: 1 month Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D59281 sys/cddl/dev/dtrace/arm/dtrace_subr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=c874d312e78fc60e6731a043fc45b47165618370 commit c874d312e78fc60e6731a043fc45b47165618370 Author: Benjamin Jacobs <freebsd@dev.thsi.be> AuthorDate: 2026-09-03 13:52:21 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-09-03 15:05:03 +0000 dtrace/arm: Fix and de-pessimize dtrace_copy Use an unprivileged load to access user memory from dtrace_copy, which is running in SVC mode. Abort the loop if the load is trapped, as it is useless, hence wasteful, to keep faulting on successive addresses. I believe that this de-pessimization should also be done on aarch64 and riscv. PR: 298064 MFC after: 1 month Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D59280 sys/cddl/dev/dtrace/arm/dtrace_asm.S | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)