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

function_graph: Move graph depth stored data to shadow stack global var

The use of the task->trace_recursion for the logic used for the function
graph depth was a bit of an abuse of that variable. Now that there
exists global vars that are per stack for registered graph traces, use that
instead.

Link: https://lore.kernel.org/linux-trace-kernel/171509106728.162236.2398372644430125344.stgit@devnote2
Link: https://lore.kernel.org/linux-trace-kernel/20240603190823.634870264@goodmis.org

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Florent Revest <revest@chromium.org>
Cc: Martin KaFai Lau <martin.lau@linux.dev>
Cc: bpf <bpf@vger.kernel.org>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Alan Maguire <alan.maguire@oracle.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Guo Ren <guoren@kernel.org>
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+32 -31
-29
include/linux/trace_recursion.h
··· 45 45 TRACE_IRQ_BIT, 46 46 47 47 /* 48 - * In the very unlikely case that an interrupt came in 49 - * at a start of graph tracing, and we want to trace 50 - * the function in that interrupt, the depth can be greater 51 - * than zero, because of the preempted start of a previous 52 - * trace. In an even more unlikely case, depth could be 2 53 - * if a softirq interrupted the start of graph tracing, 54 - * followed by an interrupt preempting a start of graph 55 - * tracing in the softirq, and depth can even be 3 56 - * if an NMI came in at the start of an interrupt function 57 - * that preempted a softirq start of a function that 58 - * preempted normal context!!!! Luckily, it can't be 59 - * greater than 3, so the next two bits are a mask 60 - * of what the depth is when we set TRACE_GRAPH_FL 61 - */ 62 - 63 - TRACE_GRAPH_DEPTH_START_BIT, 64 - TRACE_GRAPH_DEPTH_END_BIT, 65 - 66 - /* 67 48 * To implement set_graph_notrace, if this bit is set, we ignore 68 49 * function graph tracing of called functions, until the return 69 50 * function is called to clear it. ··· 58 77 #define trace_recursion_set(bit) do { (current)->trace_recursion |= (1<<(bit)); } while (0) 59 78 #define trace_recursion_clear(bit) do { (current)->trace_recursion &= ~(1<<(bit)); } while (0) 60 79 #define trace_recursion_test(bit) ((current)->trace_recursion & (1<<(bit))) 61 - 62 - #define trace_recursion_depth() \ 63 - (((current)->trace_recursion >> TRACE_GRAPH_DEPTH_START_BIT) & 3) 64 - #define trace_recursion_set_depth(depth) \ 65 - do { \ 66 - current->trace_recursion &= \ 67 - ~(3 << TRACE_GRAPH_DEPTH_START_BIT); \ 68 - current->trace_recursion |= \ 69 - ((depth) & 3) << TRACE_GRAPH_DEPTH_START_BIT; \ 70 - } while (0) 71 80 72 81 #define TRACE_CONTEXT_BITS 4 73 82
+32 -2
kernel/trace/trace.h
··· 900 900 901 901 enum { 902 902 TRACE_GRAPH_FL = 1, 903 + 904 + /* 905 + * In the very unlikely case that an interrupt came in 906 + * at a start of graph tracing, and we want to trace 907 + * the function in that interrupt, the depth can be greater 908 + * than zero, because of the preempted start of a previous 909 + * trace. In an even more unlikely case, depth could be 2 910 + * if a softirq interrupted the start of graph tracing, 911 + * followed by an interrupt preempting a start of graph 912 + * tracing in the softirq, and depth can even be 3 913 + * if an NMI came in at the start of an interrupt function 914 + * that preempted a softirq start of a function that 915 + * preempted normal context!!!! Luckily, it can't be 916 + * greater than 3, so the next two bits are a mask 917 + * of what the depth is when we set TRACE_GRAPH_FL 918 + */ 919 + 920 + TRACE_GRAPH_DEPTH_START_BIT, 921 + TRACE_GRAPH_DEPTH_END_BIT, 903 922 }; 923 + 924 + static inline unsigned long ftrace_graph_depth(unsigned long *task_var) 925 + { 926 + return (*task_var >> TRACE_GRAPH_DEPTH_START_BIT) & 3; 927 + } 928 + 929 + static inline void ftrace_graph_set_depth(unsigned long *task_var, int depth) 930 + { 931 + *task_var &= ~(3 << TRACE_GRAPH_DEPTH_START_BIT); 932 + *task_var |= (depth & 3) << TRACE_GRAPH_DEPTH_START_BIT; 933 + } 904 934 905 935 #ifdef CONFIG_DYNAMIC_FTRACE 906 936 extern struct ftrace_hash __rcu *ftrace_graph_hash; ··· 964 934 * when the depth is zero. 965 935 */ 966 936 *task_var |= TRACE_GRAPH_FL; 967 - trace_recursion_set_depth(trace->depth); 937 + ftrace_graph_set_depth(task_var, trace->depth); 968 938 969 939 /* 970 940 * If no irqs are to be traced, but a set_graph_function ··· 989 959 unsigned long *task_var = fgraph_get_task_var(gops); 990 960 991 961 if ((*task_var & TRACE_GRAPH_FL) && 992 - trace->depth == trace_recursion_depth()) 962 + trace->depth == ftrace_graph_depth(task_var)) 993 963 *task_var &= ~TRACE_GRAPH_FL; 994 964 } 995 965