xref: /linux-6.15/kernel/trace/ftrace.c (revision 493762fc)
116444a8aSArnaldo Carvalho de Melo /*
216444a8aSArnaldo Carvalho de Melo  * Infrastructure for profiling code inserted by 'gcc -pg'.
316444a8aSArnaldo Carvalho de Melo  *
416444a8aSArnaldo Carvalho de Melo  * Copyright (C) 2007-2008 Steven Rostedt <[email protected]>
516444a8aSArnaldo Carvalho de Melo  * Copyright (C) 2004-2008 Ingo Molnar <[email protected]>
616444a8aSArnaldo Carvalho de Melo  *
716444a8aSArnaldo Carvalho de Melo  * Originally ported from the -rt patch by:
816444a8aSArnaldo Carvalho de Melo  *   Copyright (C) 2007 Arnaldo Carvalho de Melo <[email protected]>
916444a8aSArnaldo Carvalho de Melo  *
1016444a8aSArnaldo Carvalho de Melo  * Based on code in the latency_tracer, that is:
1116444a8aSArnaldo Carvalho de Melo  *
1216444a8aSArnaldo Carvalho de Melo  *  Copyright (C) 2004-2006 Ingo Molnar
1316444a8aSArnaldo Carvalho de Melo  *  Copyright (C) 2004 William Lee Irwin III
1416444a8aSArnaldo Carvalho de Melo  */
1516444a8aSArnaldo Carvalho de Melo 
163d083395SSteven Rostedt #include <linux/stop_machine.h>
173d083395SSteven Rostedt #include <linux/clocksource.h>
183d083395SSteven Rostedt #include <linux/kallsyms.h>
195072c59fSSteven Rostedt #include <linux/seq_file.h>
204a2b8ddaSFrederic Weisbecker #include <linux/suspend.h>
215072c59fSSteven Rostedt #include <linux/debugfs.h>
223d083395SSteven Rostedt #include <linux/hardirq.h>
232d8b820bSIngo Molnar #include <linux/kthread.h>
245072c59fSSteven Rostedt #include <linux/uaccess.h>
25f22f9a89SAbhishek Sagar #include <linux/kprobes.h>
262d8b820bSIngo Molnar #include <linux/ftrace.h>
27b0fc494fSSteven Rostedt #include <linux/sysctl.h>
285072c59fSSteven Rostedt #include <linux/ctype.h>
293d083395SSteven Rostedt #include <linux/list.h>
3059df055fSSteven Rostedt #include <linux/hash.h>
3116444a8aSArnaldo Carvalho de Melo 
328aef2d28SSteven Rostedt #include <trace/sched.h>
338aef2d28SSteven Rostedt 
34395a59d0SAbhishek Sagar #include <asm/ftrace.h>
35395a59d0SAbhishek Sagar 
363d083395SSteven Rostedt #include "trace.h"
37bac429f0SSteven Rostedt #include "trace_stat.h"
383d083395SSteven Rostedt 
396912896eSSteven Rostedt #define FTRACE_WARN_ON(cond)			\
406912896eSSteven Rostedt 	do {					\
416912896eSSteven Rostedt 		if (WARN_ON(cond))		\
426912896eSSteven Rostedt 			ftrace_kill();		\
436912896eSSteven Rostedt 	} while (0)
446912896eSSteven Rostedt 
456912896eSSteven Rostedt #define FTRACE_WARN_ON_ONCE(cond)		\
466912896eSSteven Rostedt 	do {					\
476912896eSSteven Rostedt 		if (WARN_ON_ONCE(cond))		\
486912896eSSteven Rostedt 			ftrace_kill();		\
496912896eSSteven Rostedt 	} while (0)
506912896eSSteven Rostedt 
518fc0c701SSteven Rostedt /* hash bits for specific function selection */
528fc0c701SSteven Rostedt #define FTRACE_HASH_BITS 7
538fc0c701SSteven Rostedt #define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS)
548fc0c701SSteven Rostedt 
554eebcc81SSteven Rostedt /* ftrace_enabled is a method to turn ftrace on or off */
564eebcc81SSteven Rostedt int ftrace_enabled __read_mostly;
57d61f82d0SSteven Rostedt static int last_ftrace_enabled;
58b0fc494fSSteven Rostedt 
5960a7ecf4SSteven Rostedt /* Quick disabling of function tracer. */
6060a7ecf4SSteven Rostedt int function_trace_stop;
6160a7ecf4SSteven Rostedt 
624eebcc81SSteven Rostedt /*
634eebcc81SSteven Rostedt  * ftrace_disabled is set when an anomaly is discovered.
644eebcc81SSteven Rostedt  * ftrace_disabled is much stronger than ftrace_enabled.
654eebcc81SSteven Rostedt  */
664eebcc81SSteven Rostedt static int ftrace_disabled __read_mostly;
674eebcc81SSteven Rostedt 
6852baf119SSteven Rostedt static DEFINE_MUTEX(ftrace_lock);
69b0fc494fSSteven Rostedt 
7016444a8aSArnaldo Carvalho de Melo static struct ftrace_ops ftrace_list_end __read_mostly =
7116444a8aSArnaldo Carvalho de Melo {
7216444a8aSArnaldo Carvalho de Melo 	.func = ftrace_stub,
7316444a8aSArnaldo Carvalho de Melo };
7416444a8aSArnaldo Carvalho de Melo 
7516444a8aSArnaldo Carvalho de Melo static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end;
7616444a8aSArnaldo Carvalho de Melo ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
7760a7ecf4SSteven Rostedt ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
78df4fc315SSteven Rostedt ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
7916444a8aSArnaldo Carvalho de Melo 
80f2252935SIngo Molnar static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
8116444a8aSArnaldo Carvalho de Melo {
8216444a8aSArnaldo Carvalho de Melo 	struct ftrace_ops *op = ftrace_list;
8316444a8aSArnaldo Carvalho de Melo 
8416444a8aSArnaldo Carvalho de Melo 	/* in case someone actually ports this to alpha! */
8516444a8aSArnaldo Carvalho de Melo 	read_barrier_depends();
8616444a8aSArnaldo Carvalho de Melo 
8716444a8aSArnaldo Carvalho de Melo 	while (op != &ftrace_list_end) {
8816444a8aSArnaldo Carvalho de Melo 		/* silly alpha */
8916444a8aSArnaldo Carvalho de Melo 		read_barrier_depends();
9016444a8aSArnaldo Carvalho de Melo 		op->func(ip, parent_ip);
9116444a8aSArnaldo Carvalho de Melo 		op = op->next;
9216444a8aSArnaldo Carvalho de Melo 	};
9316444a8aSArnaldo Carvalho de Melo }
9416444a8aSArnaldo Carvalho de Melo 
95df4fc315SSteven Rostedt static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip)
96df4fc315SSteven Rostedt {
970ef8cde5SSteven Rostedt 	if (!test_tsk_trace_trace(current))
98df4fc315SSteven Rostedt 		return;
99df4fc315SSteven Rostedt 
100df4fc315SSteven Rostedt 	ftrace_pid_function(ip, parent_ip);
101df4fc315SSteven Rostedt }
102df4fc315SSteven Rostedt 
103df4fc315SSteven Rostedt static void set_ftrace_pid_function(ftrace_func_t func)
104df4fc315SSteven Rostedt {
105df4fc315SSteven Rostedt 	/* do not set ftrace_pid_function to itself! */
106df4fc315SSteven Rostedt 	if (func != ftrace_pid_func)
107df4fc315SSteven Rostedt 		ftrace_pid_function = func;
108df4fc315SSteven Rostedt }
109df4fc315SSteven Rostedt 
11016444a8aSArnaldo Carvalho de Melo /**
1113d083395SSteven Rostedt  * clear_ftrace_function - reset the ftrace function
11216444a8aSArnaldo Carvalho de Melo  *
1133d083395SSteven Rostedt  * This NULLs the ftrace function and in essence stops
1143d083395SSteven Rostedt  * tracing.  There may be lag
11516444a8aSArnaldo Carvalho de Melo  */
1163d083395SSteven Rostedt void clear_ftrace_function(void)
11716444a8aSArnaldo Carvalho de Melo {
1183d083395SSteven Rostedt 	ftrace_trace_function = ftrace_stub;
11960a7ecf4SSteven Rostedt 	__ftrace_trace_function = ftrace_stub;
120df4fc315SSteven Rostedt 	ftrace_pid_function = ftrace_stub;
1213d083395SSteven Rostedt }
12216444a8aSArnaldo Carvalho de Melo 
12360a7ecf4SSteven Rostedt #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
12460a7ecf4SSteven Rostedt /*
12560a7ecf4SSteven Rostedt  * For those archs that do not test ftrace_trace_stop in their
12660a7ecf4SSteven Rostedt  * mcount call site, we need to do it from C.
12760a7ecf4SSteven Rostedt  */
12860a7ecf4SSteven Rostedt static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip)
12960a7ecf4SSteven Rostedt {
13060a7ecf4SSteven Rostedt 	if (function_trace_stop)
13160a7ecf4SSteven Rostedt 		return;
13260a7ecf4SSteven Rostedt 
13360a7ecf4SSteven Rostedt 	__ftrace_trace_function(ip, parent_ip);
13460a7ecf4SSteven Rostedt }
13560a7ecf4SSteven Rostedt #endif
13660a7ecf4SSteven Rostedt 
137e309b41dSIngo Molnar static int __register_ftrace_function(struct ftrace_ops *ops)
1383d083395SSteven Rostedt {
13916444a8aSArnaldo Carvalho de Melo 	ops->next = ftrace_list;
14016444a8aSArnaldo Carvalho de Melo 	/*
14116444a8aSArnaldo Carvalho de Melo 	 * We are entering ops into the ftrace_list but another
14216444a8aSArnaldo Carvalho de Melo 	 * CPU might be walking that list. We need to make sure
14316444a8aSArnaldo Carvalho de Melo 	 * the ops->next pointer is valid before another CPU sees
14416444a8aSArnaldo Carvalho de Melo 	 * the ops pointer included into the ftrace_list.
14516444a8aSArnaldo Carvalho de Melo 	 */
14616444a8aSArnaldo Carvalho de Melo 	smp_wmb();
14716444a8aSArnaldo Carvalho de Melo 	ftrace_list = ops;
1483d083395SSteven Rostedt 
149b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
150df4fc315SSteven Rostedt 		ftrace_func_t func;
151df4fc315SSteven Rostedt 
152df4fc315SSteven Rostedt 		if (ops->next == &ftrace_list_end)
153df4fc315SSteven Rostedt 			func = ops->func;
154df4fc315SSteven Rostedt 		else
155df4fc315SSteven Rostedt 			func = ftrace_list_func;
156df4fc315SSteven Rostedt 
157978f3a45SSteven Rostedt 		if (ftrace_pid_trace) {
158df4fc315SSteven Rostedt 			set_ftrace_pid_function(func);
159df4fc315SSteven Rostedt 			func = ftrace_pid_func;
160df4fc315SSteven Rostedt 		}
161df4fc315SSteven Rostedt 
16216444a8aSArnaldo Carvalho de Melo 		/*
16316444a8aSArnaldo Carvalho de Melo 		 * For one func, simply call it directly.
16416444a8aSArnaldo Carvalho de Melo 		 * For more than one func, call the chain.
16516444a8aSArnaldo Carvalho de Melo 		 */
16660a7ecf4SSteven Rostedt #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
167df4fc315SSteven Rostedt 		ftrace_trace_function = func;
16860a7ecf4SSteven Rostedt #else
169df4fc315SSteven Rostedt 		__ftrace_trace_function = func;
17060a7ecf4SSteven Rostedt 		ftrace_trace_function = ftrace_test_stop_func;
17160a7ecf4SSteven Rostedt #endif
172b0fc494fSSteven Rostedt 	}
1733d083395SSteven Rostedt 
17416444a8aSArnaldo Carvalho de Melo 	return 0;
17516444a8aSArnaldo Carvalho de Melo }
17616444a8aSArnaldo Carvalho de Melo 
177e309b41dSIngo Molnar static int __unregister_ftrace_function(struct ftrace_ops *ops)
17816444a8aSArnaldo Carvalho de Melo {
17916444a8aSArnaldo Carvalho de Melo 	struct ftrace_ops **p;
18016444a8aSArnaldo Carvalho de Melo 
18116444a8aSArnaldo Carvalho de Melo 	/*
1823d083395SSteven Rostedt 	 * If we are removing the last function, then simply point
1833d083395SSteven Rostedt 	 * to the ftrace_stub.
18416444a8aSArnaldo Carvalho de Melo 	 */
18516444a8aSArnaldo Carvalho de Melo 	if (ftrace_list == ops && ops->next == &ftrace_list_end) {
18616444a8aSArnaldo Carvalho de Melo 		ftrace_trace_function = ftrace_stub;
18716444a8aSArnaldo Carvalho de Melo 		ftrace_list = &ftrace_list_end;
188e6ea44e9SSteven Rostedt 		return 0;
18916444a8aSArnaldo Carvalho de Melo 	}
19016444a8aSArnaldo Carvalho de Melo 
19116444a8aSArnaldo Carvalho de Melo 	for (p = &ftrace_list; *p != &ftrace_list_end; p = &(*p)->next)
19216444a8aSArnaldo Carvalho de Melo 		if (*p == ops)
19316444a8aSArnaldo Carvalho de Melo 			break;
19416444a8aSArnaldo Carvalho de Melo 
195e6ea44e9SSteven Rostedt 	if (*p != ops)
196e6ea44e9SSteven Rostedt 		return -1;
19716444a8aSArnaldo Carvalho de Melo 
19816444a8aSArnaldo Carvalho de Melo 	*p = (*p)->next;
19916444a8aSArnaldo Carvalho de Melo 
200b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
20116444a8aSArnaldo Carvalho de Melo 		/* If we only have one func left, then call that directly */
202df4fc315SSteven Rostedt 		if (ftrace_list->next == &ftrace_list_end) {
203df4fc315SSteven Rostedt 			ftrace_func_t func = ftrace_list->func;
204df4fc315SSteven Rostedt 
205978f3a45SSteven Rostedt 			if (ftrace_pid_trace) {
206df4fc315SSteven Rostedt 				set_ftrace_pid_function(func);
207df4fc315SSteven Rostedt 				func = ftrace_pid_func;
208df4fc315SSteven Rostedt 			}
209df4fc315SSteven Rostedt #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
210df4fc315SSteven Rostedt 			ftrace_trace_function = func;
211df4fc315SSteven Rostedt #else
212df4fc315SSteven Rostedt 			__ftrace_trace_function = func;
213df4fc315SSteven Rostedt #endif
214df4fc315SSteven Rostedt 		}
215b0fc494fSSteven Rostedt 	}
21616444a8aSArnaldo Carvalho de Melo 
217e6ea44e9SSteven Rostedt 	return 0;
2183d083395SSteven Rostedt }
2193d083395SSteven Rostedt 
220df4fc315SSteven Rostedt static void ftrace_update_pid_func(void)
221df4fc315SSteven Rostedt {
222df4fc315SSteven Rostedt 	ftrace_func_t func;
223df4fc315SSteven Rostedt 
224df4fc315SSteven Rostedt 	if (ftrace_trace_function == ftrace_stub)
22510dd3ebeSKOSAKI Motohiro 		return;
226df4fc315SSteven Rostedt 
227df4fc315SSteven Rostedt 	func = ftrace_trace_function;
228df4fc315SSteven Rostedt 
229978f3a45SSteven Rostedt 	if (ftrace_pid_trace) {
230df4fc315SSteven Rostedt 		set_ftrace_pid_function(func);
231df4fc315SSteven Rostedt 		func = ftrace_pid_func;
232df4fc315SSteven Rostedt 	} else {
23366eafebcSLiming Wang 		if (func == ftrace_pid_func)
23466eafebcSLiming Wang 			func = ftrace_pid_function;
235df4fc315SSteven Rostedt 	}
236df4fc315SSteven Rostedt 
237df4fc315SSteven Rostedt #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
238df4fc315SSteven Rostedt 	ftrace_trace_function = func;
239df4fc315SSteven Rostedt #else
240df4fc315SSteven Rostedt 	__ftrace_trace_function = func;
241df4fc315SSteven Rostedt #endif
242df4fc315SSteven Rostedt }
243df4fc315SSteven Rostedt 
244*493762fcSSteven Rostedt #ifdef CONFIG_FUNCTION_PROFILER
245*493762fcSSteven Rostedt struct ftrace_profile {
246*493762fcSSteven Rostedt 	struct hlist_node		node;
247*493762fcSSteven Rostedt 	unsigned long			ip;
248*493762fcSSteven Rostedt 	unsigned long			counter;
249*493762fcSSteven Rostedt };
250*493762fcSSteven Rostedt 
251*493762fcSSteven Rostedt struct ftrace_profile_page {
252*493762fcSSteven Rostedt 	struct ftrace_profile_page	*next;
253*493762fcSSteven Rostedt 	unsigned long			index;
254*493762fcSSteven Rostedt 	struct ftrace_profile		records[];
255*493762fcSSteven Rostedt };
256*493762fcSSteven Rostedt 
257*493762fcSSteven Rostedt #define PROFILE_RECORDS_SIZE						\
258*493762fcSSteven Rostedt 	(PAGE_SIZE - offsetof(struct ftrace_profile_page, records))
259*493762fcSSteven Rostedt 
260*493762fcSSteven Rostedt #define PROFILES_PER_PAGE					\
261*493762fcSSteven Rostedt 	(PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile))
262*493762fcSSteven Rostedt 
263*493762fcSSteven Rostedt /* TODO: make these percpu, to prevent cache line bouncing */
264*493762fcSSteven Rostedt static struct ftrace_profile_page *profile_pages_start;
265*493762fcSSteven Rostedt static struct ftrace_profile_page *profile_pages;
266*493762fcSSteven Rostedt 
267*493762fcSSteven Rostedt static struct hlist_head *ftrace_profile_hash;
268*493762fcSSteven Rostedt static int ftrace_profile_bits;
269*493762fcSSteven Rostedt static int ftrace_profile_enabled;
270*493762fcSSteven Rostedt static DEFINE_MUTEX(ftrace_profile_lock);
271*493762fcSSteven Rostedt 
272*493762fcSSteven Rostedt static DEFINE_PER_CPU(atomic_t, ftrace_profile_disable);
273*493762fcSSteven Rostedt 
274*493762fcSSteven Rostedt #define FTRACE_PROFILE_HASH_SIZE 1024 /* must be power of 2 */
275*493762fcSSteven Rostedt 
276*493762fcSSteven Rostedt static raw_spinlock_t ftrace_profile_rec_lock =
277*493762fcSSteven Rostedt 	(raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
278*493762fcSSteven Rostedt 
279*493762fcSSteven Rostedt static void *
280*493762fcSSteven Rostedt function_stat_next(void *v, int idx)
281*493762fcSSteven Rostedt {
282*493762fcSSteven Rostedt 	struct ftrace_profile *rec = v;
283*493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
284*493762fcSSteven Rostedt 
285*493762fcSSteven Rostedt 	pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK);
286*493762fcSSteven Rostedt 
287*493762fcSSteven Rostedt  again:
288*493762fcSSteven Rostedt 	rec++;
289*493762fcSSteven Rostedt 	if ((void *)rec >= (void *)&pg->records[pg->index]) {
290*493762fcSSteven Rostedt 		pg = pg->next;
291*493762fcSSteven Rostedt 		if (!pg)
292*493762fcSSteven Rostedt 			return NULL;
293*493762fcSSteven Rostedt 		rec = &pg->records[0];
294*493762fcSSteven Rostedt 		if (!rec->counter)
295*493762fcSSteven Rostedt 			goto again;
296*493762fcSSteven Rostedt 	}
297*493762fcSSteven Rostedt 
298*493762fcSSteven Rostedt 	return rec;
299*493762fcSSteven Rostedt }
300*493762fcSSteven Rostedt 
301*493762fcSSteven Rostedt static void *function_stat_start(struct tracer_stat *trace)
302*493762fcSSteven Rostedt {
303*493762fcSSteven Rostedt 	return function_stat_next(&profile_pages_start->records[0], 0);
304*493762fcSSteven Rostedt }
305*493762fcSSteven Rostedt 
306*493762fcSSteven Rostedt static int function_stat_cmp(void *p1, void *p2)
307*493762fcSSteven Rostedt {
308*493762fcSSteven Rostedt 	struct ftrace_profile *a = p1;
309*493762fcSSteven Rostedt 	struct ftrace_profile *b = p2;
310*493762fcSSteven Rostedt 
311*493762fcSSteven Rostedt 	if (a->counter < b->counter)
312*493762fcSSteven Rostedt 		return -1;
313*493762fcSSteven Rostedt 	if (a->counter > b->counter)
314*493762fcSSteven Rostedt 		return 1;
315*493762fcSSteven Rostedt 	else
316*493762fcSSteven Rostedt 		return 0;
317*493762fcSSteven Rostedt }
318*493762fcSSteven Rostedt 
319*493762fcSSteven Rostedt static int function_stat_headers(struct seq_file *m)
320*493762fcSSteven Rostedt {
321*493762fcSSteven Rostedt 	seq_printf(m, "  Function                               Hit\n"
322*493762fcSSteven Rostedt 		      "  --------                               ---\n");
323*493762fcSSteven Rostedt 	return 0;
324*493762fcSSteven Rostedt }
325*493762fcSSteven Rostedt 
326*493762fcSSteven Rostedt static int function_stat_show(struct seq_file *m, void *v)
327*493762fcSSteven Rostedt {
328*493762fcSSteven Rostedt 	struct ftrace_profile *rec = v;
329*493762fcSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
330*493762fcSSteven Rostedt 
331*493762fcSSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
332*493762fcSSteven Rostedt 
333*493762fcSSteven Rostedt 	seq_printf(m, "  %-30.30s  %10lu\n", str, rec->counter);
334*493762fcSSteven Rostedt 	return 0;
335*493762fcSSteven Rostedt }
336*493762fcSSteven Rostedt 
337*493762fcSSteven Rostedt static struct tracer_stat function_stats = {
338*493762fcSSteven Rostedt 	.name = "functions",
339*493762fcSSteven Rostedt 	.stat_start = function_stat_start,
340*493762fcSSteven Rostedt 	.stat_next = function_stat_next,
341*493762fcSSteven Rostedt 	.stat_cmp = function_stat_cmp,
342*493762fcSSteven Rostedt 	.stat_headers = function_stat_headers,
343*493762fcSSteven Rostedt 	.stat_show = function_stat_show
344*493762fcSSteven Rostedt };
345*493762fcSSteven Rostedt 
346*493762fcSSteven Rostedt static void ftrace_profile_reset(void)
347*493762fcSSteven Rostedt {
348*493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
349*493762fcSSteven Rostedt 
350*493762fcSSteven Rostedt 	pg = profile_pages = profile_pages_start;
351*493762fcSSteven Rostedt 
352*493762fcSSteven Rostedt 	while (pg) {
353*493762fcSSteven Rostedt 		memset(pg->records, 0, PROFILE_RECORDS_SIZE);
354*493762fcSSteven Rostedt 		pg->index = 0;
355*493762fcSSteven Rostedt 		pg = pg->next;
356*493762fcSSteven Rostedt 	}
357*493762fcSSteven Rostedt 
358*493762fcSSteven Rostedt 	memset(ftrace_profile_hash, 0,
359*493762fcSSteven Rostedt 	       FTRACE_PROFILE_HASH_SIZE * sizeof(struct hlist_head));
360*493762fcSSteven Rostedt }
361*493762fcSSteven Rostedt 
362*493762fcSSteven Rostedt int ftrace_profile_pages_init(void)
363*493762fcSSteven Rostedt {
364*493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
365*493762fcSSteven Rostedt 	int i;
366*493762fcSSteven Rostedt 
367*493762fcSSteven Rostedt 	/* If we already allocated, do nothing */
368*493762fcSSteven Rostedt 	if (profile_pages)
369*493762fcSSteven Rostedt 		return 0;
370*493762fcSSteven Rostedt 
371*493762fcSSteven Rostedt 	profile_pages = (void *)get_zeroed_page(GFP_KERNEL);
372*493762fcSSteven Rostedt 	if (!profile_pages)
373*493762fcSSteven Rostedt 		return -ENOMEM;
374*493762fcSSteven Rostedt 
375*493762fcSSteven Rostedt 	pg = profile_pages_start = profile_pages;
376*493762fcSSteven Rostedt 
377*493762fcSSteven Rostedt 	/* allocate 10 more pages to start */
378*493762fcSSteven Rostedt 	for (i = 0; i < 10; i++) {
379*493762fcSSteven Rostedt 		pg->next = (void *)get_zeroed_page(GFP_KERNEL);
380*493762fcSSteven Rostedt 		/*
381*493762fcSSteven Rostedt 		 * We only care about allocating profile_pages, if
382*493762fcSSteven Rostedt 		 * we failed to allocate here, hopefully we will allocate
383*493762fcSSteven Rostedt 		 * later.
384*493762fcSSteven Rostedt 		 */
385*493762fcSSteven Rostedt 		if (!pg->next)
386*493762fcSSteven Rostedt 			break;
387*493762fcSSteven Rostedt 		pg = pg->next;
388*493762fcSSteven Rostedt 	}
389*493762fcSSteven Rostedt 
390*493762fcSSteven Rostedt 	return 0;
391*493762fcSSteven Rostedt }
392*493762fcSSteven Rostedt 
393*493762fcSSteven Rostedt static int ftrace_profile_init(void)
394*493762fcSSteven Rostedt {
395*493762fcSSteven Rostedt 	int size;
396*493762fcSSteven Rostedt 
397*493762fcSSteven Rostedt 	if (ftrace_profile_hash) {
398*493762fcSSteven Rostedt 		/* If the profile is already created, simply reset it */
399*493762fcSSteven Rostedt 		ftrace_profile_reset();
400*493762fcSSteven Rostedt 		return 0;
401*493762fcSSteven Rostedt 	}
402*493762fcSSteven Rostedt 
403*493762fcSSteven Rostedt 	/*
404*493762fcSSteven Rostedt 	 * We are profiling all functions, but usually only a few thousand
405*493762fcSSteven Rostedt 	 * functions are hit. We'll make a hash of 1024 items.
406*493762fcSSteven Rostedt 	 */
407*493762fcSSteven Rostedt 	size = FTRACE_PROFILE_HASH_SIZE;
408*493762fcSSteven Rostedt 
409*493762fcSSteven Rostedt 	ftrace_profile_hash =
410*493762fcSSteven Rostedt 		kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL);
411*493762fcSSteven Rostedt 
412*493762fcSSteven Rostedt 	if (!ftrace_profile_hash)
413*493762fcSSteven Rostedt 		return -ENOMEM;
414*493762fcSSteven Rostedt 
415*493762fcSSteven Rostedt 	size--;
416*493762fcSSteven Rostedt 
417*493762fcSSteven Rostedt 	for (; size; size >>= 1)
418*493762fcSSteven Rostedt 		ftrace_profile_bits++;
419*493762fcSSteven Rostedt 
420*493762fcSSteven Rostedt 	/* Preallocate a few pages */
421*493762fcSSteven Rostedt 	if (ftrace_profile_pages_init() < 0) {
422*493762fcSSteven Rostedt 		kfree(ftrace_profile_hash);
423*493762fcSSteven Rostedt 		ftrace_profile_hash = NULL;
424*493762fcSSteven Rostedt 		return -ENOMEM;
425*493762fcSSteven Rostedt 	}
426*493762fcSSteven Rostedt 
427*493762fcSSteven Rostedt 	return 0;
428*493762fcSSteven Rostedt }
429*493762fcSSteven Rostedt 
430*493762fcSSteven Rostedt /* interrupts must be disabled */
431*493762fcSSteven Rostedt static struct ftrace_profile *ftrace_find_profiled_func(unsigned long ip)
432*493762fcSSteven Rostedt {
433*493762fcSSteven Rostedt 	struct ftrace_profile *rec;
434*493762fcSSteven Rostedt 	struct hlist_head *hhd;
435*493762fcSSteven Rostedt 	struct hlist_node *n;
436*493762fcSSteven Rostedt 	unsigned long key;
437*493762fcSSteven Rostedt 
438*493762fcSSteven Rostedt 	key = hash_long(ip, ftrace_profile_bits);
439*493762fcSSteven Rostedt 	hhd = &ftrace_profile_hash[key];
440*493762fcSSteven Rostedt 
441*493762fcSSteven Rostedt 	if (hlist_empty(hhd))
442*493762fcSSteven Rostedt 		return NULL;
443*493762fcSSteven Rostedt 
444*493762fcSSteven Rostedt 	hlist_for_each_entry_rcu(rec, n, hhd, node) {
445*493762fcSSteven Rostedt 		if (rec->ip == ip)
446*493762fcSSteven Rostedt 			return rec;
447*493762fcSSteven Rostedt 	}
448*493762fcSSteven Rostedt 
449*493762fcSSteven Rostedt 	return NULL;
450*493762fcSSteven Rostedt }
451*493762fcSSteven Rostedt 
452*493762fcSSteven Rostedt static void ftrace_add_profile(struct ftrace_profile *rec)
453*493762fcSSteven Rostedt {
454*493762fcSSteven Rostedt 	unsigned long key;
455*493762fcSSteven Rostedt 
456*493762fcSSteven Rostedt 	key = hash_long(rec->ip, ftrace_profile_bits);
457*493762fcSSteven Rostedt 	hlist_add_head_rcu(&rec->node, &ftrace_profile_hash[key]);
458*493762fcSSteven Rostedt }
459*493762fcSSteven Rostedt 
460*493762fcSSteven Rostedt /* Interrupts must be disabled calling this */
461*493762fcSSteven Rostedt static struct ftrace_profile *
462*493762fcSSteven Rostedt ftrace_profile_alloc(unsigned long ip, bool alloc_safe)
463*493762fcSSteven Rostedt {
464*493762fcSSteven Rostedt 	struct ftrace_profile *rec = NULL;
465*493762fcSSteven Rostedt 
466*493762fcSSteven Rostedt 	/* prevent recursion */
467*493762fcSSteven Rostedt 	if (atomic_inc_return(&__get_cpu_var(ftrace_profile_disable)) != 1)
468*493762fcSSteven Rostedt 		goto out;
469*493762fcSSteven Rostedt 
470*493762fcSSteven Rostedt 	__raw_spin_lock(&ftrace_profile_rec_lock);
471*493762fcSSteven Rostedt 
472*493762fcSSteven Rostedt 	/* Try to always keep another page available */
473*493762fcSSteven Rostedt 	if (!profile_pages->next && alloc_safe)
474*493762fcSSteven Rostedt 		profile_pages->next = (void *)get_zeroed_page(GFP_ATOMIC);
475*493762fcSSteven Rostedt 
476*493762fcSSteven Rostedt 	/*
477*493762fcSSteven Rostedt 	 * Try to find the function again since another
478*493762fcSSteven Rostedt 	 * task on another CPU could have added it
479*493762fcSSteven Rostedt 	 */
480*493762fcSSteven Rostedt 	rec = ftrace_find_profiled_func(ip);
481*493762fcSSteven Rostedt 	if (rec)
482*493762fcSSteven Rostedt 		goto out_unlock;
483*493762fcSSteven Rostedt 
484*493762fcSSteven Rostedt 	if (profile_pages->index == PROFILES_PER_PAGE) {
485*493762fcSSteven Rostedt 		if (!profile_pages->next)
486*493762fcSSteven Rostedt 			goto out_unlock;
487*493762fcSSteven Rostedt 		profile_pages = profile_pages->next;
488*493762fcSSteven Rostedt 	}
489*493762fcSSteven Rostedt 
490*493762fcSSteven Rostedt 	rec = &profile_pages->records[profile_pages->index++];
491*493762fcSSteven Rostedt 	rec->ip = ip;
492*493762fcSSteven Rostedt 	ftrace_add_profile(rec);
493*493762fcSSteven Rostedt 
494*493762fcSSteven Rostedt  out_unlock:
495*493762fcSSteven Rostedt 	__raw_spin_unlock(&ftrace_profile_rec_lock);
496*493762fcSSteven Rostedt  out:
497*493762fcSSteven Rostedt 	atomic_dec(&__get_cpu_var(ftrace_profile_disable));
498*493762fcSSteven Rostedt 
499*493762fcSSteven Rostedt 	return rec;
500*493762fcSSteven Rostedt }
501*493762fcSSteven Rostedt 
502*493762fcSSteven Rostedt /*
503*493762fcSSteven Rostedt  * If we are not in an interrupt, or softirq and
504*493762fcSSteven Rostedt  * and interrupts are disabled and preemption is not enabled
505*493762fcSSteven Rostedt  * (not in a spinlock) then it should be safe to allocate memory.
506*493762fcSSteven Rostedt  */
507*493762fcSSteven Rostedt static bool ftrace_safe_to_allocate(void)
508*493762fcSSteven Rostedt {
509*493762fcSSteven Rostedt 	return !in_interrupt() && irqs_disabled() && !preempt_count();
510*493762fcSSteven Rostedt }
511*493762fcSSteven Rostedt 
512*493762fcSSteven Rostedt static void
513*493762fcSSteven Rostedt function_profile_call(unsigned long ip, unsigned long parent_ip)
514*493762fcSSteven Rostedt {
515*493762fcSSteven Rostedt 	struct ftrace_profile *rec;
516*493762fcSSteven Rostedt 	unsigned long flags;
517*493762fcSSteven Rostedt 	bool alloc_safe;
518*493762fcSSteven Rostedt 
519*493762fcSSteven Rostedt 	if (!ftrace_profile_enabled)
520*493762fcSSteven Rostedt 		return;
521*493762fcSSteven Rostedt 
522*493762fcSSteven Rostedt 	alloc_safe = ftrace_safe_to_allocate();
523*493762fcSSteven Rostedt 
524*493762fcSSteven Rostedt 	local_irq_save(flags);
525*493762fcSSteven Rostedt 	rec = ftrace_find_profiled_func(ip);
526*493762fcSSteven Rostedt 	if (!rec) {
527*493762fcSSteven Rostedt 		rec = ftrace_profile_alloc(ip, alloc_safe);
528*493762fcSSteven Rostedt 		if (!rec)
529*493762fcSSteven Rostedt 			goto out;
530*493762fcSSteven Rostedt 	}
531*493762fcSSteven Rostedt 
532*493762fcSSteven Rostedt 	rec->counter++;
533*493762fcSSteven Rostedt  out:
534*493762fcSSteven Rostedt 	local_irq_restore(flags);
535*493762fcSSteven Rostedt }
536*493762fcSSteven Rostedt 
537*493762fcSSteven Rostedt static struct ftrace_ops ftrace_profile_ops __read_mostly =
538*493762fcSSteven Rostedt {
539*493762fcSSteven Rostedt 	.func = function_profile_call,
540*493762fcSSteven Rostedt };
541*493762fcSSteven Rostedt 
542*493762fcSSteven Rostedt static ssize_t
543*493762fcSSteven Rostedt ftrace_profile_write(struct file *filp, const char __user *ubuf,
544*493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
545*493762fcSSteven Rostedt {
546*493762fcSSteven Rostedt 	unsigned long val;
547*493762fcSSteven Rostedt 	char buf[64];
548*493762fcSSteven Rostedt 	int ret;
549*493762fcSSteven Rostedt 
550*493762fcSSteven Rostedt 	if (cnt >= sizeof(buf))
551*493762fcSSteven Rostedt 		return -EINVAL;
552*493762fcSSteven Rostedt 
553*493762fcSSteven Rostedt 	if (copy_from_user(&buf, ubuf, cnt))
554*493762fcSSteven Rostedt 		return -EFAULT;
555*493762fcSSteven Rostedt 
556*493762fcSSteven Rostedt 	buf[cnt] = 0;
557*493762fcSSteven Rostedt 
558*493762fcSSteven Rostedt 	ret = strict_strtoul(buf, 10, &val);
559*493762fcSSteven Rostedt 	if (ret < 0)
560*493762fcSSteven Rostedt 		return ret;
561*493762fcSSteven Rostedt 
562*493762fcSSteven Rostedt 	val = !!val;
563*493762fcSSteven Rostedt 
564*493762fcSSteven Rostedt 	mutex_lock(&ftrace_profile_lock);
565*493762fcSSteven Rostedt 	if (ftrace_profile_enabled ^ val) {
566*493762fcSSteven Rostedt 		if (val) {
567*493762fcSSteven Rostedt 			ret = ftrace_profile_init();
568*493762fcSSteven Rostedt 			if (ret < 0) {
569*493762fcSSteven Rostedt 				cnt = ret;
570*493762fcSSteven Rostedt 				goto out;
571*493762fcSSteven Rostedt 			}
572*493762fcSSteven Rostedt 
573*493762fcSSteven Rostedt 			register_ftrace_function(&ftrace_profile_ops);
574*493762fcSSteven Rostedt 			ftrace_profile_enabled = 1;
575*493762fcSSteven Rostedt 		} else {
576*493762fcSSteven Rostedt 			ftrace_profile_enabled = 0;
577*493762fcSSteven Rostedt 			unregister_ftrace_function(&ftrace_profile_ops);
578*493762fcSSteven Rostedt 		}
579*493762fcSSteven Rostedt 	}
580*493762fcSSteven Rostedt  out:
581*493762fcSSteven Rostedt 	mutex_unlock(&ftrace_profile_lock);
582*493762fcSSteven Rostedt 
583*493762fcSSteven Rostedt 	filp->f_pos += cnt;
584*493762fcSSteven Rostedt 
585*493762fcSSteven Rostedt 	return cnt;
586*493762fcSSteven Rostedt }
587*493762fcSSteven Rostedt 
588*493762fcSSteven Rostedt static ssize_t
589*493762fcSSteven Rostedt ftrace_profile_read(struct file *filp, char __user *ubuf,
590*493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
591*493762fcSSteven Rostedt {
592*493762fcSSteven Rostedt 	char buf[64];
593*493762fcSSteven Rostedt 	int r;
594*493762fcSSteven Rostedt 
595*493762fcSSteven Rostedt 	r = sprintf(buf, "%u\n", ftrace_profile_enabled);
596*493762fcSSteven Rostedt 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
597*493762fcSSteven Rostedt }
598*493762fcSSteven Rostedt 
599*493762fcSSteven Rostedt static const struct file_operations ftrace_profile_fops = {
600*493762fcSSteven Rostedt 	.open		= tracing_open_generic,
601*493762fcSSteven Rostedt 	.read		= ftrace_profile_read,
602*493762fcSSteven Rostedt 	.write		= ftrace_profile_write,
603*493762fcSSteven Rostedt };
604*493762fcSSteven Rostedt 
605*493762fcSSteven Rostedt static void ftrace_profile_debugfs(struct dentry *d_tracer)
606*493762fcSSteven Rostedt {
607*493762fcSSteven Rostedt 	struct dentry *entry;
608*493762fcSSteven Rostedt 	int ret;
609*493762fcSSteven Rostedt 
610*493762fcSSteven Rostedt 	ret = register_stat_tracer(&function_stats);
611*493762fcSSteven Rostedt 	if (ret) {
612*493762fcSSteven Rostedt 		pr_warning("Warning: could not register "
613*493762fcSSteven Rostedt 			   "function stats\n");
614*493762fcSSteven Rostedt 		return;
615*493762fcSSteven Rostedt 	}
616*493762fcSSteven Rostedt 
617*493762fcSSteven Rostedt 	entry = debugfs_create_file("function_profile_enabled", 0644,
618*493762fcSSteven Rostedt 				    d_tracer, NULL, &ftrace_profile_fops);
619*493762fcSSteven Rostedt 	if (!entry)
620*493762fcSSteven Rostedt 		pr_warning("Could not create debugfs "
621*493762fcSSteven Rostedt 			   "'function_profile_enabled' entry\n");
622*493762fcSSteven Rostedt }
623*493762fcSSteven Rostedt 
624*493762fcSSteven Rostedt #else /* CONFIG_FUNCTION_PROFILER */
625*493762fcSSteven Rostedt static void ftrace_profile_debugfs(struct dentry *d_tracer)
626*493762fcSSteven Rostedt {
627*493762fcSSteven Rostedt }
628*493762fcSSteven Rostedt #endif /* CONFIG_FUNCTION_PROFILER */
629*493762fcSSteven Rostedt 
63073d3fd96SIngo Molnar /* set when tracing only a pid */
63173d3fd96SIngo Molnar struct pid *ftrace_pid_trace;
63273d3fd96SIngo Molnar static struct pid * const ftrace_swapper_pid = &init_struct_pid;
63373d3fd96SIngo Molnar 
6343d083395SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE
63573d3fd96SIngo Molnar 
63699ecdc43SSteven Rostedt #ifndef CONFIG_FTRACE_MCOUNT_RECORD
637cb7be3b2SSteven Rostedt # error Dynamic ftrace depends on MCOUNT_RECORD
63899ecdc43SSteven Rostedt #endif
63999ecdc43SSteven Rostedt 
6408fc0c701SSteven Rostedt static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly;
6418fc0c701SSteven Rostedt 
642b6887d79SSteven Rostedt struct ftrace_func_probe {
6438fc0c701SSteven Rostedt 	struct hlist_node	node;
644b6887d79SSteven Rostedt 	struct ftrace_probe_ops	*ops;
6458fc0c701SSteven Rostedt 	unsigned long		flags;
6468fc0c701SSteven Rostedt 	unsigned long		ip;
6478fc0c701SSteven Rostedt 	void			*data;
6488fc0c701SSteven Rostedt 	struct rcu_head		rcu;
6498fc0c701SSteven Rostedt };
6508fc0c701SSteven Rostedt 
651d61f82d0SSteven Rostedt enum {
652d61f82d0SSteven Rostedt 	FTRACE_ENABLE_CALLS		= (1 << 0),
653d61f82d0SSteven Rostedt 	FTRACE_DISABLE_CALLS		= (1 << 1),
654d61f82d0SSteven Rostedt 	FTRACE_UPDATE_TRACE_FUNC	= (1 << 2),
655d61f82d0SSteven Rostedt 	FTRACE_ENABLE_MCOUNT		= (1 << 3),
656d61f82d0SSteven Rostedt 	FTRACE_DISABLE_MCOUNT		= (1 << 4),
6575a45cfe1SSteven Rostedt 	FTRACE_START_FUNC_RET		= (1 << 5),
6585a45cfe1SSteven Rostedt 	FTRACE_STOP_FUNC_RET		= (1 << 6),
659d61f82d0SSteven Rostedt };
660d61f82d0SSteven Rostedt 
6615072c59fSSteven Rostedt static int ftrace_filtered;
6625072c59fSSteven Rostedt 
663e94142a6SLai Jiangshan static struct dyn_ftrace *ftrace_new_addrs;
6643d083395SSteven Rostedt 
66541c52c0dSSteven Rostedt static DEFINE_MUTEX(ftrace_regex_lock);
6663d083395SSteven Rostedt 
6673c1720f0SSteven Rostedt struct ftrace_page {
6683c1720f0SSteven Rostedt 	struct ftrace_page	*next;
669431aa3fbSSteven Rostedt 	int			index;
6703c1720f0SSteven Rostedt 	struct dyn_ftrace	records[];
671aa5e5ceaSDavid Miller };
6723c1720f0SSteven Rostedt 
6733c1720f0SSteven Rostedt #define ENTRIES_PER_PAGE \
6743c1720f0SSteven Rostedt   ((PAGE_SIZE - sizeof(struct ftrace_page)) / sizeof(struct dyn_ftrace))
6753c1720f0SSteven Rostedt 
6763c1720f0SSteven Rostedt /* estimate from running different kernels */
6773c1720f0SSteven Rostedt #define NR_TO_INIT		10000
6783c1720f0SSteven Rostedt 
6793c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages_start;
6803c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages;
6813c1720f0SSteven Rostedt 
68237ad5084SSteven Rostedt static struct dyn_ftrace *ftrace_free_records;
68337ad5084SSteven Rostedt 
684265c831cSSteven Rostedt /*
685265c831cSSteven Rostedt  * This is a double for. Do not use 'break' to break out of the loop,
686265c831cSSteven Rostedt  * you must use a goto.
687265c831cSSteven Rostedt  */
688265c831cSSteven Rostedt #define do_for_each_ftrace_rec(pg, rec)					\
689265c831cSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {		\
690265c831cSSteven Rostedt 		int _____i;						\
691265c831cSSteven Rostedt 		for (_____i = 0; _____i < pg->index; _____i++) {	\
692265c831cSSteven Rostedt 			rec = &pg->records[_____i];
693265c831cSSteven Rostedt 
694265c831cSSteven Rostedt #define while_for_each_ftrace_rec()		\
695265c831cSSteven Rostedt 		}				\
696265c831cSSteven Rostedt 	}
697ecea656dSAbhishek Sagar 
698ecea656dSAbhishek Sagar #ifdef CONFIG_KPROBES
699f17845e5SIngo Molnar 
700f17845e5SIngo Molnar static int frozen_record_count;
701f17845e5SIngo Molnar 
702ecea656dSAbhishek Sagar static inline void freeze_record(struct dyn_ftrace *rec)
703ecea656dSAbhishek Sagar {
704ecea656dSAbhishek Sagar 	if (!(rec->flags & FTRACE_FL_FROZEN)) {
705ecea656dSAbhishek Sagar 		rec->flags |= FTRACE_FL_FROZEN;
706ecea656dSAbhishek Sagar 		frozen_record_count++;
707ecea656dSAbhishek Sagar 	}
708ecea656dSAbhishek Sagar }
709ecea656dSAbhishek Sagar 
710ecea656dSAbhishek Sagar static inline void unfreeze_record(struct dyn_ftrace *rec)
711ecea656dSAbhishek Sagar {
712ecea656dSAbhishek Sagar 	if (rec->flags & FTRACE_FL_FROZEN) {
713ecea656dSAbhishek Sagar 		rec->flags &= ~FTRACE_FL_FROZEN;
714ecea656dSAbhishek Sagar 		frozen_record_count--;
715ecea656dSAbhishek Sagar 	}
716ecea656dSAbhishek Sagar }
717ecea656dSAbhishek Sagar 
718ecea656dSAbhishek Sagar static inline int record_frozen(struct dyn_ftrace *rec)
719ecea656dSAbhishek Sagar {
720ecea656dSAbhishek Sagar 	return rec->flags & FTRACE_FL_FROZEN;
721ecea656dSAbhishek Sagar }
722ecea656dSAbhishek Sagar #else
723ecea656dSAbhishek Sagar # define freeze_record(rec)			({ 0; })
724ecea656dSAbhishek Sagar # define unfreeze_record(rec)			({ 0; })
725ecea656dSAbhishek Sagar # define record_frozen(rec)			({ 0; })
726ecea656dSAbhishek Sagar #endif /* CONFIG_KPROBES */
727ecea656dSAbhishek Sagar 
728e309b41dSIngo Molnar static void ftrace_free_rec(struct dyn_ftrace *rec)
72937ad5084SSteven Rostedt {
730ee000b7fSLai Jiangshan 	rec->freelist = ftrace_free_records;
73137ad5084SSteven Rostedt 	ftrace_free_records = rec;
73237ad5084SSteven Rostedt 	rec->flags |= FTRACE_FL_FREE;
73337ad5084SSteven Rostedt }
73437ad5084SSteven Rostedt 
735fed1939cSSteven Rostedt void ftrace_release(void *start, unsigned long size)
736fed1939cSSteven Rostedt {
737fed1939cSSteven Rostedt 	struct dyn_ftrace *rec;
738fed1939cSSteven Rostedt 	struct ftrace_page *pg;
739fed1939cSSteven Rostedt 	unsigned long s = (unsigned long)start;
740fed1939cSSteven Rostedt 	unsigned long e = s + size;
741fed1939cSSteven Rostedt 
74200fd61aeSSteven Rostedt 	if (ftrace_disabled || !start)
743fed1939cSSteven Rostedt 		return;
744fed1939cSSteven Rostedt 
74552baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
746265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
747b00f0b6dSZhaolei 		if ((rec->ip >= s) && (rec->ip < e) &&
748*493762fcSSteven Rostedt 		    !(rec->flags & FTRACE_FL_FREE))
749fed1939cSSteven Rostedt 			ftrace_free_rec(rec);
750265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
75152baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
752fed1939cSSteven Rostedt }
753fed1939cSSteven Rostedt 
754e309b41dSIngo Molnar static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
7553c1720f0SSteven Rostedt {
75637ad5084SSteven Rostedt 	struct dyn_ftrace *rec;
75737ad5084SSteven Rostedt 
75837ad5084SSteven Rostedt 	/* First check for freed records */
75937ad5084SSteven Rostedt 	if (ftrace_free_records) {
76037ad5084SSteven Rostedt 		rec = ftrace_free_records;
76137ad5084SSteven Rostedt 
76237ad5084SSteven Rostedt 		if (unlikely(!(rec->flags & FTRACE_FL_FREE))) {
7636912896eSSteven Rostedt 			FTRACE_WARN_ON_ONCE(1);
76437ad5084SSteven Rostedt 			ftrace_free_records = NULL;
76537ad5084SSteven Rostedt 			return NULL;
76637ad5084SSteven Rostedt 		}
76737ad5084SSteven Rostedt 
768ee000b7fSLai Jiangshan 		ftrace_free_records = rec->freelist;
76937ad5084SSteven Rostedt 		memset(rec, 0, sizeof(*rec));
77037ad5084SSteven Rostedt 		return rec;
77137ad5084SSteven Rostedt 	}
77237ad5084SSteven Rostedt 
7733c1720f0SSteven Rostedt 	if (ftrace_pages->index == ENTRIES_PER_PAGE) {
77408f5ac90SSteven Rostedt 		if (!ftrace_pages->next) {
77508f5ac90SSteven Rostedt 			/* allocate another page */
77608f5ac90SSteven Rostedt 			ftrace_pages->next =
77708f5ac90SSteven Rostedt 				(void *)get_zeroed_page(GFP_KERNEL);
7783c1720f0SSteven Rostedt 			if (!ftrace_pages->next)
7793c1720f0SSteven Rostedt 				return NULL;
78008f5ac90SSteven Rostedt 		}
7813c1720f0SSteven Rostedt 		ftrace_pages = ftrace_pages->next;
7823c1720f0SSteven Rostedt 	}
7833c1720f0SSteven Rostedt 
7843c1720f0SSteven Rostedt 	return &ftrace_pages->records[ftrace_pages->index++];
7853c1720f0SSteven Rostedt }
7863c1720f0SSteven Rostedt 
78708f5ac90SSteven Rostedt static struct dyn_ftrace *
788d61f82d0SSteven Rostedt ftrace_record_ip(unsigned long ip)
7893d083395SSteven Rostedt {
79008f5ac90SSteven Rostedt 	struct dyn_ftrace *rec;
7913d083395SSteven Rostedt 
792f3c7ac40SSteven Rostedt 	if (ftrace_disabled)
79308f5ac90SSteven Rostedt 		return NULL;
794d61f82d0SSteven Rostedt 
79508f5ac90SSteven Rostedt 	rec = ftrace_alloc_dyn_node(ip);
79608f5ac90SSteven Rostedt 	if (!rec)
79708f5ac90SSteven Rostedt 		return NULL;
7983d083395SSteven Rostedt 
79908f5ac90SSteven Rostedt 	rec->ip = ip;
800ee000b7fSLai Jiangshan 	rec->newlist = ftrace_new_addrs;
801e94142a6SLai Jiangshan 	ftrace_new_addrs = rec;
8023d083395SSteven Rostedt 
80308f5ac90SSteven Rostedt 	return rec;
8043d083395SSteven Rostedt }
8053d083395SSteven Rostedt 
80605736a42SSteven Rostedt static void print_ip_ins(const char *fmt, unsigned char *p)
80705736a42SSteven Rostedt {
80805736a42SSteven Rostedt 	int i;
80905736a42SSteven Rostedt 
81005736a42SSteven Rostedt 	printk(KERN_CONT "%s", fmt);
81105736a42SSteven Rostedt 
81205736a42SSteven Rostedt 	for (i = 0; i < MCOUNT_INSN_SIZE; i++)
81305736a42SSteven Rostedt 		printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
81405736a42SSteven Rostedt }
81505736a42SSteven Rostedt 
81631e88909SSteven Rostedt static void ftrace_bug(int failed, unsigned long ip)
8173c1720f0SSteven Rostedt {
818b17e8a37SSteven Rostedt 	switch (failed) {
819593eb8a2SSteven Rostedt 	case -EFAULT:
8206912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
82105736a42SSteven Rostedt 		pr_info("ftrace faulted on modifying ");
82205736a42SSteven Rostedt 		print_ip_sym(ip);
82305736a42SSteven Rostedt 		break;
824593eb8a2SSteven Rostedt 	case -EINVAL:
8256912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
82605736a42SSteven Rostedt 		pr_info("ftrace failed to modify ");
82705736a42SSteven Rostedt 		print_ip_sym(ip);
82805736a42SSteven Rostedt 		print_ip_ins(" actual: ", (unsigned char *)ip);
82905736a42SSteven Rostedt 		printk(KERN_CONT "\n");
83005736a42SSteven Rostedt 		break;
831593eb8a2SSteven Rostedt 	case -EPERM:
8326912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
833593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on writing ");
834593eb8a2SSteven Rostedt 		print_ip_sym(ip);
835593eb8a2SSteven Rostedt 		break;
836593eb8a2SSteven Rostedt 	default:
8376912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
838593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on unknown error ");
839593eb8a2SSteven Rostedt 		print_ip_sym(ip);
84005736a42SSteven Rostedt 	}
841b17e8a37SSteven Rostedt }
84205736a42SSteven Rostedt 
8433d083395SSteven Rostedt 
8443d083395SSteven Rostedt static int
84531e88909SSteven Rostedt __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
8463d083395SSteven Rostedt {
847e7d3737eSFrederic Weisbecker 	unsigned long ftrace_addr;
8486a24a244SSteven Rostedt 	unsigned long ip, fl;
849e7d3737eSFrederic Weisbecker 
850f0001207SShaohua Li 	ftrace_addr = (unsigned long)FTRACE_ADDR;
8513d083395SSteven Rostedt 
8523d083395SSteven Rostedt 	ip = rec->ip;
8533d083395SSteven Rostedt 
8543d083395SSteven Rostedt 	/*
855982c350bSSteven Rostedt 	 * If this record is not to be traced and
856982c350bSSteven Rostedt 	 * it is not enabled then do nothing.
8573d083395SSteven Rostedt 	 *
858982c350bSSteven Rostedt 	 * If this record is not to be traced and
85957794a9dSWenji Huang 	 * it is enabled then disable it.
8603d083395SSteven Rostedt 	 *
8613d083395SSteven Rostedt 	 */
862982c350bSSteven Rostedt 	if (rec->flags & FTRACE_FL_NOTRACE) {
863982c350bSSteven Rostedt 		if (rec->flags & FTRACE_FL_ENABLED)
8643d083395SSteven Rostedt 			rec->flags &= ~FTRACE_FL_ENABLED;
865982c350bSSteven Rostedt 		else
8663d083395SSteven Rostedt 			return 0;
867982c350bSSteven Rostedt 
868982c350bSSteven Rostedt 	} else if (ftrace_filtered && enable) {
869982c350bSSteven Rostedt 		/*
870982c350bSSteven Rostedt 		 * Filtering is on:
871982c350bSSteven Rostedt 		 */
872982c350bSSteven Rostedt 
873982c350bSSteven Rostedt 		fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED);
874982c350bSSteven Rostedt 
875982c350bSSteven Rostedt 		/* Record is filtered and enabled, do nothing */
876982c350bSSteven Rostedt 		if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED))
877982c350bSSteven Rostedt 			return 0;
878982c350bSSteven Rostedt 
87957794a9dSWenji Huang 		/* Record is not filtered or enabled, do nothing */
880982c350bSSteven Rostedt 		if (!fl)
881982c350bSSteven Rostedt 			return 0;
882982c350bSSteven Rostedt 
883982c350bSSteven Rostedt 		/* Record is not filtered but enabled, disable it */
884982c350bSSteven Rostedt 		if (fl == FTRACE_FL_ENABLED)
885982c350bSSteven Rostedt 			rec->flags &= ~FTRACE_FL_ENABLED;
886982c350bSSteven Rostedt 		else
887982c350bSSteven Rostedt 		/* Otherwise record is filtered but not enabled, enable it */
888982c350bSSteven Rostedt 			rec->flags |= FTRACE_FL_ENABLED;
889982c350bSSteven Rostedt 	} else {
890982c350bSSteven Rostedt 		/* Disable or not filtered */
8913d083395SSteven Rostedt 
8923d083395SSteven Rostedt 		if (enable) {
893982c350bSSteven Rostedt 			/* if record is enabled, do nothing */
8943d083395SSteven Rostedt 			if (rec->flags & FTRACE_FL_ENABLED)
8953d083395SSteven Rostedt 				return 0;
896982c350bSSteven Rostedt 
8973d083395SSteven Rostedt 			rec->flags |= FTRACE_FL_ENABLED;
898982c350bSSteven Rostedt 
8993d083395SSteven Rostedt 		} else {
900982c350bSSteven Rostedt 
90157794a9dSWenji Huang 			/* if record is not enabled, do nothing */
9023d083395SSteven Rostedt 			if (!(rec->flags & FTRACE_FL_ENABLED))
9033d083395SSteven Rostedt 				return 0;
904982c350bSSteven Rostedt 
9053d083395SSteven Rostedt 			rec->flags &= ~FTRACE_FL_ENABLED;
9063d083395SSteven Rostedt 		}
9073d083395SSteven Rostedt 	}
9083d083395SSteven Rostedt 
909982c350bSSteven Rostedt 	if (rec->flags & FTRACE_FL_ENABLED)
910e7d3737eSFrederic Weisbecker 		return ftrace_make_call(rec, ftrace_addr);
91131e88909SSteven Rostedt 	else
912e7d3737eSFrederic Weisbecker 		return ftrace_make_nop(NULL, rec, ftrace_addr);
9133d083395SSteven Rostedt }
9143d083395SSteven Rostedt 
9153d083395SSteven Rostedt static void ftrace_replace_code(int enable)
9163d083395SSteven Rostedt {
9173d083395SSteven Rostedt 	struct dyn_ftrace *rec;
9183d083395SSteven Rostedt 	struct ftrace_page *pg;
9196a24a244SSteven Rostedt 	int failed;
9203d083395SSteven Rostedt 
921265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
922918c1154SSteven Rostedt 		/*
923fa9d13cfSZhaolei 		 * Skip over free records, records that have
924fa9d13cfSZhaolei 		 * failed and not converted.
925918c1154SSteven Rostedt 		 */
926918c1154SSteven Rostedt 		if (rec->flags & FTRACE_FL_FREE ||
927fa9d13cfSZhaolei 		    rec->flags & FTRACE_FL_FAILED ||
92803303549SFrederic Weisbecker 		    !(rec->flags & FTRACE_FL_CONVERTED))
9293d083395SSteven Rostedt 			continue;
9303d083395SSteven Rostedt 
9313d083395SSteven Rostedt 		/* ignore updates to this record's mcount site */
9323d083395SSteven Rostedt 		if (get_kprobe((void *)rec->ip)) {
9333d083395SSteven Rostedt 			freeze_record(rec);
9343d083395SSteven Rostedt 			continue;
9353d083395SSteven Rostedt 		} else {
9363d083395SSteven Rostedt 			unfreeze_record(rec);
9373d083395SSteven Rostedt 		}
9383d083395SSteven Rostedt 
93931e88909SSteven Rostedt 		failed = __ftrace_replace_code(rec, enable);
940fa9d13cfSZhaolei 		if (failed) {
9413d083395SSteven Rostedt 			rec->flags |= FTRACE_FL_FAILED;
9423d083395SSteven Rostedt 			if ((system_state == SYSTEM_BOOTING) ||
9433d083395SSteven Rostedt 			    !core_kernel_text(rec->ip)) {
9443d083395SSteven Rostedt 				ftrace_free_rec(rec);
9454377245aSSteven Rostedt 				} else {
94631e88909SSteven Rostedt 				ftrace_bug(failed, rec->ip);
9474377245aSSteven Rostedt 					/* Stop processing */
9484377245aSSteven Rostedt 					return;
9494377245aSSteven Rostedt 				}
9503d083395SSteven Rostedt 		}
951265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
9523d083395SSteven Rostedt }
9533c1720f0SSteven Rostedt 
9543b47bfc1SSteven Rostedt static int
95531e88909SSteven Rostedt ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
9563c1720f0SSteven Rostedt {
95737ad5084SSteven Rostedt 	unsigned long ip;
958492a7ea5SAbhishek Sagar 	int ret;
95937ad5084SSteven Rostedt 
960492a7ea5SAbhishek Sagar 	ip = rec->ip;
9613c1720f0SSteven Rostedt 
96225aac9dcSShaohua Li 	ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
9633d083395SSteven Rostedt 	if (ret) {
96431e88909SSteven Rostedt 		ftrace_bug(ret, ip);
9653d083395SSteven Rostedt 		rec->flags |= FTRACE_FL_FAILED;
9663d083395SSteven Rostedt 		return 0;
967d61f82d0SSteven Rostedt 	}
968d61f82d0SSteven Rostedt 	return 1;
9693d083395SSteven Rostedt }
9703d083395SSteven Rostedt 
971000ab691SSteven Rostedt /*
972000ab691SSteven Rostedt  * archs can override this function if they must do something
973000ab691SSteven Rostedt  * before the modifying code is performed.
974000ab691SSteven Rostedt  */
975000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_prepare(void)
976000ab691SSteven Rostedt {
977000ab691SSteven Rostedt 	return 0;
978000ab691SSteven Rostedt }
979000ab691SSteven Rostedt 
980000ab691SSteven Rostedt /*
981000ab691SSteven Rostedt  * archs can override this function if they must do something
982000ab691SSteven Rostedt  * after the modifying code is performed.
983000ab691SSteven Rostedt  */
984000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_post_process(void)
985000ab691SSteven Rostedt {
986000ab691SSteven Rostedt 	return 0;
987000ab691SSteven Rostedt }
988000ab691SSteven Rostedt 
9893d083395SSteven Rostedt static int __ftrace_modify_code(void *data)
9903d083395SSteven Rostedt {
9913d083395SSteven Rostedt 	int *command = data;
9923d083395SSteven Rostedt 
993a3583244SSteven Rostedt 	if (*command & FTRACE_ENABLE_CALLS)
9943d083395SSteven Rostedt 		ftrace_replace_code(1);
995a3583244SSteven Rostedt 	else if (*command & FTRACE_DISABLE_CALLS)
9963d083395SSteven Rostedt 		ftrace_replace_code(0);
9973d083395SSteven Rostedt 
9983d083395SSteven Rostedt 	if (*command & FTRACE_UPDATE_TRACE_FUNC)
9993d083395SSteven Rostedt 		ftrace_update_ftrace_func(ftrace_trace_function);
10003d083395SSteven Rostedt 
10015a45cfe1SSteven Rostedt 	if (*command & FTRACE_START_FUNC_RET)
10025a45cfe1SSteven Rostedt 		ftrace_enable_ftrace_graph_caller();
10035a45cfe1SSteven Rostedt 	else if (*command & FTRACE_STOP_FUNC_RET)
10045a45cfe1SSteven Rostedt 		ftrace_disable_ftrace_graph_caller();
10055a45cfe1SSteven Rostedt 
10063d083395SSteven Rostedt 	return 0;
10073d083395SSteven Rostedt }
10083d083395SSteven Rostedt 
1009e309b41dSIngo Molnar static void ftrace_run_update_code(int command)
10103d083395SSteven Rostedt {
1011000ab691SSteven Rostedt 	int ret;
1012000ab691SSteven Rostedt 
1013000ab691SSteven Rostedt 	ret = ftrace_arch_code_modify_prepare();
1014000ab691SSteven Rostedt 	FTRACE_WARN_ON(ret);
1015000ab691SSteven Rostedt 	if (ret)
1016000ab691SSteven Rostedt 		return;
1017000ab691SSteven Rostedt 
1018784e2d76SRusty Russell 	stop_machine(__ftrace_modify_code, &command, NULL);
1019000ab691SSteven Rostedt 
1020000ab691SSteven Rostedt 	ret = ftrace_arch_code_modify_post_process();
1021000ab691SSteven Rostedt 	FTRACE_WARN_ON(ret);
10223d083395SSteven Rostedt }
10233d083395SSteven Rostedt 
10243d083395SSteven Rostedt static ftrace_func_t saved_ftrace_func;
102560a7ecf4SSteven Rostedt static int ftrace_start_up;
1026df4fc315SSteven Rostedt 
1027df4fc315SSteven Rostedt static void ftrace_startup_enable(int command)
1028df4fc315SSteven Rostedt {
1029df4fc315SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
1030df4fc315SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
1031df4fc315SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
1032df4fc315SSteven Rostedt 	}
1033df4fc315SSteven Rostedt 
1034df4fc315SSteven Rostedt 	if (!command || !ftrace_enabled)
1035df4fc315SSteven Rostedt 		return;
1036df4fc315SSteven Rostedt 
1037df4fc315SSteven Rostedt 	ftrace_run_update_code(command);
1038df4fc315SSteven Rostedt }
10393d083395SSteven Rostedt 
10405a45cfe1SSteven Rostedt static void ftrace_startup(int command)
10413d083395SSteven Rostedt {
10424eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
10434eebcc81SSteven Rostedt 		return;
10444eebcc81SSteven Rostedt 
104560a7ecf4SSteven Rostedt 	ftrace_start_up++;
1046d61f82d0SSteven Rostedt 	command |= FTRACE_ENABLE_CALLS;
10473d083395SSteven Rostedt 
1048df4fc315SSteven Rostedt 	ftrace_startup_enable(command);
10493d083395SSteven Rostedt }
10503d083395SSteven Rostedt 
10515a45cfe1SSteven Rostedt static void ftrace_shutdown(int command)
10523d083395SSteven Rostedt {
10534eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
10544eebcc81SSteven Rostedt 		return;
10554eebcc81SSteven Rostedt 
105660a7ecf4SSteven Rostedt 	ftrace_start_up--;
105760a7ecf4SSteven Rostedt 	if (!ftrace_start_up)
1058d61f82d0SSteven Rostedt 		command |= FTRACE_DISABLE_CALLS;
1059d61f82d0SSteven Rostedt 
1060d61f82d0SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
1061d61f82d0SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
1062d61f82d0SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
1063d61f82d0SSteven Rostedt 	}
1064d61f82d0SSteven Rostedt 
1065d61f82d0SSteven Rostedt 	if (!command || !ftrace_enabled)
1066e6ea44e9SSteven Rostedt 		return;
10673d083395SSteven Rostedt 
1068d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
10693d083395SSteven Rostedt }
10703d083395SSteven Rostedt 
1071e309b41dSIngo Molnar static void ftrace_startup_sysctl(void)
1072b0fc494fSSteven Rostedt {
1073d61f82d0SSteven Rostedt 	int command = FTRACE_ENABLE_MCOUNT;
1074d61f82d0SSteven Rostedt 
10754eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
10764eebcc81SSteven Rostedt 		return;
10774eebcc81SSteven Rostedt 
1078d61f82d0SSteven Rostedt 	/* Force update next time */
1079d61f82d0SSteven Rostedt 	saved_ftrace_func = NULL;
108060a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if we want ftrace running */
108160a7ecf4SSteven Rostedt 	if (ftrace_start_up)
1082d61f82d0SSteven Rostedt 		command |= FTRACE_ENABLE_CALLS;
1083d61f82d0SSteven Rostedt 
1084d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
1085b0fc494fSSteven Rostedt }
1086b0fc494fSSteven Rostedt 
1087e309b41dSIngo Molnar static void ftrace_shutdown_sysctl(void)
1088b0fc494fSSteven Rostedt {
1089d61f82d0SSteven Rostedt 	int command = FTRACE_DISABLE_MCOUNT;
1090d61f82d0SSteven Rostedt 
10914eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
10924eebcc81SSteven Rostedt 		return;
10934eebcc81SSteven Rostedt 
109460a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if ftrace is running */
109560a7ecf4SSteven Rostedt 	if (ftrace_start_up)
1096d61f82d0SSteven Rostedt 		command |= FTRACE_DISABLE_CALLS;
1097d61f82d0SSteven Rostedt 
1098d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
1099b0fc494fSSteven Rostedt }
1100b0fc494fSSteven Rostedt 
11013d083395SSteven Rostedt static cycle_t		ftrace_update_time;
11023d083395SSteven Rostedt static unsigned long	ftrace_update_cnt;
11033d083395SSteven Rostedt unsigned long		ftrace_update_tot_cnt;
11043d083395SSteven Rostedt 
110531e88909SSteven Rostedt static int ftrace_update_code(struct module *mod)
11063d083395SSteven Rostedt {
1107e94142a6SLai Jiangshan 	struct dyn_ftrace *p;
1108f22f9a89SAbhishek Sagar 	cycle_t start, stop;
11093d083395SSteven Rostedt 
1110750ed1a4SIngo Molnar 	start = ftrace_now(raw_smp_processor_id());
11113d083395SSteven Rostedt 	ftrace_update_cnt = 0;
11123d083395SSteven Rostedt 
1113e94142a6SLai Jiangshan 	while (ftrace_new_addrs) {
1114f22f9a89SAbhishek Sagar 
111508f5ac90SSteven Rostedt 		/* If something went wrong, bail without enabling anything */
111608f5ac90SSteven Rostedt 		if (unlikely(ftrace_disabled))
111708f5ac90SSteven Rostedt 			return -1;
11183d083395SSteven Rostedt 
1119e94142a6SLai Jiangshan 		p = ftrace_new_addrs;
1120ee000b7fSLai Jiangshan 		ftrace_new_addrs = p->newlist;
1121e94142a6SLai Jiangshan 		p->flags = 0L;
1122f22f9a89SAbhishek Sagar 
1123f22f9a89SAbhishek Sagar 		/* convert record (i.e, patch mcount-call with NOP) */
112431e88909SSteven Rostedt 		if (ftrace_code_disable(mod, p)) {
11250eb96701SAbhishek Sagar 			p->flags |= FTRACE_FL_CONVERTED;
11263d083395SSteven Rostedt 			ftrace_update_cnt++;
112708f5ac90SSteven Rostedt 		} else
11280eb96701SAbhishek Sagar 			ftrace_free_rec(p);
11293d083395SSteven Rostedt 	}
11303d083395SSteven Rostedt 
1131750ed1a4SIngo Molnar 	stop = ftrace_now(raw_smp_processor_id());
11323d083395SSteven Rostedt 	ftrace_update_time = stop - start;
11333d083395SSteven Rostedt 	ftrace_update_tot_cnt += ftrace_update_cnt;
11343d083395SSteven Rostedt 
113516444a8aSArnaldo Carvalho de Melo 	return 0;
113616444a8aSArnaldo Carvalho de Melo }
113716444a8aSArnaldo Carvalho de Melo 
113868bf21aaSSteven Rostedt static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
11393c1720f0SSteven Rostedt {
11403c1720f0SSteven Rostedt 	struct ftrace_page *pg;
11413c1720f0SSteven Rostedt 	int cnt;
11423c1720f0SSteven Rostedt 	int i;
11433c1720f0SSteven Rostedt 
11443c1720f0SSteven Rostedt 	/* allocate a few pages */
11453c1720f0SSteven Rostedt 	ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL);
11463c1720f0SSteven Rostedt 	if (!ftrace_pages_start)
11473c1720f0SSteven Rostedt 		return -1;
11483c1720f0SSteven Rostedt 
11493c1720f0SSteven Rostedt 	/*
11503c1720f0SSteven Rostedt 	 * Allocate a few more pages.
11513c1720f0SSteven Rostedt 	 *
11523c1720f0SSteven Rostedt 	 * TODO: have some parser search vmlinux before
11533c1720f0SSteven Rostedt 	 *   final linking to find all calls to ftrace.
11543c1720f0SSteven Rostedt 	 *   Then we can:
11553c1720f0SSteven Rostedt 	 *    a) know how many pages to allocate.
11563c1720f0SSteven Rostedt 	 *     and/or
11573c1720f0SSteven Rostedt 	 *    b) set up the table then.
11583c1720f0SSteven Rostedt 	 *
11593c1720f0SSteven Rostedt 	 *  The dynamic code is still necessary for
11603c1720f0SSteven Rostedt 	 *  modules.
11613c1720f0SSteven Rostedt 	 */
11623c1720f0SSteven Rostedt 
11633c1720f0SSteven Rostedt 	pg = ftrace_pages = ftrace_pages_start;
11643c1720f0SSteven Rostedt 
116568bf21aaSSteven Rostedt 	cnt = num_to_init / ENTRIES_PER_PAGE;
116608f5ac90SSteven Rostedt 	pr_info("ftrace: allocating %ld entries in %d pages\n",
11675821e1b7Swalimis 		num_to_init, cnt + 1);
11683c1720f0SSteven Rostedt 
11693c1720f0SSteven Rostedt 	for (i = 0; i < cnt; i++) {
11703c1720f0SSteven Rostedt 		pg->next = (void *)get_zeroed_page(GFP_KERNEL);
11713c1720f0SSteven Rostedt 
11723c1720f0SSteven Rostedt 		/* If we fail, we'll try later anyway */
11733c1720f0SSteven Rostedt 		if (!pg->next)
11743c1720f0SSteven Rostedt 			break;
11753c1720f0SSteven Rostedt 
11763c1720f0SSteven Rostedt 		pg = pg->next;
11773c1720f0SSteven Rostedt 	}
11783c1720f0SSteven Rostedt 
11793c1720f0SSteven Rostedt 	return 0;
11803c1720f0SSteven Rostedt }
11813c1720f0SSteven Rostedt 
11825072c59fSSteven Rostedt enum {
11835072c59fSSteven Rostedt 	FTRACE_ITER_FILTER	= (1 << 0),
11845072c59fSSteven Rostedt 	FTRACE_ITER_CONT	= (1 << 1),
118541c52c0dSSteven Rostedt 	FTRACE_ITER_NOTRACE	= (1 << 2),
1186eb9a7bf0SAbhishek Sagar 	FTRACE_ITER_FAILURES	= (1 << 3),
11870c75a3edSSteven Rostedt 	FTRACE_ITER_PRINTALL	= (1 << 4),
11888fc0c701SSteven Rostedt 	FTRACE_ITER_HASH	= (1 << 5),
11895072c59fSSteven Rostedt };
11905072c59fSSteven Rostedt 
11915072c59fSSteven Rostedt #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
11925072c59fSSteven Rostedt 
11935072c59fSSteven Rostedt struct ftrace_iterator {
11945072c59fSSteven Rostedt 	struct ftrace_page	*pg;
11958fc0c701SSteven Rostedt 	int			hidx;
1196431aa3fbSSteven Rostedt 	int			idx;
11975072c59fSSteven Rostedt 	unsigned		flags;
11985072c59fSSteven Rostedt 	unsigned char		buffer[FTRACE_BUFF_MAX+1];
11995072c59fSSteven Rostedt 	unsigned		buffer_idx;
12005072c59fSSteven Rostedt 	unsigned		filtered;
12015072c59fSSteven Rostedt };
12025072c59fSSteven Rostedt 
1203e309b41dSIngo Molnar static void *
12048fc0c701SSteven Rostedt t_hash_next(struct seq_file *m, void *v, loff_t *pos)
12058fc0c701SSteven Rostedt {
12068fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
12078fc0c701SSteven Rostedt 	struct hlist_node *hnd = v;
12088fc0c701SSteven Rostedt 	struct hlist_head *hhd;
12098fc0c701SSteven Rostedt 
12108fc0c701SSteven Rostedt 	WARN_ON(!(iter->flags & FTRACE_ITER_HASH));
12118fc0c701SSteven Rostedt 
12128fc0c701SSteven Rostedt 	(*pos)++;
12138fc0c701SSteven Rostedt 
12148fc0c701SSteven Rostedt  retry:
12158fc0c701SSteven Rostedt 	if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
12168fc0c701SSteven Rostedt 		return NULL;
12178fc0c701SSteven Rostedt 
12188fc0c701SSteven Rostedt 	hhd = &ftrace_func_hash[iter->hidx];
12198fc0c701SSteven Rostedt 
12208fc0c701SSteven Rostedt 	if (hlist_empty(hhd)) {
12218fc0c701SSteven Rostedt 		iter->hidx++;
12228fc0c701SSteven Rostedt 		hnd = NULL;
12238fc0c701SSteven Rostedt 		goto retry;
12248fc0c701SSteven Rostedt 	}
12258fc0c701SSteven Rostedt 
12268fc0c701SSteven Rostedt 	if (!hnd)
12278fc0c701SSteven Rostedt 		hnd = hhd->first;
12288fc0c701SSteven Rostedt 	else {
12298fc0c701SSteven Rostedt 		hnd = hnd->next;
12308fc0c701SSteven Rostedt 		if (!hnd) {
12318fc0c701SSteven Rostedt 			iter->hidx++;
12328fc0c701SSteven Rostedt 			goto retry;
12338fc0c701SSteven Rostedt 		}
12348fc0c701SSteven Rostedt 	}
12358fc0c701SSteven Rostedt 
12368fc0c701SSteven Rostedt 	return hnd;
12378fc0c701SSteven Rostedt }
12388fc0c701SSteven Rostedt 
12398fc0c701SSteven Rostedt static void *t_hash_start(struct seq_file *m, loff_t *pos)
12408fc0c701SSteven Rostedt {
12418fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
12428fc0c701SSteven Rostedt 	void *p = NULL;
12438fc0c701SSteven Rostedt 
12448fc0c701SSteven Rostedt 	iter->flags |= FTRACE_ITER_HASH;
12458fc0c701SSteven Rostedt 
12468fc0c701SSteven Rostedt 	return t_hash_next(m, p, pos);
12478fc0c701SSteven Rostedt }
12488fc0c701SSteven Rostedt 
12498fc0c701SSteven Rostedt static int t_hash_show(struct seq_file *m, void *v)
12508fc0c701SSteven Rostedt {
1251b6887d79SSteven Rostedt 	struct ftrace_func_probe *rec;
12528fc0c701SSteven Rostedt 	struct hlist_node *hnd = v;
12538fc0c701SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
12548fc0c701SSteven Rostedt 
1255b6887d79SSteven Rostedt 	rec = hlist_entry(hnd, struct ftrace_func_probe, node);
12568fc0c701SSteven Rostedt 
1257809dcf29SSteven Rostedt 	if (rec->ops->print)
1258809dcf29SSteven Rostedt 		return rec->ops->print(m, rec->ip, rec->ops, rec->data);
1259809dcf29SSteven Rostedt 
12608fc0c701SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
12618fc0c701SSteven Rostedt 	seq_printf(m, "%s:", str);
12628fc0c701SSteven Rostedt 
12638fc0c701SSteven Rostedt 	kallsyms_lookup((unsigned long)rec->ops->func, NULL, NULL, NULL, str);
12648fc0c701SSteven Rostedt 	seq_printf(m, "%s", str);
12658fc0c701SSteven Rostedt 
12668fc0c701SSteven Rostedt 	if (rec->data)
12678fc0c701SSteven Rostedt 		seq_printf(m, ":%p", rec->data);
12688fc0c701SSteven Rostedt 	seq_putc(m, '\n');
12698fc0c701SSteven Rostedt 
12708fc0c701SSteven Rostedt 	return 0;
12718fc0c701SSteven Rostedt }
12728fc0c701SSteven Rostedt 
12738fc0c701SSteven Rostedt static void *
12745072c59fSSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos)
12755072c59fSSteven Rostedt {
12765072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
12775072c59fSSteven Rostedt 	struct dyn_ftrace *rec = NULL;
12785072c59fSSteven Rostedt 
12798fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
12808fc0c701SSteven Rostedt 		return t_hash_next(m, v, pos);
12818fc0c701SSteven Rostedt 
12825072c59fSSteven Rostedt 	(*pos)++;
12835072c59fSSteven Rostedt 
12840c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL)
12850c75a3edSSteven Rostedt 		return NULL;
12860c75a3edSSteven Rostedt 
12875072c59fSSteven Rostedt  retry:
12885072c59fSSteven Rostedt 	if (iter->idx >= iter->pg->index) {
12895072c59fSSteven Rostedt 		if (iter->pg->next) {
12905072c59fSSteven Rostedt 			iter->pg = iter->pg->next;
12915072c59fSSteven Rostedt 			iter->idx = 0;
12925072c59fSSteven Rostedt 			goto retry;
129350cdaf08SLiming Wang 		} else {
129450cdaf08SLiming Wang 			iter->idx = -1;
12955072c59fSSteven Rostedt 		}
12965072c59fSSteven Rostedt 	} else {
12975072c59fSSteven Rostedt 		rec = &iter->pg->records[iter->idx++];
1298a9fdda33SSteven Rostedt 		if ((rec->flags & FTRACE_FL_FREE) ||
1299a9fdda33SSteven Rostedt 
1300a9fdda33SSteven Rostedt 		    (!(iter->flags & FTRACE_ITER_FAILURES) &&
1301eb9a7bf0SAbhishek Sagar 		     (rec->flags & FTRACE_FL_FAILED)) ||
1302eb9a7bf0SAbhishek Sagar 
1303eb9a7bf0SAbhishek Sagar 		    ((iter->flags & FTRACE_ITER_FAILURES) &&
1304a9fdda33SSteven Rostedt 		     !(rec->flags & FTRACE_FL_FAILED)) ||
1305eb9a7bf0SAbhishek Sagar 
13060183fb1cSSteven Rostedt 		    ((iter->flags & FTRACE_ITER_FILTER) &&
13070183fb1cSSteven Rostedt 		     !(rec->flags & FTRACE_FL_FILTER)) ||
13080183fb1cSSteven Rostedt 
130941c52c0dSSteven Rostedt 		    ((iter->flags & FTRACE_ITER_NOTRACE) &&
131041c52c0dSSteven Rostedt 		     !(rec->flags & FTRACE_FL_NOTRACE))) {
13115072c59fSSteven Rostedt 			rec = NULL;
13125072c59fSSteven Rostedt 			goto retry;
13135072c59fSSteven Rostedt 		}
13145072c59fSSteven Rostedt 	}
13155072c59fSSteven Rostedt 
13165072c59fSSteven Rostedt 	return rec;
13175072c59fSSteven Rostedt }
13185072c59fSSteven Rostedt 
13195072c59fSSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos)
13205072c59fSSteven Rostedt {
13215072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
13225072c59fSSteven Rostedt 	void *p = NULL;
13235072c59fSSteven Rostedt 
13248fc0c701SSteven Rostedt 	mutex_lock(&ftrace_lock);
13250c75a3edSSteven Rostedt 	/*
13260c75a3edSSteven Rostedt 	 * For set_ftrace_filter reading, if we have the filter
13270c75a3edSSteven Rostedt 	 * off, we can short cut and just print out that all
13280c75a3edSSteven Rostedt 	 * functions are enabled.
13290c75a3edSSteven Rostedt 	 */
13300c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_FILTER && !ftrace_filtered) {
13310c75a3edSSteven Rostedt 		if (*pos > 0)
13328fc0c701SSteven Rostedt 			return t_hash_start(m, pos);
13330c75a3edSSteven Rostedt 		iter->flags |= FTRACE_ITER_PRINTALL;
13340c75a3edSSteven Rostedt 		(*pos)++;
13350c75a3edSSteven Rostedt 		return iter;
13360c75a3edSSteven Rostedt 	}
13370c75a3edSSteven Rostedt 
13388fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
13398fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
13408fc0c701SSteven Rostedt 
134150cdaf08SLiming Wang 	if (*pos > 0) {
134250cdaf08SLiming Wang 		if (iter->idx < 0)
134350cdaf08SLiming Wang 			return p;
134450cdaf08SLiming Wang 		(*pos)--;
134550cdaf08SLiming Wang 		iter->idx--;
134650cdaf08SLiming Wang 	}
13475821e1b7Swalimis 
134850cdaf08SLiming Wang 	p = t_next(m, p, pos);
13495072c59fSSteven Rostedt 
13508fc0c701SSteven Rostedt 	if (!p)
13518fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
13528fc0c701SSteven Rostedt 
13535072c59fSSteven Rostedt 	return p;
13545072c59fSSteven Rostedt }
13555072c59fSSteven Rostedt 
13565072c59fSSteven Rostedt static void t_stop(struct seq_file *m, void *p)
13575072c59fSSteven Rostedt {
13588fc0c701SSteven Rostedt 	mutex_unlock(&ftrace_lock);
13595072c59fSSteven Rostedt }
13605072c59fSSteven Rostedt 
13615072c59fSSteven Rostedt static int t_show(struct seq_file *m, void *v)
13625072c59fSSteven Rostedt {
13630c75a3edSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
13645072c59fSSteven Rostedt 	struct dyn_ftrace *rec = v;
13655072c59fSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
13665072c59fSSteven Rostedt 
13678fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
13688fc0c701SSteven Rostedt 		return t_hash_show(m, v);
13698fc0c701SSteven Rostedt 
13700c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL) {
13710c75a3edSSteven Rostedt 		seq_printf(m, "#### all functions enabled ####\n");
13720c75a3edSSteven Rostedt 		return 0;
13730c75a3edSSteven Rostedt 	}
13740c75a3edSSteven Rostedt 
13755072c59fSSteven Rostedt 	if (!rec)
13765072c59fSSteven Rostedt 		return 0;
13775072c59fSSteven Rostedt 
13785072c59fSSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
13795072c59fSSteven Rostedt 
138050cdaf08SLiming Wang 	seq_printf(m, "%s\n", str);
13815072c59fSSteven Rostedt 
13825072c59fSSteven Rostedt 	return 0;
13835072c59fSSteven Rostedt }
13845072c59fSSteven Rostedt 
13855072c59fSSteven Rostedt static struct seq_operations show_ftrace_seq_ops = {
13865072c59fSSteven Rostedt 	.start = t_start,
13875072c59fSSteven Rostedt 	.next = t_next,
13885072c59fSSteven Rostedt 	.stop = t_stop,
13895072c59fSSteven Rostedt 	.show = t_show,
13905072c59fSSteven Rostedt };
13915072c59fSSteven Rostedt 
1392e309b41dSIngo Molnar static int
13935072c59fSSteven Rostedt ftrace_avail_open(struct inode *inode, struct file *file)
13945072c59fSSteven Rostedt {
13955072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
13965072c59fSSteven Rostedt 	int ret;
13975072c59fSSteven Rostedt 
13984eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
13994eebcc81SSteven Rostedt 		return -ENODEV;
14004eebcc81SSteven Rostedt 
14015072c59fSSteven Rostedt 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
14025072c59fSSteven Rostedt 	if (!iter)
14035072c59fSSteven Rostedt 		return -ENOMEM;
14045072c59fSSteven Rostedt 
14055072c59fSSteven Rostedt 	iter->pg = ftrace_pages_start;
14065072c59fSSteven Rostedt 
14075072c59fSSteven Rostedt 	ret = seq_open(file, &show_ftrace_seq_ops);
14085072c59fSSteven Rostedt 	if (!ret) {
14095072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
14104bf39a94SIngo Molnar 
14115072c59fSSteven Rostedt 		m->private = iter;
14124bf39a94SIngo Molnar 	} else {
14135072c59fSSteven Rostedt 		kfree(iter);
14144bf39a94SIngo Molnar 	}
14155072c59fSSteven Rostedt 
14165072c59fSSteven Rostedt 	return ret;
14175072c59fSSteven Rostedt }
14185072c59fSSteven Rostedt 
14195072c59fSSteven Rostedt int ftrace_avail_release(struct inode *inode, struct file *file)
14205072c59fSSteven Rostedt {
14215072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
14225072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
14235072c59fSSteven Rostedt 
14245072c59fSSteven Rostedt 	seq_release(inode, file);
14255072c59fSSteven Rostedt 	kfree(iter);
14264bf39a94SIngo Molnar 
14275072c59fSSteven Rostedt 	return 0;
14285072c59fSSteven Rostedt }
14295072c59fSSteven Rostedt 
1430eb9a7bf0SAbhishek Sagar static int
1431eb9a7bf0SAbhishek Sagar ftrace_failures_open(struct inode *inode, struct file *file)
1432eb9a7bf0SAbhishek Sagar {
1433eb9a7bf0SAbhishek Sagar 	int ret;
1434eb9a7bf0SAbhishek Sagar 	struct seq_file *m;
1435eb9a7bf0SAbhishek Sagar 	struct ftrace_iterator *iter;
1436eb9a7bf0SAbhishek Sagar 
1437eb9a7bf0SAbhishek Sagar 	ret = ftrace_avail_open(inode, file);
1438eb9a7bf0SAbhishek Sagar 	if (!ret) {
1439eb9a7bf0SAbhishek Sagar 		m = (struct seq_file *)file->private_data;
1440eb9a7bf0SAbhishek Sagar 		iter = (struct ftrace_iterator *)m->private;
1441eb9a7bf0SAbhishek Sagar 		iter->flags = FTRACE_ITER_FAILURES;
1442eb9a7bf0SAbhishek Sagar 	}
1443eb9a7bf0SAbhishek Sagar 
1444eb9a7bf0SAbhishek Sagar 	return ret;
1445eb9a7bf0SAbhishek Sagar }
1446eb9a7bf0SAbhishek Sagar 
1447eb9a7bf0SAbhishek Sagar 
144841c52c0dSSteven Rostedt static void ftrace_filter_reset(int enable)
14495072c59fSSteven Rostedt {
14505072c59fSSteven Rostedt 	struct ftrace_page *pg;
14515072c59fSSteven Rostedt 	struct dyn_ftrace *rec;
145241c52c0dSSteven Rostedt 	unsigned long type = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
14535072c59fSSteven Rostedt 
145452baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
145541c52c0dSSteven Rostedt 	if (enable)
14565072c59fSSteven Rostedt 		ftrace_filtered = 0;
1457265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
14585072c59fSSteven Rostedt 		if (rec->flags & FTRACE_FL_FAILED)
14595072c59fSSteven Rostedt 			continue;
146041c52c0dSSteven Rostedt 		rec->flags &= ~type;
1461265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
146252baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
14635072c59fSSteven Rostedt }
14645072c59fSSteven Rostedt 
1465e309b41dSIngo Molnar static int
146641c52c0dSSteven Rostedt ftrace_regex_open(struct inode *inode, struct file *file, int enable)
14675072c59fSSteven Rostedt {
14685072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
14695072c59fSSteven Rostedt 	int ret = 0;
14705072c59fSSteven Rostedt 
14714eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
14724eebcc81SSteven Rostedt 		return -ENODEV;
14734eebcc81SSteven Rostedt 
14745072c59fSSteven Rostedt 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
14755072c59fSSteven Rostedt 	if (!iter)
14765072c59fSSteven Rostedt 		return -ENOMEM;
14775072c59fSSteven Rostedt 
147841c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
14795072c59fSSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
14805072c59fSSteven Rostedt 	    !(file->f_flags & O_APPEND))
148141c52c0dSSteven Rostedt 		ftrace_filter_reset(enable);
14825072c59fSSteven Rostedt 
14835072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
14845072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
148541c52c0dSSteven Rostedt 		iter->flags = enable ? FTRACE_ITER_FILTER :
148641c52c0dSSteven Rostedt 			FTRACE_ITER_NOTRACE;
14875072c59fSSteven Rostedt 
14885072c59fSSteven Rostedt 		ret = seq_open(file, &show_ftrace_seq_ops);
14895072c59fSSteven Rostedt 		if (!ret) {
14905072c59fSSteven Rostedt 			struct seq_file *m = file->private_data;
14915072c59fSSteven Rostedt 			m->private = iter;
14925072c59fSSteven Rostedt 		} else
14935072c59fSSteven Rostedt 			kfree(iter);
14945072c59fSSteven Rostedt 	} else
14955072c59fSSteven Rostedt 		file->private_data = iter;
149641c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
14975072c59fSSteven Rostedt 
14985072c59fSSteven Rostedt 	return ret;
14995072c59fSSteven Rostedt }
15005072c59fSSteven Rostedt 
150141c52c0dSSteven Rostedt static int
150241c52c0dSSteven Rostedt ftrace_filter_open(struct inode *inode, struct file *file)
150341c52c0dSSteven Rostedt {
150441c52c0dSSteven Rostedt 	return ftrace_regex_open(inode, file, 1);
150541c52c0dSSteven Rostedt }
150641c52c0dSSteven Rostedt 
150741c52c0dSSteven Rostedt static int
150841c52c0dSSteven Rostedt ftrace_notrace_open(struct inode *inode, struct file *file)
150941c52c0dSSteven Rostedt {
151041c52c0dSSteven Rostedt 	return ftrace_regex_open(inode, file, 0);
151141c52c0dSSteven Rostedt }
151241c52c0dSSteven Rostedt 
1513e309b41dSIngo Molnar static loff_t
151441c52c0dSSteven Rostedt ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
15155072c59fSSteven Rostedt {
15165072c59fSSteven Rostedt 	loff_t ret;
15175072c59fSSteven Rostedt 
15185072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ)
15195072c59fSSteven Rostedt 		ret = seq_lseek(file, offset, origin);
15205072c59fSSteven Rostedt 	else
15215072c59fSSteven Rostedt 		file->f_pos = ret = 1;
15225072c59fSSteven Rostedt 
15235072c59fSSteven Rostedt 	return ret;
15245072c59fSSteven Rostedt }
15255072c59fSSteven Rostedt 
15265072c59fSSteven Rostedt enum {
15275072c59fSSteven Rostedt 	MATCH_FULL,
15285072c59fSSteven Rostedt 	MATCH_FRONT_ONLY,
15295072c59fSSteven Rostedt 	MATCH_MIDDLE_ONLY,
15305072c59fSSteven Rostedt 	MATCH_END_ONLY,
15315072c59fSSteven Rostedt };
15325072c59fSSteven Rostedt 
15339f4801e3SSteven Rostedt /*
15349f4801e3SSteven Rostedt  * (static function - no need for kernel doc)
15359f4801e3SSteven Rostedt  *
15369f4801e3SSteven Rostedt  * Pass in a buffer containing a glob and this function will
15379f4801e3SSteven Rostedt  * set search to point to the search part of the buffer and
15389f4801e3SSteven Rostedt  * return the type of search it is (see enum above).
15399f4801e3SSteven Rostedt  * This does modify buff.
15409f4801e3SSteven Rostedt  *
15419f4801e3SSteven Rostedt  * Returns enum type.
15429f4801e3SSteven Rostedt  *  search returns the pointer to use for comparison.
15439f4801e3SSteven Rostedt  *  not returns 1 if buff started with a '!'
15449f4801e3SSteven Rostedt  *     0 otherwise.
15459f4801e3SSteven Rostedt  */
15469f4801e3SSteven Rostedt static int
154764e7c440SSteven Rostedt ftrace_setup_glob(char *buff, int len, char **search, int *not)
15485072c59fSSteven Rostedt {
15495072c59fSSteven Rostedt 	int type = MATCH_FULL;
15509f4801e3SSteven Rostedt 	int i;
1551ea3a6d6dSSteven Rostedt 
1552ea3a6d6dSSteven Rostedt 	if (buff[0] == '!') {
15539f4801e3SSteven Rostedt 		*not = 1;
1554ea3a6d6dSSteven Rostedt 		buff++;
1555ea3a6d6dSSteven Rostedt 		len--;
15569f4801e3SSteven Rostedt 	} else
15579f4801e3SSteven Rostedt 		*not = 0;
15589f4801e3SSteven Rostedt 
15599f4801e3SSteven Rostedt 	*search = buff;
15605072c59fSSteven Rostedt 
15615072c59fSSteven Rostedt 	for (i = 0; i < len; i++) {
15625072c59fSSteven Rostedt 		if (buff[i] == '*') {
15635072c59fSSteven Rostedt 			if (!i) {
15649f4801e3SSteven Rostedt 				*search = buff + 1;
15655072c59fSSteven Rostedt 				type = MATCH_END_ONLY;
15665072c59fSSteven Rostedt 			} else {
15679f4801e3SSteven Rostedt 				if (type == MATCH_END_ONLY)
15685072c59fSSteven Rostedt 					type = MATCH_MIDDLE_ONLY;
15699f4801e3SSteven Rostedt 				else
15705072c59fSSteven Rostedt 					type = MATCH_FRONT_ONLY;
15715072c59fSSteven Rostedt 				buff[i] = 0;
15725072c59fSSteven Rostedt 				break;
15735072c59fSSteven Rostedt 			}
15745072c59fSSteven Rostedt 		}
15755072c59fSSteven Rostedt 	}
15765072c59fSSteven Rostedt 
15779f4801e3SSteven Rostedt 	return type;
15789f4801e3SSteven Rostedt }
15799f4801e3SSteven Rostedt 
158064e7c440SSteven Rostedt static int ftrace_match(char *str, char *regex, int len, int type)
15819f4801e3SSteven Rostedt {
15829f4801e3SSteven Rostedt 	int matched = 0;
15839f4801e3SSteven Rostedt 	char *ptr;
15849f4801e3SSteven Rostedt 
15859f4801e3SSteven Rostedt 	switch (type) {
15869f4801e3SSteven Rostedt 	case MATCH_FULL:
15879f4801e3SSteven Rostedt 		if (strcmp(str, regex) == 0)
15889f4801e3SSteven Rostedt 			matched = 1;
15899f4801e3SSteven Rostedt 		break;
15909f4801e3SSteven Rostedt 	case MATCH_FRONT_ONLY:
15919f4801e3SSteven Rostedt 		if (strncmp(str, regex, len) == 0)
15929f4801e3SSteven Rostedt 			matched = 1;
15939f4801e3SSteven Rostedt 		break;
15949f4801e3SSteven Rostedt 	case MATCH_MIDDLE_ONLY:
15959f4801e3SSteven Rostedt 		if (strstr(str, regex))
15969f4801e3SSteven Rostedt 			matched = 1;
15979f4801e3SSteven Rostedt 		break;
15989f4801e3SSteven Rostedt 	case MATCH_END_ONLY:
15999f4801e3SSteven Rostedt 		ptr = strstr(str, regex);
16009f4801e3SSteven Rostedt 		if (ptr && (ptr[len] == 0))
16019f4801e3SSteven Rostedt 			matched = 1;
16029f4801e3SSteven Rostedt 		break;
16039f4801e3SSteven Rostedt 	}
16049f4801e3SSteven Rostedt 
16059f4801e3SSteven Rostedt 	return matched;
16069f4801e3SSteven Rostedt }
16079f4801e3SSteven Rostedt 
160864e7c440SSteven Rostedt static int
160964e7c440SSteven Rostedt ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
161064e7c440SSteven Rostedt {
161164e7c440SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
161264e7c440SSteven Rostedt 
161364e7c440SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
161464e7c440SSteven Rostedt 	return ftrace_match(str, regex, len, type);
161564e7c440SSteven Rostedt }
161664e7c440SSteven Rostedt 
16179f4801e3SSteven Rostedt static void ftrace_match_records(char *buff, int len, int enable)
16189f4801e3SSteven Rostedt {
16196a24a244SSteven Rostedt 	unsigned int search_len;
16209f4801e3SSteven Rostedt 	struct ftrace_page *pg;
16219f4801e3SSteven Rostedt 	struct dyn_ftrace *rec;
16226a24a244SSteven Rostedt 	unsigned long flag;
16236a24a244SSteven Rostedt 	char *search;
16249f4801e3SSteven Rostedt 	int type;
16259f4801e3SSteven Rostedt 	int not;
16269f4801e3SSteven Rostedt 
16276a24a244SSteven Rostedt 	flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
16289f4801e3SSteven Rostedt 	type = ftrace_setup_glob(buff, len, &search, &not);
16299f4801e3SSteven Rostedt 
16309f4801e3SSteven Rostedt 	search_len = strlen(search);
16319f4801e3SSteven Rostedt 
163252baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
1633265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
16345072c59fSSteven Rostedt 
16355072c59fSSteven Rostedt 		if (rec->flags & FTRACE_FL_FAILED)
16365072c59fSSteven Rostedt 			continue;
16379f4801e3SSteven Rostedt 
16389f4801e3SSteven Rostedt 		if (ftrace_match_record(rec, search, search_len, type)) {
1639ea3a6d6dSSteven Rostedt 			if (not)
1640ea3a6d6dSSteven Rostedt 				rec->flags &= ~flag;
1641ea3a6d6dSSteven Rostedt 			else
164241c52c0dSSteven Rostedt 				rec->flags |= flag;
16435072c59fSSteven Rostedt 		}
1644e68746a2SSteven Rostedt 		/*
1645e68746a2SSteven Rostedt 		 * Only enable filtering if we have a function that
1646e68746a2SSteven Rostedt 		 * is filtered on.
1647e68746a2SSteven Rostedt 		 */
1648e68746a2SSteven Rostedt 		if (enable && (rec->flags & FTRACE_FL_FILTER))
1649e68746a2SSteven Rostedt 			ftrace_filtered = 1;
1650265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
165152baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
16525072c59fSSteven Rostedt }
16535072c59fSSteven Rostedt 
165464e7c440SSteven Rostedt static int
165564e7c440SSteven Rostedt ftrace_match_module_record(struct dyn_ftrace *rec, char *mod,
165664e7c440SSteven Rostedt 			   char *regex, int len, int type)
165764e7c440SSteven Rostedt {
165864e7c440SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
165964e7c440SSteven Rostedt 	char *modname;
166064e7c440SSteven Rostedt 
166164e7c440SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
166264e7c440SSteven Rostedt 
166364e7c440SSteven Rostedt 	if (!modname || strcmp(modname, mod))
166464e7c440SSteven Rostedt 		return 0;
166564e7c440SSteven Rostedt 
166664e7c440SSteven Rostedt 	/* blank search means to match all funcs in the mod */
166764e7c440SSteven Rostedt 	if (len)
166864e7c440SSteven Rostedt 		return ftrace_match(str, regex, len, type);
166964e7c440SSteven Rostedt 	else
167064e7c440SSteven Rostedt 		return 1;
167164e7c440SSteven Rostedt }
167264e7c440SSteven Rostedt 
167364e7c440SSteven Rostedt static void ftrace_match_module_records(char *buff, char *mod, int enable)
167464e7c440SSteven Rostedt {
16756a24a244SSteven Rostedt 	unsigned search_len = 0;
167664e7c440SSteven Rostedt 	struct ftrace_page *pg;
167764e7c440SSteven Rostedt 	struct dyn_ftrace *rec;
167864e7c440SSteven Rostedt 	int type = MATCH_FULL;
16796a24a244SSteven Rostedt 	char *search = buff;
16806a24a244SSteven Rostedt 	unsigned long flag;
168164e7c440SSteven Rostedt 	int not = 0;
168264e7c440SSteven Rostedt 
16836a24a244SSteven Rostedt 	flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
16846a24a244SSteven Rostedt 
168564e7c440SSteven Rostedt 	/* blank or '*' mean the same */
168664e7c440SSteven Rostedt 	if (strcmp(buff, "*") == 0)
168764e7c440SSteven Rostedt 		buff[0] = 0;
168864e7c440SSteven Rostedt 
168964e7c440SSteven Rostedt 	/* handle the case of 'dont filter this module' */
169064e7c440SSteven Rostedt 	if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) {
169164e7c440SSteven Rostedt 		buff[0] = 0;
169264e7c440SSteven Rostedt 		not = 1;
169364e7c440SSteven Rostedt 	}
169464e7c440SSteven Rostedt 
169564e7c440SSteven Rostedt 	if (strlen(buff)) {
169664e7c440SSteven Rostedt 		type = ftrace_setup_glob(buff, strlen(buff), &search, &not);
169764e7c440SSteven Rostedt 		search_len = strlen(search);
169864e7c440SSteven Rostedt 	}
169964e7c440SSteven Rostedt 
170052baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
170164e7c440SSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
170264e7c440SSteven Rostedt 
170364e7c440SSteven Rostedt 		if (rec->flags & FTRACE_FL_FAILED)
170464e7c440SSteven Rostedt 			continue;
170564e7c440SSteven Rostedt 
170664e7c440SSteven Rostedt 		if (ftrace_match_module_record(rec, mod,
170764e7c440SSteven Rostedt 					       search, search_len, type)) {
170864e7c440SSteven Rostedt 			if (not)
170964e7c440SSteven Rostedt 				rec->flags &= ~flag;
171064e7c440SSteven Rostedt 			else
171164e7c440SSteven Rostedt 				rec->flags |= flag;
171264e7c440SSteven Rostedt 		}
1713e68746a2SSteven Rostedt 		if (enable && (rec->flags & FTRACE_FL_FILTER))
1714e68746a2SSteven Rostedt 			ftrace_filtered = 1;
171564e7c440SSteven Rostedt 
171664e7c440SSteven Rostedt 	} while_for_each_ftrace_rec();
171752baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
171864e7c440SSteven Rostedt }
171964e7c440SSteven Rostedt 
1720f6180773SSteven Rostedt /*
1721f6180773SSteven Rostedt  * We register the module command as a template to show others how
1722f6180773SSteven Rostedt  * to register the a command as well.
1723f6180773SSteven Rostedt  */
1724f6180773SSteven Rostedt 
1725f6180773SSteven Rostedt static int
1726f6180773SSteven Rostedt ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
1727f6180773SSteven Rostedt {
1728f6180773SSteven Rostedt 	char *mod;
1729f6180773SSteven Rostedt 
1730f6180773SSteven Rostedt 	/*
1731f6180773SSteven Rostedt 	 * cmd == 'mod' because we only registered this func
1732f6180773SSteven Rostedt 	 * for the 'mod' ftrace_func_command.
1733f6180773SSteven Rostedt 	 * But if you register one func with multiple commands,
1734f6180773SSteven Rostedt 	 * you can tell which command was used by the cmd
1735f6180773SSteven Rostedt 	 * parameter.
1736f6180773SSteven Rostedt 	 */
1737f6180773SSteven Rostedt 
1738f6180773SSteven Rostedt 	/* we must have a module name */
1739f6180773SSteven Rostedt 	if (!param)
1740f6180773SSteven Rostedt 		return -EINVAL;
1741f6180773SSteven Rostedt 
1742f6180773SSteven Rostedt 	mod = strsep(&param, ":");
1743f6180773SSteven Rostedt 	if (!strlen(mod))
1744f6180773SSteven Rostedt 		return -EINVAL;
1745f6180773SSteven Rostedt 
1746f6180773SSteven Rostedt 	ftrace_match_module_records(func, mod, enable);
1747f6180773SSteven Rostedt 	return 0;
1748f6180773SSteven Rostedt }
1749f6180773SSteven Rostedt 
1750f6180773SSteven Rostedt static struct ftrace_func_command ftrace_mod_cmd = {
1751f6180773SSteven Rostedt 	.name			= "mod",
1752f6180773SSteven Rostedt 	.func			= ftrace_mod_callback,
1753f6180773SSteven Rostedt };
1754f6180773SSteven Rostedt 
1755f6180773SSteven Rostedt static int __init ftrace_mod_cmd_init(void)
1756f6180773SSteven Rostedt {
1757f6180773SSteven Rostedt 	return register_ftrace_command(&ftrace_mod_cmd);
1758f6180773SSteven Rostedt }
1759f6180773SSteven Rostedt device_initcall(ftrace_mod_cmd_init);
1760f6180773SSteven Rostedt 
176159df055fSSteven Rostedt static void
1762b6887d79SSteven Rostedt function_trace_probe_call(unsigned long ip, unsigned long parent_ip)
176359df055fSSteven Rostedt {
1764b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
176559df055fSSteven Rostedt 	struct hlist_head *hhd;
176659df055fSSteven Rostedt 	struct hlist_node *n;
176759df055fSSteven Rostedt 	unsigned long key;
176859df055fSSteven Rostedt 	int resched;
176959df055fSSteven Rostedt 
177059df055fSSteven Rostedt 	key = hash_long(ip, FTRACE_HASH_BITS);
177159df055fSSteven Rostedt 
177259df055fSSteven Rostedt 	hhd = &ftrace_func_hash[key];
177359df055fSSteven Rostedt 
177459df055fSSteven Rostedt 	if (hlist_empty(hhd))
177559df055fSSteven Rostedt 		return;
177659df055fSSteven Rostedt 
177759df055fSSteven Rostedt 	/*
177859df055fSSteven Rostedt 	 * Disable preemption for these calls to prevent a RCU grace
177959df055fSSteven Rostedt 	 * period. This syncs the hash iteration and freeing of items
178059df055fSSteven Rostedt 	 * on the hash. rcu_read_lock is too dangerous here.
178159df055fSSteven Rostedt 	 */
178259df055fSSteven Rostedt 	resched = ftrace_preempt_disable();
178359df055fSSteven Rostedt 	hlist_for_each_entry_rcu(entry, n, hhd, node) {
178459df055fSSteven Rostedt 		if (entry->ip == ip)
178559df055fSSteven Rostedt 			entry->ops->func(ip, parent_ip, &entry->data);
178659df055fSSteven Rostedt 	}
178759df055fSSteven Rostedt 	ftrace_preempt_enable(resched);
178859df055fSSteven Rostedt }
178959df055fSSteven Rostedt 
1790b6887d79SSteven Rostedt static struct ftrace_ops trace_probe_ops __read_mostly =
179159df055fSSteven Rostedt {
1792b6887d79SSteven Rostedt 	.func = function_trace_probe_call,
179359df055fSSteven Rostedt };
179459df055fSSteven Rostedt 
1795b6887d79SSteven Rostedt static int ftrace_probe_registered;
179659df055fSSteven Rostedt 
1797b6887d79SSteven Rostedt static void __enable_ftrace_function_probe(void)
179859df055fSSteven Rostedt {
179959df055fSSteven Rostedt 	int i;
180059df055fSSteven Rostedt 
1801b6887d79SSteven Rostedt 	if (ftrace_probe_registered)
180259df055fSSteven Rostedt 		return;
180359df055fSSteven Rostedt 
180459df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
180559df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
180659df055fSSteven Rostedt 		if (hhd->first)
180759df055fSSteven Rostedt 			break;
180859df055fSSteven Rostedt 	}
180959df055fSSteven Rostedt 	/* Nothing registered? */
181059df055fSSteven Rostedt 	if (i == FTRACE_FUNC_HASHSIZE)
181159df055fSSteven Rostedt 		return;
181259df055fSSteven Rostedt 
1813b6887d79SSteven Rostedt 	__register_ftrace_function(&trace_probe_ops);
181459df055fSSteven Rostedt 	ftrace_startup(0);
1815b6887d79SSteven Rostedt 	ftrace_probe_registered = 1;
181659df055fSSteven Rostedt }
181759df055fSSteven Rostedt 
1818b6887d79SSteven Rostedt static void __disable_ftrace_function_probe(void)
181959df055fSSteven Rostedt {
182059df055fSSteven Rostedt 	int i;
182159df055fSSteven Rostedt 
1822b6887d79SSteven Rostedt 	if (!ftrace_probe_registered)
182359df055fSSteven Rostedt 		return;
182459df055fSSteven Rostedt 
182559df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
182659df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
182759df055fSSteven Rostedt 		if (hhd->first)
182859df055fSSteven Rostedt 			return;
182959df055fSSteven Rostedt 	}
183059df055fSSteven Rostedt 
183159df055fSSteven Rostedt 	/* no more funcs left */
1832b6887d79SSteven Rostedt 	__unregister_ftrace_function(&trace_probe_ops);
183359df055fSSteven Rostedt 	ftrace_shutdown(0);
1834b6887d79SSteven Rostedt 	ftrace_probe_registered = 0;
183559df055fSSteven Rostedt }
183659df055fSSteven Rostedt 
183759df055fSSteven Rostedt 
183859df055fSSteven Rostedt static void ftrace_free_entry_rcu(struct rcu_head *rhp)
183959df055fSSteven Rostedt {
1840b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry =
1841b6887d79SSteven Rostedt 		container_of(rhp, struct ftrace_func_probe, rcu);
184259df055fSSteven Rostedt 
184359df055fSSteven Rostedt 	if (entry->ops->free)
184459df055fSSteven Rostedt 		entry->ops->free(&entry->data);
184559df055fSSteven Rostedt 	kfree(entry);
184659df055fSSteven Rostedt }
184759df055fSSteven Rostedt 
184859df055fSSteven Rostedt 
184959df055fSSteven Rostedt int
1850b6887d79SSteven Rostedt register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
185159df055fSSteven Rostedt 			      void *data)
185259df055fSSteven Rostedt {
1853b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
185459df055fSSteven Rostedt 	struct ftrace_page *pg;
185559df055fSSteven Rostedt 	struct dyn_ftrace *rec;
185659df055fSSteven Rostedt 	int type, len, not;
18576a24a244SSteven Rostedt 	unsigned long key;
185859df055fSSteven Rostedt 	int count = 0;
185959df055fSSteven Rostedt 	char *search;
186059df055fSSteven Rostedt 
186159df055fSSteven Rostedt 	type = ftrace_setup_glob(glob, strlen(glob), &search, &not);
186259df055fSSteven Rostedt 	len = strlen(search);
186359df055fSSteven Rostedt 
1864b6887d79SSteven Rostedt 	/* we do not support '!' for function probes */
186559df055fSSteven Rostedt 	if (WARN_ON(not))
186659df055fSSteven Rostedt 		return -EINVAL;
186759df055fSSteven Rostedt 
186859df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
186959df055fSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
187059df055fSSteven Rostedt 
187159df055fSSteven Rostedt 		if (rec->flags & FTRACE_FL_FAILED)
187259df055fSSteven Rostedt 			continue;
187359df055fSSteven Rostedt 
187459df055fSSteven Rostedt 		if (!ftrace_match_record(rec, search, len, type))
187559df055fSSteven Rostedt 			continue;
187659df055fSSteven Rostedt 
187759df055fSSteven Rostedt 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
187859df055fSSteven Rostedt 		if (!entry) {
1879b6887d79SSteven Rostedt 			/* If we did not process any, then return error */
188059df055fSSteven Rostedt 			if (!count)
188159df055fSSteven Rostedt 				count = -ENOMEM;
188259df055fSSteven Rostedt 			goto out_unlock;
188359df055fSSteven Rostedt 		}
188459df055fSSteven Rostedt 
188559df055fSSteven Rostedt 		count++;
188659df055fSSteven Rostedt 
188759df055fSSteven Rostedt 		entry->data = data;
188859df055fSSteven Rostedt 
188959df055fSSteven Rostedt 		/*
189059df055fSSteven Rostedt 		 * The caller might want to do something special
189159df055fSSteven Rostedt 		 * for each function we find. We call the callback
189259df055fSSteven Rostedt 		 * to give the caller an opportunity to do so.
189359df055fSSteven Rostedt 		 */
189459df055fSSteven Rostedt 		if (ops->callback) {
189559df055fSSteven Rostedt 			if (ops->callback(rec->ip, &entry->data) < 0) {
189659df055fSSteven Rostedt 				/* caller does not like this func */
189759df055fSSteven Rostedt 				kfree(entry);
189859df055fSSteven Rostedt 				continue;
189959df055fSSteven Rostedt 			}
190059df055fSSteven Rostedt 		}
190159df055fSSteven Rostedt 
190259df055fSSteven Rostedt 		entry->ops = ops;
190359df055fSSteven Rostedt 		entry->ip = rec->ip;
190459df055fSSteven Rostedt 
190559df055fSSteven Rostedt 		key = hash_long(entry->ip, FTRACE_HASH_BITS);
190659df055fSSteven Rostedt 		hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]);
190759df055fSSteven Rostedt 
190859df055fSSteven Rostedt 	} while_for_each_ftrace_rec();
1909b6887d79SSteven Rostedt 	__enable_ftrace_function_probe();
191059df055fSSteven Rostedt 
191159df055fSSteven Rostedt  out_unlock:
191259df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
191359df055fSSteven Rostedt 
191459df055fSSteven Rostedt 	return count;
191559df055fSSteven Rostedt }
191659df055fSSteven Rostedt 
191759df055fSSteven Rostedt enum {
1918b6887d79SSteven Rostedt 	PROBE_TEST_FUNC		= 1,
1919b6887d79SSteven Rostedt 	PROBE_TEST_DATA		= 2
192059df055fSSteven Rostedt };
192159df055fSSteven Rostedt 
192259df055fSSteven Rostedt static void
1923b6887d79SSteven Rostedt __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
192459df055fSSteven Rostedt 				  void *data, int flags)
192559df055fSSteven Rostedt {
1926b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
192759df055fSSteven Rostedt 	struct hlist_node *n, *tmp;
192859df055fSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
192959df055fSSteven Rostedt 	int type = MATCH_FULL;
193059df055fSSteven Rostedt 	int i, len = 0;
193159df055fSSteven Rostedt 	char *search;
193259df055fSSteven Rostedt 
193359df055fSSteven Rostedt 	if (glob && (strcmp(glob, "*") || !strlen(glob)))
193459df055fSSteven Rostedt 		glob = NULL;
193559df055fSSteven Rostedt 	else {
193659df055fSSteven Rostedt 		int not;
193759df055fSSteven Rostedt 
193859df055fSSteven Rostedt 		type = ftrace_setup_glob(glob, strlen(glob), &search, &not);
193959df055fSSteven Rostedt 		len = strlen(search);
194059df055fSSteven Rostedt 
1941b6887d79SSteven Rostedt 		/* we do not support '!' for function probes */
194259df055fSSteven Rostedt 		if (WARN_ON(not))
194359df055fSSteven Rostedt 			return;
194459df055fSSteven Rostedt 	}
194559df055fSSteven Rostedt 
194659df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
194759df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
194859df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
194959df055fSSteven Rostedt 
195059df055fSSteven Rostedt 		hlist_for_each_entry_safe(entry, n, tmp, hhd, node) {
195159df055fSSteven Rostedt 
195259df055fSSteven Rostedt 			/* break up if statements for readability */
1953b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_FUNC) && entry->ops != ops)
195459df055fSSteven Rostedt 				continue;
195559df055fSSteven Rostedt 
1956b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_DATA) && entry->data != data)
195759df055fSSteven Rostedt 				continue;
195859df055fSSteven Rostedt 
195959df055fSSteven Rostedt 			/* do this last, since it is the most expensive */
196059df055fSSteven Rostedt 			if (glob) {
196159df055fSSteven Rostedt 				kallsyms_lookup(entry->ip, NULL, NULL,
196259df055fSSteven Rostedt 						NULL, str);
196359df055fSSteven Rostedt 				if (!ftrace_match(str, glob, len, type))
196459df055fSSteven Rostedt 					continue;
196559df055fSSteven Rostedt 			}
196659df055fSSteven Rostedt 
196759df055fSSteven Rostedt 			hlist_del(&entry->node);
196859df055fSSteven Rostedt 			call_rcu(&entry->rcu, ftrace_free_entry_rcu);
196959df055fSSteven Rostedt 		}
197059df055fSSteven Rostedt 	}
1971b6887d79SSteven Rostedt 	__disable_ftrace_function_probe();
197259df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
197359df055fSSteven Rostedt }
197459df055fSSteven Rostedt 
197559df055fSSteven Rostedt void
1976b6887d79SSteven Rostedt unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
197759df055fSSteven Rostedt 				void *data)
197859df055fSSteven Rostedt {
1979b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, data,
1980b6887d79SSteven Rostedt 					  PROBE_TEST_FUNC | PROBE_TEST_DATA);
198159df055fSSteven Rostedt }
198259df055fSSteven Rostedt 
198359df055fSSteven Rostedt void
1984b6887d79SSteven Rostedt unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops)
198559df055fSSteven Rostedt {
1986b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC);
198759df055fSSteven Rostedt }
198859df055fSSteven Rostedt 
1989b6887d79SSteven Rostedt void unregister_ftrace_function_probe_all(char *glob)
199059df055fSSteven Rostedt {
1991b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, NULL, NULL, 0);
199259df055fSSteven Rostedt }
199359df055fSSteven Rostedt 
1994f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands);
1995f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex);
1996f6180773SSteven Rostedt 
1997f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd)
1998f6180773SSteven Rostedt {
1999f6180773SSteven Rostedt 	struct ftrace_func_command *p;
2000f6180773SSteven Rostedt 	int ret = 0;
2001f6180773SSteven Rostedt 
2002f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
2003f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
2004f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
2005f6180773SSteven Rostedt 			ret = -EBUSY;
2006f6180773SSteven Rostedt 			goto out_unlock;
2007f6180773SSteven Rostedt 		}
2008f6180773SSteven Rostedt 	}
2009f6180773SSteven Rostedt 	list_add(&cmd->list, &ftrace_commands);
2010f6180773SSteven Rostedt  out_unlock:
2011f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
2012f6180773SSteven Rostedt 
2013f6180773SSteven Rostedt 	return ret;
2014f6180773SSteven Rostedt }
2015f6180773SSteven Rostedt 
2016f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd)
2017f6180773SSteven Rostedt {
2018f6180773SSteven Rostedt 	struct ftrace_func_command *p, *n;
2019f6180773SSteven Rostedt 	int ret = -ENODEV;
2020f6180773SSteven Rostedt 
2021f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
2022f6180773SSteven Rostedt 	list_for_each_entry_safe(p, n, &ftrace_commands, list) {
2023f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
2024f6180773SSteven Rostedt 			ret = 0;
2025f6180773SSteven Rostedt 			list_del_init(&p->list);
2026f6180773SSteven Rostedt 			goto out_unlock;
2027f6180773SSteven Rostedt 		}
2028f6180773SSteven Rostedt 	}
2029f6180773SSteven Rostedt  out_unlock:
2030f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
2031f6180773SSteven Rostedt 
2032f6180773SSteven Rostedt 	return ret;
2033f6180773SSteven Rostedt }
2034f6180773SSteven Rostedt 
203564e7c440SSteven Rostedt static int ftrace_process_regex(char *buff, int len, int enable)
203664e7c440SSteven Rostedt {
2037f6180773SSteven Rostedt 	char *func, *command, *next = buff;
20386a24a244SSteven Rostedt 	struct ftrace_func_command *p;
2039f6180773SSteven Rostedt 	int ret = -EINVAL;
204064e7c440SSteven Rostedt 
204164e7c440SSteven Rostedt 	func = strsep(&next, ":");
204264e7c440SSteven Rostedt 
204364e7c440SSteven Rostedt 	if (!next) {
204464e7c440SSteven Rostedt 		ftrace_match_records(func, len, enable);
204564e7c440SSteven Rostedt 		return 0;
204664e7c440SSteven Rostedt 	}
204764e7c440SSteven Rostedt 
2048f6180773SSteven Rostedt 	/* command found */
204964e7c440SSteven Rostedt 
205064e7c440SSteven Rostedt 	command = strsep(&next, ":");
205164e7c440SSteven Rostedt 
2052f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
2053f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
2054f6180773SSteven Rostedt 		if (strcmp(p->name, command) == 0) {
2055f6180773SSteven Rostedt 			ret = p->func(func, command, next, enable);
2056f6180773SSteven Rostedt 			goto out_unlock;
205764e7c440SSteven Rostedt 		}
2058f6180773SSteven Rostedt 	}
2059f6180773SSteven Rostedt  out_unlock:
2060f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
206164e7c440SSteven Rostedt 
2062f6180773SSteven Rostedt 	return ret;
206364e7c440SSteven Rostedt }
206464e7c440SSteven Rostedt 
2065e309b41dSIngo Molnar static ssize_t
206641c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf,
206741c52c0dSSteven Rostedt 		   size_t cnt, loff_t *ppos, int enable)
20685072c59fSSteven Rostedt {
20695072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
20705072c59fSSteven Rostedt 	char ch;
20715072c59fSSteven Rostedt 	size_t read = 0;
20725072c59fSSteven Rostedt 	ssize_t ret;
20735072c59fSSteven Rostedt 
20745072c59fSSteven Rostedt 	if (!cnt || cnt < 0)
20755072c59fSSteven Rostedt 		return 0;
20765072c59fSSteven Rostedt 
207741c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
20785072c59fSSteven Rostedt 
20795072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
20805072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
20815072c59fSSteven Rostedt 		iter = m->private;
20825072c59fSSteven Rostedt 	} else
20835072c59fSSteven Rostedt 		iter = file->private_data;
20845072c59fSSteven Rostedt 
20855072c59fSSteven Rostedt 	if (!*ppos) {
20865072c59fSSteven Rostedt 		iter->flags &= ~FTRACE_ITER_CONT;
20875072c59fSSteven Rostedt 		iter->buffer_idx = 0;
20885072c59fSSteven Rostedt 	}
20895072c59fSSteven Rostedt 
20905072c59fSSteven Rostedt 	ret = get_user(ch, ubuf++);
20915072c59fSSteven Rostedt 	if (ret)
20925072c59fSSteven Rostedt 		goto out;
20935072c59fSSteven Rostedt 	read++;
20945072c59fSSteven Rostedt 	cnt--;
20955072c59fSSteven Rostedt 
20965072c59fSSteven Rostedt 	if (!(iter->flags & ~FTRACE_ITER_CONT)) {
20975072c59fSSteven Rostedt 		/* skip white space */
20985072c59fSSteven Rostedt 		while (cnt && isspace(ch)) {
20995072c59fSSteven Rostedt 			ret = get_user(ch, ubuf++);
21005072c59fSSteven Rostedt 			if (ret)
21015072c59fSSteven Rostedt 				goto out;
21025072c59fSSteven Rostedt 			read++;
21035072c59fSSteven Rostedt 			cnt--;
21045072c59fSSteven Rostedt 		}
21055072c59fSSteven Rostedt 
21065072c59fSSteven Rostedt 		if (isspace(ch)) {
21075072c59fSSteven Rostedt 			file->f_pos += read;
21085072c59fSSteven Rostedt 			ret = read;
21095072c59fSSteven Rostedt 			goto out;
21105072c59fSSteven Rostedt 		}
21115072c59fSSteven Rostedt 
21125072c59fSSteven Rostedt 		iter->buffer_idx = 0;
21135072c59fSSteven Rostedt 	}
21145072c59fSSteven Rostedt 
21155072c59fSSteven Rostedt 	while (cnt && !isspace(ch)) {
21165072c59fSSteven Rostedt 		if (iter->buffer_idx < FTRACE_BUFF_MAX)
21175072c59fSSteven Rostedt 			iter->buffer[iter->buffer_idx++] = ch;
21185072c59fSSteven Rostedt 		else {
21195072c59fSSteven Rostedt 			ret = -EINVAL;
21205072c59fSSteven Rostedt 			goto out;
21215072c59fSSteven Rostedt 		}
21225072c59fSSteven Rostedt 		ret = get_user(ch, ubuf++);
21235072c59fSSteven Rostedt 		if (ret)
21245072c59fSSteven Rostedt 			goto out;
21255072c59fSSteven Rostedt 		read++;
21265072c59fSSteven Rostedt 		cnt--;
21275072c59fSSteven Rostedt 	}
21285072c59fSSteven Rostedt 
21295072c59fSSteven Rostedt 	if (isspace(ch)) {
21305072c59fSSteven Rostedt 		iter->filtered++;
21315072c59fSSteven Rostedt 		iter->buffer[iter->buffer_idx] = 0;
213264e7c440SSteven Rostedt 		ret = ftrace_process_regex(iter->buffer,
213364e7c440SSteven Rostedt 					   iter->buffer_idx, enable);
213464e7c440SSteven Rostedt 		if (ret)
213564e7c440SSteven Rostedt 			goto out;
21365072c59fSSteven Rostedt 		iter->buffer_idx = 0;
21375072c59fSSteven Rostedt 	} else
21385072c59fSSteven Rostedt 		iter->flags |= FTRACE_ITER_CONT;
21395072c59fSSteven Rostedt 
21405072c59fSSteven Rostedt 
21415072c59fSSteven Rostedt 	file->f_pos += read;
21425072c59fSSteven Rostedt 
21435072c59fSSteven Rostedt 	ret = read;
21445072c59fSSteven Rostedt  out:
214541c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
21465072c59fSSteven Rostedt 
21475072c59fSSteven Rostedt 	return ret;
21485072c59fSSteven Rostedt }
21495072c59fSSteven Rostedt 
215041c52c0dSSteven Rostedt static ssize_t
215141c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf,
215241c52c0dSSteven Rostedt 		    size_t cnt, loff_t *ppos)
215341c52c0dSSteven Rostedt {
215441c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
215541c52c0dSSteven Rostedt }
215641c52c0dSSteven Rostedt 
215741c52c0dSSteven Rostedt static ssize_t
215841c52c0dSSteven Rostedt ftrace_notrace_write(struct file *file, const char __user *ubuf,
215941c52c0dSSteven Rostedt 		     size_t cnt, loff_t *ppos)
216041c52c0dSSteven Rostedt {
216141c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 0);
216241c52c0dSSteven Rostedt }
216341c52c0dSSteven Rostedt 
216441c52c0dSSteven Rostedt static void
216541c52c0dSSteven Rostedt ftrace_set_regex(unsigned char *buf, int len, int reset, int enable)
216641c52c0dSSteven Rostedt {
216741c52c0dSSteven Rostedt 	if (unlikely(ftrace_disabled))
216841c52c0dSSteven Rostedt 		return;
216941c52c0dSSteven Rostedt 
217041c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
217141c52c0dSSteven Rostedt 	if (reset)
217241c52c0dSSteven Rostedt 		ftrace_filter_reset(enable);
217341c52c0dSSteven Rostedt 	if (buf)
21747f24b31bSSteven Rostedt 		ftrace_match_records(buf, len, enable);
217541c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
217641c52c0dSSteven Rostedt }
217741c52c0dSSteven Rostedt 
217877a2b37dSSteven Rostedt /**
217977a2b37dSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
218077a2b37dSSteven Rostedt  * @buf - the string that holds the function filter text.
218177a2b37dSSteven Rostedt  * @len - the length of the string.
218277a2b37dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
218377a2b37dSSteven Rostedt  *
218477a2b37dSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
218577a2b37dSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
218677a2b37dSSteven Rostedt  */
2187e309b41dSIngo Molnar void ftrace_set_filter(unsigned char *buf, int len, int reset)
218877a2b37dSSteven Rostedt {
218941c52c0dSSteven Rostedt 	ftrace_set_regex(buf, len, reset, 1);
219041c52c0dSSteven Rostedt }
21914eebcc81SSteven Rostedt 
219241c52c0dSSteven Rostedt /**
219341c52c0dSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
219441c52c0dSSteven Rostedt  * @buf - the string that holds the function notrace text.
219541c52c0dSSteven Rostedt  * @len - the length of the string.
219641c52c0dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
219741c52c0dSSteven Rostedt  *
219841c52c0dSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
219941c52c0dSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
220041c52c0dSSteven Rostedt  * for tracing.
220141c52c0dSSteven Rostedt  */
220241c52c0dSSteven Rostedt void ftrace_set_notrace(unsigned char *buf, int len, int reset)
220341c52c0dSSteven Rostedt {
220441c52c0dSSteven Rostedt 	ftrace_set_regex(buf, len, reset, 0);
220577a2b37dSSteven Rostedt }
220677a2b37dSSteven Rostedt 
2207e309b41dSIngo Molnar static int
220841c52c0dSSteven Rostedt ftrace_regex_release(struct inode *inode, struct file *file, int enable)
22095072c59fSSteven Rostedt {
22105072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
22115072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
22125072c59fSSteven Rostedt 
221341c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
22145072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
22155072c59fSSteven Rostedt 		iter = m->private;
22165072c59fSSteven Rostedt 
22175072c59fSSteven Rostedt 		seq_release(inode, file);
22185072c59fSSteven Rostedt 	} else
22195072c59fSSteven Rostedt 		iter = file->private_data;
22205072c59fSSteven Rostedt 
22215072c59fSSteven Rostedt 	if (iter->buffer_idx) {
22225072c59fSSteven Rostedt 		iter->filtered++;
22235072c59fSSteven Rostedt 		iter->buffer[iter->buffer_idx] = 0;
22247f24b31bSSteven Rostedt 		ftrace_match_records(iter->buffer, iter->buffer_idx, enable);
22255072c59fSSteven Rostedt 	}
22265072c59fSSteven Rostedt 
2227e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
2228ee02a2e5SSteven Rostedt 	if (ftrace_start_up && ftrace_enabled)
22295072c59fSSteven Rostedt 		ftrace_run_update_code(FTRACE_ENABLE_CALLS);
2230e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
22315072c59fSSteven Rostedt 
22325072c59fSSteven Rostedt 	kfree(iter);
223341c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
22345072c59fSSteven Rostedt 	return 0;
22355072c59fSSteven Rostedt }
22365072c59fSSteven Rostedt 
223741c52c0dSSteven Rostedt static int
223841c52c0dSSteven Rostedt ftrace_filter_release(struct inode *inode, struct file *file)
223941c52c0dSSteven Rostedt {
224041c52c0dSSteven Rostedt 	return ftrace_regex_release(inode, file, 1);
224141c52c0dSSteven Rostedt }
224241c52c0dSSteven Rostedt 
224341c52c0dSSteven Rostedt static int
224441c52c0dSSteven Rostedt ftrace_notrace_release(struct inode *inode, struct file *file)
224541c52c0dSSteven Rostedt {
224641c52c0dSSteven Rostedt 	return ftrace_regex_release(inode, file, 0);
224741c52c0dSSteven Rostedt }
224841c52c0dSSteven Rostedt 
22495e2336a0SSteven Rostedt static const struct file_operations ftrace_avail_fops = {
22505072c59fSSteven Rostedt 	.open = ftrace_avail_open,
22515072c59fSSteven Rostedt 	.read = seq_read,
22525072c59fSSteven Rostedt 	.llseek = seq_lseek,
22535072c59fSSteven Rostedt 	.release = ftrace_avail_release,
22545072c59fSSteven Rostedt };
22555072c59fSSteven Rostedt 
22565e2336a0SSteven Rostedt static const struct file_operations ftrace_failures_fops = {
2257eb9a7bf0SAbhishek Sagar 	.open = ftrace_failures_open,
2258eb9a7bf0SAbhishek Sagar 	.read = seq_read,
2259eb9a7bf0SAbhishek Sagar 	.llseek = seq_lseek,
2260eb9a7bf0SAbhishek Sagar 	.release = ftrace_avail_release,
2261eb9a7bf0SAbhishek Sagar };
2262eb9a7bf0SAbhishek Sagar 
22635e2336a0SSteven Rostedt static const struct file_operations ftrace_filter_fops = {
22645072c59fSSteven Rostedt 	.open = ftrace_filter_open,
2265850a80cfSLai Jiangshan 	.read = seq_read,
22665072c59fSSteven Rostedt 	.write = ftrace_filter_write,
226741c52c0dSSteven Rostedt 	.llseek = ftrace_regex_lseek,
22685072c59fSSteven Rostedt 	.release = ftrace_filter_release,
22695072c59fSSteven Rostedt };
22705072c59fSSteven Rostedt 
22715e2336a0SSteven Rostedt static const struct file_operations ftrace_notrace_fops = {
227241c52c0dSSteven Rostedt 	.open = ftrace_notrace_open,
2273850a80cfSLai Jiangshan 	.read = seq_read,
227441c52c0dSSteven Rostedt 	.write = ftrace_notrace_write,
227541c52c0dSSteven Rostedt 	.llseek = ftrace_regex_lseek,
227641c52c0dSSteven Rostedt 	.release = ftrace_notrace_release,
227741c52c0dSSteven Rostedt };
227841c52c0dSSteven Rostedt 
2279ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
2280ea4e2bc4SSteven Rostedt 
2281ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock);
2282ea4e2bc4SSteven Rostedt 
2283ea4e2bc4SSteven Rostedt int ftrace_graph_count;
2284ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
2285ea4e2bc4SSteven Rostedt 
2286ea4e2bc4SSteven Rostedt static void *
2287ea4e2bc4SSteven Rostedt g_next(struct seq_file *m, void *v, loff_t *pos)
2288ea4e2bc4SSteven Rostedt {
2289ea4e2bc4SSteven Rostedt 	unsigned long *array = m->private;
2290ea4e2bc4SSteven Rostedt 	int index = *pos;
2291ea4e2bc4SSteven Rostedt 
2292ea4e2bc4SSteven Rostedt 	(*pos)++;
2293ea4e2bc4SSteven Rostedt 
2294ea4e2bc4SSteven Rostedt 	if (index >= ftrace_graph_count)
2295ea4e2bc4SSteven Rostedt 		return NULL;
2296ea4e2bc4SSteven Rostedt 
2297ea4e2bc4SSteven Rostedt 	return &array[index];
2298ea4e2bc4SSteven Rostedt }
2299ea4e2bc4SSteven Rostedt 
2300ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos)
2301ea4e2bc4SSteven Rostedt {
2302ea4e2bc4SSteven Rostedt 	void *p = NULL;
2303ea4e2bc4SSteven Rostedt 
2304ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
2305ea4e2bc4SSteven Rostedt 
2306f9349a8fSFrederic Weisbecker 	/* Nothing, tell g_show to print all functions are enabled */
2307f9349a8fSFrederic Weisbecker 	if (!ftrace_graph_count && !*pos)
2308f9349a8fSFrederic Weisbecker 		return (void *)1;
2309f9349a8fSFrederic Weisbecker 
2310ea4e2bc4SSteven Rostedt 	p = g_next(m, p, pos);
2311ea4e2bc4SSteven Rostedt 
2312ea4e2bc4SSteven Rostedt 	return p;
2313ea4e2bc4SSteven Rostedt }
2314ea4e2bc4SSteven Rostedt 
2315ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p)
2316ea4e2bc4SSteven Rostedt {
2317ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
2318ea4e2bc4SSteven Rostedt }
2319ea4e2bc4SSteven Rostedt 
2320ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v)
2321ea4e2bc4SSteven Rostedt {
2322ea4e2bc4SSteven Rostedt 	unsigned long *ptr = v;
2323ea4e2bc4SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
2324ea4e2bc4SSteven Rostedt 
2325ea4e2bc4SSteven Rostedt 	if (!ptr)
2326ea4e2bc4SSteven Rostedt 		return 0;
2327ea4e2bc4SSteven Rostedt 
2328f9349a8fSFrederic Weisbecker 	if (ptr == (unsigned long *)1) {
2329f9349a8fSFrederic Weisbecker 		seq_printf(m, "#### all functions enabled ####\n");
2330f9349a8fSFrederic Weisbecker 		return 0;
2331f9349a8fSFrederic Weisbecker 	}
2332f9349a8fSFrederic Weisbecker 
2333ea4e2bc4SSteven Rostedt 	kallsyms_lookup(*ptr, NULL, NULL, NULL, str);
2334ea4e2bc4SSteven Rostedt 
2335ea4e2bc4SSteven Rostedt 	seq_printf(m, "%s\n", str);
2336ea4e2bc4SSteven Rostedt 
2337ea4e2bc4SSteven Rostedt 	return 0;
2338ea4e2bc4SSteven Rostedt }
2339ea4e2bc4SSteven Rostedt 
2340ea4e2bc4SSteven Rostedt static struct seq_operations ftrace_graph_seq_ops = {
2341ea4e2bc4SSteven Rostedt 	.start = g_start,
2342ea4e2bc4SSteven Rostedt 	.next = g_next,
2343ea4e2bc4SSteven Rostedt 	.stop = g_stop,
2344ea4e2bc4SSteven Rostedt 	.show = g_show,
2345ea4e2bc4SSteven Rostedt };
2346ea4e2bc4SSteven Rostedt 
2347ea4e2bc4SSteven Rostedt static int
2348ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file)
2349ea4e2bc4SSteven Rostedt {
2350ea4e2bc4SSteven Rostedt 	int ret = 0;
2351ea4e2bc4SSteven Rostedt 
2352ea4e2bc4SSteven Rostedt 	if (unlikely(ftrace_disabled))
2353ea4e2bc4SSteven Rostedt 		return -ENODEV;
2354ea4e2bc4SSteven Rostedt 
2355ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
2356ea4e2bc4SSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
2357ea4e2bc4SSteven Rostedt 	    !(file->f_flags & O_APPEND)) {
2358ea4e2bc4SSteven Rostedt 		ftrace_graph_count = 0;
2359ea4e2bc4SSteven Rostedt 		memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
2360ea4e2bc4SSteven Rostedt 	}
2361ea4e2bc4SSteven Rostedt 
2362ea4e2bc4SSteven Rostedt 	if (file->f_mode & FMODE_READ) {
2363ea4e2bc4SSteven Rostedt 		ret = seq_open(file, &ftrace_graph_seq_ops);
2364ea4e2bc4SSteven Rostedt 		if (!ret) {
2365ea4e2bc4SSteven Rostedt 			struct seq_file *m = file->private_data;
2366ea4e2bc4SSteven Rostedt 			m->private = ftrace_graph_funcs;
2367ea4e2bc4SSteven Rostedt 		}
2368ea4e2bc4SSteven Rostedt 	} else
2369ea4e2bc4SSteven Rostedt 		file->private_data = ftrace_graph_funcs;
2370ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
2371ea4e2bc4SSteven Rostedt 
2372ea4e2bc4SSteven Rostedt 	return ret;
2373ea4e2bc4SSteven Rostedt }
2374ea4e2bc4SSteven Rostedt 
2375ea4e2bc4SSteven Rostedt static int
2376f9349a8fSFrederic Weisbecker ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2377ea4e2bc4SSteven Rostedt {
2378ea4e2bc4SSteven Rostedt 	struct dyn_ftrace *rec;
2379ea4e2bc4SSteven Rostedt 	struct ftrace_page *pg;
2380f9349a8fSFrederic Weisbecker 	int search_len;
2381ea4e2bc4SSteven Rostedt 	int found = 0;
2382f9349a8fSFrederic Weisbecker 	int type, not;
2383f9349a8fSFrederic Weisbecker 	char *search;
2384f9349a8fSFrederic Weisbecker 	bool exists;
2385f9349a8fSFrederic Weisbecker 	int i;
2386ea4e2bc4SSteven Rostedt 
2387ea4e2bc4SSteven Rostedt 	if (ftrace_disabled)
2388ea4e2bc4SSteven Rostedt 		return -ENODEV;
2389ea4e2bc4SSteven Rostedt 
2390f9349a8fSFrederic Weisbecker 	/* decode regex */
2391f9349a8fSFrederic Weisbecker 	type = ftrace_setup_glob(buffer, strlen(buffer), &search, &not);
2392f9349a8fSFrederic Weisbecker 	if (not)
2393f9349a8fSFrederic Weisbecker 		return -EINVAL;
2394f9349a8fSFrederic Weisbecker 
2395f9349a8fSFrederic Weisbecker 	search_len = strlen(search);
2396f9349a8fSFrederic Weisbecker 
239752baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
2398265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
2399ea4e2bc4SSteven Rostedt 
2400f9349a8fSFrederic Weisbecker 		if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
2401f9349a8fSFrederic Weisbecker 			break;
2402f9349a8fSFrederic Weisbecker 
2403ea4e2bc4SSteven Rostedt 		if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE))
2404ea4e2bc4SSteven Rostedt 			continue;
2405ea4e2bc4SSteven Rostedt 
2406f9349a8fSFrederic Weisbecker 		if (ftrace_match_record(rec, search, search_len, type)) {
2407f9349a8fSFrederic Weisbecker 			/* ensure it is not already in the array */
2408f9349a8fSFrederic Weisbecker 			exists = false;
2409f9349a8fSFrederic Weisbecker 			for (i = 0; i < *idx; i++)
2410f9349a8fSFrederic Weisbecker 				if (array[i] == rec->ip) {
2411f9349a8fSFrederic Weisbecker 					exists = true;
2412faec2ec5SLiming Wang 					break;
2413faec2ec5SLiming Wang 				}
2414f9349a8fSFrederic Weisbecker 			if (!exists) {
2415f9349a8fSFrederic Weisbecker 				array[(*idx)++] = rec->ip;
2416f9349a8fSFrederic Weisbecker 				found = 1;
2417f9349a8fSFrederic Weisbecker 			}
2418ea4e2bc4SSteven Rostedt 		}
2419265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
2420f9349a8fSFrederic Weisbecker 
242152baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2422ea4e2bc4SSteven Rostedt 
2423ea4e2bc4SSteven Rostedt 	return found ? 0 : -EINVAL;
2424ea4e2bc4SSteven Rostedt }
2425ea4e2bc4SSteven Rostedt 
2426ea4e2bc4SSteven Rostedt static ssize_t
2427ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf,
2428ea4e2bc4SSteven Rostedt 		   size_t cnt, loff_t *ppos)
2429ea4e2bc4SSteven Rostedt {
2430ea4e2bc4SSteven Rostedt 	unsigned char buffer[FTRACE_BUFF_MAX+1];
2431ea4e2bc4SSteven Rostedt 	unsigned long *array;
2432ea4e2bc4SSteven Rostedt 	size_t read = 0;
2433ea4e2bc4SSteven Rostedt 	ssize_t ret;
2434ea4e2bc4SSteven Rostedt 	int index = 0;
2435ea4e2bc4SSteven Rostedt 	char ch;
2436ea4e2bc4SSteven Rostedt 
2437ea4e2bc4SSteven Rostedt 	if (!cnt || cnt < 0)
2438ea4e2bc4SSteven Rostedt 		return 0;
2439ea4e2bc4SSteven Rostedt 
2440ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
2441ea4e2bc4SSteven Rostedt 
2442ea4e2bc4SSteven Rostedt 	if (ftrace_graph_count >= FTRACE_GRAPH_MAX_FUNCS) {
2443ea4e2bc4SSteven Rostedt 		ret = -EBUSY;
2444ea4e2bc4SSteven Rostedt 		goto out;
2445ea4e2bc4SSteven Rostedt 	}
2446ea4e2bc4SSteven Rostedt 
2447ea4e2bc4SSteven Rostedt 	if (file->f_mode & FMODE_READ) {
2448ea4e2bc4SSteven Rostedt 		struct seq_file *m = file->private_data;
2449ea4e2bc4SSteven Rostedt 		array = m->private;
2450ea4e2bc4SSteven Rostedt 	} else
2451ea4e2bc4SSteven Rostedt 		array = file->private_data;
2452ea4e2bc4SSteven Rostedt 
2453ea4e2bc4SSteven Rostedt 	ret = get_user(ch, ubuf++);
2454ea4e2bc4SSteven Rostedt 	if (ret)
2455ea4e2bc4SSteven Rostedt 		goto out;
2456ea4e2bc4SSteven Rostedt 	read++;
2457ea4e2bc4SSteven Rostedt 	cnt--;
2458ea4e2bc4SSteven Rostedt 
2459ea4e2bc4SSteven Rostedt 	/* skip white space */
2460ea4e2bc4SSteven Rostedt 	while (cnt && isspace(ch)) {
2461ea4e2bc4SSteven Rostedt 		ret = get_user(ch, ubuf++);
2462ea4e2bc4SSteven Rostedt 		if (ret)
2463ea4e2bc4SSteven Rostedt 			goto out;
2464ea4e2bc4SSteven Rostedt 		read++;
2465ea4e2bc4SSteven Rostedt 		cnt--;
2466ea4e2bc4SSteven Rostedt 	}
2467ea4e2bc4SSteven Rostedt 
2468ea4e2bc4SSteven Rostedt 	if (isspace(ch)) {
2469ea4e2bc4SSteven Rostedt 		*ppos += read;
2470ea4e2bc4SSteven Rostedt 		ret = read;
2471ea4e2bc4SSteven Rostedt 		goto out;
2472ea4e2bc4SSteven Rostedt 	}
2473ea4e2bc4SSteven Rostedt 
2474ea4e2bc4SSteven Rostedt 	while (cnt && !isspace(ch)) {
2475ea4e2bc4SSteven Rostedt 		if (index < FTRACE_BUFF_MAX)
2476ea4e2bc4SSteven Rostedt 			buffer[index++] = ch;
2477ea4e2bc4SSteven Rostedt 		else {
2478ea4e2bc4SSteven Rostedt 			ret = -EINVAL;
2479ea4e2bc4SSteven Rostedt 			goto out;
2480ea4e2bc4SSteven Rostedt 		}
2481ea4e2bc4SSteven Rostedt 		ret = get_user(ch, ubuf++);
2482ea4e2bc4SSteven Rostedt 		if (ret)
2483ea4e2bc4SSteven Rostedt 			goto out;
2484ea4e2bc4SSteven Rostedt 		read++;
2485ea4e2bc4SSteven Rostedt 		cnt--;
2486ea4e2bc4SSteven Rostedt 	}
2487ea4e2bc4SSteven Rostedt 	buffer[index] = 0;
2488ea4e2bc4SSteven Rostedt 
2489f9349a8fSFrederic Weisbecker 	/* we allow only one expression at a time */
2490f9349a8fSFrederic Weisbecker 	ret = ftrace_set_func(array, &ftrace_graph_count, buffer);
2491ea4e2bc4SSteven Rostedt 	if (ret)
2492ea4e2bc4SSteven Rostedt 		goto out;
2493ea4e2bc4SSteven Rostedt 
2494ea4e2bc4SSteven Rostedt 	file->f_pos += read;
2495ea4e2bc4SSteven Rostedt 
2496ea4e2bc4SSteven Rostedt 	ret = read;
2497ea4e2bc4SSteven Rostedt  out:
2498ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
2499ea4e2bc4SSteven Rostedt 
2500ea4e2bc4SSteven Rostedt 	return ret;
2501ea4e2bc4SSteven Rostedt }
2502ea4e2bc4SSteven Rostedt 
2503ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = {
2504ea4e2bc4SSteven Rostedt 	.open = ftrace_graph_open,
2505850a80cfSLai Jiangshan 	.read = seq_read,
2506ea4e2bc4SSteven Rostedt 	.write = ftrace_graph_write,
2507ea4e2bc4SSteven Rostedt };
2508ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2509ea4e2bc4SSteven Rostedt 
2510df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
25115072c59fSSteven Rostedt {
25125072c59fSSteven Rostedt 	struct dentry *entry;
25135072c59fSSteven Rostedt 
25145072c59fSSteven Rostedt 	entry = debugfs_create_file("available_filter_functions", 0444,
25155072c59fSSteven Rostedt 				    d_tracer, NULL, &ftrace_avail_fops);
25165072c59fSSteven Rostedt 	if (!entry)
25175072c59fSSteven Rostedt 		pr_warning("Could not create debugfs "
25185072c59fSSteven Rostedt 			   "'available_filter_functions' entry\n");
25195072c59fSSteven Rostedt 
2520eb9a7bf0SAbhishek Sagar 	entry = debugfs_create_file("failures", 0444,
2521eb9a7bf0SAbhishek Sagar 				    d_tracer, NULL, &ftrace_failures_fops);
2522eb9a7bf0SAbhishek Sagar 	if (!entry)
2523eb9a7bf0SAbhishek Sagar 		pr_warning("Could not create debugfs 'failures' entry\n");
2524eb9a7bf0SAbhishek Sagar 
25255072c59fSSteven Rostedt 	entry = debugfs_create_file("set_ftrace_filter", 0644, d_tracer,
25265072c59fSSteven Rostedt 				    NULL, &ftrace_filter_fops);
25275072c59fSSteven Rostedt 	if (!entry)
25285072c59fSSteven Rostedt 		pr_warning("Could not create debugfs "
25295072c59fSSteven Rostedt 			   "'set_ftrace_filter' entry\n");
253041c52c0dSSteven Rostedt 
253141c52c0dSSteven Rostedt 	entry = debugfs_create_file("set_ftrace_notrace", 0644, d_tracer,
253241c52c0dSSteven Rostedt 				    NULL, &ftrace_notrace_fops);
253341c52c0dSSteven Rostedt 	if (!entry)
253441c52c0dSSteven Rostedt 		pr_warning("Could not create debugfs "
253541c52c0dSSteven Rostedt 			   "'set_ftrace_notrace' entry\n");
2536ad90c0e3SSteven Rostedt 
2537ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
2538ea4e2bc4SSteven Rostedt 	entry = debugfs_create_file("set_graph_function", 0444, d_tracer,
2539ea4e2bc4SSteven Rostedt 				    NULL,
2540ea4e2bc4SSteven Rostedt 				    &ftrace_graph_fops);
2541ea4e2bc4SSteven Rostedt 	if (!entry)
2542ea4e2bc4SSteven Rostedt 		pr_warning("Could not create debugfs "
2543ea4e2bc4SSteven Rostedt 			   "'set_graph_function' entry\n");
2544ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2545ea4e2bc4SSteven Rostedt 
25465072c59fSSteven Rostedt 	return 0;
25475072c59fSSteven Rostedt }
25485072c59fSSteven Rostedt 
254931e88909SSteven Rostedt static int ftrace_convert_nops(struct module *mod,
255031e88909SSteven Rostedt 			       unsigned long *start,
255168bf21aaSSteven Rostedt 			       unsigned long *end)
255268bf21aaSSteven Rostedt {
255368bf21aaSSteven Rostedt 	unsigned long *p;
255468bf21aaSSteven Rostedt 	unsigned long addr;
255568bf21aaSSteven Rostedt 	unsigned long flags;
255668bf21aaSSteven Rostedt 
2557e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
255868bf21aaSSteven Rostedt 	p = start;
255968bf21aaSSteven Rostedt 	while (p < end) {
256068bf21aaSSteven Rostedt 		addr = ftrace_call_adjust(*p++);
256120e5227eSSteven Rostedt 		/*
256220e5227eSSteven Rostedt 		 * Some architecture linkers will pad between
256320e5227eSSteven Rostedt 		 * the different mcount_loc sections of different
256420e5227eSSteven Rostedt 		 * object files to satisfy alignments.
256520e5227eSSteven Rostedt 		 * Skip any NULL pointers.
256620e5227eSSteven Rostedt 		 */
256720e5227eSSteven Rostedt 		if (!addr)
256820e5227eSSteven Rostedt 			continue;
256968bf21aaSSteven Rostedt 		ftrace_record_ip(addr);
257068bf21aaSSteven Rostedt 	}
257168bf21aaSSteven Rostedt 
257208f5ac90SSteven Rostedt 	/* disable interrupts to prevent kstop machine */
257368bf21aaSSteven Rostedt 	local_irq_save(flags);
257431e88909SSteven Rostedt 	ftrace_update_code(mod);
257568bf21aaSSteven Rostedt 	local_irq_restore(flags);
2576e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
257768bf21aaSSteven Rostedt 
257868bf21aaSSteven Rostedt 	return 0;
257968bf21aaSSteven Rostedt }
258068bf21aaSSteven Rostedt 
258131e88909SSteven Rostedt void ftrace_init_module(struct module *mod,
258231e88909SSteven Rostedt 			unsigned long *start, unsigned long *end)
258390d595feSSteven Rostedt {
258400fd61aeSSteven Rostedt 	if (ftrace_disabled || start == end)
2585fed1939cSSteven Rostedt 		return;
258631e88909SSteven Rostedt 	ftrace_convert_nops(mod, start, end);
258790d595feSSteven Rostedt }
258890d595feSSteven Rostedt 
258968bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[];
259068bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[];
259168bf21aaSSteven Rostedt 
259268bf21aaSSteven Rostedt void __init ftrace_init(void)
259368bf21aaSSteven Rostedt {
259468bf21aaSSteven Rostedt 	unsigned long count, addr, flags;
259568bf21aaSSteven Rostedt 	int ret;
259668bf21aaSSteven Rostedt 
259768bf21aaSSteven Rostedt 	/* Keep the ftrace pointer to the stub */
259868bf21aaSSteven Rostedt 	addr = (unsigned long)ftrace_stub;
259968bf21aaSSteven Rostedt 
260068bf21aaSSteven Rostedt 	local_irq_save(flags);
260168bf21aaSSteven Rostedt 	ftrace_dyn_arch_init(&addr);
260268bf21aaSSteven Rostedt 	local_irq_restore(flags);
260368bf21aaSSteven Rostedt 
260468bf21aaSSteven Rostedt 	/* ftrace_dyn_arch_init places the return code in addr */
260568bf21aaSSteven Rostedt 	if (addr)
260668bf21aaSSteven Rostedt 		goto failed;
260768bf21aaSSteven Rostedt 
260868bf21aaSSteven Rostedt 	count = __stop_mcount_loc - __start_mcount_loc;
260968bf21aaSSteven Rostedt 
261068bf21aaSSteven Rostedt 	ret = ftrace_dyn_table_alloc(count);
261168bf21aaSSteven Rostedt 	if (ret)
261268bf21aaSSteven Rostedt 		goto failed;
261368bf21aaSSteven Rostedt 
261468bf21aaSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled = 1;
261568bf21aaSSteven Rostedt 
261631e88909SSteven Rostedt 	ret = ftrace_convert_nops(NULL,
261731e88909SSteven Rostedt 				  __start_mcount_loc,
261868bf21aaSSteven Rostedt 				  __stop_mcount_loc);
261968bf21aaSSteven Rostedt 
262068bf21aaSSteven Rostedt 	return;
262168bf21aaSSteven Rostedt  failed:
262268bf21aaSSteven Rostedt 	ftrace_disabled = 1;
262368bf21aaSSteven Rostedt }
262468bf21aaSSteven Rostedt 
26253d083395SSteven Rostedt #else
26260b6e4d56SFrederic Weisbecker 
26270b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void)
26280b6e4d56SFrederic Weisbecker {
26290b6e4d56SFrederic Weisbecker 	ftrace_enabled = 1;
26300b6e4d56SFrederic Weisbecker 	return 0;
26310b6e4d56SFrederic Weisbecker }
26320b6e4d56SFrederic Weisbecker device_initcall(ftrace_nodyn_init);
26330b6e4d56SFrederic Weisbecker 
2634df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
2635df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { }
26365a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */
26375a45cfe1SSteven Rostedt # define ftrace_startup(command)	do { } while (0)
26385a45cfe1SSteven Rostedt # define ftrace_shutdown(command)	do { } while (0)
2639b0fc494fSSteven Rostedt # define ftrace_startup_sysctl()	do { } while (0)
2640b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl()	do { } while (0)
26413d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */
26423d083395SSteven Rostedt 
2643df4fc315SSteven Rostedt static ssize_t
2644df4fc315SSteven Rostedt ftrace_pid_read(struct file *file, char __user *ubuf,
2645df4fc315SSteven Rostedt 		       size_t cnt, loff_t *ppos)
2646df4fc315SSteven Rostedt {
2647df4fc315SSteven Rostedt 	char buf[64];
2648df4fc315SSteven Rostedt 	int r;
2649df4fc315SSteven Rostedt 
2650e32d8956SSteven Rostedt 	if (ftrace_pid_trace == ftrace_swapper_pid)
2651e32d8956SSteven Rostedt 		r = sprintf(buf, "swapper tasks\n");
2652e32d8956SSteven Rostedt 	else if (ftrace_pid_trace)
2653cc59c9e8SLai Jiangshan 		r = sprintf(buf, "%u\n", pid_vnr(ftrace_pid_trace));
2654df4fc315SSteven Rostedt 	else
2655df4fc315SSteven Rostedt 		r = sprintf(buf, "no pid\n");
2656df4fc315SSteven Rostedt 
2657df4fc315SSteven Rostedt 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2658df4fc315SSteven Rostedt }
2659df4fc315SSteven Rostedt 
2660e32d8956SSteven Rostedt static void clear_ftrace_swapper(void)
2661e32d8956SSteven Rostedt {
2662e32d8956SSteven Rostedt 	struct task_struct *p;
2663e32d8956SSteven Rostedt 	int cpu;
2664e32d8956SSteven Rostedt 
2665e32d8956SSteven Rostedt 	get_online_cpus();
2666e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
2667e32d8956SSteven Rostedt 		p = idle_task(cpu);
2668e32d8956SSteven Rostedt 		clear_tsk_trace_trace(p);
2669e32d8956SSteven Rostedt 	}
2670e32d8956SSteven Rostedt 	put_online_cpus();
2671e32d8956SSteven Rostedt }
2672e32d8956SSteven Rostedt 
2673e32d8956SSteven Rostedt static void set_ftrace_swapper(void)
2674e32d8956SSteven Rostedt {
2675e32d8956SSteven Rostedt 	struct task_struct *p;
2676e32d8956SSteven Rostedt 	int cpu;
2677e32d8956SSteven Rostedt 
2678e32d8956SSteven Rostedt 	get_online_cpus();
2679e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
2680e32d8956SSteven Rostedt 		p = idle_task(cpu);
2681e32d8956SSteven Rostedt 		set_tsk_trace_trace(p);
2682e32d8956SSteven Rostedt 	}
2683e32d8956SSteven Rostedt 	put_online_cpus();
2684e32d8956SSteven Rostedt }
2685e32d8956SSteven Rostedt 
2686e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid)
2687978f3a45SSteven Rostedt {
2688978f3a45SSteven Rostedt 	struct task_struct *p;
2689978f3a45SSteven Rostedt 
2690229c4ef8SOleg Nesterov 	rcu_read_lock();
2691e32d8956SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
2692978f3a45SSteven Rostedt 		clear_tsk_trace_trace(p);
2693e32d8956SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
2694229c4ef8SOleg Nesterov 	rcu_read_unlock();
2695229c4ef8SOleg Nesterov 
2696e32d8956SSteven Rostedt 	put_pid(pid);
2697978f3a45SSteven Rostedt }
2698978f3a45SSteven Rostedt 
2699e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid)
2700978f3a45SSteven Rostedt {
2701978f3a45SSteven Rostedt 	struct task_struct *p;
2702978f3a45SSteven Rostedt 
2703229c4ef8SOleg Nesterov 	rcu_read_lock();
2704978f3a45SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
2705978f3a45SSteven Rostedt 		set_tsk_trace_trace(p);
2706978f3a45SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
2707229c4ef8SOleg Nesterov 	rcu_read_unlock();
2708978f3a45SSteven Rostedt }
2709978f3a45SSteven Rostedt 
2710e32d8956SSteven Rostedt static void clear_ftrace_pid_task(struct pid **pid)
2711e32d8956SSteven Rostedt {
2712e32d8956SSteven Rostedt 	if (*pid == ftrace_swapper_pid)
2713e32d8956SSteven Rostedt 		clear_ftrace_swapper();
2714e32d8956SSteven Rostedt 	else
2715e32d8956SSteven Rostedt 		clear_ftrace_pid(*pid);
2716e32d8956SSteven Rostedt 
2717e32d8956SSteven Rostedt 	*pid = NULL;
2718e32d8956SSteven Rostedt }
2719e32d8956SSteven Rostedt 
2720e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid)
2721e32d8956SSteven Rostedt {
2722e32d8956SSteven Rostedt 	if (pid == ftrace_swapper_pid)
2723e32d8956SSteven Rostedt 		set_ftrace_swapper();
2724e32d8956SSteven Rostedt 	else
2725e32d8956SSteven Rostedt 		set_ftrace_pid(pid);
2726e32d8956SSteven Rostedt }
2727e32d8956SSteven Rostedt 
2728df4fc315SSteven Rostedt static ssize_t
2729df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf,
2730df4fc315SSteven Rostedt 		   size_t cnt, loff_t *ppos)
2731df4fc315SSteven Rostedt {
2732978f3a45SSteven Rostedt 	struct pid *pid;
2733df4fc315SSteven Rostedt 	char buf[64];
2734df4fc315SSteven Rostedt 	long val;
2735df4fc315SSteven Rostedt 	int ret;
2736df4fc315SSteven Rostedt 
2737df4fc315SSteven Rostedt 	if (cnt >= sizeof(buf))
2738df4fc315SSteven Rostedt 		return -EINVAL;
2739df4fc315SSteven Rostedt 
2740df4fc315SSteven Rostedt 	if (copy_from_user(&buf, ubuf, cnt))
2741df4fc315SSteven Rostedt 		return -EFAULT;
2742df4fc315SSteven Rostedt 
2743df4fc315SSteven Rostedt 	buf[cnt] = 0;
2744df4fc315SSteven Rostedt 
2745df4fc315SSteven Rostedt 	ret = strict_strtol(buf, 10, &val);
2746df4fc315SSteven Rostedt 	if (ret < 0)
2747df4fc315SSteven Rostedt 		return ret;
2748df4fc315SSteven Rostedt 
2749e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
2750978f3a45SSteven Rostedt 	if (val < 0) {
2751df4fc315SSteven Rostedt 		/* disable pid tracing */
2752978f3a45SSteven Rostedt 		if (!ftrace_pid_trace)
2753df4fc315SSteven Rostedt 			goto out;
2754978f3a45SSteven Rostedt 
2755978f3a45SSteven Rostedt 		clear_ftrace_pid_task(&ftrace_pid_trace);
2756df4fc315SSteven Rostedt 
2757df4fc315SSteven Rostedt 	} else {
2758e32d8956SSteven Rostedt 		/* swapper task is special */
2759e32d8956SSteven Rostedt 		if (!val) {
2760e32d8956SSteven Rostedt 			pid = ftrace_swapper_pid;
2761e32d8956SSteven Rostedt 			if (pid == ftrace_pid_trace)
2762e32d8956SSteven Rostedt 				goto out;
2763e32d8956SSteven Rostedt 		} else {
2764978f3a45SSteven Rostedt 			pid = find_get_pid(val);
2765df4fc315SSteven Rostedt 
2766978f3a45SSteven Rostedt 			if (pid == ftrace_pid_trace) {
2767978f3a45SSteven Rostedt 				put_pid(pid);
2768978f3a45SSteven Rostedt 				goto out;
2769978f3a45SSteven Rostedt 			}
2770e32d8956SSteven Rostedt 		}
2771978f3a45SSteven Rostedt 
2772978f3a45SSteven Rostedt 		if (ftrace_pid_trace)
2773978f3a45SSteven Rostedt 			clear_ftrace_pid_task(&ftrace_pid_trace);
2774978f3a45SSteven Rostedt 
2775978f3a45SSteven Rostedt 		if (!pid)
2776df4fc315SSteven Rostedt 			goto out;
2777df4fc315SSteven Rostedt 
2778978f3a45SSteven Rostedt 		ftrace_pid_trace = pid;
27790ef8cde5SSteven Rostedt 
2780978f3a45SSteven Rostedt 		set_ftrace_pid_task(ftrace_pid_trace);
2781df4fc315SSteven Rostedt 	}
2782df4fc315SSteven Rostedt 
2783df4fc315SSteven Rostedt 	/* update the function call */
2784df4fc315SSteven Rostedt 	ftrace_update_pid_func();
2785df4fc315SSteven Rostedt 	ftrace_startup_enable(0);
2786df4fc315SSteven Rostedt 
2787df4fc315SSteven Rostedt  out:
2788e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2789df4fc315SSteven Rostedt 
2790df4fc315SSteven Rostedt 	return cnt;
2791df4fc315SSteven Rostedt }
2792df4fc315SSteven Rostedt 
27935e2336a0SSteven Rostedt static const struct file_operations ftrace_pid_fops = {
2794df4fc315SSteven Rostedt 	.read = ftrace_pid_read,
2795df4fc315SSteven Rostedt 	.write = ftrace_pid_write,
2796df4fc315SSteven Rostedt };
2797df4fc315SSteven Rostedt 
2798df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void)
2799df4fc315SSteven Rostedt {
2800df4fc315SSteven Rostedt 	struct dentry *d_tracer;
2801df4fc315SSteven Rostedt 	struct dentry *entry;
2802df4fc315SSteven Rostedt 
2803df4fc315SSteven Rostedt 	d_tracer = tracing_init_dentry();
2804df4fc315SSteven Rostedt 	if (!d_tracer)
2805df4fc315SSteven Rostedt 		return 0;
2806df4fc315SSteven Rostedt 
2807df4fc315SSteven Rostedt 	ftrace_init_dyn_debugfs(d_tracer);
2808df4fc315SSteven Rostedt 
2809df4fc315SSteven Rostedt 	entry = debugfs_create_file("set_ftrace_pid", 0644, d_tracer,
2810df4fc315SSteven Rostedt 				    NULL, &ftrace_pid_fops);
2811df4fc315SSteven Rostedt 	if (!entry)
2812df4fc315SSteven Rostedt 		pr_warning("Could not create debugfs "
2813df4fc315SSteven Rostedt 			   "'set_ftrace_pid' entry\n");
2814*493762fcSSteven Rostedt 
2815*493762fcSSteven Rostedt 	ftrace_profile_debugfs(d_tracer);
2816*493762fcSSteven Rostedt 
2817df4fc315SSteven Rostedt 	return 0;
2818df4fc315SSteven Rostedt }
2819df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs);
2820df4fc315SSteven Rostedt 
28213d083395SSteven Rostedt /**
282281adbdc0SSteven Rostedt  * ftrace_kill - kill ftrace
2823a2bb6a3dSSteven Rostedt  *
2824a2bb6a3dSSteven Rostedt  * This function should be used by panic code. It stops ftrace
2825a2bb6a3dSSteven Rostedt  * but in a not so nice way. If you need to simply kill ftrace
2826a2bb6a3dSSteven Rostedt  * from a non-atomic section, use ftrace_kill.
2827a2bb6a3dSSteven Rostedt  */
282881adbdc0SSteven Rostedt void ftrace_kill(void)
2829a2bb6a3dSSteven Rostedt {
2830a2bb6a3dSSteven Rostedt 	ftrace_disabled = 1;
2831a2bb6a3dSSteven Rostedt 	ftrace_enabled = 0;
2832a2bb6a3dSSteven Rostedt 	clear_ftrace_function();
2833a2bb6a3dSSteven Rostedt }
2834a2bb6a3dSSteven Rostedt 
2835a2bb6a3dSSteven Rostedt /**
28363d083395SSteven Rostedt  * register_ftrace_function - register a function for profiling
28373d083395SSteven Rostedt  * @ops - ops structure that holds the function for profiling.
28383d083395SSteven Rostedt  *
28393d083395SSteven Rostedt  * Register a function to be called by all functions in the
28403d083395SSteven Rostedt  * kernel.
28413d083395SSteven Rostedt  *
28423d083395SSteven Rostedt  * Note: @ops->func and all the functions it calls must be labeled
28433d083395SSteven Rostedt  *       with "notrace", otherwise it will go into a
28443d083395SSteven Rostedt  *       recursive loop.
28453d083395SSteven Rostedt  */
28463d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops)
28473d083395SSteven Rostedt {
2848b0fc494fSSteven Rostedt 	int ret;
2849b0fc494fSSteven Rostedt 
28504eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
28514eebcc81SSteven Rostedt 		return -1;
28524eebcc81SSteven Rostedt 
2853e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
2854e7d3737eSFrederic Weisbecker 
2855b0fc494fSSteven Rostedt 	ret = __register_ftrace_function(ops);
28565a45cfe1SSteven Rostedt 	ftrace_startup(0);
2857b0fc494fSSteven Rostedt 
2858e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2859b0fc494fSSteven Rostedt 	return ret;
28603d083395SSteven Rostedt }
28613d083395SSteven Rostedt 
28623d083395SSteven Rostedt /**
286332632920SUwe Kleine-Koenig  * unregister_ftrace_function - unregister a function for profiling.
28643d083395SSteven Rostedt  * @ops - ops structure that holds the function to unregister
28653d083395SSteven Rostedt  *
28663d083395SSteven Rostedt  * Unregister a function that was added to be called by ftrace profiling.
28673d083395SSteven Rostedt  */
28683d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops)
28693d083395SSteven Rostedt {
28703d083395SSteven Rostedt 	int ret;
28713d083395SSteven Rostedt 
2872e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
28733d083395SSteven Rostedt 	ret = __unregister_ftrace_function(ops);
28745a45cfe1SSteven Rostedt 	ftrace_shutdown(0);
2875e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2876b0fc494fSSteven Rostedt 
2877b0fc494fSSteven Rostedt 	return ret;
2878b0fc494fSSteven Rostedt }
2879b0fc494fSSteven Rostedt 
2880e309b41dSIngo Molnar int
2881b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write,
28825072c59fSSteven Rostedt 		     struct file *file, void __user *buffer, size_t *lenp,
2883b0fc494fSSteven Rostedt 		     loff_t *ppos)
2884b0fc494fSSteven Rostedt {
2885b0fc494fSSteven Rostedt 	int ret;
2886b0fc494fSSteven Rostedt 
28874eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
28884eebcc81SSteven Rostedt 		return -ENODEV;
28894eebcc81SSteven Rostedt 
2890e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
2891b0fc494fSSteven Rostedt 
28925072c59fSSteven Rostedt 	ret  = proc_dointvec(table, write, file, buffer, lenp, ppos);
2893b0fc494fSSteven Rostedt 
2894b0fc494fSSteven Rostedt 	if (ret || !write || (last_ftrace_enabled == ftrace_enabled))
2895b0fc494fSSteven Rostedt 		goto out;
2896b0fc494fSSteven Rostedt 
2897b0fc494fSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled;
2898b0fc494fSSteven Rostedt 
2899b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
2900b0fc494fSSteven Rostedt 
2901b0fc494fSSteven Rostedt 		ftrace_startup_sysctl();
2902b0fc494fSSteven Rostedt 
2903b0fc494fSSteven Rostedt 		/* we are starting ftrace again */
2904b0fc494fSSteven Rostedt 		if (ftrace_list != &ftrace_list_end) {
2905b0fc494fSSteven Rostedt 			if (ftrace_list->next == &ftrace_list_end)
2906b0fc494fSSteven Rostedt 				ftrace_trace_function = ftrace_list->func;
2907b0fc494fSSteven Rostedt 			else
2908b0fc494fSSteven Rostedt 				ftrace_trace_function = ftrace_list_func;
2909b0fc494fSSteven Rostedt 		}
2910b0fc494fSSteven Rostedt 
2911b0fc494fSSteven Rostedt 	} else {
2912b0fc494fSSteven Rostedt 		/* stopping ftrace calls (just send to ftrace_stub) */
2913b0fc494fSSteven Rostedt 		ftrace_trace_function = ftrace_stub;
2914b0fc494fSSteven Rostedt 
2915b0fc494fSSteven Rostedt 		ftrace_shutdown_sysctl();
2916b0fc494fSSteven Rostedt 	}
2917b0fc494fSSteven Rostedt 
2918b0fc494fSSteven Rostedt  out:
2919e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
29203d083395SSteven Rostedt 	return ret;
292116444a8aSArnaldo Carvalho de Melo }
2922f17845e5SIngo Molnar 
2923fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER
2924e7d3737eSFrederic Weisbecker 
2925287b6e68SFrederic Weisbecker static atomic_t ftrace_graph_active;
29264a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier;
2927f201ae23SFrederic Weisbecker 
2928e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
2929e49dc19cSSteven Rostedt {
2930e49dc19cSSteven Rostedt 	return 0;
2931e49dc19cSSteven Rostedt }
2932e49dc19cSSteven Rostedt 
2933287b6e68SFrederic Weisbecker /* The callbacks that hook a function */
2934287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return =
2935287b6e68SFrederic Weisbecker 			(trace_func_graph_ret_t)ftrace_stub;
2936e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
2937f201ae23SFrederic Weisbecker 
2938f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
2939f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
2940f201ae23SFrederic Weisbecker {
2941f201ae23SFrederic Weisbecker 	int i;
2942f201ae23SFrederic Weisbecker 	int ret = 0;
2943f201ae23SFrederic Weisbecker 	unsigned long flags;
2944f201ae23SFrederic Weisbecker 	int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE;
2945f201ae23SFrederic Weisbecker 	struct task_struct *g, *t;
2946f201ae23SFrederic Weisbecker 
2947f201ae23SFrederic Weisbecker 	for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
2948f201ae23SFrederic Weisbecker 		ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
2949f201ae23SFrederic Weisbecker 					* sizeof(struct ftrace_ret_stack),
2950f201ae23SFrederic Weisbecker 					GFP_KERNEL);
2951f201ae23SFrederic Weisbecker 		if (!ret_stack_list[i]) {
2952f201ae23SFrederic Weisbecker 			start = 0;
2953f201ae23SFrederic Weisbecker 			end = i;
2954f201ae23SFrederic Weisbecker 			ret = -ENOMEM;
2955f201ae23SFrederic Weisbecker 			goto free;
2956f201ae23SFrederic Weisbecker 		}
2957f201ae23SFrederic Weisbecker 	}
2958f201ae23SFrederic Weisbecker 
2959f201ae23SFrederic Weisbecker 	read_lock_irqsave(&tasklist_lock, flags);
2960f201ae23SFrederic Weisbecker 	do_each_thread(g, t) {
2961f201ae23SFrederic Weisbecker 		if (start == end) {
2962f201ae23SFrederic Weisbecker 			ret = -EAGAIN;
2963f201ae23SFrederic Weisbecker 			goto unlock;
2964f201ae23SFrederic Weisbecker 		}
2965f201ae23SFrederic Weisbecker 
2966f201ae23SFrederic Weisbecker 		if (t->ret_stack == NULL) {
2967f201ae23SFrederic Weisbecker 			t->curr_ret_stack = -1;
296848d68b20SFrederic Weisbecker 			/* Make sure IRQs see the -1 first: */
296948d68b20SFrederic Weisbecker 			barrier();
297048d68b20SFrederic Weisbecker 			t->ret_stack = ret_stack_list[start++];
2971380c4b14SFrederic Weisbecker 			atomic_set(&t->tracing_graph_pause, 0);
2972f201ae23SFrederic Weisbecker 			atomic_set(&t->trace_overrun, 0);
2973f201ae23SFrederic Weisbecker 		}
2974f201ae23SFrederic Weisbecker 	} while_each_thread(g, t);
2975f201ae23SFrederic Weisbecker 
2976f201ae23SFrederic Weisbecker unlock:
2977f201ae23SFrederic Weisbecker 	read_unlock_irqrestore(&tasklist_lock, flags);
2978f201ae23SFrederic Weisbecker free:
2979f201ae23SFrederic Weisbecker 	for (i = start; i < end; i++)
2980f201ae23SFrederic Weisbecker 		kfree(ret_stack_list[i]);
2981f201ae23SFrederic Weisbecker 	return ret;
2982f201ae23SFrederic Weisbecker }
2983f201ae23SFrederic Weisbecker 
29848aef2d28SSteven Rostedt static void
29858aef2d28SSteven Rostedt ftrace_graph_probe_sched_switch(struct rq *__rq, struct task_struct *prev,
29868aef2d28SSteven Rostedt 				struct task_struct *next)
29878aef2d28SSteven Rostedt {
29888aef2d28SSteven Rostedt 	unsigned long long timestamp;
29898aef2d28SSteven Rostedt 	int index;
29908aef2d28SSteven Rostedt 
2991be6f164aSSteven Rostedt 	/*
2992be6f164aSSteven Rostedt 	 * Does the user want to count the time a function was asleep.
2993be6f164aSSteven Rostedt 	 * If so, do not update the time stamps.
2994be6f164aSSteven Rostedt 	 */
2995be6f164aSSteven Rostedt 	if (trace_flags & TRACE_ITER_SLEEP_TIME)
2996be6f164aSSteven Rostedt 		return;
2997be6f164aSSteven Rostedt 
29988aef2d28SSteven Rostedt 	timestamp = trace_clock_local();
29998aef2d28SSteven Rostedt 
30008aef2d28SSteven Rostedt 	prev->ftrace_timestamp = timestamp;
30018aef2d28SSteven Rostedt 
30028aef2d28SSteven Rostedt 	/* only process tasks that we timestamped */
30038aef2d28SSteven Rostedt 	if (!next->ftrace_timestamp)
30048aef2d28SSteven Rostedt 		return;
30058aef2d28SSteven Rostedt 
30068aef2d28SSteven Rostedt 	/*
30078aef2d28SSteven Rostedt 	 * Update all the counters in next to make up for the
30088aef2d28SSteven Rostedt 	 * time next was sleeping.
30098aef2d28SSteven Rostedt 	 */
30108aef2d28SSteven Rostedt 	timestamp -= next->ftrace_timestamp;
30118aef2d28SSteven Rostedt 
30128aef2d28SSteven Rostedt 	for (index = next->curr_ret_stack; index >= 0; index--)
30138aef2d28SSteven Rostedt 		next->ret_stack[index].calltime += timestamp;
30148aef2d28SSteven Rostedt }
30158aef2d28SSteven Rostedt 
3016f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */
3017fb52607aSFrederic Weisbecker static int start_graph_tracing(void)
3018f201ae23SFrederic Weisbecker {
3019f201ae23SFrederic Weisbecker 	struct ftrace_ret_stack **ret_stack_list;
30205b058bcdSFrederic Weisbecker 	int ret, cpu;
3021f201ae23SFrederic Weisbecker 
3022f201ae23SFrederic Weisbecker 	ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
3023f201ae23SFrederic Weisbecker 				sizeof(struct ftrace_ret_stack *),
3024f201ae23SFrederic Weisbecker 				GFP_KERNEL);
3025f201ae23SFrederic Weisbecker 
3026f201ae23SFrederic Weisbecker 	if (!ret_stack_list)
3027f201ae23SFrederic Weisbecker 		return -ENOMEM;
3028f201ae23SFrederic Weisbecker 
30295b058bcdSFrederic Weisbecker 	/* The cpu_boot init_task->ret_stack will never be freed */
30305b058bcdSFrederic Weisbecker 	for_each_online_cpu(cpu)
30315b058bcdSFrederic Weisbecker 		ftrace_graph_init_task(idle_task(cpu));
30325b058bcdSFrederic Weisbecker 
3033f201ae23SFrederic Weisbecker 	do {
3034f201ae23SFrederic Weisbecker 		ret = alloc_retstack_tasklist(ret_stack_list);
3035f201ae23SFrederic Weisbecker 	} while (ret == -EAGAIN);
3036f201ae23SFrederic Weisbecker 
30378aef2d28SSteven Rostedt 	if (!ret) {
30388aef2d28SSteven Rostedt 		ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch);
30398aef2d28SSteven Rostedt 		if (ret)
30408aef2d28SSteven Rostedt 			pr_info("ftrace_graph: Couldn't activate tracepoint"
30418aef2d28SSteven Rostedt 				" probe to kernel_sched_switch\n");
30428aef2d28SSteven Rostedt 	}
30438aef2d28SSteven Rostedt 
3044f201ae23SFrederic Weisbecker 	kfree(ret_stack_list);
3045f201ae23SFrederic Weisbecker 	return ret;
3046f201ae23SFrederic Weisbecker }
3047f201ae23SFrederic Weisbecker 
30484a2b8ddaSFrederic Weisbecker /*
30494a2b8ddaSFrederic Weisbecker  * Hibernation protection.
30504a2b8ddaSFrederic Weisbecker  * The state of the current task is too much unstable during
30514a2b8ddaSFrederic Weisbecker  * suspend/restore to disk. We want to protect against that.
30524a2b8ddaSFrederic Weisbecker  */
30534a2b8ddaSFrederic Weisbecker static int
30544a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
30554a2b8ddaSFrederic Weisbecker 							void *unused)
30564a2b8ddaSFrederic Weisbecker {
30574a2b8ddaSFrederic Weisbecker 	switch (state) {
30584a2b8ddaSFrederic Weisbecker 	case PM_HIBERNATION_PREPARE:
30594a2b8ddaSFrederic Weisbecker 		pause_graph_tracing();
30604a2b8ddaSFrederic Weisbecker 		break;
30614a2b8ddaSFrederic Weisbecker 
30624a2b8ddaSFrederic Weisbecker 	case PM_POST_HIBERNATION:
30634a2b8ddaSFrederic Weisbecker 		unpause_graph_tracing();
30644a2b8ddaSFrederic Weisbecker 		break;
30654a2b8ddaSFrederic Weisbecker 	}
30664a2b8ddaSFrederic Weisbecker 	return NOTIFY_DONE;
30674a2b8ddaSFrederic Weisbecker }
30684a2b8ddaSFrederic Weisbecker 
3069287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc,
3070287b6e68SFrederic Weisbecker 			trace_func_graph_ent_t entryfunc)
307115e6cb36SFrederic Weisbecker {
3072e7d3737eSFrederic Weisbecker 	int ret = 0;
3073e7d3737eSFrederic Weisbecker 
3074e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
3075e7d3737eSFrederic Weisbecker 
307605ce5818SSteven Rostedt 	/* we currently allow only one tracer registered at a time */
307705ce5818SSteven Rostedt 	if (atomic_read(&ftrace_graph_active)) {
307805ce5818SSteven Rostedt 		ret = -EBUSY;
307905ce5818SSteven Rostedt 		goto out;
308005ce5818SSteven Rostedt 	}
308105ce5818SSteven Rostedt 
30824a2b8ddaSFrederic Weisbecker 	ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call;
30834a2b8ddaSFrederic Weisbecker 	register_pm_notifier(&ftrace_suspend_notifier);
30844a2b8ddaSFrederic Weisbecker 
3085287b6e68SFrederic Weisbecker 	atomic_inc(&ftrace_graph_active);
3086fb52607aSFrederic Weisbecker 	ret = start_graph_tracing();
3087f201ae23SFrederic Weisbecker 	if (ret) {
3088287b6e68SFrederic Weisbecker 		atomic_dec(&ftrace_graph_active);
3089f201ae23SFrederic Weisbecker 		goto out;
3090f201ae23SFrederic Weisbecker 	}
3091e53a6319SSteven Rostedt 
3092287b6e68SFrederic Weisbecker 	ftrace_graph_return = retfunc;
3093287b6e68SFrederic Weisbecker 	ftrace_graph_entry = entryfunc;
3094e53a6319SSteven Rostedt 
30955a45cfe1SSteven Rostedt 	ftrace_startup(FTRACE_START_FUNC_RET);
3096e7d3737eSFrederic Weisbecker 
3097e7d3737eSFrederic Weisbecker out:
3098e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
3099e7d3737eSFrederic Weisbecker 	return ret;
310015e6cb36SFrederic Weisbecker }
310115e6cb36SFrederic Weisbecker 
3102fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void)
310315e6cb36SFrederic Weisbecker {
3104e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
3105e7d3737eSFrederic Weisbecker 
3106287b6e68SFrederic Weisbecker 	atomic_dec(&ftrace_graph_active);
31078aef2d28SSteven Rostedt 	unregister_trace_sched_switch(ftrace_graph_probe_sched_switch);
3108287b6e68SFrederic Weisbecker 	ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
3109e49dc19cSSteven Rostedt 	ftrace_graph_entry = ftrace_graph_entry_stub;
31105a45cfe1SSteven Rostedt 	ftrace_shutdown(FTRACE_STOP_FUNC_RET);
31114a2b8ddaSFrederic Weisbecker 	unregister_pm_notifier(&ftrace_suspend_notifier);
3112e7d3737eSFrederic Weisbecker 
3113e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
311415e6cb36SFrederic Weisbecker }
3115f201ae23SFrederic Weisbecker 
3116f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */
3117fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t)
3118f201ae23SFrederic Weisbecker {
3119287b6e68SFrederic Weisbecker 	if (atomic_read(&ftrace_graph_active)) {
3120f201ae23SFrederic Weisbecker 		t->ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
3121f201ae23SFrederic Weisbecker 				* sizeof(struct ftrace_ret_stack),
3122f201ae23SFrederic Weisbecker 				GFP_KERNEL);
3123f201ae23SFrederic Weisbecker 		if (!t->ret_stack)
3124f201ae23SFrederic Weisbecker 			return;
3125f201ae23SFrederic Weisbecker 		t->curr_ret_stack = -1;
3126380c4b14SFrederic Weisbecker 		atomic_set(&t->tracing_graph_pause, 0);
3127f201ae23SFrederic Weisbecker 		atomic_set(&t->trace_overrun, 0);
31288aef2d28SSteven Rostedt 		t->ftrace_timestamp = 0;
3129f201ae23SFrederic Weisbecker 	} else
3130f201ae23SFrederic Weisbecker 		t->ret_stack = NULL;
3131f201ae23SFrederic Weisbecker }
3132f201ae23SFrederic Weisbecker 
3133fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t)
3134f201ae23SFrederic Weisbecker {
3135eae849caSFrederic Weisbecker 	struct ftrace_ret_stack	*ret_stack = t->ret_stack;
3136eae849caSFrederic Weisbecker 
3137f201ae23SFrederic Weisbecker 	t->ret_stack = NULL;
3138eae849caSFrederic Weisbecker 	/* NULL must become visible to IRQs before we free it: */
3139eae849caSFrederic Weisbecker 	barrier();
3140eae849caSFrederic Weisbecker 
3141eae849caSFrederic Weisbecker 	kfree(ret_stack);
3142f201ae23SFrederic Weisbecker }
314314a866c5SSteven Rostedt 
314414a866c5SSteven Rostedt void ftrace_graph_stop(void)
314514a866c5SSteven Rostedt {
314614a866c5SSteven Rostedt 	ftrace_stop();
314714a866c5SSteven Rostedt }
314815e6cb36SFrederic Weisbecker #endif
314915e6cb36SFrederic Weisbecker 
3150