aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_functions_graph.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-12-31 14:46:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-12-31 14:46:59 -0500
commit495d714ad140e1732e66c45d0409054b24c1a0d6 (patch)
tree373ec6619adea47d848d36f140b32def27164bbd /kernel/trace/trace_functions_graph.c
parentf12e840c819bab42621685558a01d3f46ab9a226 (diff)
parent3d739c1f6156c70eb0548aa288dcfbac9e0bd162 (diff)
Merge tag 'trace-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing updates from Steven Rostedt: - Rework of the kprobe/uprobe and synthetic events to consolidate all the dynamic event code. This will make changes in the future easier. - Partial rewrite of the function graph tracing infrastructure. This will allow for multiple users of hooking onto functions to get the callback (return) of the function. This is the ground work for having kprobes and function graph tracer using one code base. - Clean up of the histogram code that will facilitate adding more features to the histograms in the future. - Addition of str_has_prefix() and a few use cases. There currently is a similar function strstart() that is used in a few places, but only returns a bool and not a length. These instances will be removed in the future to use str_has_prefix() instead. - A few other various clean ups as well. * tag 'trace-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (57 commits) tracing: Use the return of str_has_prefix() to remove open coded numbers tracing: Have the historgram use the result of str_has_prefix() for len of prefix tracing: Use str_has_prefix() instead of using fixed sizes tracing: Use str_has_prefix() helper for histogram code string.h: Add str_has_prefix() helper function tracing: Make function ‘ftrace_exports’ static tracing: Simplify printf'ing in seq_print_sym tracing: Avoid -Wformat-nonliteral warning tracing: Merge seq_print_sym_short() and seq_print_sym_offset() tracing: Add hist trigger comments for variable-related fields tracing: Remove hist trigger synth_var_refs tracing: Use hist trigger's var_ref array to destroy var_refs tracing: Remove open-coding of hist trigger var_ref management tracing: Use var_refs[] for hist trigger reference checking tracing: Change strlen to sizeof for hist trigger static strings tracing: Remove unnecessary hist trigger struct field tracing: Fix ftrace_graph_get_ret_stack() to use task and not current seq_buf: Use size_t for len in seq_buf_puts() seq_buf: Make seq_buf_puts() null-terminate the buffer arm64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack ...
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
-rw-r--r--kernel/trace/trace_functions_graph.c334
1 files changed, 42 insertions, 292 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 086af4f5c3e8..c2af1560e856 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -16,33 +16,6 @@
16#include "trace.h" 16#include "trace.h"
17#include "trace_output.h" 17#include "trace_output.h"
18 18
19static bool kill_ftrace_graph;
20
21/**
22 * ftrace_graph_is_dead - returns true if ftrace_graph_stop() was called
23 *
24 * ftrace_graph_stop() is called when a severe error is detected in
25 * the function graph tracing. This function is called by the critical
26 * paths of function graph to keep those paths from doing any more harm.
27 */
28bool ftrace_graph_is_dead(void)
29{
30 return kill_ftrace_graph;
31}
32
33/**
34 * ftrace_graph_stop - set to permanently disable function graph tracincg
35 *
36 * In case of an error int function graph tracing, this is called
37 * to try to keep function graph tracing from causing any more harm.
38 * Usually this is pretty severe and this is called to try to at least
39 * get a warning out to the user.
40 */
41void ftrace_graph_stop(void)
42{
43 kill_ftrace_graph = true;
44}
45
46/* When set, irq functions will be ignored */ 19/* When set, irq functions will be ignored */
47static int ftrace_graph_skip_irqs; 20static int ftrace_graph_skip_irqs;
48 21
@@ -87,8 +60,12 @@ static struct tracer_opt trace_opts[] = {
87 { TRACER_OPT(funcgraph-tail, TRACE_GRAPH_PRINT_TAIL) }, 60 { TRACER_OPT(funcgraph-tail, TRACE_GRAPH_PRINT_TAIL) },
88 /* Include sleep time (scheduled out) between entry and return */ 61 /* Include sleep time (scheduled out) between entry and return */
89 { TRACER_OPT(sleep-time, TRACE_GRAPH_SLEEP_TIME) }, 62 { TRACER_OPT(sleep-time, TRACE_GRAPH_SLEEP_TIME) },
63
64#ifdef CONFIG_FUNCTION_PROFILER
90 /* Include time within nested functions */ 65 /* Include time within nested functions */
91 { TRACER_OPT(graph-time, TRACE_GRAPH_GRAPH_TIME) }, 66 { TRACER_OPT(graph-time, TRACE_GRAPH_GRAPH_TIME) },
67#endif
68
92 { } /* Empty entry */ 69 { } /* Empty entry */
93}; 70};
94 71
@@ -117,258 +94,6 @@ static void
117print_graph_duration(struct trace_array *tr, unsigned long long duration, 94print_graph_duration(struct trace_array *tr, unsigned long long duration,
118 struct trace_seq *s, u32 flags); 95 struct trace_seq *s, u32 flags);
119 96
120/* Add a function return address to the trace stack on thread info.*/
121static int
122ftrace_push_return_trace(unsigned long ret, unsigned long func,
123 unsigned long frame_pointer, unsigned long *retp)
124{
125 unsigned long long calltime;
126 int index;
127
128 if (unlikely(ftrace_graph_is_dead()))
129 return -EBUSY;
130
131 if (!current->ret_stack)
132 return -EBUSY;
133
134 /*
135 * We must make sure the ret_stack is tested before we read
136 * anything else.
137 */
138 smp_rmb();
139
140 /* The return trace stack is full */
141 if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
142 atomic_inc(&current->trace_overrun);
143 return -EBUSY;
144 }
145
146 /*
147 * The curr_ret_stack is an index to ftrace return stack of
148 * current task. Its value should be in [0, FTRACE_RETFUNC_
149 * DEPTH) when the function graph tracer is used. To support
150 * filtering out specific functions, it makes the index
151 * negative by subtracting huge value (FTRACE_NOTRACE_DEPTH)
152 * so when it sees a negative index the ftrace will ignore
153 * the record. And the index gets recovered when returning
154 * from the filtered function by adding the FTRACE_NOTRACE_
155 * DEPTH and then it'll continue to record functions normally.
156 *
157 * The curr_ret_stack is initialized to -1 and get increased
158 * in this function. So it can be less than -1 only if it was
159 * filtered out via ftrace_graph_notrace_addr() which can be
160 * set from set_graph_notrace file in tracefs by user.
161 */
162 if (current->curr_ret_stack < -1)
163 return -EBUSY;
164
165 calltime = trace_clock_local();
166
167 index = ++current->curr_ret_stack;
168 if (ftrace_graph_notrace_addr(func))
169 current->curr_ret_stack -= FTRACE_NOTRACE_DEPTH;
170 barrier();
171 current->ret_stack[index].ret = ret;
172 current->ret_stack[index].func = func;
173 current->ret_stack[index].calltime = calltime;
174#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
175 current->ret_stack[index].fp = frame_pointer;
176#endif
177#ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
178 current->ret_stack[index].retp = retp;
179#endif
180 return 0;
181}
182
183int function_graph_enter(unsigned long ret, unsigned long func,
184 unsigned long frame_pointer, unsigned long *retp)
185{
186 struct ftrace_graph_ent trace;
187
188 trace.func = func;
189 trace.depth = ++current->curr_ret_depth;
190
191 if (ftrace_push_return_trace(ret, func,
192 frame_pointer, retp))
193 goto out;
194
195 /* Only trace if the calling function expects to */
196 if (!ftrace_graph_entry(&trace))
197 goto out_ret;
198
199 return 0;
200 out_ret:
201 current->curr_ret_stack--;
202 out:
203 current->curr_ret_depth--;
204 return -EBUSY;
205}
206
207/* Retrieve a function return address to the trace stack on thread info.*/
208static void
209ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,
210 unsigned long frame_pointer)
211{
212 int index;
213
214 index = current->curr_ret_stack;
215
216 /*
217 * A negative index here means that it's just returned from a
218 * notrace'd function. Recover index to get an original
219 * return address. See ftrace_push_return_trace().
220 *
221 * TODO: Need to check whether the stack gets corrupted.
222 */
223 if (index < 0)
224 index += FTRACE_NOTRACE_DEPTH;
225
226 if (unlikely(index < 0 || index >= FTRACE_RETFUNC_DEPTH)) {
227 ftrace_graph_stop();
228 WARN_ON(1);
229 /* Might as well panic, otherwise we have no where to go */
230 *ret = (unsigned long)panic;
231 return;
232 }
233
234#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
235 /*
236 * The arch may choose to record the frame pointer used
237 * and check it here to make sure that it is what we expect it
238 * to be. If gcc does not set the place holder of the return
239 * address in the frame pointer, and does a copy instead, then
240 * the function graph trace will fail. This test detects this
241 * case.
242 *
243 * Currently, x86_32 with optimize for size (-Os) makes the latest
244 * gcc do the above.
245 *
246 * Note, -mfentry does not use frame pointers, and this test
247 * is not needed if CC_USING_FENTRY is set.
248 */
249 if (unlikely(current->ret_stack[index].fp != frame_pointer)) {
250 ftrace_graph_stop();
251 WARN(1, "Bad frame pointer: expected %lx, received %lx\n"
252 " from func %ps return to %lx\n",
253 current->ret_stack[index].fp,
254 frame_pointer,
255 (void *)current->ret_stack[index].func,
256 current->ret_stack[index].ret);
257 *ret = (unsigned long)panic;
258 return;
259 }
260#endif
261
262 *ret = current->ret_stack[index].ret;
263 trace->func = current->ret_stack[index].func;
264 trace->calltime = current->ret_stack[index].calltime;
265 trace->overrun = atomic_read(&current->trace_overrun);
266 trace->depth = current->curr_ret_depth--;
267 /*
268 * We still want to trace interrupts coming in if
269 * max_depth is set to 1. Make sure the decrement is
270 * seen before ftrace_graph_return.
271 */
272 barrier();
273}
274
275/*
276 * Send the trace to the ring-buffer.
277 * @return the original return address.
278 */
279unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
280{
281 struct ftrace_graph_ret trace;
282 unsigned long ret;
283
284 ftrace_pop_return_trace(&trace, &ret, frame_pointer);
285 trace.rettime = trace_clock_local();
286 ftrace_graph_return(&trace);
287 /*
288 * The ftrace_graph_return() may still access the current
289 * ret_stack structure, we need to make sure the update of
290 * curr_ret_stack is after that.
291 */
292 barrier();
293 current->curr_ret_stack--;
294 /*
295 * The curr_ret_stack can be less than -1 only if it was
296 * filtered out and it's about to return from the function.
297 * Recover the index and continue to trace normal functions.
298 */
299 if (current->curr_ret_stack < -1) {
300 current->curr_ret_stack += FTRACE_NOTRACE_DEPTH;
301 return ret;
302 }
303
304 if (unlikely(!ret)) {
305 ftrace_graph_stop();
306 WARN_ON(1);
307 /* Might as well panic. What else to do? */
308 ret = (unsigned long)panic;
309 }
310
311 return ret;
312}
313
314/**
315 * ftrace_graph_ret_addr - convert a potentially modified stack return address
316 * to its original value
317 *
318 * This function can be called by stack unwinding code to convert a found stack
319 * return address ('ret') to its original value, in case the function graph
320 * tracer has modified it to be 'return_to_handler'. If the address hasn't
321 * been modified, the unchanged value of 'ret' is returned.
322 *
323 * 'idx' is a state variable which should be initialized by the caller to zero
324 * before the first call.
325 *
326 * 'retp' is a pointer to the return address on the stack. It's ignored if
327 * the arch doesn't have HAVE_FUNCTION_GRAPH_RET_ADDR_PTR defined.
328 */
329#ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
330unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
331 unsigned long ret, unsigned long *retp)
332{
333 int index = task->curr_ret_stack;
334 int i;
335
336 if (ret != (unsigned long)return_to_handler)
337 return ret;
338
339 if (index < -1)
340 index += FTRACE_NOTRACE_DEPTH;
341
342 if (index < 0)
343 return ret;
344
345 for (i = 0; i <= index; i++)
346 if (task->ret_stack[i].retp == retp)
347 return task->ret_stack[i].ret;
348
349 return ret;
350}
351#else /* !HAVE_FUNCTION_GRAPH_RET_ADDR_PTR */
352unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
353 unsigned long ret, unsigned long *retp)
354{
355 int task_idx;
356
357 if (ret != (unsigned long)return_to_handler)
358 return ret;
359
360 task_idx = task->curr_ret_stack;
361
362 if (!task->ret_stack || task_idx < *idx)
363 return ret;
364
365 task_idx -= *idx;
366 (*idx)++;
367
368 return task->ret_stack[task_idx].ret;
369}
370#endif /* HAVE_FUNCTION_GRAPH_RET_ADDR_PTR */
371
372int __trace_graph_entry(struct trace_array *tr, 97int __trace_graph_entry(struct trace_array *tr,
373 struct ftrace_graph_ent *trace, 98 struct ftrace_graph_ent *trace,
374 unsigned long flags, 99 unsigned long flags,
@@ -409,6 +134,18 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
409 int cpu; 134 int cpu;
410 int pc; 135 int pc;
411 136
137 if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT))
138 return 0;
139
140 if (ftrace_graph_notrace_addr(trace->func)) {
141 trace_recursion_set(TRACE_GRAPH_NOTRACE_BIT);
142 /*
143 * Need to return 1 to have the return called
144 * that will clear the NOTRACE bit.
145 */
146 return 1;
147 }
148
412 if (!ftrace_trace_task(tr)) 149 if (!ftrace_trace_task(tr))
413 return 0; 150 return 0;
414 151
@@ -511,6 +248,11 @@ void trace_graph_return(struct ftrace_graph_ret *trace)
511 248
512 ftrace_graph_addr_finish(trace); 249 ftrace_graph_addr_finish(trace);
513 250
251 if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT)) {
252 trace_recursion_clear(TRACE_GRAPH_NOTRACE_BIT);
253 return;
254 }
255
514 local_irq_save(flags); 256 local_irq_save(flags);
515 cpu = raw_smp_processor_id(); 257 cpu = raw_smp_processor_id();
516 data = per_cpu_ptr(tr->trace_buffer.data, cpu); 258 data = per_cpu_ptr(tr->trace_buffer.data, cpu);
@@ -536,6 +278,11 @@ static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
536{ 278{
537 ftrace_graph_addr_finish(trace); 279 ftrace_graph_addr_finish(trace);
538 280
281 if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT)) {
282 trace_recursion_clear(TRACE_GRAPH_NOTRACE_BIT);
283 return;
284 }
285
539 if (tracing_thresh && 286 if (tracing_thresh &&
540 (trace->rettime - trace->calltime < tracing_thresh)) 287 (trace->rettime - trace->calltime < tracing_thresh))
541 return; 288 return;
@@ -543,17 +290,25 @@ static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
543 trace_graph_return(trace); 290 trace_graph_return(trace);
544} 291}
545 292
293static struct fgraph_ops funcgraph_thresh_ops = {
294 .entryfunc = &trace_graph_entry,
295 .retfunc = &trace_graph_thresh_return,
296};
297
298static struct fgraph_ops funcgraph_ops = {
299 .entryfunc = &trace_graph_entry,
300 .retfunc = &trace_graph_return,
301};
302
546static int graph_trace_init(struct trace_array *tr) 303static int graph_trace_init(struct trace_array *tr)
547{ 304{
548 int ret; 305 int ret;
549 306
550 set_graph_array(tr); 307 set_graph_array(tr);
551 if (tracing_thresh) 308 if (tracing_thresh)
552 ret = register_ftrace_graph(&trace_graph_thresh_return, 309 ret = register_ftrace_graph(&funcgraph_thresh_ops);
553 &trace_graph_entry);
554 else 310 else
555 ret = register_ftrace_graph(&trace_graph_return, 311 ret = register_ftrace_graph(&funcgraph_ops);
556 &trace_graph_entry);
557 if (ret) 312 if (ret)
558 return ret; 313 return ret;
559 tracing_start_cmdline_record(); 314 tracing_start_cmdline_record();
@@ -564,7 +319,10 @@ static int graph_trace_init(struct trace_array *tr)
564static void graph_trace_reset(struct trace_array *tr) 319static void graph_trace_reset(struct trace_array *tr)
565{ 320{
566 tracing_stop_cmdline_record(); 321 tracing_stop_cmdline_record();
567 unregister_ftrace_graph(); 322 if (tracing_thresh)
323 unregister_ftrace_graph(&funcgraph_thresh_ops);
324 else
325 unregister_ftrace_graph(&funcgraph_ops);
568} 326}
569 327
570static int graph_trace_update_thresh(struct trace_array *tr) 328static int graph_trace_update_thresh(struct trace_array *tr)
@@ -874,10 +632,6 @@ print_graph_entry_leaf(struct trace_iterator *iter,
874 632
875 cpu_data = per_cpu_ptr(data->cpu_data, cpu); 633 cpu_data = per_cpu_ptr(data->cpu_data, cpu);
876 634
877 /* If a graph tracer ignored set_graph_notrace */
878 if (call->depth < -1)
879 call->depth += FTRACE_NOTRACE_DEPTH;
880
881 /* 635 /*
882 * Comments display at + 1 to depth. Since 636 * Comments display at + 1 to depth. Since
883 * this is a leaf function, keep the comments 637 * this is a leaf function, keep the comments
@@ -920,10 +674,6 @@ print_graph_entry_nested(struct trace_iterator *iter,
920 struct fgraph_cpu_data *cpu_data; 674 struct fgraph_cpu_data *cpu_data;
921 int cpu = iter->cpu; 675 int cpu = iter->cpu;
922 676
923 /* If a graph tracer ignored set_graph_notrace */
924 if (call->depth < -1)
925 call->depth += FTRACE_NOTRACE_DEPTH;
926
927 cpu_data = per_cpu_ptr(data->cpu_data, cpu); 677 cpu_data = per_cpu_ptr(data->cpu_data, cpu);
928 cpu_data->depth = call->depth; 678 cpu_data->depth = call->depth;
929 679