Blame view

kernel/trace/trace_functions_graph.c 39.1 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
fb52607af   Frederic Weisbecker   tracing/function-...
2
3
4
  /*
   *
   * Function graph tracer.
9005f3ebe   Frederic Weisbecker   tracing/function-...
5
   * Copyright (c) 2008-2009 Frederic Weisbecker <fweisbec@gmail.com>
fb52607af   Frederic Weisbecker   tracing/function-...
6
7
8
9
   * Mostly borrowed from function tracer which
   * is Copyright (c) Steven Rostedt <srostedt@redhat.com>
   *
   */
fb52607af   Frederic Weisbecker   tracing/function-...
10
11
  #include <linux/uaccess.h>
  #include <linux/ftrace.h>
be7635e72   Alexander Potapenko   arch, ftrace: for...
12
  #include <linux/interrupt.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
fb52607af   Frederic Weisbecker   tracing/function-...
14
15
16
  #include <linux/fs.h>
  
  #include "trace.h"
f0868d1e2   Steven Rostedt   ftrace: set up tr...
17
  #include "trace_output.h"
fb52607af   Frederic Weisbecker   tracing/function-...
18

1b2f121c1   Steven Rostedt (Red Hat)   ftrace-graph: Rem...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  static bool kill_ftrace_graph;
  
  /**
   * ftrace_graph_is_dead - returns true if ftrace_graph_stop() was called
   *
   * ftrace_graph_stop() is called when a severe error is detected in
   * the function graph tracing. This function is called by the critical
   * paths of function graph to keep those paths from doing any more harm.
   */
  bool ftrace_graph_is_dead(void)
  {
  	return kill_ftrace_graph;
  }
  
  /**
   * ftrace_graph_stop - set to permanently disable function graph tracincg
   *
   * In case of an error int function graph tracing, this is called
   * to try to keep function graph tracing from causing any more harm.
   * Usually this is pretty severe and this is called to try to at least
   * get a warning out to the user.
   */
  void ftrace_graph_stop(void)
  {
  	kill_ftrace_graph = true;
1b2f121c1   Steven Rostedt (Red Hat)   ftrace-graph: Rem...
44
  }
b304d0441   Steven Rostedt   tracing: Do not t...
45
46
  /* When set, irq functions will be ignored */
  static int ftrace_graph_skip_irqs;
be1eca393   Jiri Olsa   tracing: Fix func...
47
  struct fgraph_cpu_data {
2fbcdb35a   Steven Rostedt   function-graph: c...
48
49
  	pid_t		last_pid;
  	int		depth;
2bd16212b   Jiri Olsa   tracing: Add func...
50
  	int		depth_irq;
be1eca393   Jiri Olsa   tracing: Fix func...
51
  	int		ignore;
f1c7f517a   Steven Rostedt   ftrace: Add funct...
52
  	unsigned long	enter_funcs[FTRACE_RETFUNC_DEPTH];
be1eca393   Jiri Olsa   tracing: Fix func...
53
54
55
  };
  
  struct fgraph_data {
6016ee13d   Namhyung Kim   perf, tracing: ad...
56
  	struct fgraph_cpu_data __percpu *cpu_data;
be1eca393   Jiri Olsa   tracing: Fix func...
57
58
59
60
61
62
  
  	/* Place to preserve last processed entry. */
  	struct ftrace_graph_ent_entry	ent;
  	struct ftrace_graph_ret_entry	ret;
  	int				failed;
  	int				cpu;
2fbcdb35a   Steven Rostedt   function-graph: c...
63
  };
287b6e68c   Frederic Weisbecker   tracing/function-...
64
  #define TRACE_GRAPH_INDENT	2
fb52607af   Frederic Weisbecker   tracing/function-...
65

1a4144286   Steven Rostedt (Red Hat)   tracing/fgraph: H...
66
  unsigned int fgraph_max_depth;
8741db532   Steven Rostedt   tracing/fgraph: A...
67

fb52607af   Frederic Weisbecker   tracing/function-...
68
  static struct tracer_opt trace_opts[] = {
9005f3ebe   Frederic Weisbecker   tracing/function-...
69
  	/* Display overruns? (for self-debug purpose) */
1a056155e   Frederic Weisbecker   tracing/function-...
70
71
72
73
74
  	{ TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) },
  	/* Display CPU ? */
  	{ TRACER_OPT(funcgraph-cpu, TRACE_GRAPH_PRINT_CPU) },
  	/* Display Overhead ? */
  	{ TRACER_OPT(funcgraph-overhead, TRACE_GRAPH_PRINT_OVERHEAD) },
11e84acc4   Frederic Weisbecker   tracing/function-...
75
76
  	/* Display proc name/pid */
  	{ TRACER_OPT(funcgraph-proc, TRACE_GRAPH_PRINT_PROC) },
9005f3ebe   Frederic Weisbecker   tracing/function-...
77
78
79
80
  	/* Display duration of execution */
  	{ TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) },
  	/* Display absolute time of an entry */
  	{ TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },
2bd16212b   Jiri Olsa   tracing: Add func...
81
82
  	/* Display interrupts */
  	{ TRACER_OPT(funcgraph-irqs, TRACE_GRAPH_PRINT_IRQS) },
607e3a292   Robert Elliott   tracing: Add func...
83
84
  	/* Display function name after trailing } */
  	{ TRACER_OPT(funcgraph-tail, TRACE_GRAPH_PRINT_TAIL) },
555772041   Steven Rostedt (Red Hat)   tracing: Move sle...
85
86
87
88
  	/* Include sleep time (scheduled out) between entry and return */
  	{ TRACER_OPT(sleep-time, TRACE_GRAPH_SLEEP_TIME) },
  	/* Include time within nested functions */
  	{ TRACER_OPT(graph-time, TRACE_GRAPH_GRAPH_TIME) },
fb52607af   Frederic Weisbecker   tracing/function-...
89
90
91
92
  	{ } /* Empty entry */
  };
  
  static struct tracer_flags tracer_flags = {
607e3a292   Robert Elliott   tracing: Add func...
93
  	/* Don't display overruns, proc, or tail by default */
9005f3ebe   Frederic Weisbecker   tracing/function-...
94
  	.val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD |
555772041   Steven Rostedt (Red Hat)   tracing: Move sle...
95
96
  	       TRACE_GRAPH_PRINT_DURATION | TRACE_GRAPH_PRINT_IRQS |
  	       TRACE_GRAPH_SLEEP_TIME | TRACE_GRAPH_GRAPH_TIME,
fb52607af   Frederic Weisbecker   tracing/function-...
97
98
  	.opts = trace_opts
  };
1a0799a8f   Frederic Weisbecker   tracing/function-...
99
  static struct trace_array *graph_array;
9005f3ebe   Frederic Weisbecker   tracing/function-...
100

ffeb80fc3   Jiri Olsa   tracing, function...
101
102
103
104
105
106
  /*
   * DURATION column is being also used to display IRQ signs,
   * following values are used by print_graph_irq and others
   * to fill in space into DURATION column.
   */
  enum {
6fc84ea70   Steven Rostedt (Red Hat)   tracing: Do not u...
107
108
109
  	FLAGS_FILL_FULL  = 1 << TRACE_GRAPH_PRINT_FILL_SHIFT,
  	FLAGS_FILL_START = 2 << TRACE_GRAPH_PRINT_FILL_SHIFT,
  	FLAGS_FILL_END   = 3 << TRACE_GRAPH_PRINT_FILL_SHIFT,
ffeb80fc3   Jiri Olsa   tracing, function...
110
  };
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
111
  static void
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
112
113
  print_graph_duration(struct trace_array *tr, unsigned long long duration,
  		     struct trace_seq *s, u32 flags);
fb52607af   Frederic Weisbecker   tracing/function-...
114

712406a6b   Steven Rostedt   tracing/function-...
115
  /* Add a function return address to the trace stack on thread info.*/
72c33b233   Steven Rostedt (VMware)   function_graph: M...
116
  static int
392374326   Steven Rostedt (VMware)   function_graph: U...
117
  ftrace_push_return_trace(unsigned long ret, unsigned long func,
9a7c348ba   Josh Poimboeuf   ftrace: Add retur...
118
  			 unsigned long frame_pointer, unsigned long *retp)
712406a6b   Steven Rostedt   tracing/function-...
119
  {
5d1a03dc5   Steven Rostedt   function-graph: m...
120
  	unsigned long long calltime;
712406a6b   Steven Rostedt   tracing/function-...
121
  	int index;
1b2f121c1   Steven Rostedt (Red Hat)   ftrace-graph: Rem...
122
123
  	if (unlikely(ftrace_graph_is_dead()))
  		return -EBUSY;
712406a6b   Steven Rostedt   tracing/function-...
124
125
  	if (!current->ret_stack)
  		return -EBUSY;
82310a327   Steven Rostedt   function-graph: e...
126
127
128
129
130
  	/*
  	 * We must make sure the ret_stack is tested before we read
  	 * anything else.
  	 */
  	smp_rmb();
712406a6b   Steven Rostedt   tracing/function-...
131
132
133
134
135
  	/* The return trace stack is full */
  	if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
  		atomic_inc(&current->trace_overrun);
  		return -EBUSY;
  	}
29ad23b00   Namhyung Kim   ftrace: Add set_g...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  	/*
  	 * The curr_ret_stack is an index to ftrace return stack of
  	 * current task.  Its value should be in [0, FTRACE_RETFUNC_
  	 * DEPTH) when the function graph tracer is used.  To support
  	 * filtering out specific functions, it makes the index
  	 * negative by subtracting huge value (FTRACE_NOTRACE_DEPTH)
  	 * so when it sees a negative index the ftrace will ignore
  	 * the record.  And the index gets recovered when returning
  	 * from the filtered function by adding the FTRACE_NOTRACE_
  	 * DEPTH and then it'll continue to record functions normally.
  	 *
  	 * The curr_ret_stack is initialized to -1 and get increased
  	 * in this function.  So it can be less than -1 only if it was
  	 * filtered out via ftrace_graph_notrace_addr() which can be
8434dc934   Steven Rostedt (Red Hat)   tracing: Convert ...
150
  	 * set from set_graph_notrace file in tracefs by user.
29ad23b00   Namhyung Kim   ftrace: Add set_g...
151
152
153
  	 */
  	if (current->curr_ret_stack < -1)
  		return -EBUSY;
5d1a03dc5   Steven Rostedt   function-graph: m...
154
  	calltime = trace_clock_local();
712406a6b   Steven Rostedt   tracing/function-...
155
  	index = ++current->curr_ret_stack;
29ad23b00   Namhyung Kim   ftrace: Add set_g...
156
157
  	if (ftrace_graph_notrace_addr(func))
  		current->curr_ret_stack -= FTRACE_NOTRACE_DEPTH;
712406a6b   Steven Rostedt   tracing/function-...
158
159
160
  	barrier();
  	current->ret_stack[index].ret = ret;
  	current->ret_stack[index].func = func;
5d1a03dc5   Steven Rostedt   function-graph: m...
161
  	current->ret_stack[index].calltime = calltime;
daa460a88   Josh Poimboeuf   ftrace: Only allo...
162
  #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
71e308a23   Steven Rostedt   function-graph: a...
163
  	current->ret_stack[index].fp = frame_pointer;
daa460a88   Josh Poimboeuf   ftrace: Only allo...
164
  #endif
9a7c348ba   Josh Poimboeuf   ftrace: Add retur...
165
166
167
  #ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
  	current->ret_stack[index].retp = retp;
  #endif
712406a6b   Steven Rostedt   tracing/function-...
168
169
  	return 0;
  }
67d7bec3f   Steven Rostedt (VMware)   function_graph: C...
170
171
172
173
174
175
  int function_graph_enter(unsigned long ret, unsigned long func,
  			 unsigned long frame_pointer, unsigned long *retp)
  {
  	struct ftrace_graph_ent trace;
  
  	trace.func = func;
392374326   Steven Rostedt (VMware)   function_graph: U...
176
  	trace.depth = ++current->curr_ret_depth;
67d7bec3f   Steven Rostedt (VMware)   function_graph: C...
177

392374326   Steven Rostedt (VMware)   function_graph: U...
178
179
180
  	if (ftrace_push_return_trace(ret, func,
  				     frame_pointer, retp))
  		goto out;
a22ff9df7   Steven Rostedt (VMware)   function_graph: R...
181
182
183
  	/* Only trace if the calling function expects to */
  	if (!ftrace_graph_entry(&trace))
  		goto out_ret;
392374326   Steven Rostedt (VMware)   function_graph: U...
184
  	return 0;
a22ff9df7   Steven Rostedt (VMware)   function_graph: R...
185
186
   out_ret:
  	current->curr_ret_stack--;
392374326   Steven Rostedt (VMware)   function_graph: U...
187
188
189
   out:
  	current->curr_ret_depth--;
  	return -EBUSY;
67d7bec3f   Steven Rostedt (VMware)   function_graph: C...
190
  }
712406a6b   Steven Rostedt   tracing/function-...
191
  /* Retrieve a function return address to the trace stack on thread info.*/
a2a16d6a3   Steven Rostedt   function-graph: a...
192
  static void
71e308a23   Steven Rostedt   function-graph: a...
193
194
  ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,
  			unsigned long frame_pointer)
712406a6b   Steven Rostedt   tracing/function-...
195
196
197
198
  {
  	int index;
  
  	index = current->curr_ret_stack;
29ad23b00   Namhyung Kim   ftrace: Add set_g...
199
200
201
202
203
204
205
206
207
208
209
  	/*
  	 * A negative index here means that it's just returned from a
  	 * notrace'd function.  Recover index to get an original
  	 * return address.  See ftrace_push_return_trace().
  	 *
  	 * TODO: Need to check whether the stack gets corrupted.
  	 */
  	if (index < 0)
  		index += FTRACE_NOTRACE_DEPTH;
  
  	if (unlikely(index < 0 || index >= FTRACE_RETFUNC_DEPTH)) {
712406a6b   Steven Rostedt   tracing/function-...
210
211
212
213
214
215
  		ftrace_graph_stop();
  		WARN_ON(1);
  		/* Might as well panic, otherwise we have no where to go */
  		*ret = (unsigned long)panic;
  		return;
  	}
e4a744ef2   Josh Poimboeuf   ftrace: Remove CO...
216
  #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
71e308a23   Steven Rostedt   function-graph: a...
217
218
219
220
221
222
223
224
225
226
  	/*
  	 * The arch may choose to record the frame pointer used
  	 * and check it here to make sure that it is what we expect it
  	 * to be. If gcc does not set the place holder of the return
  	 * address in the frame pointer, and does a copy instead, then
  	 * the function graph trace will fail. This test detects this
  	 * case.
  	 *
  	 * Currently, x86_32 with optimize for size (-Os) makes the latest
  	 * gcc do the above.
781d06248   Steven Rostedt   ftrace: Do not te...
227
228
229
  	 *
  	 * Note, -mfentry does not use frame pointers, and this test
  	 *  is not needed if CC_USING_FENTRY is set.
71e308a23   Steven Rostedt   function-graph: a...
230
231
232
233
234
  	 */
  	if (unlikely(current->ret_stack[index].fp != frame_pointer)) {
  		ftrace_graph_stop();
  		WARN(1, "Bad frame pointer: expected %lx, received %lx
  "
b375a11a2   Steven Rostedt   tracing: switch f...
235
236
  		     "  from func %ps return to %lx
  ",
71e308a23   Steven Rostedt   function-graph: a...
237
238
239
240
241
242
243
244
  		     current->ret_stack[index].fp,
  		     frame_pointer,
  		     (void *)current->ret_stack[index].func,
  		     current->ret_stack[index].ret);
  		*ret = (unsigned long)panic;
  		return;
  	}
  #endif
712406a6b   Steven Rostedt   tracing/function-...
245
246
247
248
  	*ret = current->ret_stack[index].ret;
  	trace->func = current->ret_stack[index].func;
  	trace->calltime = current->ret_stack[index].calltime;
  	trace->overrun = atomic_read(&current->trace_overrun);
d2bcf809e   Steven Rostedt (VMware)   function_graph: M...
249
250
251
252
253
254
255
  	trace->depth = current->curr_ret_depth--;
  	/*
  	 * We still want to trace interrupts coming in if
  	 * max_depth is set to 1. Make sure the decrement is
  	 * seen before ftrace_graph_return.
  	 */
  	barrier();
712406a6b   Steven Rostedt   tracing/function-...
256
257
258
259
260
261
  }
  
  /*
   * Send the trace to the ring-buffer.
   * @return the original return address.
   */
71e308a23   Steven Rostedt   function-graph: a...
262
  unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
712406a6b   Steven Rostedt   tracing/function-...
263
264
265
  {
  	struct ftrace_graph_ret trace;
  	unsigned long ret;
71e308a23   Steven Rostedt   function-graph: a...
266
  	ftrace_pop_return_trace(&trace, &ret, frame_pointer);
0012693ad   Frederic Weisbecker   tracing/function-...
267
  	trace.rettime = trace_clock_local();
d2bcf809e   Steven Rostedt (VMware)   function_graph: M...
268
269
270
271
272
273
  	ftrace_graph_return(&trace);
  	/*
  	 * The ftrace_graph_return() may still access the current
  	 * ret_stack structure, we need to make sure the update of
  	 * curr_ret_stack is after that.
  	 */
a2a16d6a3   Steven Rostedt   function-graph: a...
274
275
  	barrier();
  	current->curr_ret_stack--;
29ad23b00   Namhyung Kim   ftrace: Add set_g...
276
277
278
279
280
281
282
283
284
  	/*
  	 * The curr_ret_stack can be less than -1 only if it was
  	 * filtered out and it's about to return from the function.
  	 * Recover the index and continue to trace normal functions.
  	 */
  	if (current->curr_ret_stack < -1) {
  		current->curr_ret_stack += FTRACE_NOTRACE_DEPTH;
  		return ret;
  	}
712406a6b   Steven Rostedt   tracing/function-...
285
286
287
288
289
290
291
292
293
294
  
  	if (unlikely(!ret)) {
  		ftrace_graph_stop();
  		WARN_ON(1);
  		/* Might as well panic. What else to do? */
  		ret = (unsigned long)panic;
  	}
  
  	return ret;
  }
223918e32   Josh Poimboeuf   ftrace: Add ftrac...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  /**
   * ftrace_graph_ret_addr - convert a potentially modified stack return address
   *			   to its original value
   *
   * This function can be called by stack unwinding code to convert a found stack
   * return address ('ret') to its original value, in case the function graph
   * tracer has modified it to be 'return_to_handler'.  If the address hasn't
   * been modified, the unchanged value of 'ret' is returned.
   *
   * 'idx' is a state variable which should be initialized by the caller to zero
   * before the first call.
   *
   * 'retp' is a pointer to the return address on the stack.  It's ignored if
   * the arch doesn't have HAVE_FUNCTION_GRAPH_RET_ADDR_PTR defined.
   */
  #ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
  unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
  				    unsigned long ret, unsigned long *retp)
  {
  	int index = task->curr_ret_stack;
  	int i;
  
  	if (ret != (unsigned long)return_to_handler)
  		return ret;
  
  	if (index < -1)
  		index += FTRACE_NOTRACE_DEPTH;
  
  	if (index < 0)
  		return ret;
  
  	for (i = 0; i <= index; i++)
  		if (task->ret_stack[i].retp == retp)
  			return task->ret_stack[i].ret;
  
  	return ret;
  }
  #else /* !HAVE_FUNCTION_GRAPH_RET_ADDR_PTR */
  unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
  				    unsigned long ret, unsigned long *retp)
  {
  	int task_idx;
  
  	if (ret != (unsigned long)return_to_handler)
  		return ret;
  
  	task_idx = task->curr_ret_stack;
  
  	if (!task->ret_stack || task_idx < *idx)
  		return ret;
  
  	task_idx -= *idx;
  	(*idx)++;
  
  	return task->ret_stack[task_idx].ret;
  }
  #endif /* HAVE_FUNCTION_GRAPH_RET_ADDR_PTR */
62b915f10   Jiri Olsa   tracing: Add grap...
352
  int __trace_graph_entry(struct trace_array *tr,
1a0799a8f   Frederic Weisbecker   tracing/function-...
353
354
355
356
  				struct ftrace_graph_ent *trace,
  				unsigned long flags,
  				int pc)
  {
2425bcb92   Steven Rostedt (Red Hat)   tracing: Rename f...
357
  	struct trace_event_call *call = &event_funcgraph_entry;
1a0799a8f   Frederic Weisbecker   tracing/function-...
358
  	struct ring_buffer_event *event;
12883efb6   Steven Rostedt (Red Hat)   tracing: Consolid...
359
  	struct ring_buffer *buffer = tr->trace_buffer.buffer;
1a0799a8f   Frederic Weisbecker   tracing/function-...
360
  	struct ftrace_graph_ent_entry *entry;
e77405ad8   Steven Rostedt   tracing: pass aro...
361
  	event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT,
1a0799a8f   Frederic Weisbecker   tracing/function-...
362
363
364
365
366
  					  sizeof(*entry), flags, pc);
  	if (!event)
  		return 0;
  	entry	= ring_buffer_event_data(event);
  	entry->graph_ent			= *trace;
f306cc82a   Tom Zanussi   tracing: Update e...
367
  	if (!call_filter_check_discard(call, entry, buffer, event))
52ffabe38   Steven Rostedt (Red Hat)   tracing: Make __b...
368
  		trace_buffer_unlock_commit_nostack(buffer, event);
1a0799a8f   Frederic Weisbecker   tracing/function-...
369
370
371
  
  	return 1;
  }
b304d0441   Steven Rostedt   tracing: Do not t...
372
373
  static inline int ftrace_graph_ignore_irqs(void)
  {
e4a3f541f   Steven Rostedt   tracing: Still tr...
374
  	if (!ftrace_graph_skip_irqs || trace_recursion_test(TRACE_IRQ_BIT))
b304d0441   Steven Rostedt   tracing: Do not t...
375
376
377
378
  		return 0;
  
  	return in_irq();
  }
1a0799a8f   Frederic Weisbecker   tracing/function-...
379
380
381
382
383
384
385
386
387
  int trace_graph_entry(struct ftrace_graph_ent *trace)
  {
  	struct trace_array *tr = graph_array;
  	struct trace_array_cpu *data;
  	unsigned long flags;
  	long disabled;
  	int ret;
  	int cpu;
  	int pc;
345ddcc88   Steven Rostedt (Red Hat)   ftrace: Have set_...
388
  	if (!ftrace_trace_task(tr))
1a0799a8f   Frederic Weisbecker   tracing/function-...
389
  		return 0;
1a4144286   Steven Rostedt (Red Hat)   tracing/fgraph: H...
390
391
392
393
  	if (ftrace_graph_ignore_func(trace))
  		return 0;
  
  	if (ftrace_graph_ignore_irqs())
1a0799a8f   Frederic Weisbecker   tracing/function-...
394
  		return 0;
29ad23b00   Namhyung Kim   ftrace: Add set_g...
395
396
397
398
399
400
401
402
403
  	/*
  	 * Do not trace a function if it's filtered by set_graph_notrace.
  	 * Make the index of ret stack negative to indicate that it should
  	 * ignore further functions.  But it needs its own ret stack entry
  	 * to recover the original index in order to continue tracing after
  	 * returning from the function.
  	 */
  	if (ftrace_graph_notrace_addr(trace->func))
  		return 1;
7fa8b7171   Joel Fernandes   tracing/function_...
404
405
406
407
408
409
  	/*
  	 * Stop here if tracing_threshold is set. We only write function return
  	 * events to the ring buffer.
  	 */
  	if (tracing_thresh)
  		return 1;
1a0799a8f   Frederic Weisbecker   tracing/function-...
410
411
  	local_irq_save(flags);
  	cpu = raw_smp_processor_id();
12883efb6   Steven Rostedt (Red Hat)   tracing: Consolid...
412
  	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
1a0799a8f   Frederic Weisbecker   tracing/function-...
413
414
415
416
417
418
419
  	disabled = atomic_inc_return(&data->disabled);
  	if (likely(disabled == 1)) {
  		pc = preempt_count();
  		ret = __trace_graph_entry(tr, trace, flags, pc);
  	} else {
  		ret = 0;
  	}
1a0799a8f   Frederic Weisbecker   tracing/function-...
420
421
422
423
424
425
  
  	atomic_dec(&data->disabled);
  	local_irq_restore(flags);
  
  	return ret;
  }
0a772620a   Jiri Olsa   tracing: Make gra...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
  static void
  __trace_graph_function(struct trace_array *tr,
  		unsigned long ip, unsigned long flags, int pc)
  {
  	u64 time = trace_clock_local();
  	struct ftrace_graph_ent ent = {
  		.func  = ip,
  		.depth = 0,
  	};
  	struct ftrace_graph_ret ret = {
  		.func     = ip,
  		.depth    = 0,
  		.calltime = time,
  		.rettime  = time,
  	};
  
  	__trace_graph_entry(tr, &ent, flags, pc);
  	__trace_graph_return(tr, &ret, flags, pc);
  }
  
  void
  trace_graph_function(struct trace_array *tr,
  		unsigned long ip, unsigned long parent_ip,
  		unsigned long flags, int pc)
  {
0a772620a   Jiri Olsa   tracing: Make gra...
451
452
  	__trace_graph_function(tr, ip, flags, pc);
  }
62b915f10   Jiri Olsa   tracing: Add grap...
453
  void __trace_graph_return(struct trace_array *tr,
1a0799a8f   Frederic Weisbecker   tracing/function-...
454
455
456
457
  				struct ftrace_graph_ret *trace,
  				unsigned long flags,
  				int pc)
  {
2425bcb92   Steven Rostedt (Red Hat)   tracing: Rename f...
458
  	struct trace_event_call *call = &event_funcgraph_exit;
1a0799a8f   Frederic Weisbecker   tracing/function-...
459
  	struct ring_buffer_event *event;
12883efb6   Steven Rostedt (Red Hat)   tracing: Consolid...
460
  	struct ring_buffer *buffer = tr->trace_buffer.buffer;
1a0799a8f   Frederic Weisbecker   tracing/function-...
461
  	struct ftrace_graph_ret_entry *entry;
e77405ad8   Steven Rostedt   tracing: pass aro...
462
  	event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET,
1a0799a8f   Frederic Weisbecker   tracing/function-...
463
464
465
466
467
  					  sizeof(*entry), flags, pc);
  	if (!event)
  		return;
  	entry	= ring_buffer_event_data(event);
  	entry->ret				= *trace;
f306cc82a   Tom Zanussi   tracing: Update e...
468
  	if (!call_filter_check_discard(call, entry, buffer, event))
52ffabe38   Steven Rostedt (Red Hat)   tracing: Make __b...
469
  		trace_buffer_unlock_commit_nostack(buffer, event);
1a0799a8f   Frederic Weisbecker   tracing/function-...
470
471
472
473
474
475
476
477
478
479
  }
  
  void trace_graph_return(struct ftrace_graph_ret *trace)
  {
  	struct trace_array *tr = graph_array;
  	struct trace_array_cpu *data;
  	unsigned long flags;
  	long disabled;
  	int cpu;
  	int pc;
81f966235   Steven Rostedt (VMware)   tracing/fgraph: F...
480
  	ftrace_graph_addr_finish(trace);
1a0799a8f   Frederic Weisbecker   tracing/function-...
481
482
  	local_irq_save(flags);
  	cpu = raw_smp_processor_id();
12883efb6   Steven Rostedt (Red Hat)   tracing: Consolid...
483
  	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
1a0799a8f   Frederic Weisbecker   tracing/function-...
484
485
486
487
488
  	disabled = atomic_inc_return(&data->disabled);
  	if (likely(disabled == 1)) {
  		pc = preempt_count();
  		__trace_graph_return(tr, trace, flags, pc);
  	}
1a0799a8f   Frederic Weisbecker   tracing/function-...
489
490
491
  	atomic_dec(&data->disabled);
  	local_irq_restore(flags);
  }
24a53652e   Frederic Weisbecker   tracing: Drop the...
492
493
494
495
496
497
498
499
  void set_graph_array(struct trace_array *tr)
  {
  	graph_array = tr;
  
  	/* Make graph_array visible before we start tracing */
  
  	smp_mb();
  }
ba1afef6a   Steven Rostedt (Red Hat)   tracing: Convert ...
500
  static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
0e9501735   Tim Bird   function-graph: A...
501
  {
81f966235   Steven Rostedt (VMware)   tracing/fgraph: F...
502
  	ftrace_graph_addr_finish(trace);
0e9501735   Tim Bird   function-graph: A...
503
504
505
506
507
508
  	if (tracing_thresh &&
  	    (trace->rettime - trace->calltime < tracing_thresh))
  		return;
  	else
  		trace_graph_return(trace);
  }
fb52607af   Frederic Weisbecker   tracing/function-...
509
510
  static int graph_trace_init(struct trace_array *tr)
  {
1a0799a8f   Frederic Weisbecker   tracing/function-...
511
  	int ret;
24a53652e   Frederic Weisbecker   tracing: Drop the...
512
  	set_graph_array(tr);
0e9501735   Tim Bird   function-graph: A...
513
514
  	if (tracing_thresh)
  		ret = register_ftrace_graph(&trace_graph_thresh_return,
7fa8b7171   Joel Fernandes   tracing/function_...
515
  					    &trace_graph_entry);
0e9501735   Tim Bird   function-graph: A...
516
517
518
  	else
  		ret = register_ftrace_graph(&trace_graph_return,
  					    &trace_graph_entry);
660c7f9be   Steven Rostedt   ftrace: add threa...
519
520
521
522
523
  	if (ret)
  		return ret;
  	tracing_start_cmdline_record();
  
  	return 0;
fb52607af   Frederic Weisbecker   tracing/function-...
524
525
526
527
  }
  
  static void graph_trace_reset(struct trace_array *tr)
  {
660c7f9be   Steven Rostedt   ftrace: add threa...
528
529
  	tracing_stop_cmdline_record();
  	unregister_ftrace_graph();
fb52607af   Frederic Weisbecker   tracing/function-...
530
  }
ba1afef6a   Steven Rostedt (Red Hat)   tracing: Convert ...
531
  static int graph_trace_update_thresh(struct trace_array *tr)
6508fa761   Stanislav Fomichev   tracing: let user...
532
533
534
535
  {
  	graph_trace_reset(tr);
  	return graph_trace_init(tr);
  }
0c9e6f639   Lai Jiangshan   tracing: Simplify...
536
  static int max_bytes_for_cpu;
1a056155e   Frederic Weisbecker   tracing/function-...
537

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
538
  static void print_graph_cpu(struct trace_seq *s, int cpu)
1a056155e   Frederic Weisbecker   tracing/function-...
539
  {
d51090b34   Ingo Molnar   tracing/function-...
540
541
542
543
544
  	/*
  	 * Start with a space character - to make it stand out
  	 * to the right a bit when trace output is pasted into
  	 * email:
  	 */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
545
  	trace_seq_printf(s, " %*d) ", max_bytes_for_cpu, cpu);
1a056155e   Frederic Weisbecker   tracing/function-...
546
  }
11e84acc4   Frederic Weisbecker   tracing/function-...
547
  #define TRACE_GRAPH_PROCINFO_LENGTH	14
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
548
  static void print_graph_proc(struct trace_seq *s, pid_t pid)
11e84acc4   Frederic Weisbecker   tracing/function-...
549
  {
4ca530852   Steven Rostedt   tracing: protect ...
550
  	char comm[TASK_COMM_LEN];
11e84acc4   Frederic Weisbecker   tracing/function-...
551
552
  	/* sign + log10(MAX_INT) + '\0' */
  	char pid_str[11];
4ca530852   Steven Rostedt   tracing: protect ...
553
  	int spaces = 0;
4ca530852   Steven Rostedt   tracing: protect ...
554
555
  	int len;
  	int i;
11e84acc4   Frederic Weisbecker   tracing/function-...
556

4ca530852   Steven Rostedt   tracing: protect ...
557
  	trace_find_cmdline(pid, comm);
11e84acc4   Frederic Weisbecker   tracing/function-...
558
559
560
561
562
563
564
565
566
567
  	comm[7] = '\0';
  	sprintf(pid_str, "%d", pid);
  
  	/* 1 stands for the "-" character */
  	len = strlen(comm) + strlen(pid_str) + 1;
  
  	if (len < TRACE_GRAPH_PROCINFO_LENGTH)
  		spaces = TRACE_GRAPH_PROCINFO_LENGTH - len;
  
  	/* First spaces to align center */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
568
569
  	for (i = 0; i < spaces / 2; i++)
  		trace_seq_putc(s, ' ');
11e84acc4   Frederic Weisbecker   tracing/function-...
570

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
571
  	trace_seq_printf(s, "%s-%s", comm, pid_str);
11e84acc4   Frederic Weisbecker   tracing/function-...
572
573
  
  	/* Last spaces to align center */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
574
575
  	for (i = 0; i < spaces - (spaces / 2); i++)
  		trace_seq_putc(s, ' ');
11e84acc4   Frederic Weisbecker   tracing/function-...
576
  }
1a056155e   Frederic Weisbecker   tracing/function-...
577

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
578
  static void print_graph_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
49ff59039   Steven Rostedt   tracing: add late...
579
  {
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
580
581
  	trace_seq_putc(s, ' ');
  	trace_print_lat_fmt(s, entry);
49ff59039   Steven Rostedt   tracing: add late...
582
  }
287b6e68c   Frederic Weisbecker   tracing/function-...
583
  /* If the pid changed since the last trace, output this event */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
584
  static void
2fbcdb35a   Steven Rostedt   function-graph: c...
585
  verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data)
287b6e68c   Frederic Weisbecker   tracing/function-...
586
  {
d51090b34   Ingo Molnar   tracing/function-...
587
  	pid_t prev_pid;
9005f3ebe   Frederic Weisbecker   tracing/function-...
588
  	pid_t *last_pid;
660c7f9be   Steven Rostedt   ftrace: add threa...
589

2fbcdb35a   Steven Rostedt   function-graph: c...
590
  	if (!data)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
591
  		return;
9005f3ebe   Frederic Weisbecker   tracing/function-...
592

be1eca393   Jiri Olsa   tracing: Fix func...
593
  	last_pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
9005f3ebe   Frederic Weisbecker   tracing/function-...
594
595
  
  	if (*last_pid == pid)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
596
  		return;
fb52607af   Frederic Weisbecker   tracing/function-...
597

9005f3ebe   Frederic Weisbecker   tracing/function-...
598
599
  	prev_pid = *last_pid;
  	*last_pid = pid;
d51090b34   Ingo Molnar   tracing/function-...
600

9005f3ebe   Frederic Weisbecker   tracing/function-...
601
  	if (prev_pid == -1)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
602
  		return;
d51090b34   Ingo Molnar   tracing/function-...
603
604
605
606
607
608
609
610
  /*
   * Context-switch trace line:
  
   ------------------------------------------
   | 1)  migration/0--1  =>  sshd-1755
   ------------------------------------------
  
   */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
611
612
613
614
615
616
617
618
619
620
  	trace_seq_puts(s, " ------------------------------------------
  ");
  	print_graph_cpu(s, cpu);
  	print_graph_proc(s, prev_pid);
  	trace_seq_puts(s, " => ");
  	print_graph_proc(s, pid);
  	trace_seq_puts(s, "
   ------------------------------------------
  
  ");
287b6e68c   Frederic Weisbecker   tracing/function-...
621
  }
b91facc36   Frederic Weisbecker   tracing/function-...
622
623
  static struct ftrace_graph_ret_entry *
  get_return_for_leaf(struct trace_iterator *iter,
83a8df618   Frederic Weisbecker   tracing/function-...
624
625
  		struct ftrace_graph_ent_entry *curr)
  {
be1eca393   Jiri Olsa   tracing: Fix func...
626
627
  	struct fgraph_data *data = iter->private;
  	struct ring_buffer_iter *ring_iter = NULL;
83a8df618   Frederic Weisbecker   tracing/function-...
628
629
  	struct ring_buffer_event *event;
  	struct ftrace_graph_ret_entry *next;
be1eca393   Jiri Olsa   tracing: Fix func...
630
631
632
633
634
635
636
637
  	/*
  	 * If the previous output failed to write to the seq buffer,
  	 * then we just reuse the data from before.
  	 */
  	if (data && data->failed) {
  		curr = &data->ent;
  		next = &data->ret;
  	} else {
83a8df618   Frederic Weisbecker   tracing/function-...
638

6d158a813   Steven Rostedt   tracing: Remove N...
639
  		ring_iter = trace_buffer_iter(iter, iter->cpu);
be1eca393   Jiri Olsa   tracing: Fix func...
640
641
642
643
644
645
646
647
648
  
  		/* First peek to compare current entry and the next one */
  		if (ring_iter)
  			event = ring_buffer_iter_peek(ring_iter, NULL);
  		else {
  			/*
  			 * We need to consume the current entry to see
  			 * the next one.
  			 */
12883efb6   Steven Rostedt (Red Hat)   tracing: Consolid...
649
  			ring_buffer_consume(iter->trace_buffer->buffer, iter->cpu,
66a8cb95e   Steven Rostedt   ring-buffer: Add ...
650
  					    NULL, NULL);
12883efb6   Steven Rostedt (Red Hat)   tracing: Consolid...
651
  			event = ring_buffer_peek(iter->trace_buffer->buffer, iter->cpu,
66a8cb95e   Steven Rostedt   ring-buffer: Add ...
652
  						 NULL, NULL);
be1eca393   Jiri Olsa   tracing: Fix func...
653
  		}
83a8df618   Frederic Weisbecker   tracing/function-...
654

be1eca393   Jiri Olsa   tracing: Fix func...
655
656
657
658
  		if (!event)
  			return NULL;
  
  		next = ring_buffer_event_data(event);
83a8df618   Frederic Weisbecker   tracing/function-...
659

be1eca393   Jiri Olsa   tracing: Fix func...
660
661
662
663
664
665
  		if (data) {
  			/*
  			 * Save current and next entries for later reference
  			 * if the output fails.
  			 */
  			data->ent = *curr;
575570f02   Shaohua Li   tracing: Fix an u...
666
667
668
669
670
671
672
673
674
  			/*
  			 * If the next event is not a return type, then
  			 * we only care about what type it is. Otherwise we can
  			 * safely copy the entire event.
  			 */
  			if (next->ent.type == TRACE_GRAPH_RET)
  				data->ret = *next;
  			else
  				data->ret.ent.type = next->ent.type;
be1eca393   Jiri Olsa   tracing: Fix func...
675
676
  		}
  	}
83a8df618   Frederic Weisbecker   tracing/function-...
677
678
  
  	if (next->ent.type != TRACE_GRAPH_RET)
b91facc36   Frederic Weisbecker   tracing/function-...
679
  		return NULL;
83a8df618   Frederic Weisbecker   tracing/function-...
680
681
682
  
  	if (curr->ent.pid != next->ent.pid ||
  			curr->graph_ent.func != next->ret.func)
b91facc36   Frederic Weisbecker   tracing/function-...
683
  		return NULL;
83a8df618   Frederic Weisbecker   tracing/function-...
684

b91facc36   Frederic Weisbecker   tracing/function-...
685
686
687
688
689
  	/* this is a leaf, now advance the iterator */
  	if (ring_iter)
  		ring_buffer_read(ring_iter, NULL);
  
  	return next;
83a8df618   Frederic Weisbecker   tracing/function-...
690
  }
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
691
  static void print_graph_abs_time(u64 t, struct trace_seq *s)
d1f9cbd78   Frederic Weisbecker   tracing/function-...
692
693
694
695
696
  {
  	unsigned long usecs_rem;
  
  	usecs_rem = do_div(t, NSEC_PER_SEC);
  	usecs_rem /= 1000;
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
697
698
  	trace_seq_printf(s, "%5lu.%06lu |  ",
  			 (unsigned long)t, usecs_rem);
d1f9cbd78   Frederic Weisbecker   tracing/function-...
699
  }
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
700
  static void
d1f9cbd78   Frederic Weisbecker   tracing/function-...
701
  print_graph_irq(struct trace_iterator *iter, unsigned long addr,
d7a8d9e90   Jiri Olsa   tracing: Have gra...
702
  		enum trace_type type, int cpu, pid_t pid, u32 flags)
f8b755ac8   Frederic Weisbecker   tracing/function-...
703
  {
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
704
  	struct trace_array *tr = iter->tr;
d1f9cbd78   Frederic Weisbecker   tracing/function-...
705
  	struct trace_seq *s = &iter->seq;
678f845ed   Daniel Bristot de Oliveira   ftrace-graph: sho...
706
  	struct trace_entry *ent = iter->ent;
f8b755ac8   Frederic Weisbecker   tracing/function-...
707
708
709
  
  	if (addr < (unsigned long)__irqentry_text_start ||
  		addr >= (unsigned long)__irqentry_text_end)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
710
  		return;
f8b755ac8   Frederic Weisbecker   tracing/function-...
711

983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
712
  	if (tr->trace_flags & TRACE_ITER_CONTEXT_INFO) {
749230b06   Jiri Olsa   tracing, function...
713
  		/* Absolute time */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
714
715
  		if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
  			print_graph_abs_time(iter->ts, s);
d1f9cbd78   Frederic Weisbecker   tracing/function-...
716

749230b06   Jiri Olsa   tracing, function...
717
  		/* Cpu */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
718
719
  		if (flags & TRACE_GRAPH_PRINT_CPU)
  			print_graph_cpu(s, cpu);
49ff59039   Steven Rostedt   tracing: add late...
720

749230b06   Jiri Olsa   tracing, function...
721
722
  		/* Proc */
  		if (flags & TRACE_GRAPH_PRINT_PROC) {
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
723
724
  			print_graph_proc(s, pid);
  			trace_seq_puts(s, " | ");
749230b06   Jiri Olsa   tracing, function...
725
  		}
678f845ed   Daniel Bristot de Oliveira   ftrace-graph: sho...
726
727
  
  		/* Latency format */
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
728
  		if (tr->trace_flags & TRACE_ITER_LATENCY_FMT)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
729
  			print_graph_lat_fmt(s, ent);
9005f3ebe   Frederic Weisbecker   tracing/function-...
730
  	}
f8b755ac8   Frederic Weisbecker   tracing/function-...
731

9005f3ebe   Frederic Weisbecker   tracing/function-...
732
  	/* No overhead */
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
733
  	print_graph_duration(tr, 0, s, flags | FLAGS_FILL_START);
f8b755ac8   Frederic Weisbecker   tracing/function-...
734

9005f3ebe   Frederic Weisbecker   tracing/function-...
735
  	if (type == TRACE_GRAPH_ENT)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
736
  		trace_seq_puts(s, "==========>");
9005f3ebe   Frederic Weisbecker   tracing/function-...
737
  	else
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
738
  		trace_seq_puts(s, "<==========");
9005f3ebe   Frederic Weisbecker   tracing/function-...
739

983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
740
  	print_graph_duration(tr, 0, s, flags | FLAGS_FILL_END);
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
741
742
  	trace_seq_putc(s, '
  ');
f8b755ac8   Frederic Weisbecker   tracing/function-...
743
  }
83a8df618   Frederic Weisbecker   tracing/function-...
744

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
745
  void
0706f1c48   Steven Rostedt   tracing: adding f...
746
  trace_print_graph_duration(unsigned long long duration, struct trace_seq *s)
83a8df618   Frederic Weisbecker   tracing/function-...
747
748
  {
  	unsigned long nsecs_rem = do_div(duration, 1000);
166d3c799   Frederic Weisbecker   tracing/function-...
749
  	/* log10(ULONG_MAX) + '\0' */
4526d0676   Byungchul Park   function_graph: F...
750
  	char usecs_str[21];
166d3c799   Frederic Weisbecker   tracing/function-...
751
  	char nsecs_str[5];
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
752
  	int len;
166d3c799   Frederic Weisbecker   tracing/function-...
753
  	int i;
4526d0676   Byungchul Park   function_graph: F...
754
  	sprintf(usecs_str, "%lu", (unsigned long) duration);
166d3c799   Frederic Weisbecker   tracing/function-...
755
756
  
  	/* Print msecs */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
757
  	trace_seq_printf(s, "%s", usecs_str);
166d3c799   Frederic Weisbecker   tracing/function-...
758

4526d0676   Byungchul Park   function_graph: F...
759
  	len = strlen(usecs_str);
166d3c799   Frederic Weisbecker   tracing/function-...
760
761
762
  
  	/* Print nsecs (we don't want to exceed 7 numbers) */
  	if (len < 7) {
14cae9bd2   Borislav Petkov   tracing: Fix func...
763
764
765
  		size_t slen = min_t(size_t, sizeof(nsecs_str), 8UL - len);
  
  		snprintf(nsecs_str, slen, "%03lu", nsecs_rem);
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
766
  		trace_seq_printf(s, ".%s", nsecs_str);
82c355e81   Steven Rostedt (Red Hat)   ftrace: Fix funct...
767
  		len += strlen(nsecs_str) + 1;
166d3c799   Frederic Weisbecker   tracing/function-...
768
  	}
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
769
  	trace_seq_puts(s, " us ");
166d3c799   Frederic Weisbecker   tracing/function-...
770
771
  
  	/* Print remaining spaces to fit the row's width */
82c355e81   Steven Rostedt (Red Hat)   ftrace: Fix funct...
772
  	for (i = len; i < 8; i++)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
773
  		trace_seq_putc(s, ' ');
0706f1c48   Steven Rostedt   tracing: adding f...
774
  }
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
775
  static void
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
776
777
  print_graph_duration(struct trace_array *tr, unsigned long long duration,
  		     struct trace_seq *s, u32 flags)
0706f1c48   Steven Rostedt   tracing: adding f...
778
  {
749230b06   Jiri Olsa   tracing, function...
779
  	if (!(flags & TRACE_GRAPH_PRINT_DURATION) ||
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
780
  	    !(tr->trace_flags & TRACE_ITER_CONTEXT_INFO))
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
781
  		return;
ffeb80fc3   Jiri Olsa   tracing, function...
782
783
  
  	/* No real adata, just filling the column with spaces */
6fc84ea70   Steven Rostedt (Red Hat)   tracing: Do not u...
784
785
  	switch (flags & TRACE_GRAPH_PRINT_FILL_MASK) {
  	case FLAGS_FILL_FULL:
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
786
787
  		trace_seq_puts(s, "              |  ");
  		return;
6fc84ea70   Steven Rostedt (Red Hat)   tracing: Do not u...
788
  	case FLAGS_FILL_START:
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
789
790
  		trace_seq_puts(s, "  ");
  		return;
6fc84ea70   Steven Rostedt (Red Hat)   tracing: Do not u...
791
  	case FLAGS_FILL_END:
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
792
793
  		trace_seq_puts(s, " |");
  		return;
ffeb80fc3   Jiri Olsa   tracing, function...
794
795
796
  	}
  
  	/* Signal a overhead of time execution to the output */
8e1e1df29   Byungchul Park   tracing: Add addi...
797
798
799
  	if (flags & TRACE_GRAPH_PRINT_OVERHEAD)
  		trace_seq_printf(s, "%c ", trace_find_mark(duration));
  	else
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
800
  		trace_seq_puts(s, "  ");
0706f1c48   Steven Rostedt   tracing: adding f...
801

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
802
803
  	trace_print_graph_duration(duration, s);
  	trace_seq_puts(s, "|  ");
83a8df618   Frederic Weisbecker   tracing/function-...
804
  }
83a8df618   Frederic Weisbecker   tracing/function-...
805
  /* Case of a leaf function on its call entry */
287b6e68c   Frederic Weisbecker   tracing/function-...
806
  static enum print_line_t
83a8df618   Frederic Weisbecker   tracing/function-...
807
  print_graph_entry_leaf(struct trace_iterator *iter,
b91facc36   Frederic Weisbecker   tracing/function-...
808
  		struct ftrace_graph_ent_entry *entry,
d7a8d9e90   Jiri Olsa   tracing: Have gra...
809
810
  		struct ftrace_graph_ret_entry *ret_entry,
  		struct trace_seq *s, u32 flags)
fb52607af   Frederic Weisbecker   tracing/function-...
811
  {
2fbcdb35a   Steven Rostedt   function-graph: c...
812
  	struct fgraph_data *data = iter->private;
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
813
  	struct trace_array *tr = iter->tr;
83a8df618   Frederic Weisbecker   tracing/function-...
814
  	struct ftrace_graph_ret *graph_ret;
83a8df618   Frederic Weisbecker   tracing/function-...
815
816
  	struct ftrace_graph_ent *call;
  	unsigned long long duration;
1fe4293f4   Changbin Du   tracing: Fix miss...
817
  	int cpu = iter->cpu;
1a056155e   Frederic Weisbecker   tracing/function-...
818
  	int i;
fb52607af   Frederic Weisbecker   tracing/function-...
819

83a8df618   Frederic Weisbecker   tracing/function-...
820
821
822
  	graph_ret = &ret_entry->ret;
  	call = &entry->graph_ent;
  	duration = graph_ret->rettime - graph_ret->calltime;
2fbcdb35a   Steven Rostedt   function-graph: c...
823
  	if (data) {
f1c7f517a   Steven Rostedt   ftrace: Add funct...
824
  		struct fgraph_cpu_data *cpu_data;
f1c7f517a   Steven Rostedt   ftrace: Add funct...
825
826
  
  		cpu_data = per_cpu_ptr(data->cpu_data, cpu);
2fbcdb35a   Steven Rostedt   function-graph: c...
827

794de08a1   Steven Rostedt (Red Hat)   fgraph: Handle a ...
828
829
830
  		/* If a graph tracer ignored set_graph_notrace */
  		if (call->depth < -1)
  			call->depth += FTRACE_NOTRACE_DEPTH;
2fbcdb35a   Steven Rostedt   function-graph: c...
831
832
833
834
835
  		/*
  		 * Comments display at + 1 to depth. Since
  		 * this is a leaf function, keep the comments
  		 * equal to this depth.
  		 */
f1c7f517a   Steven Rostedt   ftrace: Add funct...
836
837
838
  		cpu_data->depth = call->depth - 1;
  
  		/* No need to keep this function around for this depth */
794de08a1   Steven Rostedt (Red Hat)   fgraph: Handle a ...
839
840
  		if (call->depth < FTRACE_RETFUNC_DEPTH &&
  		    !WARN_ON_ONCE(call->depth < 0))
f1c7f517a   Steven Rostedt   ftrace: Add funct...
841
  			cpu_data->enter_funcs[call->depth] = 0;
2fbcdb35a   Steven Rostedt   function-graph: c...
842
  	}
ffeb80fc3   Jiri Olsa   tracing, function...
843
  	/* Overhead and duration */
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
844
  	print_graph_duration(tr, duration, s, flags);
1a056155e   Frederic Weisbecker   tracing/function-...
845

83a8df618   Frederic Weisbecker   tracing/function-...
846
  	/* Function */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
847
848
  	for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++)
  		trace_seq_putc(s, ' ');
83a8df618   Frederic Weisbecker   tracing/function-...
849

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
850
851
  	trace_seq_printf(s, "%ps();
  ", (void *)call->func);
83a8df618   Frederic Weisbecker   tracing/function-...
852

1fe4293f4   Changbin Du   tracing: Fix miss...
853
854
  	print_graph_irq(iter, graph_ret->func, TRACE_GRAPH_RET,
  			cpu, iter->ent->pid, flags);
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
855
  	return trace_handle_return(s);
83a8df618   Frederic Weisbecker   tracing/function-...
856
857
858
  }
  
  static enum print_line_t
2fbcdb35a   Steven Rostedt   function-graph: c...
859
860
  print_graph_entry_nested(struct trace_iterator *iter,
  			 struct ftrace_graph_ent_entry *entry,
d7a8d9e90   Jiri Olsa   tracing: Have gra...
861
  			 struct trace_seq *s, int cpu, u32 flags)
83a8df618   Frederic Weisbecker   tracing/function-...
862
  {
83a8df618   Frederic Weisbecker   tracing/function-...
863
  	struct ftrace_graph_ent *call = &entry->graph_ent;
2fbcdb35a   Steven Rostedt   function-graph: c...
864
  	struct fgraph_data *data = iter->private;
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
865
  	struct trace_array *tr = iter->tr;
2fbcdb35a   Steven Rostedt   function-graph: c...
866
867
868
  	int i;
  
  	if (data) {
f1c7f517a   Steven Rostedt   ftrace: Add funct...
869
  		struct fgraph_cpu_data *cpu_data;
2fbcdb35a   Steven Rostedt   function-graph: c...
870
  		int cpu = iter->cpu;
2fbcdb35a   Steven Rostedt   function-graph: c...
871

794de08a1   Steven Rostedt (Red Hat)   fgraph: Handle a ...
872
873
874
  		/* If a graph tracer ignored set_graph_notrace */
  		if (call->depth < -1)
  			call->depth += FTRACE_NOTRACE_DEPTH;
f1c7f517a   Steven Rostedt   ftrace: Add funct...
875
876
877
878
  		cpu_data = per_cpu_ptr(data->cpu_data, cpu);
  		cpu_data->depth = call->depth;
  
  		/* Save this function pointer to see if the exit matches */
794de08a1   Steven Rostedt (Red Hat)   fgraph: Handle a ...
879
880
  		if (call->depth < FTRACE_RETFUNC_DEPTH &&
  		    !WARN_ON_ONCE(call->depth < 0))
f1c7f517a   Steven Rostedt   ftrace: Add funct...
881
  			cpu_data->enter_funcs[call->depth] = call->func;
2fbcdb35a   Steven Rostedt   function-graph: c...
882
  	}
83a8df618   Frederic Weisbecker   tracing/function-...
883

9005f3ebe   Frederic Weisbecker   tracing/function-...
884
  	/* No time */
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
885
  	print_graph_duration(tr, 0, s, flags | FLAGS_FILL_FULL);
f8b755ac8   Frederic Weisbecker   tracing/function-...
886

83a8df618   Frederic Weisbecker   tracing/function-...
887
  	/* Function */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
888
889
890
891
892
  	for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++)
  		trace_seq_putc(s, ' ');
  
  	trace_seq_printf(s, "%ps() {
  ", (void *)call->func);
287b6e68c   Frederic Weisbecker   tracing/function-...
893

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
894
  	if (trace_seq_has_overflowed(s))
83a8df618   Frederic Weisbecker   tracing/function-...
895
  		return TRACE_TYPE_PARTIAL_LINE;
b91facc36   Frederic Weisbecker   tracing/function-...
896
897
898
899
900
  	/*
  	 * we already consumed the current entry to check the next one
  	 * and see if this is a leaf.
  	 */
  	return TRACE_TYPE_NO_CONSUME;
287b6e68c   Frederic Weisbecker   tracing/function-...
901
  }
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
902
  static void
ac5f6c968   Steven Rostedt   function-graph: c...
903
  print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
d7a8d9e90   Jiri Olsa   tracing: Have gra...
904
  		     int type, unsigned long addr, u32 flags)
83a8df618   Frederic Weisbecker   tracing/function-...
905
  {
2fbcdb35a   Steven Rostedt   function-graph: c...
906
  	struct fgraph_data *data = iter->private;
83a8df618   Frederic Weisbecker   tracing/function-...
907
  	struct trace_entry *ent = iter->ent;
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
908
  	struct trace_array *tr = iter->tr;
ac5f6c968   Steven Rostedt   function-graph: c...
909
  	int cpu = iter->cpu;
83a8df618   Frederic Weisbecker   tracing/function-...
910

1a056155e   Frederic Weisbecker   tracing/function-...
911
  	/* Pid */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
912
  	verif_pid(s, ent->pid, cpu, data);
9005f3ebe   Frederic Weisbecker   tracing/function-...
913

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
914
  	if (type)
ac5f6c968   Steven Rostedt   function-graph: c...
915
  		/* Interrupt */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
916
  		print_graph_irq(iter, addr, type, cpu, ent->pid, flags);
83a8df618   Frederic Weisbecker   tracing/function-...
917

983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
918
  	if (!(tr->trace_flags & TRACE_ITER_CONTEXT_INFO))
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
919
  		return;
749230b06   Jiri Olsa   tracing, function...
920

9005f3ebe   Frederic Weisbecker   tracing/function-...
921
  	/* Absolute time */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
922
923
  	if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
  		print_graph_abs_time(iter->ts, s);
9005f3ebe   Frederic Weisbecker   tracing/function-...
924

1a056155e   Frederic Weisbecker   tracing/function-...
925
  	/* Cpu */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
926
927
  	if (flags & TRACE_GRAPH_PRINT_CPU)
  		print_graph_cpu(s, cpu);
11e84acc4   Frederic Weisbecker   tracing/function-...
928
929
  
  	/* Proc */
d7a8d9e90   Jiri Olsa   tracing: Have gra...
930
  	if (flags & TRACE_GRAPH_PRINT_PROC) {
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
931
932
  		print_graph_proc(s, ent->pid);
  		trace_seq_puts(s, " | ");
1a056155e   Frederic Weisbecker   tracing/function-...
933
  	}
83a8df618   Frederic Weisbecker   tracing/function-...
934

49ff59039   Steven Rostedt   tracing: add late...
935
  	/* Latency format */
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
936
  	if (tr->trace_flags & TRACE_ITER_LATENCY_FMT)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
937
  		print_graph_lat_fmt(s, ent);
49ff59039   Steven Rostedt   tracing: add late...
938

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
939
  	return;
ac5f6c968   Steven Rostedt   function-graph: c...
940
  }
2bd16212b   Jiri Olsa   tracing: Add func...
941
942
943
944
945
  /*
   * Entry check for irq code
   *
   * returns 1 if
   *  - we are inside irq code
25985edce   Lucas De Marchi   Fix common misspe...
946
   *  - we just entered irq code
2bd16212b   Jiri Olsa   tracing: Add func...
947
948
949
950
951
952
953
954
955
956
   *
   * retunns 0 if
   *  - funcgraph-interrupts option is set
   *  - we are not inside irq code
   */
  static int
  check_irq_entry(struct trace_iterator *iter, u32 flags,
  		unsigned long addr, int depth)
  {
  	int cpu = iter->cpu;
a9d61173d   Jiri Olsa   tracing: Add prop...
957
  	int *depth_irq;
2bd16212b   Jiri Olsa   tracing: Add func...
958
  	struct fgraph_data *data = iter->private;
2bd16212b   Jiri Olsa   tracing: Add func...
959

a9d61173d   Jiri Olsa   tracing: Add prop...
960
961
962
963
964
965
966
  	/*
  	 * If we are either displaying irqs, or we got called as
  	 * a graph event and private data does not exist,
  	 * then we bypass the irq check.
  	 */
  	if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
  	    (!data))
2bd16212b   Jiri Olsa   tracing: Add func...
967
  		return 0;
a9d61173d   Jiri Olsa   tracing: Add prop...
968
  	depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
2bd16212b   Jiri Olsa   tracing: Add func...
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
  	/*
  	 * We are inside the irq code
  	 */
  	if (*depth_irq >= 0)
  		return 1;
  
  	if ((addr < (unsigned long)__irqentry_text_start) ||
  	    (addr >= (unsigned long)__irqentry_text_end))
  		return 0;
  
  	/*
  	 * We are entering irq code.
  	 */
  	*depth_irq = depth;
  	return 1;
  }
  
  /*
   * Return check for irq code
   *
   * returns 1 if
   *  - we are inside irq code
   *  - we just left irq code
   *
   * returns 0 if
   *  - funcgraph-interrupts option is set
   *  - we are not inside irq code
   */
  static int
  check_irq_return(struct trace_iterator *iter, u32 flags, int depth)
  {
  	int cpu = iter->cpu;
a9d61173d   Jiri Olsa   tracing: Add prop...
1001
  	int *depth_irq;
2bd16212b   Jiri Olsa   tracing: Add func...
1002
  	struct fgraph_data *data = iter->private;
2bd16212b   Jiri Olsa   tracing: Add func...
1003

a9d61173d   Jiri Olsa   tracing: Add prop...
1004
1005
1006
1007
1008
1009
1010
  	/*
  	 * If we are either displaying irqs, or we got called as
  	 * a graph event and private data does not exist,
  	 * then we bypass the irq check.
  	 */
  	if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
  	    (!data))
2bd16212b   Jiri Olsa   tracing: Add func...
1011
  		return 0;
a9d61173d   Jiri Olsa   tracing: Add prop...
1012
  	depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
2bd16212b   Jiri Olsa   tracing: Add func...
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  	/*
  	 * We are not inside the irq code.
  	 */
  	if (*depth_irq == -1)
  		return 0;
  
  	/*
  	 * We are inside the irq code, and this is returning entry.
  	 * Let's not trace it and clear the entry depth, since
  	 * we are out of irq code.
  	 *
  	 * This condition ensures that we 'leave the irq code' once
  	 * we are out of the entry depth. Thus protecting us from
  	 * the RETURN entry loss.
  	 */
  	if (*depth_irq >= depth) {
  		*depth_irq = -1;
  		return 1;
  	}
  
  	/*
  	 * We are inside the irq code, and this is not the entry.
  	 */
  	return 1;
  }
ac5f6c968   Steven Rostedt   function-graph: c...
1038
1039
  static enum print_line_t
  print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1040
  			struct trace_iterator *iter, u32 flags)
ac5f6c968   Steven Rostedt   function-graph: c...
1041
  {
be1eca393   Jiri Olsa   tracing: Fix func...
1042
  	struct fgraph_data *data = iter->private;
ac5f6c968   Steven Rostedt   function-graph: c...
1043
1044
  	struct ftrace_graph_ent *call = &field->graph_ent;
  	struct ftrace_graph_ret_entry *leaf_ret;
be1eca393   Jiri Olsa   tracing: Fix func...
1045
1046
  	static enum print_line_t ret;
  	int cpu = iter->cpu;
ac5f6c968   Steven Rostedt   function-graph: c...
1047

2bd16212b   Jiri Olsa   tracing: Add func...
1048
1049
  	if (check_irq_entry(iter, flags, call->func, call->depth))
  		return TRACE_TYPE_HANDLED;
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1050
  	print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags);
ac5f6c968   Steven Rostedt   function-graph: c...
1051

b91facc36   Frederic Weisbecker   tracing/function-...
1052
1053
  	leaf_ret = get_return_for_leaf(iter, field);
  	if (leaf_ret)
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1054
  		ret = print_graph_entry_leaf(iter, field, leaf_ret, s, flags);
83a8df618   Frederic Weisbecker   tracing/function-...
1055
  	else
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1056
  		ret = print_graph_entry_nested(iter, field, s, cpu, flags);
83a8df618   Frederic Weisbecker   tracing/function-...
1057

be1eca393   Jiri Olsa   tracing: Fix func...
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  	if (data) {
  		/*
  		 * If we failed to write our output, then we need to make
  		 * note of it. Because we already consumed our entry.
  		 */
  		if (s->full) {
  			data->failed = 1;
  			data->cpu = cpu;
  		} else
  			data->failed = 0;
  	}
  
  	return ret;
83a8df618   Frederic Weisbecker   tracing/function-...
1071
1072
1073
  }
  
  static enum print_line_t
287b6e68c   Frederic Weisbecker   tracing/function-...
1074
  print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1075
1076
  		   struct trace_entry *ent, struct trace_iterator *iter,
  		   u32 flags)
287b6e68c   Frederic Weisbecker   tracing/function-...
1077
  {
83a8df618   Frederic Weisbecker   tracing/function-...
1078
  	unsigned long long duration = trace->rettime - trace->calltime;
2fbcdb35a   Steven Rostedt   function-graph: c...
1079
  	struct fgraph_data *data = iter->private;
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1080
  	struct trace_array *tr = iter->tr;
2fbcdb35a   Steven Rostedt   function-graph: c...
1081
1082
  	pid_t pid = ent->pid;
  	int cpu = iter->cpu;
f1c7f517a   Steven Rostedt   ftrace: Add funct...
1083
  	int func_match = 1;
2fbcdb35a   Steven Rostedt   function-graph: c...
1084
  	int i;
2bd16212b   Jiri Olsa   tracing: Add func...
1085
1086
  	if (check_irq_return(iter, flags, trace->depth))
  		return TRACE_TYPE_HANDLED;
2fbcdb35a   Steven Rostedt   function-graph: c...
1087
  	if (data) {
f1c7f517a   Steven Rostedt   ftrace: Add funct...
1088
1089
1090
1091
  		struct fgraph_cpu_data *cpu_data;
  		int cpu = iter->cpu;
  
  		cpu_data = per_cpu_ptr(data->cpu_data, cpu);
2fbcdb35a   Steven Rostedt   function-graph: c...
1092
1093
1094
1095
1096
1097
  
  		/*
  		 * Comments display at + 1 to depth. This is the
  		 * return from a function, we now want the comments
  		 * to display at the same level of the bracket.
  		 */
f1c7f517a   Steven Rostedt   ftrace: Add funct...
1098
  		cpu_data->depth = trace->depth - 1;
794de08a1   Steven Rostedt (Red Hat)   fgraph: Handle a ...
1099
1100
  		if (trace->depth < FTRACE_RETFUNC_DEPTH &&
  		    !WARN_ON_ONCE(trace->depth < 0)) {
f1c7f517a   Steven Rostedt   ftrace: Add funct...
1101
1102
1103
1104
  			if (cpu_data->enter_funcs[trace->depth] != trace->func)
  				func_match = 0;
  			cpu_data->enter_funcs[trace->depth] = 0;
  		}
2fbcdb35a   Steven Rostedt   function-graph: c...
1105
  	}
287b6e68c   Frederic Weisbecker   tracing/function-...
1106

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1107
  	print_graph_prologue(iter, s, 0, 0, flags);
437f24fb8   Steven Rostedt   ftrace: add cpu a...
1108

ffeb80fc3   Jiri Olsa   tracing, function...
1109
  	/* Overhead and duration */
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1110
  	print_graph_duration(tr, duration, s, flags);
1a056155e   Frederic Weisbecker   tracing/function-...
1111

83a8df618   Frederic Weisbecker   tracing/function-...
1112
  	/* Closing brace */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1113
1114
  	for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++)
  		trace_seq_putc(s, ' ');
287b6e68c   Frederic Weisbecker   tracing/function-...
1115

f1c7f517a   Steven Rostedt   ftrace: Add funct...
1116
1117
1118
1119
  	/*
  	 * If the return function does not have a matching entry,
  	 * then the entry was lost. Instead of just printing
  	 * the '}' and letting the user guess what function this
607e3a292   Robert Elliott   tracing: Add func...
1120
1121
  	 * belongs to, write out the function name. Always do
  	 * that if the funcgraph-tail option is enabled.
f1c7f517a   Steven Rostedt   ftrace: Add funct...
1122
  	 */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1123
1124
1125
1126
1127
1128
  	if (func_match && !(flags & TRACE_GRAPH_PRINT_TAIL))
  		trace_seq_puts(s, "}
  ");
  	else
  		trace_seq_printf(s, "} /* %ps */
  ", (void *)trace->func);
fb52607af   Frederic Weisbecker   tracing/function-...
1129

83a8df618   Frederic Weisbecker   tracing/function-...
1130
  	/* Overrun */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1131
1132
1133
1134
  	if (flags & TRACE_GRAPH_PRINT_OVERRUN)
  		trace_seq_printf(s, " (Overruns: %lu)
  ",
  				 trace->overrun);
f8b755ac8   Frederic Weisbecker   tracing/function-...
1135

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1136
1137
  	print_graph_irq(iter, trace->func, TRACE_GRAPH_RET,
  			cpu, pid, flags);
f8b755ac8   Frederic Weisbecker   tracing/function-...
1138

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1139
  	return trace_handle_return(s);
287b6e68c   Frederic Weisbecker   tracing/function-...
1140
  }
1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1141
  static enum print_line_t
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1142
1143
  print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
  		    struct trace_iterator *iter, u32 flags)
1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1144
  {
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1145
1146
  	struct trace_array *tr = iter->tr;
  	unsigned long sym_flags = (tr->trace_flags & TRACE_ITER_SYM_MASK);
2fbcdb35a   Steven Rostedt   function-graph: c...
1147
  	struct fgraph_data *data = iter->private;
5087f8d2a   Steven Rostedt   function-graph: s...
1148
  	struct trace_event *event;
2fbcdb35a   Steven Rostedt   function-graph: c...
1149
  	int depth = 0;
1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1150
  	int ret;
2fbcdb35a   Steven Rostedt   function-graph: c...
1151
1152
1153
  	int i;
  
  	if (data)
be1eca393   Jiri Olsa   tracing: Fix func...
1154
  		depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth;
9005f3ebe   Frederic Weisbecker   tracing/function-...
1155

9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1156
  	print_graph_prologue(iter, s, 0, 0, flags);
d1f9cbd78   Frederic Weisbecker   tracing/function-...
1157

9005f3ebe   Frederic Weisbecker   tracing/function-...
1158
  	/* No time */
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1159
  	print_graph_duration(tr, 0, s, flags | FLAGS_FILL_FULL);
1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1160

1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1161
  	/* Indentation */
2fbcdb35a   Steven Rostedt   function-graph: c...
1162
  	if (depth > 0)
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1163
1164
  		for (i = 0; i < (depth + 1) * TRACE_GRAPH_INDENT; i++)
  			trace_seq_putc(s, ' ');
1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1165
1166
  
  	/* The comment */
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1167
  	trace_seq_puts(s, "/* ");
769b0441f   Frederic Weisbecker   tracing/core: dro...
1168

5087f8d2a   Steven Rostedt   function-graph: s...
1169
  	switch (iter->ent->type) {
613dccdf6   Namhyung Kim   function_graph: H...
1170
1171
1172
1173
1174
  	case TRACE_BPUTS:
  		ret = trace_print_bputs_msg_only(iter);
  		if (ret != TRACE_TYPE_HANDLED)
  			return ret;
  		break;
5087f8d2a   Steven Rostedt   function-graph: s...
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
  	case TRACE_BPRINT:
  		ret = trace_print_bprintk_msg_only(iter);
  		if (ret != TRACE_TYPE_HANDLED)
  			return ret;
  		break;
  	case TRACE_PRINT:
  		ret = trace_print_printk_msg_only(iter);
  		if (ret != TRACE_TYPE_HANDLED)
  			return ret;
  		break;
  	default:
  		event = ftrace_find_event(ent->type);
  		if (!event)
  			return TRACE_TYPE_UNHANDLED;
a9a577638   Steven Rostedt   tracing: Allow ev...
1189
  		ret = event->funcs->trace(iter, sym_flags, event);
5087f8d2a   Steven Rostedt   function-graph: s...
1190
1191
1192
  		if (ret != TRACE_TYPE_HANDLED)
  			return ret;
  	}
1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1193

5ac483784   Steven Rostedt (Red Hat)   tracing: Use trac...
1194
1195
  	if (trace_seq_has_overflowed(s))
  		goto out;
412d0bb55   Frederic Weisbecker   tracing/function-...
1196
  	/* Strip ending newline */
3a161d99c   Steven Rostedt (Red Hat)   tracing: Create s...
1197
1198
1199
1200
  	if (s->buffer[s->seq.len - 1] == '
  ') {
  		s->buffer[s->seq.len - 1] = '\0';
  		s->seq.len--;
412d0bb55   Frederic Weisbecker   tracing/function-...
1201
  	}
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1202
1203
  	trace_seq_puts(s, " */
  ");
5ac483784   Steven Rostedt (Red Hat)   tracing: Use trac...
1204
   out:
9d9add34e   Steven Rostedt (Red Hat)   tracing: Have fun...
1205
  	return trace_handle_return(s);
1fd8f2a3f   Frederic Weisbecker   tracing/function-...
1206
  }
287b6e68c   Frederic Weisbecker   tracing/function-...
1207
  enum print_line_t
321e68b09   Jiri Olsa   tracing, function...
1208
  print_graph_function_flags(struct trace_iterator *iter, u32 flags)
287b6e68c   Frederic Weisbecker   tracing/function-...
1209
  {
be1eca393   Jiri Olsa   tracing: Fix func...
1210
1211
  	struct ftrace_graph_ent_entry *field;
  	struct fgraph_data *data = iter->private;
287b6e68c   Frederic Weisbecker   tracing/function-...
1212
  	struct trace_entry *entry = iter->ent;
5087f8d2a   Steven Rostedt   function-graph: s...
1213
  	struct trace_seq *s = &iter->seq;
be1eca393   Jiri Olsa   tracing: Fix func...
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  	int cpu = iter->cpu;
  	int ret;
  
  	if (data && per_cpu_ptr(data->cpu_data, cpu)->ignore) {
  		per_cpu_ptr(data->cpu_data, cpu)->ignore = 0;
  		return TRACE_TYPE_HANDLED;
  	}
  
  	/*
  	 * If the last output failed, there's a possibility we need
  	 * to print out the missing entry which would never go out.
  	 */
  	if (data && data->failed) {
  		field = &data->ent;
  		iter->cpu = data->cpu;
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1229
  		ret = print_graph_entry(field, s, iter, flags);
be1eca393   Jiri Olsa   tracing: Fix func...
1230
1231
1232
1233
1234
1235
1236
  		if (ret == TRACE_TYPE_HANDLED && iter->cpu != cpu) {
  			per_cpu_ptr(data->cpu_data, iter->cpu)->ignore = 1;
  			ret = TRACE_TYPE_NO_CONSUME;
  		}
  		iter->cpu = cpu;
  		return ret;
  	}
fb52607af   Frederic Weisbecker   tracing/function-...
1237

287b6e68c   Frederic Weisbecker   tracing/function-...
1238
1239
  	switch (entry->type) {
  	case TRACE_GRAPH_ENT: {
38ceb592f   Lai Jiangshan   tracing: Fix inva...
1240
1241
1242
1243
1244
1245
  		/*
  		 * print_graph_entry() may consume the current event,
  		 * thus @field may become invalid, so we need to save it.
  		 * sizeof(struct ftrace_graph_ent_entry) is very small,
  		 * it can be safely saved at the stack.
  		 */
be1eca393   Jiri Olsa   tracing: Fix func...
1246
  		struct ftrace_graph_ent_entry saved;
287b6e68c   Frederic Weisbecker   tracing/function-...
1247
  		trace_assign_type(field, entry);
38ceb592f   Lai Jiangshan   tracing: Fix inva...
1248
  		saved = *field;
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1249
  		return print_graph_entry(&saved, s, iter, flags);
287b6e68c   Frederic Weisbecker   tracing/function-...
1250
1251
1252
1253
  	}
  	case TRACE_GRAPH_RET: {
  		struct ftrace_graph_ret_entry *field;
  		trace_assign_type(field, entry);
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1254
  		return print_graph_return(&field->ret, s, entry, iter, flags);
287b6e68c   Frederic Weisbecker   tracing/function-...
1255
  	}
62b915f10   Jiri Olsa   tracing: Add grap...
1256
1257
1258
1259
  	case TRACE_STACK:
  	case TRACE_FN:
  		/* dont trace stack and functions as comments */
  		return TRACE_TYPE_UNHANDLED;
287b6e68c   Frederic Weisbecker   tracing/function-...
1260
  	default:
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1261
  		return print_graph_comment(s, entry, iter, flags);
fb52607af   Frederic Weisbecker   tracing/function-...
1262
  	}
5087f8d2a   Steven Rostedt   function-graph: s...
1263
1264
  
  	return TRACE_TYPE_HANDLED;
fb52607af   Frederic Weisbecker   tracing/function-...
1265
  }
9106b6938   Jiri Olsa   tracing: Add ftra...
1266
  static enum print_line_t
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1267
1268
  print_graph_function(struct trace_iterator *iter)
  {
321e68b09   Jiri Olsa   tracing, function...
1269
  	return print_graph_function_flags(iter, tracer_flags.val);
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1270
1271
1272
  }
  
  static enum print_line_t
a9a577638   Steven Rostedt   tracing: Allow ev...
1273
1274
  print_graph_function_event(struct trace_iterator *iter, int flags,
  			   struct trace_event *event)
9106b6938   Jiri Olsa   tracing: Add ftra...
1275
1276
1277
  {
  	return print_graph_function(iter);
  }
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1278
  static void print_lat_header(struct seq_file *s, u32 flags)
49ff59039   Steven Rostedt   tracing: add late...
1279
1280
1281
1282
1283
  {
  	static const char spaces[] = "                "	/* 16 spaces */
  		"    "					/* 4 spaces */
  		"                 ";			/* 17 spaces */
  	int size = 0;
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1284
  	if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
49ff59039   Steven Rostedt   tracing: add late...
1285
  		size += 16;
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1286
  	if (flags & TRACE_GRAPH_PRINT_CPU)
49ff59039   Steven Rostedt   tracing: add late...
1287
  		size += 4;
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1288
  	if (flags & TRACE_GRAPH_PRINT_PROC)
49ff59039   Steven Rostedt   tracing: add late...
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
  		size += 17;
  
  	seq_printf(s, "#%.*s  _-----=> irqs-off        
  ", size, spaces);
  	seq_printf(s, "#%.*s / _----=> need-resched    
  ", size, spaces);
  	seq_printf(s, "#%.*s| / _---=> hardirq/softirq 
  ", size, spaces);
  	seq_printf(s, "#%.*s|| / _--=> preempt-depth   
  ", size, spaces);
199abfab4   Jiri Olsa   tracing, function...
1299
1300
  	seq_printf(s, "#%.*s||| /                      
  ", size, spaces);
49ff59039   Steven Rostedt   tracing: add late...
1301
  }
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1302
1303
  static void __print_graph_headers_flags(struct trace_array *tr,
  					struct seq_file *s, u32 flags)
decbec383   Frederic Weisbecker   tracing/function-...
1304
  {
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1305
  	int lat = tr->trace_flags & TRACE_ITER_LATENCY_FMT;
49ff59039   Steven Rostedt   tracing: add late...
1306
1307
  
  	if (lat)
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1308
  		print_lat_header(s, flags);
49ff59039   Steven Rostedt   tracing: add late...
1309

decbec383   Frederic Weisbecker   tracing/function-...
1310
  	/* 1st line */
1177e4364   Rasmus Villemoes   trace: Replace si...
1311
  	seq_putc(s, '#');
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1312
  	if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1313
  		seq_puts(s, "     TIME       ");
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1314
  	if (flags & TRACE_GRAPH_PRINT_CPU)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1315
  		seq_puts(s, " CPU");
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1316
  	if (flags & TRACE_GRAPH_PRINT_PROC)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1317
  		seq_puts(s, "  TASK/PID       ");
49ff59039   Steven Rostedt   tracing: add late...
1318
  	if (lat)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1319
  		seq_puts(s, "||||");
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1320
  	if (flags & TRACE_GRAPH_PRINT_DURATION)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1321
1322
1323
  		seq_puts(s, "  DURATION   ");
  	seq_puts(s, "               FUNCTION CALLS
  ");
decbec383   Frederic Weisbecker   tracing/function-...
1324
1325
  
  	/* 2nd line */
1177e4364   Rasmus Villemoes   trace: Replace si...
1326
  	seq_putc(s, '#');
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1327
  	if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1328
  		seq_puts(s, "      |         ");
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1329
  	if (flags & TRACE_GRAPH_PRINT_CPU)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1330
  		seq_puts(s, " |  ");
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1331
  	if (flags & TRACE_GRAPH_PRINT_PROC)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1332
  		seq_puts(s, "   |    |        ");
49ff59039   Steven Rostedt   tracing: add late...
1333
  	if (lat)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1334
  		seq_puts(s, "||||");
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1335
  	if (flags & TRACE_GRAPH_PRINT_DURATION)
fa6f0cc75   Rasmus Villemoes   tracing: Replace ...
1336
1337
1338
  		seq_puts(s, "   |   |      ");
  	seq_puts(s, "               |   |   |   |
  ");
decbec383   Frederic Weisbecker   tracing/function-...
1339
  }
9005f3ebe   Frederic Weisbecker   tracing/function-...
1340

ba1afef6a   Steven Rostedt (Red Hat)   tracing: Convert ...
1341
  static void print_graph_headers(struct seq_file *s)
d7a8d9e90   Jiri Olsa   tracing: Have gra...
1342
1343
1344
  {
  	print_graph_headers_flags(s, tracer_flags.val);
  }
0a772620a   Jiri Olsa   tracing: Make gra...
1345
1346
1347
  void print_graph_headers_flags(struct seq_file *s, u32 flags)
  {
  	struct trace_iterator *iter = s->private;
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1348
  	struct trace_array *tr = iter->tr;
0a772620a   Jiri Olsa   tracing: Make gra...
1349

983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1350
  	if (!(tr->trace_flags & TRACE_ITER_CONTEXT_INFO))
749230b06   Jiri Olsa   tracing, function...
1351
  		return;
983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1352
  	if (tr->trace_flags & TRACE_ITER_LATENCY_FMT) {
0a772620a   Jiri Olsa   tracing: Make gra...
1353
1354
1355
1356
1357
  		/* print nothing if the buffers are empty */
  		if (trace_empty(iter))
  			return;
  
  		print_trace_header(s, iter);
321e68b09   Jiri Olsa   tracing, function...
1358
  	}
0a772620a   Jiri Olsa   tracing: Make gra...
1359

983f938ae   Steven Rostedt (Red Hat)   tracing: Move tra...
1360
  	__print_graph_headers_flags(tr, s, flags);
0a772620a   Jiri Olsa   tracing: Make gra...
1361
  }
62b915f10   Jiri Olsa   tracing: Add grap...
1362
  void graph_trace_open(struct trace_iterator *iter)
9005f3ebe   Frederic Weisbecker   tracing/function-...
1363
  {
2fbcdb35a   Steven Rostedt   function-graph: c...
1364
  	/* pid and depth on the last trace processed */
be1eca393   Jiri Olsa   tracing: Fix func...
1365
  	struct fgraph_data *data;
ef99b88b1   Rabin Vincent   tracing: Handle f...
1366
  	gfp_t gfpflags;
9005f3ebe   Frederic Weisbecker   tracing/function-...
1367
  	int cpu;
be1eca393   Jiri Olsa   tracing: Fix func...
1368
  	iter->private = NULL;
ef99b88b1   Rabin Vincent   tracing: Handle f...
1369
1370
1371
1372
  	/* We can be called in atomic context via ftrace_dump() */
  	gfpflags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
  
  	data = kzalloc(sizeof(*data), gfpflags);
2fbcdb35a   Steven Rostedt   function-graph: c...
1373
  	if (!data)
be1eca393   Jiri Olsa   tracing: Fix func...
1374
  		goto out_err;
ef99b88b1   Rabin Vincent   tracing: Handle f...
1375
  	data->cpu_data = alloc_percpu_gfp(struct fgraph_cpu_data, gfpflags);
be1eca393   Jiri Olsa   tracing: Fix func...
1376
1377
1378
1379
1380
1381
1382
  	if (!data->cpu_data)
  		goto out_err_free;
  
  	for_each_possible_cpu(cpu) {
  		pid_t *pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
  		int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
  		int *ignore = &(per_cpu_ptr(data->cpu_data, cpu)->ignore);
2bd16212b   Jiri Olsa   tracing: Add func...
1383
  		int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
be1eca393   Jiri Olsa   tracing: Fix func...
1384
1385
1386
  		*pid = -1;
  		*depth = 0;
  		*ignore = 0;
2bd16212b   Jiri Olsa   tracing: Add func...
1387
  		*depth_irq = -1;
be1eca393   Jiri Olsa   tracing: Fix func...
1388
  	}
9005f3ebe   Frederic Weisbecker   tracing/function-...
1389

2fbcdb35a   Steven Rostedt   function-graph: c...
1390
  	iter->private = data;
be1eca393   Jiri Olsa   tracing: Fix func...
1391
1392
1393
1394
1395
1396
  
  	return;
  
   out_err_free:
  	kfree(data);
   out_err:
a395d6a7e   Joe Perches   kernel/...: conve...
1397
1398
  	pr_warn("function graph tracer: not enough memory
  ");
9005f3ebe   Frederic Weisbecker   tracing/function-...
1399
  }
62b915f10   Jiri Olsa   tracing: Add grap...
1400
  void graph_trace_close(struct trace_iterator *iter)
9005f3ebe   Frederic Weisbecker   tracing/function-...
1401
  {
be1eca393   Jiri Olsa   tracing: Fix func...
1402
1403
1404
1405
1406
1407
  	struct fgraph_data *data = iter->private;
  
  	if (data) {
  		free_percpu(data->cpu_data);
  		kfree(data);
  	}
9005f3ebe   Frederic Weisbecker   tracing/function-...
1408
  }
8c1a49aed   Steven Rostedt (Red Hat)   tracing: Pass tra...
1409
1410
  static int
  func_graph_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
b304d0441   Steven Rostedt   tracing: Do not t...
1411
1412
1413
  {
  	if (bit == TRACE_GRAPH_PRINT_IRQS)
  		ftrace_graph_skip_irqs = !set;
555772041   Steven Rostedt (Red Hat)   tracing: Move sle...
1414
1415
1416
1417
1418
  	if (bit == TRACE_GRAPH_SLEEP_TIME)
  		ftrace_graph_sleep_time_control(set);
  
  	if (bit == TRACE_GRAPH_GRAPH_TIME)
  		ftrace_graph_graph_time_control(set);
b304d0441   Steven Rostedt   tracing: Do not t...
1419
1420
  	return 0;
  }
a9a577638   Steven Rostedt   tracing: Allow ev...
1421
1422
1423
  static struct trace_event_functions graph_functions = {
  	.trace		= print_graph_function_event,
  };
9106b6938   Jiri Olsa   tracing: Add ftra...
1424
1425
  static struct trace_event graph_trace_entry_event = {
  	.type		= TRACE_GRAPH_ENT,
a9a577638   Steven Rostedt   tracing: Allow ev...
1426
  	.funcs		= &graph_functions,
9106b6938   Jiri Olsa   tracing: Add ftra...
1427
1428
1429
1430
  };
  
  static struct trace_event graph_trace_ret_event = {
  	.type		= TRACE_GRAPH_RET,
a9a577638   Steven Rostedt   tracing: Allow ev...
1431
  	.funcs		= &graph_functions
9106b6938   Jiri Olsa   tracing: Add ftra...
1432
  };
8f7689933   Steven Rostedt (Red Hat)   tracing: Add ref_...
1433
  static struct tracer graph_trace __tracer_data = {
ef18012b2   Steven Rostedt   tracing: remove f...
1434
  	.name		= "function_graph",
6508fa761   Stanislav Fomichev   tracing: let user...
1435
  	.update_thresh	= graph_trace_update_thresh,
9005f3ebe   Frederic Weisbecker   tracing/function-...
1436
  	.open		= graph_trace_open,
be1eca393   Jiri Olsa   tracing: Fix func...
1437
  	.pipe_open	= graph_trace_open,
9005f3ebe   Frederic Weisbecker   tracing/function-...
1438
  	.close		= graph_trace_close,
be1eca393   Jiri Olsa   tracing: Fix func...
1439
  	.pipe_close	= graph_trace_close,
ef18012b2   Steven Rostedt   tracing: remove f...
1440
1441
  	.init		= graph_trace_init,
  	.reset		= graph_trace_reset,
decbec383   Frederic Weisbecker   tracing/function-...
1442
1443
  	.print_line	= print_graph_function,
  	.print_header	= print_graph_headers,
fb52607af   Frederic Weisbecker   tracing/function-...
1444
  	.flags		= &tracer_flags,
b304d0441   Steven Rostedt   tracing: Do not t...
1445
  	.set_flag	= func_graph_set_flag,
7447dce96   Frederic Weisbecker   tracing/function-...
1446
1447
1448
  #ifdef CONFIG_FTRACE_SELFTEST
  	.selftest	= trace_selftest_startup_function_graph,
  #endif
fb52607af   Frederic Weisbecker   tracing/function-...
1449
  };
8741db532   Steven Rostedt   tracing/fgraph: A...
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
  
  static ssize_t
  graph_depth_write(struct file *filp, const char __user *ubuf, size_t cnt,
  		  loff_t *ppos)
  {
  	unsigned long val;
  	int ret;
  
  	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
  	if (ret)
  		return ret;
1a4144286   Steven Rostedt (Red Hat)   tracing/fgraph: H...
1461
  	fgraph_max_depth = val;
8741db532   Steven Rostedt   tracing/fgraph: A...
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
  
  	*ppos += cnt;
  
  	return cnt;
  }
  
  static ssize_t
  graph_depth_read(struct file *filp, char __user *ubuf, size_t cnt,
  		 loff_t *ppos)
  {
  	char buf[15]; /* More than enough to hold UINT_MAX + "
  "*/
  	int n;
1a4144286   Steven Rostedt (Red Hat)   tracing/fgraph: H...
1475
1476
  	n = sprintf(buf, "%d
  ", fgraph_max_depth);
8741db532   Steven Rostedt   tracing/fgraph: A...
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  
  	return simple_read_from_buffer(ubuf, cnt, ppos, buf, n);
  }
  
  static const struct file_operations graph_depth_fops = {
  	.open		= tracing_open_generic,
  	.write		= graph_depth_write,
  	.read		= graph_depth_read,
  	.llseek		= generic_file_llseek,
  };
8434dc934   Steven Rostedt (Red Hat)   tracing: Convert ...
1487
  static __init int init_graph_tracefs(void)
8741db532   Steven Rostedt   tracing/fgraph: A...
1488
1489
1490
1491
  {
  	struct dentry *d_tracer;
  
  	d_tracer = tracing_init_dentry();
14a5ae40f   Steven Rostedt (Red Hat)   tracing: Use IS_E...
1492
  	if (IS_ERR(d_tracer))
8741db532   Steven Rostedt   tracing/fgraph: A...
1493
1494
1495
1496
1497
1498
1499
  		return 0;
  
  	trace_create_file("max_graph_depth", 0644, d_tracer,
  			  NULL, &graph_depth_fops);
  
  	return 0;
  }
8434dc934   Steven Rostedt (Red Hat)   tracing: Convert ...
1500
  fs_initcall(init_graph_tracefs);
8741db532   Steven Rostedt   tracing/fgraph: A...
1501

fb52607af   Frederic Weisbecker   tracing/function-...
1502
1503
  static __init int init_graph_trace(void)
  {
9b130ad5b   Alexey Dobriyan   treewide: make "n...
1504
  	max_bytes_for_cpu = snprintf(NULL, 0, "%u", nr_cpu_ids - 1);
0c9e6f639   Lai Jiangshan   tracing: Simplify...
1505

9023c9309   Steven Rostedt (Red Hat)   tracing: Rename (...
1506
  	if (!register_trace_event(&graph_trace_entry_event)) {
a395d6a7e   Joe Perches   kernel/...: conve...
1507
1508
  		pr_warn("Warning: could not register graph trace events
  ");
9106b6938   Jiri Olsa   tracing: Add ftra...
1509
1510
  		return 1;
  	}
9023c9309   Steven Rostedt (Red Hat)   tracing: Rename (...
1511
  	if (!register_trace_event(&graph_trace_ret_event)) {
a395d6a7e   Joe Perches   kernel/...: conve...
1512
1513
  		pr_warn("Warning: could not register graph trace events
  ");
9106b6938   Jiri Olsa   tracing: Add ftra...
1514
1515
  		return 1;
  	}
fb52607af   Frederic Weisbecker   tracing/function-...
1516
1517
  	return register_tracer(&graph_trace);
  }
6f4156723   Steven Rostedt   tracing: Allow tr...
1518
  core_initcall(init_graph_trace);