Skip to content

Commit fea7c9a

Browse files
rostedtSasha Levin
authored andcommitted
fgraph: Do not call handlers direct when not using ftrace_ops
[ Upstream commit f4ff9f6 ] The function graph tracer was modified to us the ftrace_ops of the function tracer. This simplified the code as well as allowed more features of the function graph tracer. Not all architectures were converted over as it required the implementation of HAVE_DYNAMIC_FTRACE_WITH_ARGS to implement. For those architectures, it still did it the old way where the function graph tracer handle was called by the function tracer trampoline. The handler then had to check the hash to see if the registered handlers wanted to be called by that function or not. In order to speed up the function graph tracer that used ftrace_ops, if only one callback was registered with function graph, it would call its function directly via a static call. Now, if the architecture does not support the use of using ftrace_ops and still has the ftrace function trampoline calling the function graph handler, then by doing a direct call it removes the check against the handler's hash (list of functions it wants callbacks to), and it may call that handler for functions that the handler did not request calls for. On 32bit x86, which does not support the ftrace_ops use with function graph tracer, it shows the issue: ~# trace-cmd start -p function -l schedule ~# trace-cmd show # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | 2) * 11898.94 us | schedule(); 3) # 1783.041 us | schedule(); 1) | schedule() { ------------------------------------------ 1) bash-8369 => kworker-7669 ------------------------------------------ 1) | schedule() { ------------------------------------------ 1) kworker-7669 => bash-8369 ------------------------------------------ 1) + 97.004 us | } 1) | schedule() { [..] Now by starting the function tracer is another instance: ~# trace-cmd start -B foo -p function This causes the function graph tracer to trace all functions (because the function trace calls the function graph tracer for each on, and the function graph trace is doing a direct call): ~# trace-cmd show # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | 1) 1.669 us | } /* preempt_count_sub */ 1) + 10.443 us | } /* _raw_spin_unlock_irqrestore */ 1) | tick_program_event() { 1) | clockevents_program_event() { 1) 1.044 us | ktime_get(); 1) 6.481 us | lapic_next_event(); 1) + 10.114 us | } 1) + 11.790 us | } 1) ! 181.223 us | } /* hrtimer_interrupt */ 1) ! 184.624 us | } /* __sysvec_apic_timer_interrupt */ 1) | irq_exit_rcu() { 1) 0.678 us | preempt_count_sub(); When it should still only be tracing the schedule() function. To fix this, add a macro FGRAPH_NO_DIRECT to be set to 0 when the architecture does not support function graph use of ftrace_ops, and set to 1 otherwise. Then use this macro to know to allow function graph tracer to call the handlers directly or not. Cc: stable@vger.kernel.org Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Mark Rutland <mark.rutland@arm.com> Link: https://patch.msgid.link/20260218104244.5f14dade@gandalf.local.home Fixes: cc60ee8 ("function_graph: Use static_call and branch to optimize entry function") Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent b4700c0 commit fea7c9a

2 files changed

Lines changed: 21 additions & 4 deletions

File tree

include/linux/ftrace.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -994,10 +994,17 @@ static inline bool is_ftrace_trampoline(unsigned long addr)
994994

995995
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
996996
#ifndef ftrace_graph_func
997-
#define ftrace_graph_func ftrace_stub
998-
#define FTRACE_OPS_GRAPH_STUB FTRACE_OPS_FL_STUB
997+
# define ftrace_graph_func ftrace_stub
998+
# define FTRACE_OPS_GRAPH_STUB FTRACE_OPS_FL_STUB
999+
/*
1000+
* The function graph is called every time the function tracer is called.
1001+
* It must always test the ops hash and cannot just directly call
1002+
* the handler.
1003+
*/
1004+
# define FGRAPH_NO_DIRECT 1
9991005
#else
1000-
#define FTRACE_OPS_GRAPH_STUB 0
1006+
# define FTRACE_OPS_GRAPH_STUB 0
1007+
# define FGRAPH_NO_DIRECT 0
10011008
#endif
10021009
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
10031010

kernel/trace/fgraph.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,11 @@ static struct fgraph_ops fgraph_stub = {
502502
static struct fgraph_ops *fgraph_direct_gops = &fgraph_stub;
503503
DEFINE_STATIC_CALL(fgraph_func, ftrace_graph_entry_stub);
504504
DEFINE_STATIC_CALL(fgraph_retfunc, ftrace_graph_ret_stub);
505+
#if FGRAPH_NO_DIRECT
506+
static DEFINE_STATIC_KEY_FALSE(fgraph_do_direct);
507+
#else
505508
static DEFINE_STATIC_KEY_TRUE(fgraph_do_direct);
509+
#endif
506510

507511
/**
508512
* ftrace_graph_stop - set to permanently disable function graph tracing
@@ -792,7 +796,7 @@ __ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointe
792796
bitmap = get_bitmap_bits(current, offset);
793797

794798
#ifdef CONFIG_HAVE_STATIC_CALL
795-
if (static_branch_likely(&fgraph_do_direct)) {
799+
if (!FGRAPH_NO_DIRECT && static_branch_likely(&fgraph_do_direct)) {
796800
if (test_bit(fgraph_direct_gops->idx, &bitmap))
797801
static_call(fgraph_retfunc)(&trace, fgraph_direct_gops);
798802
} else
@@ -1211,6 +1215,9 @@ static void ftrace_graph_enable_direct(bool enable_branch, struct fgraph_ops *go
12111215
trace_func_graph_ret_t retfunc = NULL;
12121216
int i;
12131217

1218+
if (FGRAPH_NO_DIRECT)
1219+
return;
1220+
12141221
if (gops) {
12151222
func = gops->entryfunc;
12161223
retfunc = gops->retfunc;
@@ -1234,6 +1241,9 @@ static void ftrace_graph_enable_direct(bool enable_branch, struct fgraph_ops *go
12341241

12351242
static void ftrace_graph_disable_direct(bool disable_branch)
12361243
{
1244+
if (FGRAPH_NO_DIRECT)
1245+
return;
1246+
12371247
if (disable_branch)
12381248
static_branch_disable(&fgraph_do_direct);
12391249
static_call_update(fgraph_func, ftrace_graph_entry_stub);

0 commit comments

Comments
 (0)