perf_arch_fetch_caller_regs() sets regs->pc to the return address of the function it is used in (CALLER_ADDR0), but points regs->regs[29] at that function's own frame record, whose saved LR is that same return address. perf_callchain_kernel() reports regs->pc and then unwinds from the frame record at x29, so the caller shows up twice at the top of every kernel callchain built from perf_fetch_caller_regs(): tracepoint events, software events emitted by __perf_sw_event_sched() (context-switches, cgroup-switches, cpu-migrations), and bpf_get_stack() and bpf_get_stackid() in tracepoint, raw tracepoint, tp_btf and fentry/fexit programs. E.g., for a tracepoint program attached to sched_process_fork: __traceiter_sched_process_fork+0x44 __traceiter_sched_process_fork+0x44 kernel_clone+0x250 ... Use __builtin_frame_address(1), the caller's frame record, the same way kunwind_init_from_caller() does, so that pc and x29 describe the same frame. x86 had the same duplicate entry, fixed by commit 6d08340d1e35 ("Revert "perf/x86: Always store regs->ip in perf_callchain_kernel()""). Fixes: 5b09a094f2fb ("arm64: perf: Fix callchain parse error with kernel tracepoint events") Signed-off-by: Andrii Nakryiko --- arch/arm64/include/asm/perf_event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h index ee45b4e77347..13efb46f0fe8 100644 --- a/arch/arm64/include/asm/perf_event.h +++ b/arch/arm64/include/asm/perf_event.h @@ -15,7 +15,7 @@ #define perf_arch_fetch_caller_regs(regs, __ip) { \ (regs)->pc = (__ip); \ - (regs)->regs[29] = (unsigned long) __builtin_frame_address(0); \ + (regs)->regs[29] = (unsigned long) __builtin_frame_address(1); \ (regs)->sp = current_stack_pointer; \ (regs)->pstate = PSR_MODE_EL1h; \ } -- 2.53.1-Meta