xref: /linux-6.15/kernel/trace/ftrace.c (revision 52baf119)
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>
3016444a8aSArnaldo Carvalho de Melo 
31395a59d0SAbhishek Sagar #include <asm/ftrace.h>
32395a59d0SAbhishek Sagar 
333d083395SSteven Rostedt #include "trace.h"
343d083395SSteven Rostedt 
356912896eSSteven Rostedt #define FTRACE_WARN_ON(cond)			\
366912896eSSteven Rostedt 	do {					\
376912896eSSteven Rostedt 		if (WARN_ON(cond))		\
386912896eSSteven Rostedt 			ftrace_kill();		\
396912896eSSteven Rostedt 	} while (0)
406912896eSSteven Rostedt 
416912896eSSteven Rostedt #define FTRACE_WARN_ON_ONCE(cond)		\
426912896eSSteven Rostedt 	do {					\
436912896eSSteven Rostedt 		if (WARN_ON_ONCE(cond))		\
446912896eSSteven Rostedt 			ftrace_kill();		\
456912896eSSteven Rostedt 	} while (0)
466912896eSSteven Rostedt 
474eebcc81SSteven Rostedt /* ftrace_enabled is a method to turn ftrace on or off */
484eebcc81SSteven Rostedt int ftrace_enabled __read_mostly;
49d61f82d0SSteven Rostedt static int last_ftrace_enabled;
50b0fc494fSSteven Rostedt 
510ef8cde5SSteven Rostedt /* set when tracing only a pid */
52978f3a45SSteven Rostedt struct pid *ftrace_pid_trace;
5321bbecdaSSteven Rostedt static struct pid * const ftrace_swapper_pid = &init_struct_pid;
54df4fc315SSteven Rostedt 
5560a7ecf4SSteven Rostedt /* Quick disabling of function tracer. */
5660a7ecf4SSteven Rostedt int function_trace_stop;
5760a7ecf4SSteven Rostedt 
584eebcc81SSteven Rostedt /*
594eebcc81SSteven Rostedt  * ftrace_disabled is set when an anomaly is discovered.
604eebcc81SSteven Rostedt  * ftrace_disabled is much stronger than ftrace_enabled.
614eebcc81SSteven Rostedt  */
624eebcc81SSteven Rostedt static int ftrace_disabled __read_mostly;
634eebcc81SSteven Rostedt 
64*52baf119SSteven Rostedt static DEFINE_MUTEX(ftrace_lock);
65b0fc494fSSteven Rostedt static DEFINE_MUTEX(ftrace_sysctl_lock);
66df4fc315SSteven Rostedt static DEFINE_MUTEX(ftrace_start_lock);
67b0fc494fSSteven Rostedt 
6816444a8aSArnaldo Carvalho de Melo static struct ftrace_ops ftrace_list_end __read_mostly =
6916444a8aSArnaldo Carvalho de Melo {
7016444a8aSArnaldo Carvalho de Melo 	.func = ftrace_stub,
7116444a8aSArnaldo Carvalho de Melo };
7216444a8aSArnaldo Carvalho de Melo 
7316444a8aSArnaldo Carvalho de Melo static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end;
7416444a8aSArnaldo Carvalho de Melo ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
7560a7ecf4SSteven Rostedt ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
76df4fc315SSteven Rostedt ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
7716444a8aSArnaldo Carvalho de Melo 
78f2252935SIngo Molnar static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
7916444a8aSArnaldo Carvalho de Melo {
8016444a8aSArnaldo Carvalho de Melo 	struct ftrace_ops *op = ftrace_list;
8116444a8aSArnaldo Carvalho de Melo 
8216444a8aSArnaldo Carvalho de Melo 	/* in case someone actually ports this to alpha! */
8316444a8aSArnaldo Carvalho de Melo 	read_barrier_depends();
8416444a8aSArnaldo Carvalho de Melo 
8516444a8aSArnaldo Carvalho de Melo 	while (op != &ftrace_list_end) {
8616444a8aSArnaldo Carvalho de Melo 		/* silly alpha */
8716444a8aSArnaldo Carvalho de Melo 		read_barrier_depends();
8816444a8aSArnaldo Carvalho de Melo 		op->func(ip, parent_ip);
8916444a8aSArnaldo Carvalho de Melo 		op = op->next;
9016444a8aSArnaldo Carvalho de Melo 	};
9116444a8aSArnaldo Carvalho de Melo }
9216444a8aSArnaldo Carvalho de Melo 
93df4fc315SSteven Rostedt static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip)
94df4fc315SSteven Rostedt {
950ef8cde5SSteven Rostedt 	if (!test_tsk_trace_trace(current))
96df4fc315SSteven Rostedt 		return;
97df4fc315SSteven Rostedt 
98df4fc315SSteven Rostedt 	ftrace_pid_function(ip, parent_ip);
99df4fc315SSteven Rostedt }
100df4fc315SSteven Rostedt 
101df4fc315SSteven Rostedt static void set_ftrace_pid_function(ftrace_func_t func)
102df4fc315SSteven Rostedt {
103df4fc315SSteven Rostedt 	/* do not set ftrace_pid_function to itself! */
104df4fc315SSteven Rostedt 	if (func != ftrace_pid_func)
105df4fc315SSteven Rostedt 		ftrace_pid_function = func;
106df4fc315SSteven Rostedt }
107df4fc315SSteven Rostedt 
10816444a8aSArnaldo Carvalho de Melo /**
1093d083395SSteven Rostedt  * clear_ftrace_function - reset the ftrace function
11016444a8aSArnaldo Carvalho de Melo  *
1113d083395SSteven Rostedt  * This NULLs the ftrace function and in essence stops
1123d083395SSteven Rostedt  * tracing.  There may be lag
11316444a8aSArnaldo Carvalho de Melo  */
1143d083395SSteven Rostedt void clear_ftrace_function(void)
11516444a8aSArnaldo Carvalho de Melo {
1163d083395SSteven Rostedt 	ftrace_trace_function = ftrace_stub;
11760a7ecf4SSteven Rostedt 	__ftrace_trace_function = ftrace_stub;
118df4fc315SSteven Rostedt 	ftrace_pid_function = ftrace_stub;
1193d083395SSteven Rostedt }
12016444a8aSArnaldo Carvalho de Melo 
12160a7ecf4SSteven Rostedt #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
12260a7ecf4SSteven Rostedt /*
12360a7ecf4SSteven Rostedt  * For those archs that do not test ftrace_trace_stop in their
12460a7ecf4SSteven Rostedt  * mcount call site, we need to do it from C.
12560a7ecf4SSteven Rostedt  */
12660a7ecf4SSteven Rostedt static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip)
12760a7ecf4SSteven Rostedt {
12860a7ecf4SSteven Rostedt 	if (function_trace_stop)
12960a7ecf4SSteven Rostedt 		return;
13060a7ecf4SSteven Rostedt 
13160a7ecf4SSteven Rostedt 	__ftrace_trace_function(ip, parent_ip);
13260a7ecf4SSteven Rostedt }
13360a7ecf4SSteven Rostedt #endif
13460a7ecf4SSteven Rostedt 
135e309b41dSIngo Molnar static int __register_ftrace_function(struct ftrace_ops *ops)
1363d083395SSteven Rostedt {
137*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
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 
174*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
17516444a8aSArnaldo Carvalho de Melo 
17616444a8aSArnaldo Carvalho de Melo 	return 0;
17716444a8aSArnaldo Carvalho de Melo }
17816444a8aSArnaldo Carvalho de Melo 
179e309b41dSIngo Molnar static int __unregister_ftrace_function(struct ftrace_ops *ops)
18016444a8aSArnaldo Carvalho de Melo {
18116444a8aSArnaldo Carvalho de Melo 	struct ftrace_ops **p;
18216444a8aSArnaldo Carvalho de Melo 	int ret = 0;
18316444a8aSArnaldo Carvalho de Melo 
184*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
18516444a8aSArnaldo Carvalho de Melo 
18616444a8aSArnaldo Carvalho de Melo 	/*
1873d083395SSteven Rostedt 	 * If we are removing the last function, then simply point
1883d083395SSteven Rostedt 	 * to the ftrace_stub.
18916444a8aSArnaldo Carvalho de Melo 	 */
19016444a8aSArnaldo Carvalho de Melo 	if (ftrace_list == ops && ops->next == &ftrace_list_end) {
19116444a8aSArnaldo Carvalho de Melo 		ftrace_trace_function = ftrace_stub;
19216444a8aSArnaldo Carvalho de Melo 		ftrace_list = &ftrace_list_end;
19316444a8aSArnaldo Carvalho de Melo 		goto out;
19416444a8aSArnaldo Carvalho de Melo 	}
19516444a8aSArnaldo Carvalho de Melo 
19616444a8aSArnaldo Carvalho de Melo 	for (p = &ftrace_list; *p != &ftrace_list_end; p = &(*p)->next)
19716444a8aSArnaldo Carvalho de Melo 		if (*p == ops)
19816444a8aSArnaldo Carvalho de Melo 			break;
19916444a8aSArnaldo Carvalho de Melo 
20016444a8aSArnaldo Carvalho de Melo 	if (*p != ops) {
20116444a8aSArnaldo Carvalho de Melo 		ret = -1;
20216444a8aSArnaldo Carvalho de Melo 		goto out;
20316444a8aSArnaldo Carvalho de Melo 	}
20416444a8aSArnaldo Carvalho de Melo 
20516444a8aSArnaldo Carvalho de Melo 	*p = (*p)->next;
20616444a8aSArnaldo Carvalho de Melo 
207b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
20816444a8aSArnaldo Carvalho de Melo 		/* If we only have one func left, then call that directly */
209df4fc315SSteven Rostedt 		if (ftrace_list->next == &ftrace_list_end) {
210df4fc315SSteven Rostedt 			ftrace_func_t func = ftrace_list->func;
211df4fc315SSteven Rostedt 
212978f3a45SSteven Rostedt 			if (ftrace_pid_trace) {
213df4fc315SSteven Rostedt 				set_ftrace_pid_function(func);
214df4fc315SSteven Rostedt 				func = ftrace_pid_func;
215df4fc315SSteven Rostedt 			}
216df4fc315SSteven Rostedt #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
217df4fc315SSteven Rostedt 			ftrace_trace_function = func;
218df4fc315SSteven Rostedt #else
219df4fc315SSteven Rostedt 			__ftrace_trace_function = func;
220df4fc315SSteven Rostedt #endif
221df4fc315SSteven Rostedt 		}
222b0fc494fSSteven Rostedt 	}
22316444a8aSArnaldo Carvalho de Melo 
22416444a8aSArnaldo Carvalho de Melo  out:
225*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2263d083395SSteven Rostedt 
2273d083395SSteven Rostedt 	return ret;
2283d083395SSteven Rostedt }
2293d083395SSteven Rostedt 
230df4fc315SSteven Rostedt static void ftrace_update_pid_func(void)
231df4fc315SSteven Rostedt {
232df4fc315SSteven Rostedt 	ftrace_func_t func;
233df4fc315SSteven Rostedt 
234*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
235df4fc315SSteven Rostedt 
236df4fc315SSteven Rostedt 	if (ftrace_trace_function == ftrace_stub)
237df4fc315SSteven Rostedt 		goto out;
238df4fc315SSteven Rostedt 
239df4fc315SSteven Rostedt 	func = ftrace_trace_function;
240df4fc315SSteven Rostedt 
241978f3a45SSteven Rostedt 	if (ftrace_pid_trace) {
242df4fc315SSteven Rostedt 		set_ftrace_pid_function(func);
243df4fc315SSteven Rostedt 		func = ftrace_pid_func;
244df4fc315SSteven Rostedt 	} else {
24566eafebcSLiming Wang 		if (func == ftrace_pid_func)
24666eafebcSLiming Wang 			func = ftrace_pid_function;
247df4fc315SSteven Rostedt 	}
248df4fc315SSteven Rostedt 
249df4fc315SSteven Rostedt #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
250df4fc315SSteven Rostedt 	ftrace_trace_function = func;
251df4fc315SSteven Rostedt #else
252df4fc315SSteven Rostedt 	__ftrace_trace_function = func;
253df4fc315SSteven Rostedt #endif
254df4fc315SSteven Rostedt 
255df4fc315SSteven Rostedt  out:
256*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
257df4fc315SSteven Rostedt }
258df4fc315SSteven Rostedt 
2593d083395SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE
26099ecdc43SSteven Rostedt #ifndef CONFIG_FTRACE_MCOUNT_RECORD
261cb7be3b2SSteven Rostedt # error Dynamic ftrace depends on MCOUNT_RECORD
26299ecdc43SSteven Rostedt #endif
26399ecdc43SSteven Rostedt 
264d61f82d0SSteven Rostedt enum {
265d61f82d0SSteven Rostedt 	FTRACE_ENABLE_CALLS		= (1 << 0),
266d61f82d0SSteven Rostedt 	FTRACE_DISABLE_CALLS		= (1 << 1),
267d61f82d0SSteven Rostedt 	FTRACE_UPDATE_TRACE_FUNC	= (1 << 2),
268d61f82d0SSteven Rostedt 	FTRACE_ENABLE_MCOUNT		= (1 << 3),
269d61f82d0SSteven Rostedt 	FTRACE_DISABLE_MCOUNT		= (1 << 4),
2705a45cfe1SSteven Rostedt 	FTRACE_START_FUNC_RET		= (1 << 5),
2715a45cfe1SSteven Rostedt 	FTRACE_STOP_FUNC_RET		= (1 << 6),
272d61f82d0SSteven Rostedt };
273d61f82d0SSteven Rostedt 
2745072c59fSSteven Rostedt static int ftrace_filtered;
2755072c59fSSteven Rostedt 
27608f5ac90SSteven Rostedt static LIST_HEAD(ftrace_new_addrs);
2773d083395SSteven Rostedt 
27841c52c0dSSteven Rostedt static DEFINE_MUTEX(ftrace_regex_lock);
2793d083395SSteven Rostedt 
2803c1720f0SSteven Rostedt struct ftrace_page {
2813c1720f0SSteven Rostedt 	struct ftrace_page	*next;
282431aa3fbSSteven Rostedt 	int			index;
2833c1720f0SSteven Rostedt 	struct dyn_ftrace	records[];
284aa5e5ceaSDavid Miller };
2853c1720f0SSteven Rostedt 
2863c1720f0SSteven Rostedt #define ENTRIES_PER_PAGE \
2873c1720f0SSteven Rostedt   ((PAGE_SIZE - sizeof(struct ftrace_page)) / sizeof(struct dyn_ftrace))
2883c1720f0SSteven Rostedt 
2893c1720f0SSteven Rostedt /* estimate from running different kernels */
2903c1720f0SSteven Rostedt #define NR_TO_INIT		10000
2913c1720f0SSteven Rostedt 
2923c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages_start;
2933c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages;
2943c1720f0SSteven Rostedt 
29537ad5084SSteven Rostedt static struct dyn_ftrace *ftrace_free_records;
29637ad5084SSteven Rostedt 
297265c831cSSteven Rostedt /*
298265c831cSSteven Rostedt  * This is a double for. Do not use 'break' to break out of the loop,
299265c831cSSteven Rostedt  * you must use a goto.
300265c831cSSteven Rostedt  */
301265c831cSSteven Rostedt #define do_for_each_ftrace_rec(pg, rec)					\
302265c831cSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {		\
303265c831cSSteven Rostedt 		int _____i;						\
304265c831cSSteven Rostedt 		for (_____i = 0; _____i < pg->index; _____i++) {	\
305265c831cSSteven Rostedt 			rec = &pg->records[_____i];
306265c831cSSteven Rostedt 
307265c831cSSteven Rostedt #define while_for_each_ftrace_rec()		\
308265c831cSSteven Rostedt 		}				\
309265c831cSSteven Rostedt 	}
310ecea656dSAbhishek Sagar 
311ecea656dSAbhishek Sagar #ifdef CONFIG_KPROBES
312f17845e5SIngo Molnar 
313f17845e5SIngo Molnar static int frozen_record_count;
314f17845e5SIngo Molnar 
315ecea656dSAbhishek Sagar static inline void freeze_record(struct dyn_ftrace *rec)
316ecea656dSAbhishek Sagar {
317ecea656dSAbhishek Sagar 	if (!(rec->flags & FTRACE_FL_FROZEN)) {
318ecea656dSAbhishek Sagar 		rec->flags |= FTRACE_FL_FROZEN;
319ecea656dSAbhishek Sagar 		frozen_record_count++;
320ecea656dSAbhishek Sagar 	}
321ecea656dSAbhishek Sagar }
322ecea656dSAbhishek Sagar 
323ecea656dSAbhishek Sagar static inline void unfreeze_record(struct dyn_ftrace *rec)
324ecea656dSAbhishek Sagar {
325ecea656dSAbhishek Sagar 	if (rec->flags & FTRACE_FL_FROZEN) {
326ecea656dSAbhishek Sagar 		rec->flags &= ~FTRACE_FL_FROZEN;
327ecea656dSAbhishek Sagar 		frozen_record_count--;
328ecea656dSAbhishek Sagar 	}
329ecea656dSAbhishek Sagar }
330ecea656dSAbhishek Sagar 
331ecea656dSAbhishek Sagar static inline int record_frozen(struct dyn_ftrace *rec)
332ecea656dSAbhishek Sagar {
333ecea656dSAbhishek Sagar 	return rec->flags & FTRACE_FL_FROZEN;
334ecea656dSAbhishek Sagar }
335ecea656dSAbhishek Sagar #else
336ecea656dSAbhishek Sagar # define freeze_record(rec)			({ 0; })
337ecea656dSAbhishek Sagar # define unfreeze_record(rec)			({ 0; })
338ecea656dSAbhishek Sagar # define record_frozen(rec)			({ 0; })
339ecea656dSAbhishek Sagar #endif /* CONFIG_KPROBES */
340ecea656dSAbhishek Sagar 
341e309b41dSIngo Molnar static void ftrace_free_rec(struct dyn_ftrace *rec)
34237ad5084SSteven Rostedt {
34337ad5084SSteven Rostedt 	rec->ip = (unsigned long)ftrace_free_records;
34437ad5084SSteven Rostedt 	ftrace_free_records = rec;
34537ad5084SSteven Rostedt 	rec->flags |= FTRACE_FL_FREE;
34637ad5084SSteven Rostedt }
34737ad5084SSteven Rostedt 
348fed1939cSSteven Rostedt void ftrace_release(void *start, unsigned long size)
349fed1939cSSteven Rostedt {
350fed1939cSSteven Rostedt 	struct dyn_ftrace *rec;
351fed1939cSSteven Rostedt 	struct ftrace_page *pg;
352fed1939cSSteven Rostedt 	unsigned long s = (unsigned long)start;
353fed1939cSSteven Rostedt 	unsigned long e = s + size;
354fed1939cSSteven Rostedt 
35500fd61aeSSteven Rostedt 	if (ftrace_disabled || !start)
356fed1939cSSteven Rostedt 		return;
357fed1939cSSteven Rostedt 
358*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
359265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
360fed1939cSSteven Rostedt 		if ((rec->ip >= s) && (rec->ip < e))
361fed1939cSSteven Rostedt 			ftrace_free_rec(rec);
362265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
363*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
364fed1939cSSteven Rostedt }
365fed1939cSSteven Rostedt 
366e309b41dSIngo Molnar static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
3673c1720f0SSteven Rostedt {
36837ad5084SSteven Rostedt 	struct dyn_ftrace *rec;
36937ad5084SSteven Rostedt 
37037ad5084SSteven Rostedt 	/* First check for freed records */
37137ad5084SSteven Rostedt 	if (ftrace_free_records) {
37237ad5084SSteven Rostedt 		rec = ftrace_free_records;
37337ad5084SSteven Rostedt 
37437ad5084SSteven Rostedt 		if (unlikely(!(rec->flags & FTRACE_FL_FREE))) {
3756912896eSSteven Rostedt 			FTRACE_WARN_ON_ONCE(1);
37637ad5084SSteven Rostedt 			ftrace_free_records = NULL;
37737ad5084SSteven Rostedt 			return NULL;
37837ad5084SSteven Rostedt 		}
37937ad5084SSteven Rostedt 
38037ad5084SSteven Rostedt 		ftrace_free_records = (void *)rec->ip;
38137ad5084SSteven Rostedt 		memset(rec, 0, sizeof(*rec));
38237ad5084SSteven Rostedt 		return rec;
38337ad5084SSteven Rostedt 	}
38437ad5084SSteven Rostedt 
3853c1720f0SSteven Rostedt 	if (ftrace_pages->index == ENTRIES_PER_PAGE) {
38608f5ac90SSteven Rostedt 		if (!ftrace_pages->next) {
38708f5ac90SSteven Rostedt 			/* allocate another page */
38808f5ac90SSteven Rostedt 			ftrace_pages->next =
38908f5ac90SSteven Rostedt 				(void *)get_zeroed_page(GFP_KERNEL);
3903c1720f0SSteven Rostedt 			if (!ftrace_pages->next)
3913c1720f0SSteven Rostedt 				return NULL;
39208f5ac90SSteven Rostedt 		}
3933c1720f0SSteven Rostedt 		ftrace_pages = ftrace_pages->next;
3943c1720f0SSteven Rostedt 	}
3953c1720f0SSteven Rostedt 
3963c1720f0SSteven Rostedt 	return &ftrace_pages->records[ftrace_pages->index++];
3973c1720f0SSteven Rostedt }
3983c1720f0SSteven Rostedt 
39908f5ac90SSteven Rostedt static struct dyn_ftrace *
400d61f82d0SSteven Rostedt ftrace_record_ip(unsigned long ip)
4013d083395SSteven Rostedt {
40208f5ac90SSteven Rostedt 	struct dyn_ftrace *rec;
4033d083395SSteven Rostedt 
404f3c7ac40SSteven Rostedt 	if (ftrace_disabled)
40508f5ac90SSteven Rostedt 		return NULL;
406d61f82d0SSteven Rostedt 
40708f5ac90SSteven Rostedt 	rec = ftrace_alloc_dyn_node(ip);
40808f5ac90SSteven Rostedt 	if (!rec)
40908f5ac90SSteven Rostedt 		return NULL;
4103d083395SSteven Rostedt 
41108f5ac90SSteven Rostedt 	rec->ip = ip;
4123d083395SSteven Rostedt 
41308f5ac90SSteven Rostedt 	list_add(&rec->list, &ftrace_new_addrs);
4143d083395SSteven Rostedt 
41508f5ac90SSteven Rostedt 	return rec;
4163d083395SSteven Rostedt }
4173d083395SSteven Rostedt 
41805736a42SSteven Rostedt static void print_ip_ins(const char *fmt, unsigned char *p)
41905736a42SSteven Rostedt {
42005736a42SSteven Rostedt 	int i;
42105736a42SSteven Rostedt 
42205736a42SSteven Rostedt 	printk(KERN_CONT "%s", fmt);
42305736a42SSteven Rostedt 
42405736a42SSteven Rostedt 	for (i = 0; i < MCOUNT_INSN_SIZE; i++)
42505736a42SSteven Rostedt 		printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
42605736a42SSteven Rostedt }
42705736a42SSteven Rostedt 
42831e88909SSteven Rostedt static void ftrace_bug(int failed, unsigned long ip)
4293c1720f0SSteven Rostedt {
430b17e8a37SSteven Rostedt 	switch (failed) {
431593eb8a2SSteven Rostedt 	case -EFAULT:
4326912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
43305736a42SSteven Rostedt 		pr_info("ftrace faulted on modifying ");
43405736a42SSteven Rostedt 		print_ip_sym(ip);
43505736a42SSteven Rostedt 		break;
436593eb8a2SSteven Rostedt 	case -EINVAL:
4376912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
43805736a42SSteven Rostedt 		pr_info("ftrace failed to modify ");
43905736a42SSteven Rostedt 		print_ip_sym(ip);
44005736a42SSteven Rostedt 		print_ip_ins(" actual: ", (unsigned char *)ip);
44105736a42SSteven Rostedt 		printk(KERN_CONT "\n");
44205736a42SSteven Rostedt 		break;
443593eb8a2SSteven Rostedt 	case -EPERM:
4446912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
445593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on writing ");
446593eb8a2SSteven Rostedt 		print_ip_sym(ip);
447593eb8a2SSteven Rostedt 		break;
448593eb8a2SSteven Rostedt 	default:
4496912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
450593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on unknown error ");
451593eb8a2SSteven Rostedt 		print_ip_sym(ip);
45205736a42SSteven Rostedt 	}
453b17e8a37SSteven Rostedt }
45405736a42SSteven Rostedt 
4553d083395SSteven Rostedt 
4563d083395SSteven Rostedt static int
45731e88909SSteven Rostedt __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
4583d083395SSteven Rostedt {
4593d083395SSteven Rostedt 	unsigned long ip, fl;
460e7d3737eSFrederic Weisbecker 	unsigned long ftrace_addr;
461e7d3737eSFrederic Weisbecker 
462f0001207SShaohua Li 	ftrace_addr = (unsigned long)FTRACE_ADDR;
4633d083395SSteven Rostedt 
4643d083395SSteven Rostedt 	ip = rec->ip;
4653d083395SSteven Rostedt 
4663d083395SSteven Rostedt 	/*
467982c350bSSteven Rostedt 	 * If this record is not to be traced and
468982c350bSSteven Rostedt 	 * it is not enabled then do nothing.
4693d083395SSteven Rostedt 	 *
470982c350bSSteven Rostedt 	 * If this record is not to be traced and
47157794a9dSWenji Huang 	 * it is enabled then disable it.
4723d083395SSteven Rostedt 	 *
4733d083395SSteven Rostedt 	 */
474982c350bSSteven Rostedt 	if (rec->flags & FTRACE_FL_NOTRACE) {
475982c350bSSteven Rostedt 		if (rec->flags & FTRACE_FL_ENABLED)
4763d083395SSteven Rostedt 			rec->flags &= ~FTRACE_FL_ENABLED;
477982c350bSSteven Rostedt 		else
4783d083395SSteven Rostedt 			return 0;
479982c350bSSteven Rostedt 
480982c350bSSteven Rostedt 	} else if (ftrace_filtered && enable) {
481982c350bSSteven Rostedt 		/*
482982c350bSSteven Rostedt 		 * Filtering is on:
483982c350bSSteven Rostedt 		 */
484982c350bSSteven Rostedt 
485982c350bSSteven Rostedt 		fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED);
486982c350bSSteven Rostedt 
487982c350bSSteven Rostedt 		/* Record is filtered and enabled, do nothing */
488982c350bSSteven Rostedt 		if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED))
489982c350bSSteven Rostedt 			return 0;
490982c350bSSteven Rostedt 
49157794a9dSWenji Huang 		/* Record is not filtered or enabled, do nothing */
492982c350bSSteven Rostedt 		if (!fl)
493982c350bSSteven Rostedt 			return 0;
494982c350bSSteven Rostedt 
495982c350bSSteven Rostedt 		/* Record is not filtered but enabled, disable it */
496982c350bSSteven Rostedt 		if (fl == FTRACE_FL_ENABLED)
497982c350bSSteven Rostedt 			rec->flags &= ~FTRACE_FL_ENABLED;
498982c350bSSteven Rostedt 		else
499982c350bSSteven Rostedt 		/* Otherwise record is filtered but not enabled, enable it */
500982c350bSSteven Rostedt 			rec->flags |= FTRACE_FL_ENABLED;
501982c350bSSteven Rostedt 	} else {
502982c350bSSteven Rostedt 		/* Disable or not filtered */
5033d083395SSteven Rostedt 
5043d083395SSteven Rostedt 		if (enable) {
505982c350bSSteven Rostedt 			/* if record is enabled, do nothing */
5063d083395SSteven Rostedt 			if (rec->flags & FTRACE_FL_ENABLED)
5073d083395SSteven Rostedt 				return 0;
508982c350bSSteven Rostedt 
5093d083395SSteven Rostedt 			rec->flags |= FTRACE_FL_ENABLED;
510982c350bSSteven Rostedt 
5113d083395SSteven Rostedt 		} else {
512982c350bSSteven Rostedt 
51357794a9dSWenji Huang 			/* if record is not enabled, do nothing */
5143d083395SSteven Rostedt 			if (!(rec->flags & FTRACE_FL_ENABLED))
5153d083395SSteven Rostedt 				return 0;
516982c350bSSteven Rostedt 
5173d083395SSteven Rostedt 			rec->flags &= ~FTRACE_FL_ENABLED;
5183d083395SSteven Rostedt 		}
5193d083395SSteven Rostedt 	}
5203d083395SSteven Rostedt 
521982c350bSSteven Rostedt 	if (rec->flags & FTRACE_FL_ENABLED)
522e7d3737eSFrederic Weisbecker 		return ftrace_make_call(rec, ftrace_addr);
52331e88909SSteven Rostedt 	else
524e7d3737eSFrederic Weisbecker 		return ftrace_make_nop(NULL, rec, ftrace_addr);
5253d083395SSteven Rostedt }
5263d083395SSteven Rostedt 
5273d083395SSteven Rostedt static void ftrace_replace_code(int enable)
5283d083395SSteven Rostedt {
529265c831cSSteven Rostedt 	int failed;
5303d083395SSteven Rostedt 	struct dyn_ftrace *rec;
5313d083395SSteven Rostedt 	struct ftrace_page *pg;
5323d083395SSteven Rostedt 
533265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
534918c1154SSteven Rostedt 		/*
535918c1154SSteven Rostedt 		 * Skip over free records and records that have
536918c1154SSteven Rostedt 		 * failed.
537918c1154SSteven Rostedt 		 */
538918c1154SSteven Rostedt 		if (rec->flags & FTRACE_FL_FREE ||
539918c1154SSteven Rostedt 		    rec->flags & FTRACE_FL_FAILED)
5403d083395SSteven Rostedt 			continue;
5413d083395SSteven Rostedt 
5423d083395SSteven Rostedt 		/* ignore updates to this record's mcount site */
5433d083395SSteven Rostedt 		if (get_kprobe((void *)rec->ip)) {
5443d083395SSteven Rostedt 			freeze_record(rec);
5453d083395SSteven Rostedt 			continue;
5463d083395SSteven Rostedt 		} else {
5473d083395SSteven Rostedt 			unfreeze_record(rec);
5483d083395SSteven Rostedt 		}
5493d083395SSteven Rostedt 
55031e88909SSteven Rostedt 		failed = __ftrace_replace_code(rec, enable);
5513d083395SSteven Rostedt 		if (failed && (rec->flags & FTRACE_FL_CONVERTED)) {
5523d083395SSteven Rostedt 			rec->flags |= FTRACE_FL_FAILED;
5533d083395SSteven Rostedt 			if ((system_state == SYSTEM_BOOTING) ||
5543d083395SSteven Rostedt 			    !core_kernel_text(rec->ip)) {
5553d083395SSteven Rostedt 				ftrace_free_rec(rec);
556b17e8a37SSteven Rostedt 			} else
55731e88909SSteven Rostedt 				ftrace_bug(failed, rec->ip);
5583d083395SSteven Rostedt 		}
559265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
5603d083395SSteven Rostedt }
5613c1720f0SSteven Rostedt 
5623b47bfc1SSteven Rostedt static int
56331e88909SSteven Rostedt ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
5643c1720f0SSteven Rostedt {
56537ad5084SSteven Rostedt 	unsigned long ip;
566492a7ea5SAbhishek Sagar 	int ret;
56737ad5084SSteven Rostedt 
568492a7ea5SAbhishek Sagar 	ip = rec->ip;
5693c1720f0SSteven Rostedt 
57025aac9dcSShaohua Li 	ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
5713d083395SSteven Rostedt 	if (ret) {
57231e88909SSteven Rostedt 		ftrace_bug(ret, ip);
5733d083395SSteven Rostedt 		rec->flags |= FTRACE_FL_FAILED;
5743d083395SSteven Rostedt 		return 0;
575d61f82d0SSteven Rostedt 	}
576d61f82d0SSteven Rostedt 	return 1;
5773d083395SSteven Rostedt }
5783d083395SSteven Rostedt 
5793d083395SSteven Rostedt static int __ftrace_modify_code(void *data)
5803d083395SSteven Rostedt {
5813d083395SSteven Rostedt 	int *command = data;
5823d083395SSteven Rostedt 
583a3583244SSteven Rostedt 	if (*command & FTRACE_ENABLE_CALLS)
5843d083395SSteven Rostedt 		ftrace_replace_code(1);
585a3583244SSteven Rostedt 	else if (*command & FTRACE_DISABLE_CALLS)
5863d083395SSteven Rostedt 		ftrace_replace_code(0);
5873d083395SSteven Rostedt 
5883d083395SSteven Rostedt 	if (*command & FTRACE_UPDATE_TRACE_FUNC)
5893d083395SSteven Rostedt 		ftrace_update_ftrace_func(ftrace_trace_function);
5903d083395SSteven Rostedt 
5915a45cfe1SSteven Rostedt 	if (*command & FTRACE_START_FUNC_RET)
5925a45cfe1SSteven Rostedt 		ftrace_enable_ftrace_graph_caller();
5935a45cfe1SSteven Rostedt 	else if (*command & FTRACE_STOP_FUNC_RET)
5945a45cfe1SSteven Rostedt 		ftrace_disable_ftrace_graph_caller();
5955a45cfe1SSteven Rostedt 
5963d083395SSteven Rostedt 	return 0;
5973d083395SSteven Rostedt }
5983d083395SSteven Rostedt 
599e309b41dSIngo Molnar static void ftrace_run_update_code(int command)
6003d083395SSteven Rostedt {
601784e2d76SRusty Russell 	stop_machine(__ftrace_modify_code, &command, NULL);
6023d083395SSteven Rostedt }
6033d083395SSteven Rostedt 
6043d083395SSteven Rostedt static ftrace_func_t saved_ftrace_func;
60560a7ecf4SSteven Rostedt static int ftrace_start_up;
606df4fc315SSteven Rostedt 
607df4fc315SSteven Rostedt static void ftrace_startup_enable(int command)
608df4fc315SSteven Rostedt {
609df4fc315SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
610df4fc315SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
611df4fc315SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
612df4fc315SSteven Rostedt 	}
613df4fc315SSteven Rostedt 
614df4fc315SSteven Rostedt 	if (!command || !ftrace_enabled)
615df4fc315SSteven Rostedt 		return;
616df4fc315SSteven Rostedt 
617df4fc315SSteven Rostedt 	ftrace_run_update_code(command);
618df4fc315SSteven Rostedt }
6193d083395SSteven Rostedt 
6205a45cfe1SSteven Rostedt static void ftrace_startup(int command)
6213d083395SSteven Rostedt {
6224eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
6234eebcc81SSteven Rostedt 		return;
6244eebcc81SSteven Rostedt 
625cb7be3b2SSteven Rostedt 	mutex_lock(&ftrace_start_lock);
62660a7ecf4SSteven Rostedt 	ftrace_start_up++;
627d61f82d0SSteven Rostedt 	command |= FTRACE_ENABLE_CALLS;
6283d083395SSteven Rostedt 
629df4fc315SSteven Rostedt 	ftrace_startup_enable(command);
630d61f82d0SSteven Rostedt 
631cb7be3b2SSteven Rostedt 	mutex_unlock(&ftrace_start_lock);
6323d083395SSteven Rostedt }
6333d083395SSteven Rostedt 
6345a45cfe1SSteven Rostedt static void ftrace_shutdown(int command)
6353d083395SSteven Rostedt {
6364eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
6374eebcc81SSteven Rostedt 		return;
6384eebcc81SSteven Rostedt 
639cb7be3b2SSteven Rostedt 	mutex_lock(&ftrace_start_lock);
64060a7ecf4SSteven Rostedt 	ftrace_start_up--;
64160a7ecf4SSteven Rostedt 	if (!ftrace_start_up)
642d61f82d0SSteven Rostedt 		command |= FTRACE_DISABLE_CALLS;
643d61f82d0SSteven Rostedt 
644d61f82d0SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
645d61f82d0SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
646d61f82d0SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
647d61f82d0SSteven Rostedt 	}
648d61f82d0SSteven Rostedt 
649d61f82d0SSteven Rostedt 	if (!command || !ftrace_enabled)
6503d083395SSteven Rostedt 		goto out;
6513d083395SSteven Rostedt 
652d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
6533d083395SSteven Rostedt  out:
654cb7be3b2SSteven Rostedt 	mutex_unlock(&ftrace_start_lock);
6553d083395SSteven Rostedt }
6563d083395SSteven Rostedt 
657e309b41dSIngo Molnar static void ftrace_startup_sysctl(void)
658b0fc494fSSteven Rostedt {
659d61f82d0SSteven Rostedt 	int command = FTRACE_ENABLE_MCOUNT;
660d61f82d0SSteven Rostedt 
6614eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
6624eebcc81SSteven Rostedt 		return;
6634eebcc81SSteven Rostedt 
664cb7be3b2SSteven Rostedt 	mutex_lock(&ftrace_start_lock);
665d61f82d0SSteven Rostedt 	/* Force update next time */
666d61f82d0SSteven Rostedt 	saved_ftrace_func = NULL;
66760a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if we want ftrace running */
66860a7ecf4SSteven Rostedt 	if (ftrace_start_up)
669d61f82d0SSteven Rostedt 		command |= FTRACE_ENABLE_CALLS;
670d61f82d0SSteven Rostedt 
671d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
672cb7be3b2SSteven Rostedt 	mutex_unlock(&ftrace_start_lock);
673b0fc494fSSteven Rostedt }
674b0fc494fSSteven Rostedt 
675e309b41dSIngo Molnar static void ftrace_shutdown_sysctl(void)
676b0fc494fSSteven Rostedt {
677d61f82d0SSteven Rostedt 	int command = FTRACE_DISABLE_MCOUNT;
678d61f82d0SSteven Rostedt 
6794eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
6804eebcc81SSteven Rostedt 		return;
6814eebcc81SSteven Rostedt 
682cb7be3b2SSteven Rostedt 	mutex_lock(&ftrace_start_lock);
68360a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if ftrace is running */
68460a7ecf4SSteven Rostedt 	if (ftrace_start_up)
685d61f82d0SSteven Rostedt 		command |= FTRACE_DISABLE_CALLS;
686d61f82d0SSteven Rostedt 
687d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
688cb7be3b2SSteven Rostedt 	mutex_unlock(&ftrace_start_lock);
689b0fc494fSSteven Rostedt }
690b0fc494fSSteven Rostedt 
6913d083395SSteven Rostedt static cycle_t		ftrace_update_time;
6923d083395SSteven Rostedt static unsigned long	ftrace_update_cnt;
6933d083395SSteven Rostedt unsigned long		ftrace_update_tot_cnt;
6943d083395SSteven Rostedt 
69531e88909SSteven Rostedt static int ftrace_update_code(struct module *mod)
6963d083395SSteven Rostedt {
69708f5ac90SSteven Rostedt 	struct dyn_ftrace *p, *t;
698f22f9a89SAbhishek Sagar 	cycle_t start, stop;
6993d083395SSteven Rostedt 
700750ed1a4SIngo Molnar 	start = ftrace_now(raw_smp_processor_id());
7013d083395SSteven Rostedt 	ftrace_update_cnt = 0;
7023d083395SSteven Rostedt 
70308f5ac90SSteven Rostedt 	list_for_each_entry_safe(p, t, &ftrace_new_addrs, list) {
704f22f9a89SAbhishek Sagar 
70508f5ac90SSteven Rostedt 		/* If something went wrong, bail without enabling anything */
70608f5ac90SSteven Rostedt 		if (unlikely(ftrace_disabled))
70708f5ac90SSteven Rostedt 			return -1;
7083d083395SSteven Rostedt 
70908f5ac90SSteven Rostedt 		list_del_init(&p->list);
710f22f9a89SAbhishek Sagar 
711f22f9a89SAbhishek Sagar 		/* convert record (i.e, patch mcount-call with NOP) */
71231e88909SSteven Rostedt 		if (ftrace_code_disable(mod, p)) {
7130eb96701SAbhishek Sagar 			p->flags |= FTRACE_FL_CONVERTED;
7143d083395SSteven Rostedt 			ftrace_update_cnt++;
71508f5ac90SSteven Rostedt 		} else
7160eb96701SAbhishek Sagar 			ftrace_free_rec(p);
7173d083395SSteven Rostedt 	}
7183d083395SSteven Rostedt 
719750ed1a4SIngo Molnar 	stop = ftrace_now(raw_smp_processor_id());
7203d083395SSteven Rostedt 	ftrace_update_time = stop - start;
7213d083395SSteven Rostedt 	ftrace_update_tot_cnt += ftrace_update_cnt;
7223d083395SSteven Rostedt 
72316444a8aSArnaldo Carvalho de Melo 	return 0;
72416444a8aSArnaldo Carvalho de Melo }
72516444a8aSArnaldo Carvalho de Melo 
72668bf21aaSSteven Rostedt static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
7273c1720f0SSteven Rostedt {
7283c1720f0SSteven Rostedt 	struct ftrace_page *pg;
7293c1720f0SSteven Rostedt 	int cnt;
7303c1720f0SSteven Rostedt 	int i;
7313c1720f0SSteven Rostedt 
7323c1720f0SSteven Rostedt 	/* allocate a few pages */
7333c1720f0SSteven Rostedt 	ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL);
7343c1720f0SSteven Rostedt 	if (!ftrace_pages_start)
7353c1720f0SSteven Rostedt 		return -1;
7363c1720f0SSteven Rostedt 
7373c1720f0SSteven Rostedt 	/*
7383c1720f0SSteven Rostedt 	 * Allocate a few more pages.
7393c1720f0SSteven Rostedt 	 *
7403c1720f0SSteven Rostedt 	 * TODO: have some parser search vmlinux before
7413c1720f0SSteven Rostedt 	 *   final linking to find all calls to ftrace.
7423c1720f0SSteven Rostedt 	 *   Then we can:
7433c1720f0SSteven Rostedt 	 *    a) know how many pages to allocate.
7443c1720f0SSteven Rostedt 	 *     and/or
7453c1720f0SSteven Rostedt 	 *    b) set up the table then.
7463c1720f0SSteven Rostedt 	 *
7473c1720f0SSteven Rostedt 	 *  The dynamic code is still necessary for
7483c1720f0SSteven Rostedt 	 *  modules.
7493c1720f0SSteven Rostedt 	 */
7503c1720f0SSteven Rostedt 
7513c1720f0SSteven Rostedt 	pg = ftrace_pages = ftrace_pages_start;
7523c1720f0SSteven Rostedt 
75368bf21aaSSteven Rostedt 	cnt = num_to_init / ENTRIES_PER_PAGE;
75408f5ac90SSteven Rostedt 	pr_info("ftrace: allocating %ld entries in %d pages\n",
7555821e1b7Swalimis 		num_to_init, cnt + 1);
7563c1720f0SSteven Rostedt 
7573c1720f0SSteven Rostedt 	for (i = 0; i < cnt; i++) {
7583c1720f0SSteven Rostedt 		pg->next = (void *)get_zeroed_page(GFP_KERNEL);
7593c1720f0SSteven Rostedt 
7603c1720f0SSteven Rostedt 		/* If we fail, we'll try later anyway */
7613c1720f0SSteven Rostedt 		if (!pg->next)
7623c1720f0SSteven Rostedt 			break;
7633c1720f0SSteven Rostedt 
7643c1720f0SSteven Rostedt 		pg = pg->next;
7653c1720f0SSteven Rostedt 	}
7663c1720f0SSteven Rostedt 
7673c1720f0SSteven Rostedt 	return 0;
7683c1720f0SSteven Rostedt }
7693c1720f0SSteven Rostedt 
7705072c59fSSteven Rostedt enum {
7715072c59fSSteven Rostedt 	FTRACE_ITER_FILTER	= (1 << 0),
7725072c59fSSteven Rostedt 	FTRACE_ITER_CONT	= (1 << 1),
77341c52c0dSSteven Rostedt 	FTRACE_ITER_NOTRACE	= (1 << 2),
774eb9a7bf0SAbhishek Sagar 	FTRACE_ITER_FAILURES	= (1 << 3),
7750c75a3edSSteven Rostedt 	FTRACE_ITER_PRINTALL	= (1 << 4),
7765072c59fSSteven Rostedt };
7775072c59fSSteven Rostedt 
7785072c59fSSteven Rostedt #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
7795072c59fSSteven Rostedt 
7805072c59fSSteven Rostedt struct ftrace_iterator {
7815072c59fSSteven Rostedt 	struct ftrace_page	*pg;
782431aa3fbSSteven Rostedt 	int			idx;
7835072c59fSSteven Rostedt 	unsigned		flags;
7845072c59fSSteven Rostedt 	unsigned char		buffer[FTRACE_BUFF_MAX+1];
7855072c59fSSteven Rostedt 	unsigned		buffer_idx;
7865072c59fSSteven Rostedt 	unsigned		filtered;
7875072c59fSSteven Rostedt };
7885072c59fSSteven Rostedt 
789e309b41dSIngo Molnar static void *
7905072c59fSSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos)
7915072c59fSSteven Rostedt {
7925072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
7935072c59fSSteven Rostedt 	struct dyn_ftrace *rec = NULL;
7945072c59fSSteven Rostedt 
7955072c59fSSteven Rostedt 	(*pos)++;
7965072c59fSSteven Rostedt 
7970c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL)
7980c75a3edSSteven Rostedt 		return NULL;
7990c75a3edSSteven Rostedt 
800*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
8015072c59fSSteven Rostedt  retry:
8025072c59fSSteven Rostedt 	if (iter->idx >= iter->pg->index) {
8035072c59fSSteven Rostedt 		if (iter->pg->next) {
8045072c59fSSteven Rostedt 			iter->pg = iter->pg->next;
8055072c59fSSteven Rostedt 			iter->idx = 0;
8065072c59fSSteven Rostedt 			goto retry;
80750cdaf08SLiming Wang 		} else {
80850cdaf08SLiming Wang 			iter->idx = -1;
8095072c59fSSteven Rostedt 		}
8105072c59fSSteven Rostedt 	} else {
8115072c59fSSteven Rostedt 		rec = &iter->pg->records[iter->idx++];
812a9fdda33SSteven Rostedt 		if ((rec->flags & FTRACE_FL_FREE) ||
813a9fdda33SSteven Rostedt 
814a9fdda33SSteven Rostedt 		    (!(iter->flags & FTRACE_ITER_FAILURES) &&
815eb9a7bf0SAbhishek Sagar 		     (rec->flags & FTRACE_FL_FAILED)) ||
816eb9a7bf0SAbhishek Sagar 
817eb9a7bf0SAbhishek Sagar 		    ((iter->flags & FTRACE_ITER_FAILURES) &&
818a9fdda33SSteven Rostedt 		     !(rec->flags & FTRACE_FL_FAILED)) ||
819eb9a7bf0SAbhishek Sagar 
8200183fb1cSSteven Rostedt 		    ((iter->flags & FTRACE_ITER_FILTER) &&
8210183fb1cSSteven Rostedt 		     !(rec->flags & FTRACE_FL_FILTER)) ||
8220183fb1cSSteven Rostedt 
82341c52c0dSSteven Rostedt 		    ((iter->flags & FTRACE_ITER_NOTRACE) &&
82441c52c0dSSteven Rostedt 		     !(rec->flags & FTRACE_FL_NOTRACE))) {
8255072c59fSSteven Rostedt 			rec = NULL;
8265072c59fSSteven Rostedt 			goto retry;
8275072c59fSSteven Rostedt 		}
8285072c59fSSteven Rostedt 	}
829*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
8305072c59fSSteven Rostedt 
8315072c59fSSteven Rostedt 	return rec;
8325072c59fSSteven Rostedt }
8335072c59fSSteven Rostedt 
8345072c59fSSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos)
8355072c59fSSteven Rostedt {
8365072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
8375072c59fSSteven Rostedt 	void *p = NULL;
8385072c59fSSteven Rostedt 
8390c75a3edSSteven Rostedt 	/*
8400c75a3edSSteven Rostedt 	 * For set_ftrace_filter reading, if we have the filter
8410c75a3edSSteven Rostedt 	 * off, we can short cut and just print out that all
8420c75a3edSSteven Rostedt 	 * functions are enabled.
8430c75a3edSSteven Rostedt 	 */
8440c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_FILTER && !ftrace_filtered) {
8450c75a3edSSteven Rostedt 		if (*pos > 0)
8460c75a3edSSteven Rostedt 			return NULL;
8470c75a3edSSteven Rostedt 		iter->flags |= FTRACE_ITER_PRINTALL;
8480c75a3edSSteven Rostedt 		(*pos)++;
8490c75a3edSSteven Rostedt 		return iter;
8500c75a3edSSteven Rostedt 	}
8510c75a3edSSteven Rostedt 
85250cdaf08SLiming Wang 	if (*pos > 0) {
85350cdaf08SLiming Wang 		if (iter->idx < 0)
85450cdaf08SLiming Wang 			return p;
85550cdaf08SLiming Wang 		(*pos)--;
85650cdaf08SLiming Wang 		iter->idx--;
85750cdaf08SLiming Wang 	}
8585821e1b7Swalimis 
85950cdaf08SLiming Wang 	p = t_next(m, p, pos);
8605072c59fSSteven Rostedt 
8615072c59fSSteven Rostedt 	return p;
8625072c59fSSteven Rostedt }
8635072c59fSSteven Rostedt 
8645072c59fSSteven Rostedt static void t_stop(struct seq_file *m, void *p)
8655072c59fSSteven Rostedt {
8665072c59fSSteven Rostedt }
8675072c59fSSteven Rostedt 
8685072c59fSSteven Rostedt static int t_show(struct seq_file *m, void *v)
8695072c59fSSteven Rostedt {
8700c75a3edSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
8715072c59fSSteven Rostedt 	struct dyn_ftrace *rec = v;
8725072c59fSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
8735072c59fSSteven Rostedt 
8740c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL) {
8750c75a3edSSteven Rostedt 		seq_printf(m, "#### all functions enabled ####\n");
8760c75a3edSSteven Rostedt 		return 0;
8770c75a3edSSteven Rostedt 	}
8780c75a3edSSteven Rostedt 
8795072c59fSSteven Rostedt 	if (!rec)
8805072c59fSSteven Rostedt 		return 0;
8815072c59fSSteven Rostedt 
8825072c59fSSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
8835072c59fSSteven Rostedt 
88450cdaf08SLiming Wang 	seq_printf(m, "%s\n", str);
8855072c59fSSteven Rostedt 
8865072c59fSSteven Rostedt 	return 0;
8875072c59fSSteven Rostedt }
8885072c59fSSteven Rostedt 
8895072c59fSSteven Rostedt static struct seq_operations show_ftrace_seq_ops = {
8905072c59fSSteven Rostedt 	.start = t_start,
8915072c59fSSteven Rostedt 	.next = t_next,
8925072c59fSSteven Rostedt 	.stop = t_stop,
8935072c59fSSteven Rostedt 	.show = t_show,
8945072c59fSSteven Rostedt };
8955072c59fSSteven Rostedt 
896e309b41dSIngo Molnar static int
8975072c59fSSteven Rostedt ftrace_avail_open(struct inode *inode, struct file *file)
8985072c59fSSteven Rostedt {
8995072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
9005072c59fSSteven Rostedt 	int ret;
9015072c59fSSteven Rostedt 
9024eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
9034eebcc81SSteven Rostedt 		return -ENODEV;
9044eebcc81SSteven Rostedt 
9055072c59fSSteven Rostedt 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
9065072c59fSSteven Rostedt 	if (!iter)
9075072c59fSSteven Rostedt 		return -ENOMEM;
9085072c59fSSteven Rostedt 
9095072c59fSSteven Rostedt 	iter->pg = ftrace_pages_start;
9105072c59fSSteven Rostedt 
9115072c59fSSteven Rostedt 	ret = seq_open(file, &show_ftrace_seq_ops);
9125072c59fSSteven Rostedt 	if (!ret) {
9135072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
9144bf39a94SIngo Molnar 
9155072c59fSSteven Rostedt 		m->private = iter;
9164bf39a94SIngo Molnar 	} else {
9175072c59fSSteven Rostedt 		kfree(iter);
9184bf39a94SIngo Molnar 	}
9195072c59fSSteven Rostedt 
9205072c59fSSteven Rostedt 	return ret;
9215072c59fSSteven Rostedt }
9225072c59fSSteven Rostedt 
9235072c59fSSteven Rostedt int ftrace_avail_release(struct inode *inode, struct file *file)
9245072c59fSSteven Rostedt {
9255072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
9265072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
9275072c59fSSteven Rostedt 
9285072c59fSSteven Rostedt 	seq_release(inode, file);
9295072c59fSSteven Rostedt 	kfree(iter);
9304bf39a94SIngo Molnar 
9315072c59fSSteven Rostedt 	return 0;
9325072c59fSSteven Rostedt }
9335072c59fSSteven Rostedt 
934eb9a7bf0SAbhishek Sagar static int
935eb9a7bf0SAbhishek Sagar ftrace_failures_open(struct inode *inode, struct file *file)
936eb9a7bf0SAbhishek Sagar {
937eb9a7bf0SAbhishek Sagar 	int ret;
938eb9a7bf0SAbhishek Sagar 	struct seq_file *m;
939eb9a7bf0SAbhishek Sagar 	struct ftrace_iterator *iter;
940eb9a7bf0SAbhishek Sagar 
941eb9a7bf0SAbhishek Sagar 	ret = ftrace_avail_open(inode, file);
942eb9a7bf0SAbhishek Sagar 	if (!ret) {
943eb9a7bf0SAbhishek Sagar 		m = (struct seq_file *)file->private_data;
944eb9a7bf0SAbhishek Sagar 		iter = (struct ftrace_iterator *)m->private;
945eb9a7bf0SAbhishek Sagar 		iter->flags = FTRACE_ITER_FAILURES;
946eb9a7bf0SAbhishek Sagar 	}
947eb9a7bf0SAbhishek Sagar 
948eb9a7bf0SAbhishek Sagar 	return ret;
949eb9a7bf0SAbhishek Sagar }
950eb9a7bf0SAbhishek Sagar 
951eb9a7bf0SAbhishek Sagar 
95241c52c0dSSteven Rostedt static void ftrace_filter_reset(int enable)
9535072c59fSSteven Rostedt {
9545072c59fSSteven Rostedt 	struct ftrace_page *pg;
9555072c59fSSteven Rostedt 	struct dyn_ftrace *rec;
95641c52c0dSSteven Rostedt 	unsigned long type = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
9575072c59fSSteven Rostedt 
958*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
95941c52c0dSSteven Rostedt 	if (enable)
9605072c59fSSteven Rostedt 		ftrace_filtered = 0;
961265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
9625072c59fSSteven Rostedt 		if (rec->flags & FTRACE_FL_FAILED)
9635072c59fSSteven Rostedt 			continue;
96441c52c0dSSteven Rostedt 		rec->flags &= ~type;
965265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
966*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
9675072c59fSSteven Rostedt }
9685072c59fSSteven Rostedt 
969e309b41dSIngo Molnar static int
97041c52c0dSSteven Rostedt ftrace_regex_open(struct inode *inode, struct file *file, int enable)
9715072c59fSSteven Rostedt {
9725072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
9735072c59fSSteven Rostedt 	int ret = 0;
9745072c59fSSteven Rostedt 
9754eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
9764eebcc81SSteven Rostedt 		return -ENODEV;
9774eebcc81SSteven Rostedt 
9785072c59fSSteven Rostedt 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
9795072c59fSSteven Rostedt 	if (!iter)
9805072c59fSSteven Rostedt 		return -ENOMEM;
9815072c59fSSteven Rostedt 
98241c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
9835072c59fSSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
9845072c59fSSteven Rostedt 	    !(file->f_flags & O_APPEND))
98541c52c0dSSteven Rostedt 		ftrace_filter_reset(enable);
9865072c59fSSteven Rostedt 
9875072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
9885072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
98941c52c0dSSteven Rostedt 		iter->flags = enable ? FTRACE_ITER_FILTER :
99041c52c0dSSteven Rostedt 			FTRACE_ITER_NOTRACE;
9915072c59fSSteven Rostedt 
9925072c59fSSteven Rostedt 		ret = seq_open(file, &show_ftrace_seq_ops);
9935072c59fSSteven Rostedt 		if (!ret) {
9945072c59fSSteven Rostedt 			struct seq_file *m = file->private_data;
9955072c59fSSteven Rostedt 			m->private = iter;
9965072c59fSSteven Rostedt 		} else
9975072c59fSSteven Rostedt 			kfree(iter);
9985072c59fSSteven Rostedt 	} else
9995072c59fSSteven Rostedt 		file->private_data = iter;
100041c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
10015072c59fSSteven Rostedt 
10025072c59fSSteven Rostedt 	return ret;
10035072c59fSSteven Rostedt }
10045072c59fSSteven Rostedt 
100541c52c0dSSteven Rostedt static int
100641c52c0dSSteven Rostedt ftrace_filter_open(struct inode *inode, struct file *file)
100741c52c0dSSteven Rostedt {
100841c52c0dSSteven Rostedt 	return ftrace_regex_open(inode, file, 1);
100941c52c0dSSteven Rostedt }
101041c52c0dSSteven Rostedt 
101141c52c0dSSteven Rostedt static int
101241c52c0dSSteven Rostedt ftrace_notrace_open(struct inode *inode, struct file *file)
101341c52c0dSSteven Rostedt {
101441c52c0dSSteven Rostedt 	return ftrace_regex_open(inode, file, 0);
101541c52c0dSSteven Rostedt }
101641c52c0dSSteven Rostedt 
1017e309b41dSIngo Molnar static ssize_t
101841c52c0dSSteven Rostedt ftrace_regex_read(struct file *file, char __user *ubuf,
10195072c59fSSteven Rostedt 		       size_t cnt, loff_t *ppos)
10205072c59fSSteven Rostedt {
10215072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ)
10225072c59fSSteven Rostedt 		return seq_read(file, ubuf, cnt, ppos);
10235072c59fSSteven Rostedt 	else
10245072c59fSSteven Rostedt 		return -EPERM;
10255072c59fSSteven Rostedt }
10265072c59fSSteven Rostedt 
1027e309b41dSIngo Molnar static loff_t
102841c52c0dSSteven Rostedt ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
10295072c59fSSteven Rostedt {
10305072c59fSSteven Rostedt 	loff_t ret;
10315072c59fSSteven Rostedt 
10325072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ)
10335072c59fSSteven Rostedt 		ret = seq_lseek(file, offset, origin);
10345072c59fSSteven Rostedt 	else
10355072c59fSSteven Rostedt 		file->f_pos = ret = 1;
10365072c59fSSteven Rostedt 
10375072c59fSSteven Rostedt 	return ret;
10385072c59fSSteven Rostedt }
10395072c59fSSteven Rostedt 
10405072c59fSSteven Rostedt enum {
10415072c59fSSteven Rostedt 	MATCH_FULL,
10425072c59fSSteven Rostedt 	MATCH_FRONT_ONLY,
10435072c59fSSteven Rostedt 	MATCH_MIDDLE_ONLY,
10445072c59fSSteven Rostedt 	MATCH_END_ONLY,
10455072c59fSSteven Rostedt };
10465072c59fSSteven Rostedt 
10479f4801e3SSteven Rostedt /*
10489f4801e3SSteven Rostedt  * (static function - no need for kernel doc)
10499f4801e3SSteven Rostedt  *
10509f4801e3SSteven Rostedt  * Pass in a buffer containing a glob and this function will
10519f4801e3SSteven Rostedt  * set search to point to the search part of the buffer and
10529f4801e3SSteven Rostedt  * return the type of search it is (see enum above).
10539f4801e3SSteven Rostedt  * This does modify buff.
10549f4801e3SSteven Rostedt  *
10559f4801e3SSteven Rostedt  * Returns enum type.
10569f4801e3SSteven Rostedt  *  search returns the pointer to use for comparison.
10579f4801e3SSteven Rostedt  *  not returns 1 if buff started with a '!'
10589f4801e3SSteven Rostedt  *     0 otherwise.
10599f4801e3SSteven Rostedt  */
10609f4801e3SSteven Rostedt static int
106164e7c440SSteven Rostedt ftrace_setup_glob(char *buff, int len, char **search, int *not)
10625072c59fSSteven Rostedt {
10635072c59fSSteven Rostedt 	int type = MATCH_FULL;
10649f4801e3SSteven Rostedt 	int i;
1065ea3a6d6dSSteven Rostedt 
1066ea3a6d6dSSteven Rostedt 	if (buff[0] == '!') {
10679f4801e3SSteven Rostedt 		*not = 1;
1068ea3a6d6dSSteven Rostedt 		buff++;
1069ea3a6d6dSSteven Rostedt 		len--;
10709f4801e3SSteven Rostedt 	} else
10719f4801e3SSteven Rostedt 		*not = 0;
10729f4801e3SSteven Rostedt 
10739f4801e3SSteven Rostedt 	*search = buff;
10745072c59fSSteven Rostedt 
10755072c59fSSteven Rostedt 	for (i = 0; i < len; i++) {
10765072c59fSSteven Rostedt 		if (buff[i] == '*') {
10775072c59fSSteven Rostedt 			if (!i) {
10789f4801e3SSteven Rostedt 				*search = buff + 1;
10795072c59fSSteven Rostedt 				type = MATCH_END_ONLY;
10805072c59fSSteven Rostedt 			} else {
10819f4801e3SSteven Rostedt 				if (type == MATCH_END_ONLY)
10825072c59fSSteven Rostedt 					type = MATCH_MIDDLE_ONLY;
10839f4801e3SSteven Rostedt 				else
10845072c59fSSteven Rostedt 					type = MATCH_FRONT_ONLY;
10855072c59fSSteven Rostedt 				buff[i] = 0;
10865072c59fSSteven Rostedt 				break;
10875072c59fSSteven Rostedt 			}
10885072c59fSSteven Rostedt 		}
10895072c59fSSteven Rostedt 	}
10905072c59fSSteven Rostedt 
10919f4801e3SSteven Rostedt 	return type;
10929f4801e3SSteven Rostedt }
10939f4801e3SSteven Rostedt 
109464e7c440SSteven Rostedt static int ftrace_match(char *str, char *regex, int len, int type)
10959f4801e3SSteven Rostedt {
10969f4801e3SSteven Rostedt 	int matched = 0;
10979f4801e3SSteven Rostedt 	char *ptr;
10989f4801e3SSteven Rostedt 
10999f4801e3SSteven Rostedt 	switch (type) {
11009f4801e3SSteven Rostedt 	case MATCH_FULL:
11019f4801e3SSteven Rostedt 		if (strcmp(str, regex) == 0)
11029f4801e3SSteven Rostedt 			matched = 1;
11039f4801e3SSteven Rostedt 		break;
11049f4801e3SSteven Rostedt 	case MATCH_FRONT_ONLY:
11059f4801e3SSteven Rostedt 		if (strncmp(str, regex, len) == 0)
11069f4801e3SSteven Rostedt 			matched = 1;
11079f4801e3SSteven Rostedt 		break;
11089f4801e3SSteven Rostedt 	case MATCH_MIDDLE_ONLY:
11099f4801e3SSteven Rostedt 		if (strstr(str, regex))
11109f4801e3SSteven Rostedt 			matched = 1;
11119f4801e3SSteven Rostedt 		break;
11129f4801e3SSteven Rostedt 	case MATCH_END_ONLY:
11139f4801e3SSteven Rostedt 		ptr = strstr(str, regex);
11149f4801e3SSteven Rostedt 		if (ptr && (ptr[len] == 0))
11159f4801e3SSteven Rostedt 			matched = 1;
11169f4801e3SSteven Rostedt 		break;
11179f4801e3SSteven Rostedt 	}
11189f4801e3SSteven Rostedt 
11199f4801e3SSteven Rostedt 	return matched;
11209f4801e3SSteven Rostedt }
11219f4801e3SSteven Rostedt 
112264e7c440SSteven Rostedt static int
112364e7c440SSteven Rostedt ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
112464e7c440SSteven Rostedt {
112564e7c440SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
112664e7c440SSteven Rostedt 
112764e7c440SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
112864e7c440SSteven Rostedt 	return ftrace_match(str, regex, len, type);
112964e7c440SSteven Rostedt }
113064e7c440SSteven Rostedt 
11319f4801e3SSteven Rostedt static void ftrace_match_records(char *buff, int len, int enable)
11329f4801e3SSteven Rostedt {
11339f4801e3SSteven Rostedt 	char *search;
11349f4801e3SSteven Rostedt 	struct ftrace_page *pg;
11359f4801e3SSteven Rostedt 	struct dyn_ftrace *rec;
11369f4801e3SSteven Rostedt 	int type;
11379f4801e3SSteven Rostedt 	unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
11389f4801e3SSteven Rostedt 	unsigned search_len;
11399f4801e3SSteven Rostedt 	int not;
11409f4801e3SSteven Rostedt 
11419f4801e3SSteven Rostedt 	type = ftrace_setup_glob(buff, len, &search, &not);
11429f4801e3SSteven Rostedt 
11439f4801e3SSteven Rostedt 	search_len = strlen(search);
11449f4801e3SSteven Rostedt 
1145*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
1146265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
11475072c59fSSteven Rostedt 
11485072c59fSSteven Rostedt 		if (rec->flags & FTRACE_FL_FAILED)
11495072c59fSSteven Rostedt 			continue;
11509f4801e3SSteven Rostedt 
11519f4801e3SSteven Rostedt 		if (ftrace_match_record(rec, search, search_len, type)) {
1152ea3a6d6dSSteven Rostedt 			if (not)
1153ea3a6d6dSSteven Rostedt 				rec->flags &= ~flag;
1154ea3a6d6dSSteven Rostedt 			else
115541c52c0dSSteven Rostedt 				rec->flags |= flag;
11565072c59fSSteven Rostedt 		}
1157e68746a2SSteven Rostedt 		/*
1158e68746a2SSteven Rostedt 		 * Only enable filtering if we have a function that
1159e68746a2SSteven Rostedt 		 * is filtered on.
1160e68746a2SSteven Rostedt 		 */
1161e68746a2SSteven Rostedt 		if (enable && (rec->flags & FTRACE_FL_FILTER))
1162e68746a2SSteven Rostedt 			ftrace_filtered = 1;
1163265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
1164*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
11655072c59fSSteven Rostedt }
11665072c59fSSteven Rostedt 
116764e7c440SSteven Rostedt static int
116864e7c440SSteven Rostedt ftrace_match_module_record(struct dyn_ftrace *rec, char *mod,
116964e7c440SSteven Rostedt 			   char *regex, int len, int type)
117064e7c440SSteven Rostedt {
117164e7c440SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
117264e7c440SSteven Rostedt 	char *modname;
117364e7c440SSteven Rostedt 
117464e7c440SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
117564e7c440SSteven Rostedt 
117664e7c440SSteven Rostedt 	if (!modname || strcmp(modname, mod))
117764e7c440SSteven Rostedt 		return 0;
117864e7c440SSteven Rostedt 
117964e7c440SSteven Rostedt 	/* blank search means to match all funcs in the mod */
118064e7c440SSteven Rostedt 	if (len)
118164e7c440SSteven Rostedt 		return ftrace_match(str, regex, len, type);
118264e7c440SSteven Rostedt 	else
118364e7c440SSteven Rostedt 		return 1;
118464e7c440SSteven Rostedt }
118564e7c440SSteven Rostedt 
118664e7c440SSteven Rostedt static void ftrace_match_module_records(char *buff, char *mod, int enable)
118764e7c440SSteven Rostedt {
118864e7c440SSteven Rostedt 	char *search = buff;
118964e7c440SSteven Rostedt 	struct ftrace_page *pg;
119064e7c440SSteven Rostedt 	struct dyn_ftrace *rec;
119164e7c440SSteven Rostedt 	int type = MATCH_FULL;
119264e7c440SSteven Rostedt 	unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
119364e7c440SSteven Rostedt 	unsigned search_len = 0;
119464e7c440SSteven Rostedt 	int not = 0;
119564e7c440SSteven Rostedt 
119664e7c440SSteven Rostedt 	/* blank or '*' mean the same */
119764e7c440SSteven Rostedt 	if (strcmp(buff, "*") == 0)
119864e7c440SSteven Rostedt 		buff[0] = 0;
119964e7c440SSteven Rostedt 
120064e7c440SSteven Rostedt 	/* handle the case of 'dont filter this module' */
120164e7c440SSteven Rostedt 	if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) {
120264e7c440SSteven Rostedt 		buff[0] = 0;
120364e7c440SSteven Rostedt 		not = 1;
120464e7c440SSteven Rostedt 	}
120564e7c440SSteven Rostedt 
120664e7c440SSteven Rostedt 	if (strlen(buff)) {
120764e7c440SSteven Rostedt 		type = ftrace_setup_glob(buff, strlen(buff), &search, &not);
120864e7c440SSteven Rostedt 		search_len = strlen(search);
120964e7c440SSteven Rostedt 	}
121064e7c440SSteven Rostedt 
1211*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
121264e7c440SSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
121364e7c440SSteven Rostedt 
121464e7c440SSteven Rostedt 		if (rec->flags & FTRACE_FL_FAILED)
121564e7c440SSteven Rostedt 			continue;
121664e7c440SSteven Rostedt 
121764e7c440SSteven Rostedt 		if (ftrace_match_module_record(rec, mod,
121864e7c440SSteven Rostedt 					       search, search_len, type)) {
121964e7c440SSteven Rostedt 			if (not)
122064e7c440SSteven Rostedt 				rec->flags &= ~flag;
122164e7c440SSteven Rostedt 			else
122264e7c440SSteven Rostedt 				rec->flags |= flag;
122364e7c440SSteven Rostedt 		}
1224e68746a2SSteven Rostedt 		if (enable && (rec->flags & FTRACE_FL_FILTER))
1225e68746a2SSteven Rostedt 			ftrace_filtered = 1;
122664e7c440SSteven Rostedt 
122764e7c440SSteven Rostedt 	} while_for_each_ftrace_rec();
1228*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
122964e7c440SSteven Rostedt }
123064e7c440SSteven Rostedt 
1231f6180773SSteven Rostedt /*
1232f6180773SSteven Rostedt  * We register the module command as a template to show others how
1233f6180773SSteven Rostedt  * to register the a command as well.
1234f6180773SSteven Rostedt  */
1235f6180773SSteven Rostedt 
1236f6180773SSteven Rostedt static int
1237f6180773SSteven Rostedt ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
1238f6180773SSteven Rostedt {
1239f6180773SSteven Rostedt 	char *mod;
1240f6180773SSteven Rostedt 
1241f6180773SSteven Rostedt 	/*
1242f6180773SSteven Rostedt 	 * cmd == 'mod' because we only registered this func
1243f6180773SSteven Rostedt 	 * for the 'mod' ftrace_func_command.
1244f6180773SSteven Rostedt 	 * But if you register one func with multiple commands,
1245f6180773SSteven Rostedt 	 * you can tell which command was used by the cmd
1246f6180773SSteven Rostedt 	 * parameter.
1247f6180773SSteven Rostedt 	 */
1248f6180773SSteven Rostedt 
1249f6180773SSteven Rostedt 	/* we must have a module name */
1250f6180773SSteven Rostedt 	if (!param)
1251f6180773SSteven Rostedt 		return -EINVAL;
1252f6180773SSteven Rostedt 
1253f6180773SSteven Rostedt 	mod = strsep(&param, ":");
1254f6180773SSteven Rostedt 	if (!strlen(mod))
1255f6180773SSteven Rostedt 		return -EINVAL;
1256f6180773SSteven Rostedt 
1257f6180773SSteven Rostedt 	ftrace_match_module_records(func, mod, enable);
1258f6180773SSteven Rostedt 	return 0;
1259f6180773SSteven Rostedt }
1260f6180773SSteven Rostedt 
1261f6180773SSteven Rostedt static struct ftrace_func_command ftrace_mod_cmd = {
1262f6180773SSteven Rostedt 	.name			= "mod",
1263f6180773SSteven Rostedt 	.func			= ftrace_mod_callback,
1264f6180773SSteven Rostedt };
1265f6180773SSteven Rostedt 
1266f6180773SSteven Rostedt static int __init ftrace_mod_cmd_init(void)
1267f6180773SSteven Rostedt {
1268f6180773SSteven Rostedt 	return register_ftrace_command(&ftrace_mod_cmd);
1269f6180773SSteven Rostedt }
1270f6180773SSteven Rostedt device_initcall(ftrace_mod_cmd_init);
1271f6180773SSteven Rostedt 
1272f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands);
1273f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex);
1274f6180773SSteven Rostedt 
1275f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd)
1276f6180773SSteven Rostedt {
1277f6180773SSteven Rostedt 	struct ftrace_func_command *p;
1278f6180773SSteven Rostedt 	int ret = 0;
1279f6180773SSteven Rostedt 
1280f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
1281f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
1282f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
1283f6180773SSteven Rostedt 			ret = -EBUSY;
1284f6180773SSteven Rostedt 			goto out_unlock;
1285f6180773SSteven Rostedt 		}
1286f6180773SSteven Rostedt 	}
1287f6180773SSteven Rostedt 	list_add(&cmd->list, &ftrace_commands);
1288f6180773SSteven Rostedt  out_unlock:
1289f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
1290f6180773SSteven Rostedt 
1291f6180773SSteven Rostedt 	return ret;
1292f6180773SSteven Rostedt }
1293f6180773SSteven Rostedt 
1294f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd)
1295f6180773SSteven Rostedt {
1296f6180773SSteven Rostedt 	struct ftrace_func_command *p, *n;
1297f6180773SSteven Rostedt 	int ret = -ENODEV;
1298f6180773SSteven Rostedt 
1299f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
1300f6180773SSteven Rostedt 	list_for_each_entry_safe(p, n, &ftrace_commands, list) {
1301f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
1302f6180773SSteven Rostedt 			ret = 0;
1303f6180773SSteven Rostedt 			list_del_init(&p->list);
1304f6180773SSteven Rostedt 			goto out_unlock;
1305f6180773SSteven Rostedt 		}
1306f6180773SSteven Rostedt 	}
1307f6180773SSteven Rostedt  out_unlock:
1308f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
1309f6180773SSteven Rostedt 
1310f6180773SSteven Rostedt 	return ret;
1311f6180773SSteven Rostedt }
1312f6180773SSteven Rostedt 
131364e7c440SSteven Rostedt static int ftrace_process_regex(char *buff, int len, int enable)
131464e7c440SSteven Rostedt {
1315f6180773SSteven Rostedt 	struct ftrace_func_command *p;
1316f6180773SSteven Rostedt 	char *func, *command, *next = buff;
1317f6180773SSteven Rostedt 	int ret = -EINVAL;
131864e7c440SSteven Rostedt 
131964e7c440SSteven Rostedt 	func = strsep(&next, ":");
132064e7c440SSteven Rostedt 
132164e7c440SSteven Rostedt 	if (!next) {
132264e7c440SSteven Rostedt 		ftrace_match_records(func, len, enable);
132364e7c440SSteven Rostedt 		return 0;
132464e7c440SSteven Rostedt 	}
132564e7c440SSteven Rostedt 
1326f6180773SSteven Rostedt 	/* command found */
132764e7c440SSteven Rostedt 
132864e7c440SSteven Rostedt 	command = strsep(&next, ":");
132964e7c440SSteven Rostedt 
1330f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
1331f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
1332f6180773SSteven Rostedt 		if (strcmp(p->name, command) == 0) {
1333f6180773SSteven Rostedt 			ret = p->func(func, command, next, enable);
1334f6180773SSteven Rostedt 			goto out_unlock;
133564e7c440SSteven Rostedt 		}
1336f6180773SSteven Rostedt 	}
1337f6180773SSteven Rostedt  out_unlock:
1338f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
133964e7c440SSteven Rostedt 
1340f6180773SSteven Rostedt 	return ret;
134164e7c440SSteven Rostedt }
134264e7c440SSteven Rostedt 
1343e309b41dSIngo Molnar static ssize_t
134441c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf,
134541c52c0dSSteven Rostedt 		   size_t cnt, loff_t *ppos, int enable)
13465072c59fSSteven Rostedt {
13475072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
13485072c59fSSteven Rostedt 	char ch;
13495072c59fSSteven Rostedt 	size_t read = 0;
13505072c59fSSteven Rostedt 	ssize_t ret;
13515072c59fSSteven Rostedt 
13525072c59fSSteven Rostedt 	if (!cnt || cnt < 0)
13535072c59fSSteven Rostedt 		return 0;
13545072c59fSSteven Rostedt 
135541c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
13565072c59fSSteven Rostedt 
13575072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
13585072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
13595072c59fSSteven Rostedt 		iter = m->private;
13605072c59fSSteven Rostedt 	} else
13615072c59fSSteven Rostedt 		iter = file->private_data;
13625072c59fSSteven Rostedt 
13635072c59fSSteven Rostedt 	if (!*ppos) {
13645072c59fSSteven Rostedt 		iter->flags &= ~FTRACE_ITER_CONT;
13655072c59fSSteven Rostedt 		iter->buffer_idx = 0;
13665072c59fSSteven Rostedt 	}
13675072c59fSSteven Rostedt 
13685072c59fSSteven Rostedt 	ret = get_user(ch, ubuf++);
13695072c59fSSteven Rostedt 	if (ret)
13705072c59fSSteven Rostedt 		goto out;
13715072c59fSSteven Rostedt 	read++;
13725072c59fSSteven Rostedt 	cnt--;
13735072c59fSSteven Rostedt 
13745072c59fSSteven Rostedt 	if (!(iter->flags & ~FTRACE_ITER_CONT)) {
13755072c59fSSteven Rostedt 		/* skip white space */
13765072c59fSSteven Rostedt 		while (cnt && isspace(ch)) {
13775072c59fSSteven Rostedt 			ret = get_user(ch, ubuf++);
13785072c59fSSteven Rostedt 			if (ret)
13795072c59fSSteven Rostedt 				goto out;
13805072c59fSSteven Rostedt 			read++;
13815072c59fSSteven Rostedt 			cnt--;
13825072c59fSSteven Rostedt 		}
13835072c59fSSteven Rostedt 
13845072c59fSSteven Rostedt 		if (isspace(ch)) {
13855072c59fSSteven Rostedt 			file->f_pos += read;
13865072c59fSSteven Rostedt 			ret = read;
13875072c59fSSteven Rostedt 			goto out;
13885072c59fSSteven Rostedt 		}
13895072c59fSSteven Rostedt 
13905072c59fSSteven Rostedt 		iter->buffer_idx = 0;
13915072c59fSSteven Rostedt 	}
13925072c59fSSteven Rostedt 
13935072c59fSSteven Rostedt 	while (cnt && !isspace(ch)) {
13945072c59fSSteven Rostedt 		if (iter->buffer_idx < FTRACE_BUFF_MAX)
13955072c59fSSteven Rostedt 			iter->buffer[iter->buffer_idx++] = ch;
13965072c59fSSteven Rostedt 		else {
13975072c59fSSteven Rostedt 			ret = -EINVAL;
13985072c59fSSteven Rostedt 			goto out;
13995072c59fSSteven Rostedt 		}
14005072c59fSSteven Rostedt 		ret = get_user(ch, ubuf++);
14015072c59fSSteven Rostedt 		if (ret)
14025072c59fSSteven Rostedt 			goto out;
14035072c59fSSteven Rostedt 		read++;
14045072c59fSSteven Rostedt 		cnt--;
14055072c59fSSteven Rostedt 	}
14065072c59fSSteven Rostedt 
14075072c59fSSteven Rostedt 	if (isspace(ch)) {
14085072c59fSSteven Rostedt 		iter->filtered++;
14095072c59fSSteven Rostedt 		iter->buffer[iter->buffer_idx] = 0;
141064e7c440SSteven Rostedt 		ret = ftrace_process_regex(iter->buffer,
141164e7c440SSteven Rostedt 					   iter->buffer_idx, enable);
141264e7c440SSteven Rostedt 		if (ret)
141364e7c440SSteven Rostedt 			goto out;
14145072c59fSSteven Rostedt 		iter->buffer_idx = 0;
14155072c59fSSteven Rostedt 	} else
14165072c59fSSteven Rostedt 		iter->flags |= FTRACE_ITER_CONT;
14175072c59fSSteven Rostedt 
14185072c59fSSteven Rostedt 
14195072c59fSSteven Rostedt 	file->f_pos += read;
14205072c59fSSteven Rostedt 
14215072c59fSSteven Rostedt 	ret = read;
14225072c59fSSteven Rostedt  out:
142341c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
14245072c59fSSteven Rostedt 
14255072c59fSSteven Rostedt 	return ret;
14265072c59fSSteven Rostedt }
14275072c59fSSteven Rostedt 
142841c52c0dSSteven Rostedt static ssize_t
142941c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf,
143041c52c0dSSteven Rostedt 		    size_t cnt, loff_t *ppos)
143141c52c0dSSteven Rostedt {
143241c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
143341c52c0dSSteven Rostedt }
143441c52c0dSSteven Rostedt 
143541c52c0dSSteven Rostedt static ssize_t
143641c52c0dSSteven Rostedt ftrace_notrace_write(struct file *file, const char __user *ubuf,
143741c52c0dSSteven Rostedt 		     size_t cnt, loff_t *ppos)
143841c52c0dSSteven Rostedt {
143941c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 0);
144041c52c0dSSteven Rostedt }
144141c52c0dSSteven Rostedt 
144241c52c0dSSteven Rostedt static void
144341c52c0dSSteven Rostedt ftrace_set_regex(unsigned char *buf, int len, int reset, int enable)
144441c52c0dSSteven Rostedt {
144541c52c0dSSteven Rostedt 	if (unlikely(ftrace_disabled))
144641c52c0dSSteven Rostedt 		return;
144741c52c0dSSteven Rostedt 
144841c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
144941c52c0dSSteven Rostedt 	if (reset)
145041c52c0dSSteven Rostedt 		ftrace_filter_reset(enable);
145141c52c0dSSteven Rostedt 	if (buf)
14527f24b31bSSteven Rostedt 		ftrace_match_records(buf, len, enable);
145341c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
145441c52c0dSSteven Rostedt }
145541c52c0dSSteven Rostedt 
145677a2b37dSSteven Rostedt /**
145777a2b37dSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
145877a2b37dSSteven Rostedt  * @buf - the string that holds the function filter text.
145977a2b37dSSteven Rostedt  * @len - the length of the string.
146077a2b37dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
146177a2b37dSSteven Rostedt  *
146277a2b37dSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
146377a2b37dSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
146477a2b37dSSteven Rostedt  */
1465e309b41dSIngo Molnar void ftrace_set_filter(unsigned char *buf, int len, int reset)
146677a2b37dSSteven Rostedt {
146741c52c0dSSteven Rostedt 	ftrace_set_regex(buf, len, reset, 1);
146841c52c0dSSteven Rostedt }
14694eebcc81SSteven Rostedt 
147041c52c0dSSteven Rostedt /**
147141c52c0dSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
147241c52c0dSSteven Rostedt  * @buf - the string that holds the function notrace text.
147341c52c0dSSteven Rostedt  * @len - the length of the string.
147441c52c0dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
147541c52c0dSSteven Rostedt  *
147641c52c0dSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
147741c52c0dSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
147841c52c0dSSteven Rostedt  * for tracing.
147941c52c0dSSteven Rostedt  */
148041c52c0dSSteven Rostedt void ftrace_set_notrace(unsigned char *buf, int len, int reset)
148141c52c0dSSteven Rostedt {
148241c52c0dSSteven Rostedt 	ftrace_set_regex(buf, len, reset, 0);
148377a2b37dSSteven Rostedt }
148477a2b37dSSteven Rostedt 
1485e309b41dSIngo Molnar static int
148641c52c0dSSteven Rostedt ftrace_regex_release(struct inode *inode, struct file *file, int enable)
14875072c59fSSteven Rostedt {
14885072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
14895072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
14905072c59fSSteven Rostedt 
149141c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
14925072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
14935072c59fSSteven Rostedt 		iter = m->private;
14945072c59fSSteven Rostedt 
14955072c59fSSteven Rostedt 		seq_release(inode, file);
14965072c59fSSteven Rostedt 	} else
14975072c59fSSteven Rostedt 		iter = file->private_data;
14985072c59fSSteven Rostedt 
14995072c59fSSteven Rostedt 	if (iter->buffer_idx) {
15005072c59fSSteven Rostedt 		iter->filtered++;
15015072c59fSSteven Rostedt 		iter->buffer[iter->buffer_idx] = 0;
15027f24b31bSSteven Rostedt 		ftrace_match_records(iter->buffer, iter->buffer_idx, enable);
15035072c59fSSteven Rostedt 	}
15045072c59fSSteven Rostedt 
15055072c59fSSteven Rostedt 	mutex_lock(&ftrace_sysctl_lock);
1506cb7be3b2SSteven Rostedt 	mutex_lock(&ftrace_start_lock);
1507ee02a2e5SSteven Rostedt 	if (ftrace_start_up && ftrace_enabled)
15085072c59fSSteven Rostedt 		ftrace_run_update_code(FTRACE_ENABLE_CALLS);
1509cb7be3b2SSteven Rostedt 	mutex_unlock(&ftrace_start_lock);
15105072c59fSSteven Rostedt 	mutex_unlock(&ftrace_sysctl_lock);
15115072c59fSSteven Rostedt 
15125072c59fSSteven Rostedt 	kfree(iter);
151341c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
15145072c59fSSteven Rostedt 	return 0;
15155072c59fSSteven Rostedt }
15165072c59fSSteven Rostedt 
151741c52c0dSSteven Rostedt static int
151841c52c0dSSteven Rostedt ftrace_filter_release(struct inode *inode, struct file *file)
151941c52c0dSSteven Rostedt {
152041c52c0dSSteven Rostedt 	return ftrace_regex_release(inode, file, 1);
152141c52c0dSSteven Rostedt }
152241c52c0dSSteven Rostedt 
152341c52c0dSSteven Rostedt static int
152441c52c0dSSteven Rostedt ftrace_notrace_release(struct inode *inode, struct file *file)
152541c52c0dSSteven Rostedt {
152641c52c0dSSteven Rostedt 	return ftrace_regex_release(inode, file, 0);
152741c52c0dSSteven Rostedt }
152841c52c0dSSteven Rostedt 
15295072c59fSSteven Rostedt static struct file_operations ftrace_avail_fops = {
15305072c59fSSteven Rostedt 	.open = ftrace_avail_open,
15315072c59fSSteven Rostedt 	.read = seq_read,
15325072c59fSSteven Rostedt 	.llseek = seq_lseek,
15335072c59fSSteven Rostedt 	.release = ftrace_avail_release,
15345072c59fSSteven Rostedt };
15355072c59fSSteven Rostedt 
1536eb9a7bf0SAbhishek Sagar static struct file_operations ftrace_failures_fops = {
1537eb9a7bf0SAbhishek Sagar 	.open = ftrace_failures_open,
1538eb9a7bf0SAbhishek Sagar 	.read = seq_read,
1539eb9a7bf0SAbhishek Sagar 	.llseek = seq_lseek,
1540eb9a7bf0SAbhishek Sagar 	.release = ftrace_avail_release,
1541eb9a7bf0SAbhishek Sagar };
1542eb9a7bf0SAbhishek Sagar 
15435072c59fSSteven Rostedt static struct file_operations ftrace_filter_fops = {
15445072c59fSSteven Rostedt 	.open = ftrace_filter_open,
154541c52c0dSSteven Rostedt 	.read = ftrace_regex_read,
15465072c59fSSteven Rostedt 	.write = ftrace_filter_write,
154741c52c0dSSteven Rostedt 	.llseek = ftrace_regex_lseek,
15485072c59fSSteven Rostedt 	.release = ftrace_filter_release,
15495072c59fSSteven Rostedt };
15505072c59fSSteven Rostedt 
155141c52c0dSSteven Rostedt static struct file_operations ftrace_notrace_fops = {
155241c52c0dSSteven Rostedt 	.open = ftrace_notrace_open,
155341c52c0dSSteven Rostedt 	.read = ftrace_regex_read,
155441c52c0dSSteven Rostedt 	.write = ftrace_notrace_write,
155541c52c0dSSteven Rostedt 	.llseek = ftrace_regex_lseek,
155641c52c0dSSteven Rostedt 	.release = ftrace_notrace_release,
155741c52c0dSSteven Rostedt };
155841c52c0dSSteven Rostedt 
1559ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
1560ea4e2bc4SSteven Rostedt 
1561ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock);
1562ea4e2bc4SSteven Rostedt 
1563ea4e2bc4SSteven Rostedt int ftrace_graph_count;
1564ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
1565ea4e2bc4SSteven Rostedt 
1566ea4e2bc4SSteven Rostedt static void *
1567ea4e2bc4SSteven Rostedt g_next(struct seq_file *m, void *v, loff_t *pos)
1568ea4e2bc4SSteven Rostedt {
1569ea4e2bc4SSteven Rostedt 	unsigned long *array = m->private;
1570ea4e2bc4SSteven Rostedt 	int index = *pos;
1571ea4e2bc4SSteven Rostedt 
1572ea4e2bc4SSteven Rostedt 	(*pos)++;
1573ea4e2bc4SSteven Rostedt 
1574ea4e2bc4SSteven Rostedt 	if (index >= ftrace_graph_count)
1575ea4e2bc4SSteven Rostedt 		return NULL;
1576ea4e2bc4SSteven Rostedt 
1577ea4e2bc4SSteven Rostedt 	return &array[index];
1578ea4e2bc4SSteven Rostedt }
1579ea4e2bc4SSteven Rostedt 
1580ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos)
1581ea4e2bc4SSteven Rostedt {
1582ea4e2bc4SSteven Rostedt 	void *p = NULL;
1583ea4e2bc4SSteven Rostedt 
1584ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
1585ea4e2bc4SSteven Rostedt 
1586ea4e2bc4SSteven Rostedt 	p = g_next(m, p, pos);
1587ea4e2bc4SSteven Rostedt 
1588ea4e2bc4SSteven Rostedt 	return p;
1589ea4e2bc4SSteven Rostedt }
1590ea4e2bc4SSteven Rostedt 
1591ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p)
1592ea4e2bc4SSteven Rostedt {
1593ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
1594ea4e2bc4SSteven Rostedt }
1595ea4e2bc4SSteven Rostedt 
1596ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v)
1597ea4e2bc4SSteven Rostedt {
1598ea4e2bc4SSteven Rostedt 	unsigned long *ptr = v;
1599ea4e2bc4SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
1600ea4e2bc4SSteven Rostedt 
1601ea4e2bc4SSteven Rostedt 	if (!ptr)
1602ea4e2bc4SSteven Rostedt 		return 0;
1603ea4e2bc4SSteven Rostedt 
1604ea4e2bc4SSteven Rostedt 	kallsyms_lookup(*ptr, NULL, NULL, NULL, str);
1605ea4e2bc4SSteven Rostedt 
1606ea4e2bc4SSteven Rostedt 	seq_printf(m, "%s\n", str);
1607ea4e2bc4SSteven Rostedt 
1608ea4e2bc4SSteven Rostedt 	return 0;
1609ea4e2bc4SSteven Rostedt }
1610ea4e2bc4SSteven Rostedt 
1611ea4e2bc4SSteven Rostedt static struct seq_operations ftrace_graph_seq_ops = {
1612ea4e2bc4SSteven Rostedt 	.start = g_start,
1613ea4e2bc4SSteven Rostedt 	.next = g_next,
1614ea4e2bc4SSteven Rostedt 	.stop = g_stop,
1615ea4e2bc4SSteven Rostedt 	.show = g_show,
1616ea4e2bc4SSteven Rostedt };
1617ea4e2bc4SSteven Rostedt 
1618ea4e2bc4SSteven Rostedt static int
1619ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file)
1620ea4e2bc4SSteven Rostedt {
1621ea4e2bc4SSteven Rostedt 	int ret = 0;
1622ea4e2bc4SSteven Rostedt 
1623ea4e2bc4SSteven Rostedt 	if (unlikely(ftrace_disabled))
1624ea4e2bc4SSteven Rostedt 		return -ENODEV;
1625ea4e2bc4SSteven Rostedt 
1626ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
1627ea4e2bc4SSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
1628ea4e2bc4SSteven Rostedt 	    !(file->f_flags & O_APPEND)) {
1629ea4e2bc4SSteven Rostedt 		ftrace_graph_count = 0;
1630ea4e2bc4SSteven Rostedt 		memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
1631ea4e2bc4SSteven Rostedt 	}
1632ea4e2bc4SSteven Rostedt 
1633ea4e2bc4SSteven Rostedt 	if (file->f_mode & FMODE_READ) {
1634ea4e2bc4SSteven Rostedt 		ret = seq_open(file, &ftrace_graph_seq_ops);
1635ea4e2bc4SSteven Rostedt 		if (!ret) {
1636ea4e2bc4SSteven Rostedt 			struct seq_file *m = file->private_data;
1637ea4e2bc4SSteven Rostedt 			m->private = ftrace_graph_funcs;
1638ea4e2bc4SSteven Rostedt 		}
1639ea4e2bc4SSteven Rostedt 	} else
1640ea4e2bc4SSteven Rostedt 		file->private_data = ftrace_graph_funcs;
1641ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
1642ea4e2bc4SSteven Rostedt 
1643ea4e2bc4SSteven Rostedt 	return ret;
1644ea4e2bc4SSteven Rostedt }
1645ea4e2bc4SSteven Rostedt 
1646ea4e2bc4SSteven Rostedt static ssize_t
1647ea4e2bc4SSteven Rostedt ftrace_graph_read(struct file *file, char __user *ubuf,
1648ea4e2bc4SSteven Rostedt 		       size_t cnt, loff_t *ppos)
1649ea4e2bc4SSteven Rostedt {
1650ea4e2bc4SSteven Rostedt 	if (file->f_mode & FMODE_READ)
1651ea4e2bc4SSteven Rostedt 		return seq_read(file, ubuf, cnt, ppos);
1652ea4e2bc4SSteven Rostedt 	else
1653ea4e2bc4SSteven Rostedt 		return -EPERM;
1654ea4e2bc4SSteven Rostedt }
1655ea4e2bc4SSteven Rostedt 
1656ea4e2bc4SSteven Rostedt static int
1657ea4e2bc4SSteven Rostedt ftrace_set_func(unsigned long *array, int idx, char *buffer)
1658ea4e2bc4SSteven Rostedt {
1659ea4e2bc4SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
1660ea4e2bc4SSteven Rostedt 	struct dyn_ftrace *rec;
1661ea4e2bc4SSteven Rostedt 	struct ftrace_page *pg;
1662ea4e2bc4SSteven Rostedt 	int found = 0;
1663265c831cSSteven Rostedt 	int j;
1664ea4e2bc4SSteven Rostedt 
1665ea4e2bc4SSteven Rostedt 	if (ftrace_disabled)
1666ea4e2bc4SSteven Rostedt 		return -ENODEV;
1667ea4e2bc4SSteven Rostedt 
1668*52baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
1669265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
1670ea4e2bc4SSteven Rostedt 
1671ea4e2bc4SSteven Rostedt 		if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE))
1672ea4e2bc4SSteven Rostedt 			continue;
1673ea4e2bc4SSteven Rostedt 
1674ea4e2bc4SSteven Rostedt 		kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
1675ea4e2bc4SSteven Rostedt 		if (strcmp(str, buffer) == 0) {
1676265c831cSSteven Rostedt 			/* Return 1 if we add it to the array */
1677ea4e2bc4SSteven Rostedt 			found = 1;
1678faec2ec5SLiming Wang 			for (j = 0; j < idx; j++)
1679faec2ec5SLiming Wang 				if (array[j] == rec->ip) {
1680faec2ec5SLiming Wang 					found = 0;
1681faec2ec5SLiming Wang 					break;
1682faec2ec5SLiming Wang 				}
1683faec2ec5SLiming Wang 			if (found)
1684ea4e2bc4SSteven Rostedt 				array[idx] = rec->ip;
1685265c831cSSteven Rostedt 			goto out;
1686ea4e2bc4SSteven Rostedt 		}
1687265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
1688265c831cSSteven Rostedt  out:
1689*52baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
1690ea4e2bc4SSteven Rostedt 
1691ea4e2bc4SSteven Rostedt 	return found ? 0 : -EINVAL;
1692ea4e2bc4SSteven Rostedt }
1693ea4e2bc4SSteven Rostedt 
1694ea4e2bc4SSteven Rostedt static ssize_t
1695ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf,
1696ea4e2bc4SSteven Rostedt 		   size_t cnt, loff_t *ppos)
1697ea4e2bc4SSteven Rostedt {
1698ea4e2bc4SSteven Rostedt 	unsigned char buffer[FTRACE_BUFF_MAX+1];
1699ea4e2bc4SSteven Rostedt 	unsigned long *array;
1700ea4e2bc4SSteven Rostedt 	size_t read = 0;
1701ea4e2bc4SSteven Rostedt 	ssize_t ret;
1702ea4e2bc4SSteven Rostedt 	int index = 0;
1703ea4e2bc4SSteven Rostedt 	char ch;
1704ea4e2bc4SSteven Rostedt 
1705ea4e2bc4SSteven Rostedt 	if (!cnt || cnt < 0)
1706ea4e2bc4SSteven Rostedt 		return 0;
1707ea4e2bc4SSteven Rostedt 
1708ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
1709ea4e2bc4SSteven Rostedt 
1710ea4e2bc4SSteven Rostedt 	if (ftrace_graph_count >= FTRACE_GRAPH_MAX_FUNCS) {
1711ea4e2bc4SSteven Rostedt 		ret = -EBUSY;
1712ea4e2bc4SSteven Rostedt 		goto out;
1713ea4e2bc4SSteven Rostedt 	}
1714ea4e2bc4SSteven Rostedt 
1715ea4e2bc4SSteven Rostedt 	if (file->f_mode & FMODE_READ) {
1716ea4e2bc4SSteven Rostedt 		struct seq_file *m = file->private_data;
1717ea4e2bc4SSteven Rostedt 		array = m->private;
1718ea4e2bc4SSteven Rostedt 	} else
1719ea4e2bc4SSteven Rostedt 		array = file->private_data;
1720ea4e2bc4SSteven Rostedt 
1721ea4e2bc4SSteven Rostedt 	ret = get_user(ch, ubuf++);
1722ea4e2bc4SSteven Rostedt 	if (ret)
1723ea4e2bc4SSteven Rostedt 		goto out;
1724ea4e2bc4SSteven Rostedt 	read++;
1725ea4e2bc4SSteven Rostedt 	cnt--;
1726ea4e2bc4SSteven Rostedt 
1727ea4e2bc4SSteven Rostedt 	/* skip white space */
1728ea4e2bc4SSteven Rostedt 	while (cnt && isspace(ch)) {
1729ea4e2bc4SSteven Rostedt 		ret = get_user(ch, ubuf++);
1730ea4e2bc4SSteven Rostedt 		if (ret)
1731ea4e2bc4SSteven Rostedt 			goto out;
1732ea4e2bc4SSteven Rostedt 		read++;
1733ea4e2bc4SSteven Rostedt 		cnt--;
1734ea4e2bc4SSteven Rostedt 	}
1735ea4e2bc4SSteven Rostedt 
1736ea4e2bc4SSteven Rostedt 	if (isspace(ch)) {
1737ea4e2bc4SSteven Rostedt 		*ppos += read;
1738ea4e2bc4SSteven Rostedt 		ret = read;
1739ea4e2bc4SSteven Rostedt 		goto out;
1740ea4e2bc4SSteven Rostedt 	}
1741ea4e2bc4SSteven Rostedt 
1742ea4e2bc4SSteven Rostedt 	while (cnt && !isspace(ch)) {
1743ea4e2bc4SSteven Rostedt 		if (index < FTRACE_BUFF_MAX)
1744ea4e2bc4SSteven Rostedt 			buffer[index++] = ch;
1745ea4e2bc4SSteven Rostedt 		else {
1746ea4e2bc4SSteven Rostedt 			ret = -EINVAL;
1747ea4e2bc4SSteven Rostedt 			goto out;
1748ea4e2bc4SSteven Rostedt 		}
1749ea4e2bc4SSteven Rostedt 		ret = get_user(ch, ubuf++);
1750ea4e2bc4SSteven Rostedt 		if (ret)
1751ea4e2bc4SSteven Rostedt 			goto out;
1752ea4e2bc4SSteven Rostedt 		read++;
1753ea4e2bc4SSteven Rostedt 		cnt--;
1754ea4e2bc4SSteven Rostedt 	}
1755ea4e2bc4SSteven Rostedt 	buffer[index] = 0;
1756ea4e2bc4SSteven Rostedt 
1757ea4e2bc4SSteven Rostedt 	/* we allow only one at a time */
1758ea4e2bc4SSteven Rostedt 	ret = ftrace_set_func(array, ftrace_graph_count, buffer);
1759ea4e2bc4SSteven Rostedt 	if (ret)
1760ea4e2bc4SSteven Rostedt 		goto out;
1761ea4e2bc4SSteven Rostedt 
1762ea4e2bc4SSteven Rostedt 	ftrace_graph_count++;
1763ea4e2bc4SSteven Rostedt 
1764ea4e2bc4SSteven Rostedt 	file->f_pos += read;
1765ea4e2bc4SSteven Rostedt 
1766ea4e2bc4SSteven Rostedt 	ret = read;
1767ea4e2bc4SSteven Rostedt  out:
1768ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
1769ea4e2bc4SSteven Rostedt 
1770ea4e2bc4SSteven Rostedt 	return ret;
1771ea4e2bc4SSteven Rostedt }
1772ea4e2bc4SSteven Rostedt 
1773ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = {
1774ea4e2bc4SSteven Rostedt 	.open = ftrace_graph_open,
1775ea4e2bc4SSteven Rostedt 	.read = ftrace_graph_read,
1776ea4e2bc4SSteven Rostedt 	.write = ftrace_graph_write,
1777ea4e2bc4SSteven Rostedt };
1778ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
1779ea4e2bc4SSteven Rostedt 
1780df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
17815072c59fSSteven Rostedt {
17825072c59fSSteven Rostedt 	struct dentry *entry;
17835072c59fSSteven Rostedt 
17845072c59fSSteven Rostedt 	entry = debugfs_create_file("available_filter_functions", 0444,
17855072c59fSSteven Rostedt 				    d_tracer, NULL, &ftrace_avail_fops);
17865072c59fSSteven Rostedt 	if (!entry)
17875072c59fSSteven Rostedt 		pr_warning("Could not create debugfs "
17885072c59fSSteven Rostedt 			   "'available_filter_functions' entry\n");
17895072c59fSSteven Rostedt 
1790eb9a7bf0SAbhishek Sagar 	entry = debugfs_create_file("failures", 0444,
1791eb9a7bf0SAbhishek Sagar 				    d_tracer, NULL, &ftrace_failures_fops);
1792eb9a7bf0SAbhishek Sagar 	if (!entry)
1793eb9a7bf0SAbhishek Sagar 		pr_warning("Could not create debugfs 'failures' entry\n");
1794eb9a7bf0SAbhishek Sagar 
17955072c59fSSteven Rostedt 	entry = debugfs_create_file("set_ftrace_filter", 0644, d_tracer,
17965072c59fSSteven Rostedt 				    NULL, &ftrace_filter_fops);
17975072c59fSSteven Rostedt 	if (!entry)
17985072c59fSSteven Rostedt 		pr_warning("Could not create debugfs "
17995072c59fSSteven Rostedt 			   "'set_ftrace_filter' entry\n");
180041c52c0dSSteven Rostedt 
180141c52c0dSSteven Rostedt 	entry = debugfs_create_file("set_ftrace_notrace", 0644, d_tracer,
180241c52c0dSSteven Rostedt 				    NULL, &ftrace_notrace_fops);
180341c52c0dSSteven Rostedt 	if (!entry)
180441c52c0dSSteven Rostedt 		pr_warning("Could not create debugfs "
180541c52c0dSSteven Rostedt 			   "'set_ftrace_notrace' entry\n");
1806ad90c0e3SSteven Rostedt 
1807ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
1808ea4e2bc4SSteven Rostedt 	entry = debugfs_create_file("set_graph_function", 0444, d_tracer,
1809ea4e2bc4SSteven Rostedt 				    NULL,
1810ea4e2bc4SSteven Rostedt 				    &ftrace_graph_fops);
1811ea4e2bc4SSteven Rostedt 	if (!entry)
1812ea4e2bc4SSteven Rostedt 		pr_warning("Could not create debugfs "
1813ea4e2bc4SSteven Rostedt 			   "'set_graph_function' entry\n");
1814ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
1815ea4e2bc4SSteven Rostedt 
18165072c59fSSteven Rostedt 	return 0;
18175072c59fSSteven Rostedt }
18185072c59fSSteven Rostedt 
181931e88909SSteven Rostedt static int ftrace_convert_nops(struct module *mod,
182031e88909SSteven Rostedt 			       unsigned long *start,
182168bf21aaSSteven Rostedt 			       unsigned long *end)
182268bf21aaSSteven Rostedt {
182368bf21aaSSteven Rostedt 	unsigned long *p;
182468bf21aaSSteven Rostedt 	unsigned long addr;
182568bf21aaSSteven Rostedt 	unsigned long flags;
182668bf21aaSSteven Rostedt 
182708f5ac90SSteven Rostedt 	mutex_lock(&ftrace_start_lock);
182868bf21aaSSteven Rostedt 	p = start;
182968bf21aaSSteven Rostedt 	while (p < end) {
183068bf21aaSSteven Rostedt 		addr = ftrace_call_adjust(*p++);
183120e5227eSSteven Rostedt 		/*
183220e5227eSSteven Rostedt 		 * Some architecture linkers will pad between
183320e5227eSSteven Rostedt 		 * the different mcount_loc sections of different
183420e5227eSSteven Rostedt 		 * object files to satisfy alignments.
183520e5227eSSteven Rostedt 		 * Skip any NULL pointers.
183620e5227eSSteven Rostedt 		 */
183720e5227eSSteven Rostedt 		if (!addr)
183820e5227eSSteven Rostedt 			continue;
183968bf21aaSSteven Rostedt 		ftrace_record_ip(addr);
184068bf21aaSSteven Rostedt 	}
184168bf21aaSSteven Rostedt 
184208f5ac90SSteven Rostedt 	/* disable interrupts to prevent kstop machine */
184368bf21aaSSteven Rostedt 	local_irq_save(flags);
184431e88909SSteven Rostedt 	ftrace_update_code(mod);
184568bf21aaSSteven Rostedt 	local_irq_restore(flags);
184608f5ac90SSteven Rostedt 	mutex_unlock(&ftrace_start_lock);
184768bf21aaSSteven Rostedt 
184868bf21aaSSteven Rostedt 	return 0;
184968bf21aaSSteven Rostedt }
185068bf21aaSSteven Rostedt 
185131e88909SSteven Rostedt void ftrace_init_module(struct module *mod,
185231e88909SSteven Rostedt 			unsigned long *start, unsigned long *end)
185390d595feSSteven Rostedt {
185400fd61aeSSteven Rostedt 	if (ftrace_disabled || start == end)
1855fed1939cSSteven Rostedt 		return;
185631e88909SSteven Rostedt 	ftrace_convert_nops(mod, start, end);
185790d595feSSteven Rostedt }
185890d595feSSteven Rostedt 
185968bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[];
186068bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[];
186168bf21aaSSteven Rostedt 
186268bf21aaSSteven Rostedt void __init ftrace_init(void)
186368bf21aaSSteven Rostedt {
186468bf21aaSSteven Rostedt 	unsigned long count, addr, flags;
186568bf21aaSSteven Rostedt 	int ret;
186668bf21aaSSteven Rostedt 
186768bf21aaSSteven Rostedt 	/* Keep the ftrace pointer to the stub */
186868bf21aaSSteven Rostedt 	addr = (unsigned long)ftrace_stub;
186968bf21aaSSteven Rostedt 
187068bf21aaSSteven Rostedt 	local_irq_save(flags);
187168bf21aaSSteven Rostedt 	ftrace_dyn_arch_init(&addr);
187268bf21aaSSteven Rostedt 	local_irq_restore(flags);
187368bf21aaSSteven Rostedt 
187468bf21aaSSteven Rostedt 	/* ftrace_dyn_arch_init places the return code in addr */
187568bf21aaSSteven Rostedt 	if (addr)
187668bf21aaSSteven Rostedt 		goto failed;
187768bf21aaSSteven Rostedt 
187868bf21aaSSteven Rostedt 	count = __stop_mcount_loc - __start_mcount_loc;
187968bf21aaSSteven Rostedt 
188068bf21aaSSteven Rostedt 	ret = ftrace_dyn_table_alloc(count);
188168bf21aaSSteven Rostedt 	if (ret)
188268bf21aaSSteven Rostedt 		goto failed;
188368bf21aaSSteven Rostedt 
188468bf21aaSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled = 1;
188568bf21aaSSteven Rostedt 
188631e88909SSteven Rostedt 	ret = ftrace_convert_nops(NULL,
188731e88909SSteven Rostedt 				  __start_mcount_loc,
188868bf21aaSSteven Rostedt 				  __stop_mcount_loc);
188968bf21aaSSteven Rostedt 
189068bf21aaSSteven Rostedt 	return;
189168bf21aaSSteven Rostedt  failed:
189268bf21aaSSteven Rostedt 	ftrace_disabled = 1;
189368bf21aaSSteven Rostedt }
189468bf21aaSSteven Rostedt 
18953d083395SSteven Rostedt #else
18960b6e4d56SFrederic Weisbecker 
18970b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void)
18980b6e4d56SFrederic Weisbecker {
18990b6e4d56SFrederic Weisbecker 	ftrace_enabled = 1;
19000b6e4d56SFrederic Weisbecker 	return 0;
19010b6e4d56SFrederic Weisbecker }
19020b6e4d56SFrederic Weisbecker device_initcall(ftrace_nodyn_init);
19030b6e4d56SFrederic Weisbecker 
1904df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
1905df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { }
19065a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */
19075a45cfe1SSteven Rostedt # define ftrace_startup(command)	do { } while (0)
19085a45cfe1SSteven Rostedt # define ftrace_shutdown(command)	do { } while (0)
1909b0fc494fSSteven Rostedt # define ftrace_startup_sysctl()	do { } while (0)
1910b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl()	do { } while (0)
19113d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */
19123d083395SSteven Rostedt 
1913df4fc315SSteven Rostedt static ssize_t
1914df4fc315SSteven Rostedt ftrace_pid_read(struct file *file, char __user *ubuf,
1915df4fc315SSteven Rostedt 		       size_t cnt, loff_t *ppos)
1916df4fc315SSteven Rostedt {
1917df4fc315SSteven Rostedt 	char buf[64];
1918df4fc315SSteven Rostedt 	int r;
1919df4fc315SSteven Rostedt 
1920e32d8956SSteven Rostedt 	if (ftrace_pid_trace == ftrace_swapper_pid)
1921e32d8956SSteven Rostedt 		r = sprintf(buf, "swapper tasks\n");
1922e32d8956SSteven Rostedt 	else if (ftrace_pid_trace)
1923978f3a45SSteven Rostedt 		r = sprintf(buf, "%u\n", pid_nr(ftrace_pid_trace));
1924df4fc315SSteven Rostedt 	else
1925df4fc315SSteven Rostedt 		r = sprintf(buf, "no pid\n");
1926df4fc315SSteven Rostedt 
1927df4fc315SSteven Rostedt 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1928df4fc315SSteven Rostedt }
1929df4fc315SSteven Rostedt 
1930e32d8956SSteven Rostedt static void clear_ftrace_swapper(void)
1931e32d8956SSteven Rostedt {
1932e32d8956SSteven Rostedt 	struct task_struct *p;
1933e32d8956SSteven Rostedt 	int cpu;
1934e32d8956SSteven Rostedt 
1935e32d8956SSteven Rostedt 	get_online_cpus();
1936e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
1937e32d8956SSteven Rostedt 		p = idle_task(cpu);
1938e32d8956SSteven Rostedt 		clear_tsk_trace_trace(p);
1939e32d8956SSteven Rostedt 	}
1940e32d8956SSteven Rostedt 	put_online_cpus();
1941e32d8956SSteven Rostedt }
1942e32d8956SSteven Rostedt 
1943e32d8956SSteven Rostedt static void set_ftrace_swapper(void)
1944e32d8956SSteven Rostedt {
1945e32d8956SSteven Rostedt 	struct task_struct *p;
1946e32d8956SSteven Rostedt 	int cpu;
1947e32d8956SSteven Rostedt 
1948e32d8956SSteven Rostedt 	get_online_cpus();
1949e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
1950e32d8956SSteven Rostedt 		p = idle_task(cpu);
1951e32d8956SSteven Rostedt 		set_tsk_trace_trace(p);
1952e32d8956SSteven Rostedt 	}
1953e32d8956SSteven Rostedt 	put_online_cpus();
1954e32d8956SSteven Rostedt }
1955e32d8956SSteven Rostedt 
1956e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid)
1957978f3a45SSteven Rostedt {
1958978f3a45SSteven Rostedt 	struct task_struct *p;
1959978f3a45SSteven Rostedt 
1960229c4ef8SOleg Nesterov 	rcu_read_lock();
1961e32d8956SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
1962978f3a45SSteven Rostedt 		clear_tsk_trace_trace(p);
1963e32d8956SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
1964229c4ef8SOleg Nesterov 	rcu_read_unlock();
1965229c4ef8SOleg Nesterov 
1966e32d8956SSteven Rostedt 	put_pid(pid);
1967978f3a45SSteven Rostedt }
1968978f3a45SSteven Rostedt 
1969e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid)
1970978f3a45SSteven Rostedt {
1971978f3a45SSteven Rostedt 	struct task_struct *p;
1972978f3a45SSteven Rostedt 
1973229c4ef8SOleg Nesterov 	rcu_read_lock();
1974978f3a45SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
1975978f3a45SSteven Rostedt 		set_tsk_trace_trace(p);
1976978f3a45SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
1977229c4ef8SOleg Nesterov 	rcu_read_unlock();
1978978f3a45SSteven Rostedt }
1979978f3a45SSteven Rostedt 
1980e32d8956SSteven Rostedt static void clear_ftrace_pid_task(struct pid **pid)
1981e32d8956SSteven Rostedt {
1982e32d8956SSteven Rostedt 	if (*pid == ftrace_swapper_pid)
1983e32d8956SSteven Rostedt 		clear_ftrace_swapper();
1984e32d8956SSteven Rostedt 	else
1985e32d8956SSteven Rostedt 		clear_ftrace_pid(*pid);
1986e32d8956SSteven Rostedt 
1987e32d8956SSteven Rostedt 	*pid = NULL;
1988e32d8956SSteven Rostedt }
1989e32d8956SSteven Rostedt 
1990e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid)
1991e32d8956SSteven Rostedt {
1992e32d8956SSteven Rostedt 	if (pid == ftrace_swapper_pid)
1993e32d8956SSteven Rostedt 		set_ftrace_swapper();
1994e32d8956SSteven Rostedt 	else
1995e32d8956SSteven Rostedt 		set_ftrace_pid(pid);
1996e32d8956SSteven Rostedt }
1997e32d8956SSteven Rostedt 
1998df4fc315SSteven Rostedt static ssize_t
1999df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf,
2000df4fc315SSteven Rostedt 		   size_t cnt, loff_t *ppos)
2001df4fc315SSteven Rostedt {
2002978f3a45SSteven Rostedt 	struct pid *pid;
2003df4fc315SSteven Rostedt 	char buf[64];
2004df4fc315SSteven Rostedt 	long val;
2005df4fc315SSteven Rostedt 	int ret;
2006df4fc315SSteven Rostedt 
2007df4fc315SSteven Rostedt 	if (cnt >= sizeof(buf))
2008df4fc315SSteven Rostedt 		return -EINVAL;
2009df4fc315SSteven Rostedt 
2010df4fc315SSteven Rostedt 	if (copy_from_user(&buf, ubuf, cnt))
2011df4fc315SSteven Rostedt 		return -EFAULT;
2012df4fc315SSteven Rostedt 
2013df4fc315SSteven Rostedt 	buf[cnt] = 0;
2014df4fc315SSteven Rostedt 
2015df4fc315SSteven Rostedt 	ret = strict_strtol(buf, 10, &val);
2016df4fc315SSteven Rostedt 	if (ret < 0)
2017df4fc315SSteven Rostedt 		return ret;
2018df4fc315SSteven Rostedt 
2019df4fc315SSteven Rostedt 	mutex_lock(&ftrace_start_lock);
2020978f3a45SSteven Rostedt 	if (val < 0) {
2021df4fc315SSteven Rostedt 		/* disable pid tracing */
2022978f3a45SSteven Rostedt 		if (!ftrace_pid_trace)
2023df4fc315SSteven Rostedt 			goto out;
2024978f3a45SSteven Rostedt 
2025978f3a45SSteven Rostedt 		clear_ftrace_pid_task(&ftrace_pid_trace);
2026df4fc315SSteven Rostedt 
2027df4fc315SSteven Rostedt 	} else {
2028e32d8956SSteven Rostedt 		/* swapper task is special */
2029e32d8956SSteven Rostedt 		if (!val) {
2030e32d8956SSteven Rostedt 			pid = ftrace_swapper_pid;
2031e32d8956SSteven Rostedt 			if (pid == ftrace_pid_trace)
2032e32d8956SSteven Rostedt 				goto out;
2033e32d8956SSteven Rostedt 		} else {
2034978f3a45SSteven Rostedt 			pid = find_get_pid(val);
2035df4fc315SSteven Rostedt 
2036978f3a45SSteven Rostedt 			if (pid == ftrace_pid_trace) {
2037978f3a45SSteven Rostedt 				put_pid(pid);
2038978f3a45SSteven Rostedt 				goto out;
2039978f3a45SSteven Rostedt 			}
2040e32d8956SSteven Rostedt 		}
2041978f3a45SSteven Rostedt 
2042978f3a45SSteven Rostedt 		if (ftrace_pid_trace)
2043978f3a45SSteven Rostedt 			clear_ftrace_pid_task(&ftrace_pid_trace);
2044978f3a45SSteven Rostedt 
2045978f3a45SSteven Rostedt 		if (!pid)
2046df4fc315SSteven Rostedt 			goto out;
2047df4fc315SSteven Rostedt 
2048978f3a45SSteven Rostedt 		ftrace_pid_trace = pid;
20490ef8cde5SSteven Rostedt 
2050978f3a45SSteven Rostedt 		set_ftrace_pid_task(ftrace_pid_trace);
2051df4fc315SSteven Rostedt 	}
2052df4fc315SSteven Rostedt 
2053df4fc315SSteven Rostedt 	/* update the function call */
2054df4fc315SSteven Rostedt 	ftrace_update_pid_func();
2055df4fc315SSteven Rostedt 	ftrace_startup_enable(0);
2056df4fc315SSteven Rostedt 
2057df4fc315SSteven Rostedt  out:
2058df4fc315SSteven Rostedt 	mutex_unlock(&ftrace_start_lock);
2059df4fc315SSteven Rostedt 
2060df4fc315SSteven Rostedt 	return cnt;
2061df4fc315SSteven Rostedt }
2062df4fc315SSteven Rostedt 
2063df4fc315SSteven Rostedt static struct file_operations ftrace_pid_fops = {
2064df4fc315SSteven Rostedt 	.read = ftrace_pid_read,
2065df4fc315SSteven Rostedt 	.write = ftrace_pid_write,
2066df4fc315SSteven Rostedt };
2067df4fc315SSteven Rostedt 
2068df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void)
2069df4fc315SSteven Rostedt {
2070df4fc315SSteven Rostedt 	struct dentry *d_tracer;
2071df4fc315SSteven Rostedt 	struct dentry *entry;
2072df4fc315SSteven Rostedt 
2073df4fc315SSteven Rostedt 	d_tracer = tracing_init_dentry();
2074df4fc315SSteven Rostedt 	if (!d_tracer)
2075df4fc315SSteven Rostedt 		return 0;
2076df4fc315SSteven Rostedt 
2077df4fc315SSteven Rostedt 	ftrace_init_dyn_debugfs(d_tracer);
2078df4fc315SSteven Rostedt 
2079df4fc315SSteven Rostedt 	entry = debugfs_create_file("set_ftrace_pid", 0644, d_tracer,
2080df4fc315SSteven Rostedt 				    NULL, &ftrace_pid_fops);
2081df4fc315SSteven Rostedt 	if (!entry)
2082df4fc315SSteven Rostedt 		pr_warning("Could not create debugfs "
2083df4fc315SSteven Rostedt 			   "'set_ftrace_pid' entry\n");
2084df4fc315SSteven Rostedt 	return 0;
2085df4fc315SSteven Rostedt }
2086df4fc315SSteven Rostedt 
2087df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs);
2088df4fc315SSteven Rostedt 
20893d083395SSteven Rostedt /**
209081adbdc0SSteven Rostedt  * ftrace_kill - kill ftrace
2091a2bb6a3dSSteven Rostedt  *
2092a2bb6a3dSSteven Rostedt  * This function should be used by panic code. It stops ftrace
2093a2bb6a3dSSteven Rostedt  * but in a not so nice way. If you need to simply kill ftrace
2094a2bb6a3dSSteven Rostedt  * from a non-atomic section, use ftrace_kill.
2095a2bb6a3dSSteven Rostedt  */
209681adbdc0SSteven Rostedt void ftrace_kill(void)
2097a2bb6a3dSSteven Rostedt {
2098a2bb6a3dSSteven Rostedt 	ftrace_disabled = 1;
2099a2bb6a3dSSteven Rostedt 	ftrace_enabled = 0;
2100a2bb6a3dSSteven Rostedt 	clear_ftrace_function();
2101a2bb6a3dSSteven Rostedt }
2102a2bb6a3dSSteven Rostedt 
2103a2bb6a3dSSteven Rostedt /**
21043d083395SSteven Rostedt  * register_ftrace_function - register a function for profiling
21053d083395SSteven Rostedt  * @ops - ops structure that holds the function for profiling.
21063d083395SSteven Rostedt  *
21073d083395SSteven Rostedt  * Register a function to be called by all functions in the
21083d083395SSteven Rostedt  * kernel.
21093d083395SSteven Rostedt  *
21103d083395SSteven Rostedt  * Note: @ops->func and all the functions it calls must be labeled
21113d083395SSteven Rostedt  *       with "notrace", otherwise it will go into a
21123d083395SSteven Rostedt  *       recursive loop.
21133d083395SSteven Rostedt  */
21143d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops)
21153d083395SSteven Rostedt {
2116b0fc494fSSteven Rostedt 	int ret;
2117b0fc494fSSteven Rostedt 
21184eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
21194eebcc81SSteven Rostedt 		return -1;
21204eebcc81SSteven Rostedt 
2121b0fc494fSSteven Rostedt 	mutex_lock(&ftrace_sysctl_lock);
2122e7d3737eSFrederic Weisbecker 
2123b0fc494fSSteven Rostedt 	ret = __register_ftrace_function(ops);
21245a45cfe1SSteven Rostedt 	ftrace_startup(0);
2125b0fc494fSSteven Rostedt 
2126e7d3737eSFrederic Weisbecker 	mutex_unlock(&ftrace_sysctl_lock);
2127b0fc494fSSteven Rostedt 	return ret;
21283d083395SSteven Rostedt }
21293d083395SSteven Rostedt 
21303d083395SSteven Rostedt /**
213132632920SUwe Kleine-Koenig  * unregister_ftrace_function - unregister a function for profiling.
21323d083395SSteven Rostedt  * @ops - ops structure that holds the function to unregister
21333d083395SSteven Rostedt  *
21343d083395SSteven Rostedt  * Unregister a function that was added to be called by ftrace profiling.
21353d083395SSteven Rostedt  */
21363d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops)
21373d083395SSteven Rostedt {
21383d083395SSteven Rostedt 	int ret;
21393d083395SSteven Rostedt 
2140b0fc494fSSteven Rostedt 	mutex_lock(&ftrace_sysctl_lock);
21413d083395SSteven Rostedt 	ret = __unregister_ftrace_function(ops);
21425a45cfe1SSteven Rostedt 	ftrace_shutdown(0);
2143b0fc494fSSteven Rostedt 	mutex_unlock(&ftrace_sysctl_lock);
2144b0fc494fSSteven Rostedt 
2145b0fc494fSSteven Rostedt 	return ret;
2146b0fc494fSSteven Rostedt }
2147b0fc494fSSteven Rostedt 
2148e309b41dSIngo Molnar int
2149b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write,
21505072c59fSSteven Rostedt 		     struct file *file, void __user *buffer, size_t *lenp,
2151b0fc494fSSteven Rostedt 		     loff_t *ppos)
2152b0fc494fSSteven Rostedt {
2153b0fc494fSSteven Rostedt 	int ret;
2154b0fc494fSSteven Rostedt 
21554eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
21564eebcc81SSteven Rostedt 		return -ENODEV;
21574eebcc81SSteven Rostedt 
2158b0fc494fSSteven Rostedt 	mutex_lock(&ftrace_sysctl_lock);
2159b0fc494fSSteven Rostedt 
21605072c59fSSteven Rostedt 	ret  = proc_dointvec(table, write, file, buffer, lenp, ppos);
2161b0fc494fSSteven Rostedt 
2162b0fc494fSSteven Rostedt 	if (ret || !write || (last_ftrace_enabled == ftrace_enabled))
2163b0fc494fSSteven Rostedt 		goto out;
2164b0fc494fSSteven Rostedt 
2165b0fc494fSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled;
2166b0fc494fSSteven Rostedt 
2167b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
2168b0fc494fSSteven Rostedt 
2169b0fc494fSSteven Rostedt 		ftrace_startup_sysctl();
2170b0fc494fSSteven Rostedt 
2171b0fc494fSSteven Rostedt 		/* we are starting ftrace again */
2172b0fc494fSSteven Rostedt 		if (ftrace_list != &ftrace_list_end) {
2173b0fc494fSSteven Rostedt 			if (ftrace_list->next == &ftrace_list_end)
2174b0fc494fSSteven Rostedt 				ftrace_trace_function = ftrace_list->func;
2175b0fc494fSSteven Rostedt 			else
2176b0fc494fSSteven Rostedt 				ftrace_trace_function = ftrace_list_func;
2177b0fc494fSSteven Rostedt 		}
2178b0fc494fSSteven Rostedt 
2179b0fc494fSSteven Rostedt 	} else {
2180b0fc494fSSteven Rostedt 		/* stopping ftrace calls (just send to ftrace_stub) */
2181b0fc494fSSteven Rostedt 		ftrace_trace_function = ftrace_stub;
2182b0fc494fSSteven Rostedt 
2183b0fc494fSSteven Rostedt 		ftrace_shutdown_sysctl();
2184b0fc494fSSteven Rostedt 	}
2185b0fc494fSSteven Rostedt 
2186b0fc494fSSteven Rostedt  out:
2187b0fc494fSSteven Rostedt 	mutex_unlock(&ftrace_sysctl_lock);
21883d083395SSteven Rostedt 	return ret;
218916444a8aSArnaldo Carvalho de Melo }
2190f17845e5SIngo Molnar 
2191fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER
2192e7d3737eSFrederic Weisbecker 
2193287b6e68SFrederic Weisbecker static atomic_t ftrace_graph_active;
21944a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier;
2195f201ae23SFrederic Weisbecker 
2196e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
2197e49dc19cSSteven Rostedt {
2198e49dc19cSSteven Rostedt 	return 0;
2199e49dc19cSSteven Rostedt }
2200e49dc19cSSteven Rostedt 
2201287b6e68SFrederic Weisbecker /* The callbacks that hook a function */
2202287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return =
2203287b6e68SFrederic Weisbecker 			(trace_func_graph_ret_t)ftrace_stub;
2204e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
2205f201ae23SFrederic Weisbecker 
2206f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
2207f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
2208f201ae23SFrederic Weisbecker {
2209f201ae23SFrederic Weisbecker 	int i;
2210f201ae23SFrederic Weisbecker 	int ret = 0;
2211f201ae23SFrederic Weisbecker 	unsigned long flags;
2212f201ae23SFrederic Weisbecker 	int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE;
2213f201ae23SFrederic Weisbecker 	struct task_struct *g, *t;
2214f201ae23SFrederic Weisbecker 
2215f201ae23SFrederic Weisbecker 	for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
2216f201ae23SFrederic Weisbecker 		ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
2217f201ae23SFrederic Weisbecker 					* sizeof(struct ftrace_ret_stack),
2218f201ae23SFrederic Weisbecker 					GFP_KERNEL);
2219f201ae23SFrederic Weisbecker 		if (!ret_stack_list[i]) {
2220f201ae23SFrederic Weisbecker 			start = 0;
2221f201ae23SFrederic Weisbecker 			end = i;
2222f201ae23SFrederic Weisbecker 			ret = -ENOMEM;
2223f201ae23SFrederic Weisbecker 			goto free;
2224f201ae23SFrederic Weisbecker 		}
2225f201ae23SFrederic Weisbecker 	}
2226f201ae23SFrederic Weisbecker 
2227f201ae23SFrederic Weisbecker 	read_lock_irqsave(&tasklist_lock, flags);
2228f201ae23SFrederic Weisbecker 	do_each_thread(g, t) {
2229f201ae23SFrederic Weisbecker 		if (start == end) {
2230f201ae23SFrederic Weisbecker 			ret = -EAGAIN;
2231f201ae23SFrederic Weisbecker 			goto unlock;
2232f201ae23SFrederic Weisbecker 		}
2233f201ae23SFrederic Weisbecker 
2234f201ae23SFrederic Weisbecker 		if (t->ret_stack == NULL) {
2235f201ae23SFrederic Weisbecker 			t->curr_ret_stack = -1;
223648d68b20SFrederic Weisbecker 			/* Make sure IRQs see the -1 first: */
223748d68b20SFrederic Weisbecker 			barrier();
223848d68b20SFrederic Weisbecker 			t->ret_stack = ret_stack_list[start++];
2239380c4b14SFrederic Weisbecker 			atomic_set(&t->tracing_graph_pause, 0);
2240f201ae23SFrederic Weisbecker 			atomic_set(&t->trace_overrun, 0);
2241f201ae23SFrederic Weisbecker 		}
2242f201ae23SFrederic Weisbecker 	} while_each_thread(g, t);
2243f201ae23SFrederic Weisbecker 
2244f201ae23SFrederic Weisbecker unlock:
2245f201ae23SFrederic Weisbecker 	read_unlock_irqrestore(&tasklist_lock, flags);
2246f201ae23SFrederic Weisbecker free:
2247f201ae23SFrederic Weisbecker 	for (i = start; i < end; i++)
2248f201ae23SFrederic Weisbecker 		kfree(ret_stack_list[i]);
2249f201ae23SFrederic Weisbecker 	return ret;
2250f201ae23SFrederic Weisbecker }
2251f201ae23SFrederic Weisbecker 
2252f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */
2253fb52607aSFrederic Weisbecker static int start_graph_tracing(void)
2254f201ae23SFrederic Weisbecker {
2255f201ae23SFrederic Weisbecker 	struct ftrace_ret_stack **ret_stack_list;
2256f201ae23SFrederic Weisbecker 	int ret;
2257f201ae23SFrederic Weisbecker 
2258f201ae23SFrederic Weisbecker 	ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
2259f201ae23SFrederic Weisbecker 				sizeof(struct ftrace_ret_stack *),
2260f201ae23SFrederic Weisbecker 				GFP_KERNEL);
2261f201ae23SFrederic Weisbecker 
2262f201ae23SFrederic Weisbecker 	if (!ret_stack_list)
2263f201ae23SFrederic Weisbecker 		return -ENOMEM;
2264f201ae23SFrederic Weisbecker 
2265f201ae23SFrederic Weisbecker 	do {
2266f201ae23SFrederic Weisbecker 		ret = alloc_retstack_tasklist(ret_stack_list);
2267f201ae23SFrederic Weisbecker 	} while (ret == -EAGAIN);
2268f201ae23SFrederic Weisbecker 
2269f201ae23SFrederic Weisbecker 	kfree(ret_stack_list);
2270f201ae23SFrederic Weisbecker 	return ret;
2271f201ae23SFrederic Weisbecker }
2272f201ae23SFrederic Weisbecker 
22734a2b8ddaSFrederic Weisbecker /*
22744a2b8ddaSFrederic Weisbecker  * Hibernation protection.
22754a2b8ddaSFrederic Weisbecker  * The state of the current task is too much unstable during
22764a2b8ddaSFrederic Weisbecker  * suspend/restore to disk. We want to protect against that.
22774a2b8ddaSFrederic Weisbecker  */
22784a2b8ddaSFrederic Weisbecker static int
22794a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
22804a2b8ddaSFrederic Weisbecker 							void *unused)
22814a2b8ddaSFrederic Weisbecker {
22824a2b8ddaSFrederic Weisbecker 	switch (state) {
22834a2b8ddaSFrederic Weisbecker 	case PM_HIBERNATION_PREPARE:
22844a2b8ddaSFrederic Weisbecker 		pause_graph_tracing();
22854a2b8ddaSFrederic Weisbecker 		break;
22864a2b8ddaSFrederic Weisbecker 
22874a2b8ddaSFrederic Weisbecker 	case PM_POST_HIBERNATION:
22884a2b8ddaSFrederic Weisbecker 		unpause_graph_tracing();
22894a2b8ddaSFrederic Weisbecker 		break;
22904a2b8ddaSFrederic Weisbecker 	}
22914a2b8ddaSFrederic Weisbecker 	return NOTIFY_DONE;
22924a2b8ddaSFrederic Weisbecker }
22934a2b8ddaSFrederic Weisbecker 
2294287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc,
2295287b6e68SFrederic Weisbecker 			trace_func_graph_ent_t entryfunc)
229615e6cb36SFrederic Weisbecker {
2297e7d3737eSFrederic Weisbecker 	int ret = 0;
2298e7d3737eSFrederic Weisbecker 
2299e7d3737eSFrederic Weisbecker 	mutex_lock(&ftrace_sysctl_lock);
2300e7d3737eSFrederic Weisbecker 
23014a2b8ddaSFrederic Weisbecker 	ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call;
23024a2b8ddaSFrederic Weisbecker 	register_pm_notifier(&ftrace_suspend_notifier);
23034a2b8ddaSFrederic Weisbecker 
2304287b6e68SFrederic Weisbecker 	atomic_inc(&ftrace_graph_active);
2305fb52607aSFrederic Weisbecker 	ret = start_graph_tracing();
2306f201ae23SFrederic Weisbecker 	if (ret) {
2307287b6e68SFrederic Weisbecker 		atomic_dec(&ftrace_graph_active);
2308f201ae23SFrederic Weisbecker 		goto out;
2309f201ae23SFrederic Weisbecker 	}
2310e53a6319SSteven Rostedt 
2311287b6e68SFrederic Weisbecker 	ftrace_graph_return = retfunc;
2312287b6e68SFrederic Weisbecker 	ftrace_graph_entry = entryfunc;
2313e53a6319SSteven Rostedt 
23145a45cfe1SSteven Rostedt 	ftrace_startup(FTRACE_START_FUNC_RET);
2315e7d3737eSFrederic Weisbecker 
2316e7d3737eSFrederic Weisbecker out:
2317e7d3737eSFrederic Weisbecker 	mutex_unlock(&ftrace_sysctl_lock);
2318e7d3737eSFrederic Weisbecker 	return ret;
231915e6cb36SFrederic Weisbecker }
232015e6cb36SFrederic Weisbecker 
2321fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void)
232215e6cb36SFrederic Weisbecker {
2323e7d3737eSFrederic Weisbecker 	mutex_lock(&ftrace_sysctl_lock);
2324e7d3737eSFrederic Weisbecker 
2325287b6e68SFrederic Weisbecker 	atomic_dec(&ftrace_graph_active);
2326287b6e68SFrederic Weisbecker 	ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
2327e49dc19cSSteven Rostedt 	ftrace_graph_entry = ftrace_graph_entry_stub;
23285a45cfe1SSteven Rostedt 	ftrace_shutdown(FTRACE_STOP_FUNC_RET);
23294a2b8ddaSFrederic Weisbecker 	unregister_pm_notifier(&ftrace_suspend_notifier);
2330e7d3737eSFrederic Weisbecker 
2331e7d3737eSFrederic Weisbecker 	mutex_unlock(&ftrace_sysctl_lock);
233215e6cb36SFrederic Weisbecker }
2333f201ae23SFrederic Weisbecker 
2334f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */
2335fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t)
2336f201ae23SFrederic Weisbecker {
2337287b6e68SFrederic Weisbecker 	if (atomic_read(&ftrace_graph_active)) {
2338f201ae23SFrederic Weisbecker 		t->ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
2339f201ae23SFrederic Weisbecker 				* sizeof(struct ftrace_ret_stack),
2340f201ae23SFrederic Weisbecker 				GFP_KERNEL);
2341f201ae23SFrederic Weisbecker 		if (!t->ret_stack)
2342f201ae23SFrederic Weisbecker 			return;
2343f201ae23SFrederic Weisbecker 		t->curr_ret_stack = -1;
2344380c4b14SFrederic Weisbecker 		atomic_set(&t->tracing_graph_pause, 0);
2345f201ae23SFrederic Weisbecker 		atomic_set(&t->trace_overrun, 0);
2346f201ae23SFrederic Weisbecker 	} else
2347f201ae23SFrederic Weisbecker 		t->ret_stack = NULL;
2348f201ae23SFrederic Weisbecker }
2349f201ae23SFrederic Weisbecker 
2350fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t)
2351f201ae23SFrederic Weisbecker {
2352eae849caSFrederic Weisbecker 	struct ftrace_ret_stack	*ret_stack = t->ret_stack;
2353eae849caSFrederic Weisbecker 
2354f201ae23SFrederic Weisbecker 	t->ret_stack = NULL;
2355eae849caSFrederic Weisbecker 	/* NULL must become visible to IRQs before we free it: */
2356eae849caSFrederic Weisbecker 	barrier();
2357eae849caSFrederic Weisbecker 
2358eae849caSFrederic Weisbecker 	kfree(ret_stack);
2359f201ae23SFrederic Weisbecker }
236014a866c5SSteven Rostedt 
236114a866c5SSteven Rostedt void ftrace_graph_stop(void)
236214a866c5SSteven Rostedt {
236314a866c5SSteven Rostedt 	ftrace_stop();
236414a866c5SSteven Rostedt }
236515e6cb36SFrederic Weisbecker #endif
236615e6cb36SFrederic Weisbecker 
2367