On Fri, 6 Dec 2024 17:20:03 +0900 Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx> wrote: > Hi, > > Sorry, I found a problem on arm64 on qemu. Let me recheck it. > > [ 592.422044] # test_fprobe_entry: EXPECTATION FAILED at lib/test_fprobe.c:38 > [ 592.422044] Expected (preempt_count() == 0 && !({ unsigned long _flags; do { ({ unsigned long __dummy; typeof(_flags) __dummy2; (void)(&__dummy == &__dummy2); 1; }); _flags = arch_local_save_flags(); } while (0); ({ ({ unsigned long __dummy; typeof(_flags) __dummy2; (void)(&__dummy == &__dummy2); 1; }); arch_irqs_disabled_flags(_flags); }); })) to be false, but is true This checks the handler is called with preempt off. On x86_64, the ftrace_graph_func calls function_graph_enter_regs() with ftrace_test_recursion_trylock() as below; void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs; unsigned long *stack = (unsigned long *)kernel_stack_pointer(regs); unsigned long return_hooker = (unsigned long)&return_to_handler; unsigned long *parent = (unsigned long *)stack; int bit; if (unlikely(skip_ftrace_return())) return; bit = ftrace_test_recursion_trylock(ip, *parent); if (bit < 0) return; if (!function_graph_enter_regs(*parent, ip, 0, parent, fregs)) *parent = return_hooker; ftrace_test_recursion_unlock(bit); } However, arm64 version does not; void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { unsigned long return_hooker = (unsigned long)&return_to_handler; unsigned long frame_pointer = arch_ftrace_regs(fregs)->fp; unsigned long *parent = &arch_ftrace_regs(fregs)->lr; unsigned long old; if (unlikely(atomic_read(¤t->tracing_graph_pause))) return; old = *parent; if (!function_graph_enter_regs(old, ip, frame_pointer, (void *)frame_pointer, fregs)) { *parent = return_hooker; } } Is it a bug or intended? Thank you, -- Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>