Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'ftrace-v6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull ftrace fixes from Steven Rostedt:

- Always try to initialize the idle functions when graph tracer starts

A bug was found that when a CPU is offline when graph tracing starts
and then comes online, that CPU is not traced. The fix to that was to
move the initialization of the idle shadow stack over to the hot plug
online logic, which also handle onlined CPUs. The issue was that it
removed the initialization of the shadow stack when graph tracing
starts, but the callbacks to the hot plug logic do nothing if graph
tracing isn't currently running. Although that fix fixed the onlining
of a CPU during tracing, it broke the CPUs that were already online.

- Have microblaze not try to get the "true parent" in function tracing

If function tracing and graph tracing are both enabled at the same
time the parent of the functions traced by the function tracer may
sometimes be the graph tracing trampoline. The graph tracing hijacks
the return pointer of the function to trace it, but that can
interfere with the function tracing parent output.

This was fixed by using the ftrace_graph_ret_addr() function passing
in the kernel stack pointer using the ftrace_regs_get_stack_pointer()
function. But Al Viro reported that Microblaze does not implement the
kernel_stack_pointer(regs) helper function that
ftrace_regs_get_stack_pointer() uses and fails to compile when
function graph tracing is enabled.

It was first thought that this was a microblaze issue, but the real
cause is that this only works when an architecture implements
HAVE_DYNAMIC_FTRACE_WITH_ARGS, as a requirement for that config is to
have ftrace always pass a valid ftrace_regs to the callbacks. That
also means that the architecture supports
ftrace_regs_get_stack_pointer()

Microblaze does not set HAVE_DYNAMIC_FTRACE_WITH_ARGS nor does it
implement ftrace_regs_get_stack_pointer() which caused it to fail to
build. Only implement the "true parent" logic if an architecture has
that config set"

* tag 'ftrace-v6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
ftrace: Do not find "true_parent" if HAVE_DYNAMIC_FTRACE_WITH_ARGS is not set
fgraph: Still initialize idle shadow stacks when starting

+9 -2
+7 -1
kernel/trace/fgraph.c
··· 1215 1215 static int start_graph_tracing(void) 1216 1216 { 1217 1217 unsigned long **ret_stack_list; 1218 - int ret; 1218 + int ret, cpu; 1219 1219 1220 1220 ret_stack_list = kcalloc(FTRACE_RETSTACK_ALLOC_SIZE, 1221 1221 sizeof(*ret_stack_list), GFP_KERNEL); 1222 1222 1223 1223 if (!ret_stack_list) 1224 1224 return -ENOMEM; 1225 + 1226 + /* The cpu_boot init_task->ret_stack will never be freed */ 1227 + for_each_online_cpu(cpu) { 1228 + if (!idle_task(cpu)->ret_stack) 1229 + ftrace_graph_init_idle_task(idle_task(cpu), cpu); 1230 + } 1225 1231 1226 1232 do { 1227 1233 ret = alloc_retstack_tasklist(ret_stack_list);
+2 -1
kernel/trace/trace_functions.c
··· 176 176 tracing_reset_online_cpus(&tr->array_buffer); 177 177 } 178 178 179 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 179 + /* fregs are guaranteed not to be NULL if HAVE_DYNAMIC_FTRACE_WITH_ARGS is set */ 180 + #if defined(CONFIG_FUNCTION_GRAPH_TRACER) && defined(CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS) 180 181 static __always_inline unsigned long 181 182 function_get_true_parent_ip(unsigned long parent_ip, struct ftrace_regs *fregs) 182 183 {