Skip to content
/ linux Public

Commit c71ea5a

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 5026010 commit c71ea5a

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
@@ -1032,10 +1032,17 @@ static inline bool is_ftrace_trampoline(unsigned long addr)
10321032

10331033
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
10341034
#ifndef ftrace_graph_func
1035-
#define ftrace_graph_func ftrace_stub
1036-
#define FTRACE_OPS_GRAPH_STUB FTRACE_OPS_FL_STUB
1035+
# define ftrace_graph_func ftrace_stub
1036+
# define FTRACE_OPS_GRAPH_STUB FTRACE_OPS_FL_STUB
1037+
/*
1038+
* The function graph is called every time the function tracer is called.
1039+
* It must always test the ops hash and cannot just directly call
1040+
* the handler.
1041+
*/
1042+
# define FGRAPH_NO_DIRECT 1
10371043
#else
1038-
#define FTRACE_OPS_GRAPH_STUB 0
1044+
# define FTRACE_OPS_GRAPH_STUB 0
1045+
# define FGRAPH_NO_DIRECT 0
10391046
#endif
10401047
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
10411048

kernel/trace/fgraph.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,11 @@ static struct fgraph_ops fgraph_stub = {
542542
static struct fgraph_ops *fgraph_direct_gops = &fgraph_stub;
543543
DEFINE_STATIC_CALL(fgraph_func, ftrace_graph_entry_stub);
544544
DEFINE_STATIC_CALL(fgraph_retfunc, ftrace_graph_ret_stub);
545+
#if FGRAPH_NO_DIRECT
546+
static DEFINE_STATIC_KEY_FALSE(fgraph_do_direct);
547+
#else
545548
static DEFINE_STATIC_KEY_TRUE(fgraph_do_direct);
549+
#endif
546550

547551
/**
548552
* ftrace_graph_stop - set to permanently disable function graph tracing
@@ -846,7 +850,7 @@ __ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointe
846850
bitmap = get_bitmap_bits(current, offset);
847851

848852
#ifdef CONFIG_HAVE_STATIC_CALL
849-
if (static_branch_likely(&fgraph_do_direct)) {
853+
if (!FGRAPH_NO_DIRECT && static_branch_likely(&fgraph_do_direct)) {
850854
if (test_bit(fgraph_direct_gops->idx, &bitmap))
851855
static_call(fgraph_retfunc)(&trace, fgraph_direct_gops, fregs);
852856
} else
@@ -1293,6 +1297,9 @@ static void ftrace_graph_enable_direct(bool enable_branch, struct fgraph_ops *go
12931297
trace_func_graph_ret_t retfunc = NULL;
12941298
int i;
12951299

1300+
if (FGRAPH_NO_DIRECT)
1301+
return;
1302+
12961303
if (gops) {
12971304
func = gops->entryfunc;
12981305
retfunc = gops->retfunc;
@@ -1316,6 +1323,9 @@ static void ftrace_graph_enable_direct(bool enable_branch, struct fgraph_ops *go
13161323

13171324
static void ftrace_graph_disable_direct(bool disable_branch)
13181325
{
1326+
if (FGRAPH_NO_DIRECT)
1327+
return;
1328+
13191329
if (disable_branch)
13201330
static_branch_disable(&fgraph_do_direct);
13211331
static_call_update(fgraph_func, ftrace_graph_entry_stub);

0 commit comments

Comments
 (0)