Skip to content

Commit d5c17a4

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 9eb80e5 commit d5c17a4

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

include/linux/ftrace.h

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

10651065
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
10661066
#ifndef ftrace_graph_func
1067-
#define ftrace_graph_func ftrace_stub
1068-
#define FTRACE_OPS_GRAPH_STUB FTRACE_OPS_FL_STUB
1067+
# define ftrace_graph_func ftrace_stub
1068+
# define FTRACE_OPS_GRAPH_STUB FTRACE_OPS_FL_STUB
1069+
/*
1070+
* The function graph is called every time the function tracer is called.
1071+
* It must always test the ops hash and cannot just directly call
1072+
* the handler.
1073+
*/
1074+
# define FGRAPH_NO_DIRECT 1
10691075
#else
1070-
#define FTRACE_OPS_GRAPH_STUB 0
1076+
# define FTRACE_OPS_GRAPH_STUB 0
1077+
# define FGRAPH_NO_DIRECT 0
10711078
#endif
10721079
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
10731080

kernel/trace/fgraph.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,11 @@ static struct fgraph_ops fgraph_stub = {
539539
static struct fgraph_ops *fgraph_direct_gops = &fgraph_stub;
540540
DEFINE_STATIC_CALL(fgraph_func, ftrace_graph_entry_stub);
541541
DEFINE_STATIC_CALL(fgraph_retfunc, ftrace_graph_ret_stub);
542+
#if FGRAPH_NO_DIRECT
543+
static DEFINE_STATIC_KEY_FALSE(fgraph_do_direct);
544+
#else
542545
static DEFINE_STATIC_KEY_TRUE(fgraph_do_direct);
546+
#endif
543547

544548
/**
545549
* ftrace_graph_stop - set to permanently disable function graph tracing
@@ -843,7 +847,7 @@ __ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointe
843847
bitmap = get_bitmap_bits(current, offset);
844848

845849
#ifdef CONFIG_HAVE_STATIC_CALL
846-
if (static_branch_likely(&fgraph_do_direct)) {
850+
if (!FGRAPH_NO_DIRECT && static_branch_likely(&fgraph_do_direct)) {
847851
if (test_bit(fgraph_direct_gops->idx, &bitmap))
848852
static_call(fgraph_retfunc)(&trace, fgraph_direct_gops, fregs);
849853
} else
@@ -1285,6 +1289,9 @@ static void ftrace_graph_enable_direct(bool enable_branch, struct fgraph_ops *go
12851289
trace_func_graph_ret_t retfunc = NULL;
12861290
int i;
12871291

1292+
if (FGRAPH_NO_DIRECT)
1293+
return;
1294+
12881295
if (gops) {
12891296
func = gops->entryfunc;
12901297
retfunc = gops->retfunc;
@@ -1308,6 +1315,9 @@ static void ftrace_graph_enable_direct(bool enable_branch, struct fgraph_ops *go
13081315

13091316
static void ftrace_graph_disable_direct(bool disable_branch)
13101317
{
1318+
if (FGRAPH_NO_DIRECT)
1319+
return;
1320+
13111321
if (disable_branch)
13121322
static_branch_disable(&fgraph_do_direct);
13131323
static_call_update(fgraph_func, ftrace_graph_entry_stub);

0 commit comments

Comments
 (0)