Re: [PATCH] riscv: ftrace: Fix ftrace_modify_call failure on kprobed functions
Pu Lehui <[email protected]>
| Newsgroups | org.infradead.lists.linux-riscv,org.kernel.vger.bpf,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Gentle ping~ Hi all, Is this commit looks proper? On 2026/8/2 17:49, Pu Lehui wrote: > From: Pu Lehui <[email protected]> > > We are frequently hitting the following splat during the riscv bpf > selftests: > > 00000000026dc75a: expected (7c3ff297) but got (00100073) > ------------[ ftrace bug ]------------ > ftrace failed to modify > [<ffffffff03c44c1c>] bpf_kfunc_common_test+0x4/0x20 [bpf_testmod] > actual: e7:82:c2:ce > Updating ftrace call site to call a different ftrace function > ftrace record flags: 80100002 > (2) > expected tramp: ffffffff80043904 > ------------[ cut here ]------------ > WARNING: kernel/trace/ftrace.c:2278 at ftrace_bug+0x46e/0x4b0, CPU#1: test_progs/98 > ... > [<ffffffff80008f4e>] ftrace_bug+0x46e/0x4b0 > [<ffffffff803d3e86>] ftrace_replace_code+0x16e/0x170 > [<ffffffff803d42b6>] ftrace_modify_all_code+0x12e/0x1b8 > [<ffffffff800430f4>] arch_ftrace_update_code+0x14/0x28 > [<ffffffff803e0324>] ftrace_startup+0x14c/0x2a0 > [<ffffffff803e133c>] ftrace_startup_subops+0x584/0x1050 > [<ffffffff804500e6>] register_ftrace_graph+0x4e6/0x1018 > [<ffffffff804cf9f6>] register_fprobe_ips+0xc66/0x12f8 > [<ffffffff8049abe8>] bpf_kprobe_multi_link_attach+0x5d8/0xe68 > [<ffffffff8050fcaa>] __sys_bpf+0x3d5a/0x47f0 > [<ffffffff805107ee>] __riscv_sys_bpf+0xae/0x168 > [<ffffffff80034d78>] syscall_handler+0x60/0x100 > [<ffffffff8228b4f4>] do_trap_ecall_u+0x174/0x208 > [<ffffffff822b69c4>] handle_exception+0x16c/0x178 > > After debugging, it can be triggered by similar commands below: > ``` > echo do_nanosleep > set_ftrace_filter > echo function > current_tracer > echo 'p do_nanosleep' > kprobe_events > echo 1 > events/kprobes/enable > echo 'f do_nanosleep' > dynamic_events > echo 1 > events/fprobes/enable > ``` > > The reason is that attaching a kprobe to an ftrace-traced function entry > replaces its initial auipc insn with ebreak. When ftrace_modify_call > later runs, it expects auipc insn, so verification fails and triggers > ftrace_bug. > > The expected auipc logic remains conceptually unchanged, and kprobe > single-stepping ensures normal execution. Therefore, if the first insn > is ebreak, bypassing the check to continue patching the jalr insn is > safe and avoids ftrace failures. > > Fixes: b2137c3b6d7a ("riscv: ftrace: prepare ftrace for atomic code patching") > Signed-off-by: Pu Lehui <[email protected]> > --- > arch/riscv/kernel/ftrace.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c > index b430edfb83f4..be8b68514417 100644 > --- a/arch/riscv/kernel/ftrace.c > +++ b/arch/riscv/kernel/ftrace.c > @@ -12,6 +12,7 @@ > #include <linux/stop_machine.h> > #include <asm/cacheflush.h> > #include <asm/text-patching.h> > +#include <asm/insn.h> > > #ifdef CONFIG_DYNAMIC_FTRACE > void ftrace_arch_code_modify_prepare(void) > @@ -63,7 +64,9 @@ static int __ftrace_modify_call(unsigned long source, unsigned long target, bool > if (copy_from_kernel_nofault(replaced, (void *)source, 2 * MCOUNT_INSN_SIZE)) > return -EFAULT; > > - if (replaced[0] != call[0]) { > + /* Bypass the check if the auipc insn is a kprobe breakpoint */ > + if (replaced[0] != call[0] && > + !(riscv_insn_is_ebreak(replaced[0]) || riscv_insn_is_c_ebreak(replaced[0]))) { > pr_err("%p: expected (%08x) but got (%08x)\n", > (void *)source, call[0], replaced[0]); > return -EINVAL; _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv