xref: /linux-6.15/kernel/trace/ftrace.c (revision 9f50afcc)
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
136d49e352SNadia Yvette Chambers  *  Copyright (C) 2004 Nadia Yvette Chambers
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>
255855feadSSteven Rostedt #include <linux/bsearch.h>
2656d82e00SPaul Gortmaker #include <linux/module.h>
272d8b820bSIngo Molnar #include <linux/ftrace.h>
28b0fc494fSSteven Rostedt #include <linux/sysctl.h>
295a0e3ad6STejun Heo #include <linux/slab.h>
305072c59fSSteven Rostedt #include <linux/ctype.h>
3168950619SSteven Rostedt #include <linux/sort.h>
323d083395SSteven Rostedt #include <linux/list.h>
3359df055fSSteven Rostedt #include <linux/hash.h>
343f379b03SPaul E. McKenney #include <linux/rcupdate.h>
3516444a8aSArnaldo Carvalho de Melo 
36ad8d75ffSSteven Rostedt #include <trace/events/sched.h>
378aef2d28SSteven Rostedt 
382af15d6aSSteven Rostedt #include <asm/setup.h>
39395a59d0SAbhishek Sagar 
400706f1c4SSteven Rostedt #include "trace_output.h"
41bac429f0SSteven Rostedt #include "trace_stat.h"
423d083395SSteven Rostedt 
436912896eSSteven Rostedt #define FTRACE_WARN_ON(cond)			\
440778d9adSSteven Rostedt 	({					\
450778d9adSSteven Rostedt 		int ___r = cond;		\
460778d9adSSteven Rostedt 		if (WARN_ON(___r))		\
476912896eSSteven Rostedt 			ftrace_kill();		\
480778d9adSSteven Rostedt 		___r;				\
490778d9adSSteven Rostedt 	})
506912896eSSteven Rostedt 
516912896eSSteven Rostedt #define FTRACE_WARN_ON_ONCE(cond)		\
520778d9adSSteven Rostedt 	({					\
530778d9adSSteven Rostedt 		int ___r = cond;		\
540778d9adSSteven Rostedt 		if (WARN_ON_ONCE(___r))		\
556912896eSSteven Rostedt 			ftrace_kill();		\
560778d9adSSteven Rostedt 		___r;				\
570778d9adSSteven Rostedt 	})
586912896eSSteven Rostedt 
598fc0c701SSteven Rostedt /* hash bits for specific function selection */
608fc0c701SSteven Rostedt #define FTRACE_HASH_BITS 7
618fc0c701SSteven Rostedt #define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS)
6233dc9b12SSteven Rostedt #define FTRACE_HASH_DEFAULT_BITS 10
6333dc9b12SSteven Rostedt #define FTRACE_HASH_MAX_BITS 12
648fc0c701SSteven Rostedt 
65e248491aSJiri Olsa #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL)
66e248491aSJiri Olsa 
672f5f6ad9SSteven Rostedt static struct ftrace_ops ftrace_list_end __read_mostly = {
682f5f6ad9SSteven Rostedt 	.func		= ftrace_stub,
694740974aSSteven Rostedt 	.flags		= FTRACE_OPS_FL_RECURSION_SAFE,
702f5f6ad9SSteven Rostedt };
712f5f6ad9SSteven Rostedt 
724eebcc81SSteven Rostedt /* ftrace_enabled is a method to turn ftrace on or off */
734eebcc81SSteven Rostedt int ftrace_enabled __read_mostly;
74d61f82d0SSteven Rostedt static int last_ftrace_enabled;
75b0fc494fSSteven Rostedt 
7660a7ecf4SSteven Rostedt /* Quick disabling of function tracer. */
772f5f6ad9SSteven Rostedt int function_trace_stop __read_mostly;
782f5f6ad9SSteven Rostedt 
792f5f6ad9SSteven Rostedt /* Current function tracing op */
802f5f6ad9SSteven Rostedt struct ftrace_ops *function_trace_op __read_mostly = &ftrace_list_end;
8160a7ecf4SSteven Rostedt 
82756d17eeS[email protected] /* List for set_ftrace_pid's pids. */
83756d17eeS[email protected] LIST_HEAD(ftrace_pids);
84756d17eeS[email protected] struct ftrace_pid {
85756d17eeS[email protected] 	struct list_head list;
86756d17eeS[email protected] 	struct pid *pid;
87756d17eeS[email protected] };
88756d17eeS[email protected] 
894eebcc81SSteven Rostedt /*
904eebcc81SSteven Rostedt  * ftrace_disabled is set when an anomaly is discovered.
914eebcc81SSteven Rostedt  * ftrace_disabled is much stronger than ftrace_enabled.
924eebcc81SSteven Rostedt  */
934eebcc81SSteven Rostedt static int ftrace_disabled __read_mostly;
944eebcc81SSteven Rostedt 
9552baf119SSteven Rostedt static DEFINE_MUTEX(ftrace_lock);
96b0fc494fSSteven Rostedt 
97b848914cSSteven Rostedt static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end;
98e248491aSJiri Olsa static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end;
99b848914cSSteven Rostedt static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
10016444a8aSArnaldo Carvalho de Melo ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
101df4fc315SSteven Rostedt ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
1022b499381SSteven Rostedt static struct ftrace_ops global_ops;
103e248491aSJiri Olsa static struct ftrace_ops control_ops;
10416444a8aSArnaldo Carvalho de Melo 
1052f5f6ad9SSteven Rostedt #if ARCH_SUPPORTS_FTRACE_OPS
1062f5f6ad9SSteven Rostedt static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
107a1e2e31dSSteven Rostedt 				 struct ftrace_ops *op, struct pt_regs *regs);
1082f5f6ad9SSteven Rostedt #else
1092f5f6ad9SSteven Rostedt /* See comment below, where ftrace_ops_list_func is defined */
1102f5f6ad9SSteven Rostedt static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);
1112f5f6ad9SSteven Rostedt #define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops)
1122f5f6ad9SSteven Rostedt #endif
113b848914cSSteven Rostedt 
1140a016409SSteven Rostedt /*
1150a016409SSteven Rostedt  * Traverse the ftrace_global_list, invoking all entries.  The reason that we
1160a016409SSteven Rostedt  * can use rcu_dereference_raw() is that elements removed from this list
1170a016409SSteven Rostedt  * are simply leaked, so there is no need to interact with a grace-period
1180a016409SSteven Rostedt  * mechanism.  The rcu_dereference_raw() calls are needed to handle
1190a016409SSteven Rostedt  * concurrent insertions into the ftrace_global_list.
1200a016409SSteven Rostedt  *
1210a016409SSteven Rostedt  * Silly Alpha and silly pointer-speculation compiler optimizations!
1220a016409SSteven Rostedt  */
1230a016409SSteven Rostedt #define do_for_each_ftrace_op(op, list)			\
1240a016409SSteven Rostedt 	op = rcu_dereference_raw(list);			\
1250a016409SSteven Rostedt 	do
1260a016409SSteven Rostedt 
1270a016409SSteven Rostedt /*
1280a016409SSteven Rostedt  * Optimized for just a single item in the list (as that is the normal case).
1290a016409SSteven Rostedt  */
1300a016409SSteven Rostedt #define while_for_each_ftrace_op(op)				\
1310a016409SSteven Rostedt 	while (likely(op = rcu_dereference_raw((op)->next)) &&	\
1320a016409SSteven Rostedt 	       unlikely((op) != &ftrace_list_end))
1330a016409SSteven Rostedt 
134ea701f11SSteven Rostedt /**
135ea701f11SSteven Rostedt  * ftrace_nr_registered_ops - return number of ops registered
136ea701f11SSteven Rostedt  *
137ea701f11SSteven Rostedt  * Returns the number of ftrace_ops registered and tracing functions
138ea701f11SSteven Rostedt  */
139ea701f11SSteven Rostedt int ftrace_nr_registered_ops(void)
140ea701f11SSteven Rostedt {
141ea701f11SSteven Rostedt 	struct ftrace_ops *ops;
142ea701f11SSteven Rostedt 	int cnt = 0;
143ea701f11SSteven Rostedt 
144ea701f11SSteven Rostedt 	mutex_lock(&ftrace_lock);
145ea701f11SSteven Rostedt 
146ea701f11SSteven Rostedt 	for (ops = ftrace_ops_list;
147ea701f11SSteven Rostedt 	     ops != &ftrace_list_end; ops = ops->next)
148ea701f11SSteven Rostedt 		cnt++;
149ea701f11SSteven Rostedt 
150ea701f11SSteven Rostedt 	mutex_unlock(&ftrace_lock);
151ea701f11SSteven Rostedt 
152ea701f11SSteven Rostedt 	return cnt;
153ea701f11SSteven Rostedt }
154ea701f11SSteven Rostedt 
1552f5f6ad9SSteven Rostedt static void
1562f5f6ad9SSteven Rostedt ftrace_global_list_func(unsigned long ip, unsigned long parent_ip,
157a1e2e31dSSteven Rostedt 			struct ftrace_ops *op, struct pt_regs *regs)
15816444a8aSArnaldo Carvalho de Melo {
159c29f122cSSteven Rostedt 	int bit;
160c29f122cSSteven Rostedt 
161edc15cafSSteven Rostedt 	bit = trace_test_and_set_recursion(TRACE_GLOBAL_START, TRACE_GLOBAL_MAX);
162edc15cafSSteven Rostedt 	if (bit < 0)
163b1cff0adSSteven Rostedt 		return;
164b1cff0adSSteven Rostedt 
1650a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_global_list) {
166a1e2e31dSSteven Rostedt 		op->func(ip, parent_ip, op, regs);
1670a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
168edc15cafSSteven Rostedt 
169edc15cafSSteven Rostedt 	trace_clear_recursion(bit);
17016444a8aSArnaldo Carvalho de Melo }
17116444a8aSArnaldo Carvalho de Melo 
1722f5f6ad9SSteven Rostedt static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip,
173a1e2e31dSSteven Rostedt 			    struct ftrace_ops *op, struct pt_regs *regs)
174df4fc315SSteven Rostedt {
1750ef8cde5SSteven Rostedt 	if (!test_tsk_trace_trace(current))
176df4fc315SSteven Rostedt 		return;
177df4fc315SSteven Rostedt 
178a1e2e31dSSteven Rostedt 	ftrace_pid_function(ip, parent_ip, op, regs);
179df4fc315SSteven Rostedt }
180df4fc315SSteven Rostedt 
181df4fc315SSteven Rostedt static void set_ftrace_pid_function(ftrace_func_t func)
182df4fc315SSteven Rostedt {
183df4fc315SSteven Rostedt 	/* do not set ftrace_pid_function to itself! */
184df4fc315SSteven Rostedt 	if (func != ftrace_pid_func)
185df4fc315SSteven Rostedt 		ftrace_pid_function = func;
186df4fc315SSteven Rostedt }
187df4fc315SSteven Rostedt 
18816444a8aSArnaldo Carvalho de Melo /**
1893d083395SSteven Rostedt  * clear_ftrace_function - reset the ftrace function
19016444a8aSArnaldo Carvalho de Melo  *
1913d083395SSteven Rostedt  * This NULLs the ftrace function and in essence stops
1923d083395SSteven Rostedt  * tracing.  There may be lag
19316444a8aSArnaldo Carvalho de Melo  */
1943d083395SSteven Rostedt void clear_ftrace_function(void)
19516444a8aSArnaldo Carvalho de Melo {
1963d083395SSteven Rostedt 	ftrace_trace_function = ftrace_stub;
197df4fc315SSteven Rostedt 	ftrace_pid_function = ftrace_stub;
1983d083395SSteven Rostedt }
19916444a8aSArnaldo Carvalho de Melo 
200e248491aSJiri Olsa static void control_ops_disable_all(struct ftrace_ops *ops)
201e248491aSJiri Olsa {
202e248491aSJiri Olsa 	int cpu;
203e248491aSJiri Olsa 
204e248491aSJiri Olsa 	for_each_possible_cpu(cpu)
205e248491aSJiri Olsa 		*per_cpu_ptr(ops->disabled, cpu) = 1;
206e248491aSJiri Olsa }
207e248491aSJiri Olsa 
208e248491aSJiri Olsa static int control_ops_alloc(struct ftrace_ops *ops)
209e248491aSJiri Olsa {
210e248491aSJiri Olsa 	int __percpu *disabled;
211e248491aSJiri Olsa 
212e248491aSJiri Olsa 	disabled = alloc_percpu(int);
213e248491aSJiri Olsa 	if (!disabled)
214e248491aSJiri Olsa 		return -ENOMEM;
215e248491aSJiri Olsa 
216e248491aSJiri Olsa 	ops->disabled = disabled;
217e248491aSJiri Olsa 	control_ops_disable_all(ops);
218e248491aSJiri Olsa 	return 0;
219e248491aSJiri Olsa }
220e248491aSJiri Olsa 
221e248491aSJiri Olsa static void control_ops_free(struct ftrace_ops *ops)
222e248491aSJiri Olsa {
223e248491aSJiri Olsa 	free_percpu(ops->disabled);
224e248491aSJiri Olsa }
225e248491aSJiri Olsa 
2262b499381SSteven Rostedt static void update_global_ops(void)
227491d0dcfSSteven Rostedt {
228491d0dcfSSteven Rostedt 	ftrace_func_t func;
229491d0dcfSSteven Rostedt 
230491d0dcfSSteven Rostedt 	/*
231491d0dcfSSteven Rostedt 	 * If there's only one function registered, then call that
232491d0dcfSSteven Rostedt 	 * function directly. Otherwise, we need to iterate over the
233491d0dcfSSteven Rostedt 	 * registered callers.
234491d0dcfSSteven Rostedt 	 */
235b848914cSSteven Rostedt 	if (ftrace_global_list == &ftrace_list_end ||
23663503794SSteven Rostedt 	    ftrace_global_list->next == &ftrace_list_end) {
237b848914cSSteven Rostedt 		func = ftrace_global_list->func;
23863503794SSteven Rostedt 		/*
23963503794SSteven Rostedt 		 * As we are calling the function directly.
24063503794SSteven Rostedt 		 * If it does not have recursion protection,
24163503794SSteven Rostedt 		 * the function_trace_op needs to be updated
24263503794SSteven Rostedt 		 * accordingly.
24363503794SSteven Rostedt 		 */
24463503794SSteven Rostedt 		if (ftrace_global_list->flags & FTRACE_OPS_FL_RECURSION_SAFE)
24563503794SSteven Rostedt 			global_ops.flags |= FTRACE_OPS_FL_RECURSION_SAFE;
246491d0dcfSSteven Rostedt 		else
24763503794SSteven Rostedt 			global_ops.flags &= ~FTRACE_OPS_FL_RECURSION_SAFE;
24863503794SSteven Rostedt 	} else {
249b848914cSSteven Rostedt 		func = ftrace_global_list_func;
25063503794SSteven Rostedt 		/* The list has its own recursion protection. */
25163503794SSteven Rostedt 		global_ops.flags |= FTRACE_OPS_FL_RECURSION_SAFE;
25263503794SSteven Rostedt 	}
25363503794SSteven Rostedt 
254491d0dcfSSteven Rostedt 
255491d0dcfSSteven Rostedt 	/* If we filter on pids, update to use the pid function */
256491d0dcfSSteven Rostedt 	if (!list_empty(&ftrace_pids)) {
257491d0dcfSSteven Rostedt 		set_ftrace_pid_function(func);
258491d0dcfSSteven Rostedt 		func = ftrace_pid_func;
259491d0dcfSSteven Rostedt 	}
2602b499381SSteven Rostedt 
2612b499381SSteven Rostedt 	global_ops.func = func;
2622b499381SSteven Rostedt }
2632b499381SSteven Rostedt 
2642b499381SSteven Rostedt static void update_ftrace_function(void)
2652b499381SSteven Rostedt {
2662b499381SSteven Rostedt 	ftrace_func_t func;
2672b499381SSteven Rostedt 
2682b499381SSteven Rostedt 	update_global_ops();
2692b499381SSteven Rostedt 
270cdbe61bfSSteven Rostedt 	/*
271cdbe61bfSSteven Rostedt 	 * If we are at the end of the list and this ops is
2724740974aSSteven Rostedt 	 * recursion safe and not dynamic and the arch supports passing ops,
2734740974aSSteven Rostedt 	 * then have the mcount trampoline call the function directly.
274cdbe61bfSSteven Rostedt 	 */
275b848914cSSteven Rostedt 	if (ftrace_ops_list == &ftrace_list_end ||
276cdbe61bfSSteven Rostedt 	    (ftrace_ops_list->next == &ftrace_list_end &&
2772f5f6ad9SSteven Rostedt 	     !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC) &&
2784740974aSSteven Rostedt 	     (ftrace_ops_list->flags & FTRACE_OPS_FL_RECURSION_SAFE) &&
279ccf3672dSSteven Rostedt 	     !FTRACE_FORCE_LIST_FUNC)) {
2802f5f6ad9SSteven Rostedt 		/* Set the ftrace_ops that the arch callback uses */
2812f5f6ad9SSteven Rostedt 		if (ftrace_ops_list == &global_ops)
2822f5f6ad9SSteven Rostedt 			function_trace_op = ftrace_global_list;
283b848914cSSteven Rostedt 		else
2842f5f6ad9SSteven Rostedt 			function_trace_op = ftrace_ops_list;
2852f5f6ad9SSteven Rostedt 		func = ftrace_ops_list->func;
2862f5f6ad9SSteven Rostedt 	} else {
2872f5f6ad9SSteven Rostedt 		/* Just use the default ftrace_ops */
2882f5f6ad9SSteven Rostedt 		function_trace_op = &ftrace_list_end;
289b848914cSSteven Rostedt 		func = ftrace_ops_list_func;
2902f5f6ad9SSteven Rostedt 	}
2912b499381SSteven Rostedt 
292491d0dcfSSteven Rostedt 	ftrace_trace_function = func;
293491d0dcfSSteven Rostedt }
294491d0dcfSSteven Rostedt 
2952b499381SSteven Rostedt static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
2963d083395SSteven Rostedt {
2972b499381SSteven Rostedt 	ops->next = *list;
29816444a8aSArnaldo Carvalho de Melo 	/*
299b848914cSSteven Rostedt 	 * We are entering ops into the list but another
30016444a8aSArnaldo Carvalho de Melo 	 * CPU might be walking that list. We need to make sure
30116444a8aSArnaldo Carvalho de Melo 	 * the ops->next pointer is valid before another CPU sees
302b848914cSSteven Rostedt 	 * the ops pointer included into the list.
30316444a8aSArnaldo Carvalho de Melo 	 */
3042b499381SSteven Rostedt 	rcu_assign_pointer(*list, ops);
3052b499381SSteven Rostedt }
3063d083395SSteven Rostedt 
3072b499381SSteven Rostedt static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
3082b499381SSteven Rostedt {
3092b499381SSteven Rostedt 	struct ftrace_ops **p;
3102b499381SSteven Rostedt 
3112b499381SSteven Rostedt 	/*
3122b499381SSteven Rostedt 	 * If we are removing the last function, then simply point
3132b499381SSteven Rostedt 	 * to the ftrace_stub.
3142b499381SSteven Rostedt 	 */
3152b499381SSteven Rostedt 	if (*list == ops && ops->next == &ftrace_list_end) {
3162b499381SSteven Rostedt 		*list = &ftrace_list_end;
3172b499381SSteven Rostedt 		return 0;
3182b499381SSteven Rostedt 	}
3192b499381SSteven Rostedt 
3202b499381SSteven Rostedt 	for (p = list; *p != &ftrace_list_end; p = &(*p)->next)
3212b499381SSteven Rostedt 		if (*p == ops)
3222b499381SSteven Rostedt 			break;
3232b499381SSteven Rostedt 
3242b499381SSteven Rostedt 	if (*p != ops)
3252b499381SSteven Rostedt 		return -1;
3262b499381SSteven Rostedt 
3272b499381SSteven Rostedt 	*p = (*p)->next;
3282b499381SSteven Rostedt 	return 0;
3292b499381SSteven Rostedt }
3302b499381SSteven Rostedt 
331e248491aSJiri Olsa static void add_ftrace_list_ops(struct ftrace_ops **list,
332e248491aSJiri Olsa 				struct ftrace_ops *main_ops,
333e248491aSJiri Olsa 				struct ftrace_ops *ops)
334e248491aSJiri Olsa {
335e248491aSJiri Olsa 	int first = *list == &ftrace_list_end;
336e248491aSJiri Olsa 	add_ftrace_ops(list, ops);
337e248491aSJiri Olsa 	if (first)
338e248491aSJiri Olsa 		add_ftrace_ops(&ftrace_ops_list, main_ops);
339e248491aSJiri Olsa }
340e248491aSJiri Olsa 
341e248491aSJiri Olsa static int remove_ftrace_list_ops(struct ftrace_ops **list,
342e248491aSJiri Olsa 				  struct ftrace_ops *main_ops,
343e248491aSJiri Olsa 				  struct ftrace_ops *ops)
344e248491aSJiri Olsa {
345e248491aSJiri Olsa 	int ret = remove_ftrace_ops(list, ops);
346e248491aSJiri Olsa 	if (!ret && *list == &ftrace_list_end)
347e248491aSJiri Olsa 		ret = remove_ftrace_ops(&ftrace_ops_list, main_ops);
348e248491aSJiri Olsa 	return ret;
349e248491aSJiri Olsa }
350e248491aSJiri Olsa 
3512b499381SSteven Rostedt static int __register_ftrace_function(struct ftrace_ops *ops)
3522b499381SSteven Rostedt {
3538d240dd8SBorislav Petkov 	if (unlikely(ftrace_disabled))
3542b499381SSteven Rostedt 		return -ENODEV;
3552b499381SSteven Rostedt 
3562b499381SSteven Rostedt 	if (FTRACE_WARN_ON(ops == &global_ops))
3572b499381SSteven Rostedt 		return -EINVAL;
3582b499381SSteven Rostedt 
359b848914cSSteven Rostedt 	if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED))
360b848914cSSteven Rostedt 		return -EBUSY;
361b848914cSSteven Rostedt 
362e248491aSJiri Olsa 	/* We don't support both control and global flags set. */
363e248491aSJiri Olsa 	if ((ops->flags & FL_GLOBAL_CONTROL_MASK) == FL_GLOBAL_CONTROL_MASK)
364e248491aSJiri Olsa 		return -EINVAL;
365e248491aSJiri Olsa 
36606aeaaeaSMasami Hiramatsu #ifndef CONFIG_DYNAMIC_FTRACE_WITH_REGS
36708f6fba5SSteven Rostedt 	/*
36808f6fba5SSteven Rostedt 	 * If the ftrace_ops specifies SAVE_REGS, then it only can be used
36908f6fba5SSteven Rostedt 	 * if the arch supports it, or SAVE_REGS_IF_SUPPORTED is also set.
37008f6fba5SSteven Rostedt 	 * Setting SAVE_REGS_IF_SUPPORTED makes SAVE_REGS irrelevant.
37108f6fba5SSteven Rostedt 	 */
37208f6fba5SSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_SAVE_REGS &&
37308f6fba5SSteven Rostedt 	    !(ops->flags & FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED))
37408f6fba5SSteven Rostedt 		return -EINVAL;
37508f6fba5SSteven Rostedt 
37608f6fba5SSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED)
37708f6fba5SSteven Rostedt 		ops->flags |= FTRACE_OPS_FL_SAVE_REGS;
37808f6fba5SSteven Rostedt #endif
37908f6fba5SSteven Rostedt 
380cdbe61bfSSteven Rostedt 	if (!core_kernel_data((unsigned long)ops))
381cdbe61bfSSteven Rostedt 		ops->flags |= FTRACE_OPS_FL_DYNAMIC;
382cdbe61bfSSteven Rostedt 
383b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
384e248491aSJiri Olsa 		add_ftrace_list_ops(&ftrace_global_list, &global_ops, ops);
385b848914cSSteven Rostedt 		ops->flags |= FTRACE_OPS_FL_ENABLED;
386e248491aSJiri Olsa 	} else if (ops->flags & FTRACE_OPS_FL_CONTROL) {
387e248491aSJiri Olsa 		if (control_ops_alloc(ops))
388e248491aSJiri Olsa 			return -ENOMEM;
389e248491aSJiri Olsa 		add_ftrace_list_ops(&ftrace_control_list, &control_ops, ops);
390b848914cSSteven Rostedt 	} else
391b848914cSSteven Rostedt 		add_ftrace_ops(&ftrace_ops_list, ops);
392b848914cSSteven Rostedt 
393491d0dcfSSteven Rostedt 	if (ftrace_enabled)
394491d0dcfSSteven Rostedt 		update_ftrace_function();
3953d083395SSteven Rostedt 
39616444a8aSArnaldo Carvalho de Melo 	return 0;
39716444a8aSArnaldo Carvalho de Melo }
39816444a8aSArnaldo Carvalho de Melo 
399e309b41dSIngo Molnar static int __unregister_ftrace_function(struct ftrace_ops *ops)
40016444a8aSArnaldo Carvalho de Melo {
4012b499381SSteven Rostedt 	int ret;
40216444a8aSArnaldo Carvalho de Melo 
4032b499381SSteven Rostedt 	if (ftrace_disabled)
4042b499381SSteven Rostedt 		return -ENODEV;
40516444a8aSArnaldo Carvalho de Melo 
406b848914cSSteven Rostedt 	if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
407b848914cSSteven Rostedt 		return -EBUSY;
408b848914cSSteven Rostedt 
4092b499381SSteven Rostedt 	if (FTRACE_WARN_ON(ops == &global_ops))
4102b499381SSteven Rostedt 		return -EINVAL;
41116444a8aSArnaldo Carvalho de Melo 
412b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
413e248491aSJiri Olsa 		ret = remove_ftrace_list_ops(&ftrace_global_list,
414e248491aSJiri Olsa 					     &global_ops, ops);
415b848914cSSteven Rostedt 		if (!ret)
416b848914cSSteven Rostedt 			ops->flags &= ~FTRACE_OPS_FL_ENABLED;
417e248491aSJiri Olsa 	} else if (ops->flags & FTRACE_OPS_FL_CONTROL) {
418e248491aSJiri Olsa 		ret = remove_ftrace_list_ops(&ftrace_control_list,
419e248491aSJiri Olsa 					     &control_ops, ops);
420e248491aSJiri Olsa 		if (!ret) {
421e248491aSJiri Olsa 			/*
422e248491aSJiri Olsa 			 * The ftrace_ops is now removed from the list,
423e248491aSJiri Olsa 			 * so there'll be no new users. We must ensure
424e248491aSJiri Olsa 			 * all current users are done before we free
425e248491aSJiri Olsa 			 * the control data.
426e248491aSJiri Olsa 			 */
427e248491aSJiri Olsa 			synchronize_sched();
428e248491aSJiri Olsa 			control_ops_free(ops);
429e248491aSJiri Olsa 		}
430b848914cSSteven Rostedt 	} else
431b848914cSSteven Rostedt 		ret = remove_ftrace_ops(&ftrace_ops_list, ops);
432b848914cSSteven Rostedt 
4332b499381SSteven Rostedt 	if (ret < 0)
4342b499381SSteven Rostedt 		return ret;
435b848914cSSteven Rostedt 
436491d0dcfSSteven Rostedt 	if (ftrace_enabled)
437491d0dcfSSteven Rostedt 		update_ftrace_function();
43816444a8aSArnaldo Carvalho de Melo 
439cdbe61bfSSteven Rostedt 	/*
440cdbe61bfSSteven Rostedt 	 * Dynamic ops may be freed, we must make sure that all
441cdbe61bfSSteven Rostedt 	 * callers are done before leaving this function.
442cdbe61bfSSteven Rostedt 	 */
443cdbe61bfSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
444cdbe61bfSSteven Rostedt 		synchronize_sched();
445cdbe61bfSSteven Rostedt 
446e6ea44e9SSteven Rostedt 	return 0;
4473d083395SSteven Rostedt }
4483d083395SSteven Rostedt 
449df4fc315SSteven Rostedt static void ftrace_update_pid_func(void)
450df4fc315SSteven Rostedt {
451491d0dcfSSteven Rostedt 	/* Only do something if we are tracing something */
452df4fc315SSteven Rostedt 	if (ftrace_trace_function == ftrace_stub)
45310dd3ebeSKOSAKI Motohiro 		return;
454df4fc315SSteven Rostedt 
455491d0dcfSSteven Rostedt 	update_ftrace_function();
456df4fc315SSteven Rostedt }
457df4fc315SSteven Rostedt 
458493762fcSSteven Rostedt #ifdef CONFIG_FUNCTION_PROFILER
459493762fcSSteven Rostedt struct ftrace_profile {
460493762fcSSteven Rostedt 	struct hlist_node		node;
461493762fcSSteven Rostedt 	unsigned long			ip;
462493762fcSSteven Rostedt 	unsigned long			counter;
4630706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
4640706f1c4SSteven Rostedt 	unsigned long long		time;
465e330b3bcSChase Douglas 	unsigned long long		time_squared;
4660706f1c4SSteven Rostedt #endif
467493762fcSSteven Rostedt };
468493762fcSSteven Rostedt 
469493762fcSSteven Rostedt struct ftrace_profile_page {
470493762fcSSteven Rostedt 	struct ftrace_profile_page	*next;
471493762fcSSteven Rostedt 	unsigned long			index;
472493762fcSSteven Rostedt 	struct ftrace_profile		records[];
473493762fcSSteven Rostedt };
474493762fcSSteven Rostedt 
475cafb168aSSteven Rostedt struct ftrace_profile_stat {
476cafb168aSSteven Rostedt 	atomic_t			disabled;
477cafb168aSSteven Rostedt 	struct hlist_head		*hash;
478cafb168aSSteven Rostedt 	struct ftrace_profile_page	*pages;
479cafb168aSSteven Rostedt 	struct ftrace_profile_page	*start;
480cafb168aSSteven Rostedt 	struct tracer_stat		stat;
481cafb168aSSteven Rostedt };
482cafb168aSSteven Rostedt 
483493762fcSSteven Rostedt #define PROFILE_RECORDS_SIZE						\
484493762fcSSteven Rostedt 	(PAGE_SIZE - offsetof(struct ftrace_profile_page, records))
485493762fcSSteven Rostedt 
486493762fcSSteven Rostedt #define PROFILES_PER_PAGE					\
487493762fcSSteven Rostedt 	(PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile))
488493762fcSSteven Rostedt 
489fb9fb015SSteven Rostedt static int ftrace_profile_bits __read_mostly;
490fb9fb015SSteven Rostedt static int ftrace_profile_enabled __read_mostly;
491fb9fb015SSteven Rostedt 
492fb9fb015SSteven Rostedt /* ftrace_profile_lock - synchronize the enable and disable of the profiler */
493493762fcSSteven Rostedt static DEFINE_MUTEX(ftrace_profile_lock);
494493762fcSSteven Rostedt 
495cafb168aSSteven Rostedt static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats);
496493762fcSSteven Rostedt 
497493762fcSSteven Rostedt #define FTRACE_PROFILE_HASH_SIZE 1024 /* must be power of 2 */
498493762fcSSteven Rostedt 
499493762fcSSteven Rostedt static void *
500493762fcSSteven Rostedt function_stat_next(void *v, int idx)
501493762fcSSteven Rostedt {
502493762fcSSteven Rostedt 	struct ftrace_profile *rec = v;
503493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
504493762fcSSteven Rostedt 
505493762fcSSteven Rostedt 	pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK);
506493762fcSSteven Rostedt 
507493762fcSSteven Rostedt  again:
5080296e425SLi Zefan 	if (idx != 0)
509493762fcSSteven Rostedt 		rec++;
5100296e425SLi Zefan 
511493762fcSSteven Rostedt 	if ((void *)rec >= (void *)&pg->records[pg->index]) {
512493762fcSSteven Rostedt 		pg = pg->next;
513493762fcSSteven Rostedt 		if (!pg)
514493762fcSSteven Rostedt 			return NULL;
515493762fcSSteven Rostedt 		rec = &pg->records[0];
516493762fcSSteven Rostedt 		if (!rec->counter)
517493762fcSSteven Rostedt 			goto again;
518493762fcSSteven Rostedt 	}
519493762fcSSteven Rostedt 
520493762fcSSteven Rostedt 	return rec;
521493762fcSSteven Rostedt }
522493762fcSSteven Rostedt 
523493762fcSSteven Rostedt static void *function_stat_start(struct tracer_stat *trace)
524493762fcSSteven Rostedt {
525cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat =
526cafb168aSSteven Rostedt 		container_of(trace, struct ftrace_profile_stat, stat);
527cafb168aSSteven Rostedt 
528cafb168aSSteven Rostedt 	if (!stat || !stat->start)
529cafb168aSSteven Rostedt 		return NULL;
530cafb168aSSteven Rostedt 
531cafb168aSSteven Rostedt 	return function_stat_next(&stat->start->records[0], 0);
532493762fcSSteven Rostedt }
533493762fcSSteven Rostedt 
5340706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
5350706f1c4SSteven Rostedt /* function graph compares on total time */
5360706f1c4SSteven Rostedt static int function_stat_cmp(void *p1, void *p2)
5370706f1c4SSteven Rostedt {
5380706f1c4SSteven Rostedt 	struct ftrace_profile *a = p1;
5390706f1c4SSteven Rostedt 	struct ftrace_profile *b = p2;
5400706f1c4SSteven Rostedt 
5410706f1c4SSteven Rostedt 	if (a->time < b->time)
5420706f1c4SSteven Rostedt 		return -1;
5430706f1c4SSteven Rostedt 	if (a->time > b->time)
5440706f1c4SSteven Rostedt 		return 1;
5450706f1c4SSteven Rostedt 	else
5460706f1c4SSteven Rostedt 		return 0;
5470706f1c4SSteven Rostedt }
5480706f1c4SSteven Rostedt #else
5490706f1c4SSteven Rostedt /* not function graph compares against hits */
550493762fcSSteven Rostedt static int function_stat_cmp(void *p1, void *p2)
551493762fcSSteven Rostedt {
552493762fcSSteven Rostedt 	struct ftrace_profile *a = p1;
553493762fcSSteven Rostedt 	struct ftrace_profile *b = p2;
554493762fcSSteven Rostedt 
555493762fcSSteven Rostedt 	if (a->counter < b->counter)
556493762fcSSteven Rostedt 		return -1;
557493762fcSSteven Rostedt 	if (a->counter > b->counter)
558493762fcSSteven Rostedt 		return 1;
559493762fcSSteven Rostedt 	else
560493762fcSSteven Rostedt 		return 0;
561493762fcSSteven Rostedt }
5620706f1c4SSteven Rostedt #endif
563493762fcSSteven Rostedt 
564493762fcSSteven Rostedt static int function_stat_headers(struct seq_file *m)
565493762fcSSteven Rostedt {
5660706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
56734886c8bSSteven Rostedt 	seq_printf(m, "  Function                               "
568e330b3bcSChase Douglas 		   "Hit    Time            Avg             s^2\n"
56934886c8bSSteven Rostedt 		      "  --------                               "
570e330b3bcSChase Douglas 		   "---    ----            ---             ---\n");
5710706f1c4SSteven Rostedt #else
572493762fcSSteven Rostedt 	seq_printf(m, "  Function                               Hit\n"
573493762fcSSteven Rostedt 		      "  --------                               ---\n");
5740706f1c4SSteven Rostedt #endif
575493762fcSSteven Rostedt 	return 0;
576493762fcSSteven Rostedt }
577493762fcSSteven Rostedt 
578493762fcSSteven Rostedt static int function_stat_show(struct seq_file *m, void *v)
579493762fcSSteven Rostedt {
580493762fcSSteven Rostedt 	struct ftrace_profile *rec = v;
581493762fcSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
5823aaba20fSLi Zefan 	int ret = 0;
5830706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
58434886c8bSSteven Rostedt 	static struct trace_seq s;
58534886c8bSSteven Rostedt 	unsigned long long avg;
586e330b3bcSChase Douglas 	unsigned long long stddev;
5870706f1c4SSteven Rostedt #endif
5883aaba20fSLi Zefan 	mutex_lock(&ftrace_profile_lock);
5893aaba20fSLi Zefan 
5903aaba20fSLi Zefan 	/* we raced with function_profile_reset() */
5913aaba20fSLi Zefan 	if (unlikely(rec->counter == 0)) {
5923aaba20fSLi Zefan 		ret = -EBUSY;
5933aaba20fSLi Zefan 		goto out;
5943aaba20fSLi Zefan 	}
595493762fcSSteven Rostedt 
596493762fcSSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
5970706f1c4SSteven Rostedt 	seq_printf(m, "  %-30.30s  %10lu", str, rec->counter);
598493762fcSSteven Rostedt 
5990706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
6000706f1c4SSteven Rostedt 	seq_printf(m, "    ");
60134886c8bSSteven Rostedt 	avg = rec->time;
60234886c8bSSteven Rostedt 	do_div(avg, rec->counter);
60334886c8bSSteven Rostedt 
604e330b3bcSChase Douglas 	/* Sample standard deviation (s^2) */
605e330b3bcSChase Douglas 	if (rec->counter <= 1)
606e330b3bcSChase Douglas 		stddev = 0;
607e330b3bcSChase Douglas 	else {
608e330b3bcSChase Douglas 		stddev = rec->time_squared - rec->counter * avg * avg;
609e330b3bcSChase Douglas 		/*
610e330b3bcSChase Douglas 		 * Divide only 1000 for ns^2 -> us^2 conversion.
611e330b3bcSChase Douglas 		 * trace_print_graph_duration will divide 1000 again.
612e330b3bcSChase Douglas 		 */
613e330b3bcSChase Douglas 		do_div(stddev, (rec->counter - 1) * 1000);
614e330b3bcSChase Douglas 	}
615e330b3bcSChase Douglas 
61634886c8bSSteven Rostedt 	trace_seq_init(&s);
61734886c8bSSteven Rostedt 	trace_print_graph_duration(rec->time, &s);
61834886c8bSSteven Rostedt 	trace_seq_puts(&s, "    ");
61934886c8bSSteven Rostedt 	trace_print_graph_duration(avg, &s);
620e330b3bcSChase Douglas 	trace_seq_puts(&s, "    ");
621e330b3bcSChase Douglas 	trace_print_graph_duration(stddev, &s);
6220706f1c4SSteven Rostedt 	trace_print_seq(m, &s);
6230706f1c4SSteven Rostedt #endif
6240706f1c4SSteven Rostedt 	seq_putc(m, '\n');
6253aaba20fSLi Zefan out:
6263aaba20fSLi Zefan 	mutex_unlock(&ftrace_profile_lock);
6270706f1c4SSteven Rostedt 
6283aaba20fSLi Zefan 	return ret;
629493762fcSSteven Rostedt }
630493762fcSSteven Rostedt 
631cafb168aSSteven Rostedt static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
632493762fcSSteven Rostedt {
633493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
634493762fcSSteven Rostedt 
635cafb168aSSteven Rostedt 	pg = stat->pages = stat->start;
636493762fcSSteven Rostedt 
637493762fcSSteven Rostedt 	while (pg) {
638493762fcSSteven Rostedt 		memset(pg->records, 0, PROFILE_RECORDS_SIZE);
639493762fcSSteven Rostedt 		pg->index = 0;
640493762fcSSteven Rostedt 		pg = pg->next;
641493762fcSSteven Rostedt 	}
642493762fcSSteven Rostedt 
643cafb168aSSteven Rostedt 	memset(stat->hash, 0,
644493762fcSSteven Rostedt 	       FTRACE_PROFILE_HASH_SIZE * sizeof(struct hlist_head));
645493762fcSSteven Rostedt }
646493762fcSSteven Rostedt 
647cafb168aSSteven Rostedt int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)
648493762fcSSteven Rostedt {
649493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
650318e0a73SSteven Rostedt 	int functions;
651318e0a73SSteven Rostedt 	int pages;
652493762fcSSteven Rostedt 	int i;
653493762fcSSteven Rostedt 
654493762fcSSteven Rostedt 	/* If we already allocated, do nothing */
655cafb168aSSteven Rostedt 	if (stat->pages)
656493762fcSSteven Rostedt 		return 0;
657493762fcSSteven Rostedt 
658cafb168aSSteven Rostedt 	stat->pages = (void *)get_zeroed_page(GFP_KERNEL);
659cafb168aSSteven Rostedt 	if (!stat->pages)
660493762fcSSteven Rostedt 		return -ENOMEM;
661493762fcSSteven Rostedt 
662318e0a73SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE
663318e0a73SSteven Rostedt 	functions = ftrace_update_tot_cnt;
664318e0a73SSteven Rostedt #else
665318e0a73SSteven Rostedt 	/*
666318e0a73SSteven Rostedt 	 * We do not know the number of functions that exist because
667318e0a73SSteven Rostedt 	 * dynamic tracing is what counts them. With past experience
668318e0a73SSteven Rostedt 	 * we have around 20K functions. That should be more than enough.
669318e0a73SSteven Rostedt 	 * It is highly unlikely we will execute every function in
670318e0a73SSteven Rostedt 	 * the kernel.
671318e0a73SSteven Rostedt 	 */
672318e0a73SSteven Rostedt 	functions = 20000;
673318e0a73SSteven Rostedt #endif
674318e0a73SSteven Rostedt 
675cafb168aSSteven Rostedt 	pg = stat->start = stat->pages;
676493762fcSSteven Rostedt 
677318e0a73SSteven Rostedt 	pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE);
678318e0a73SSteven Rostedt 
67939e30cd1SNamhyung Kim 	for (i = 1; i < pages; i++) {
680493762fcSSteven Rostedt 		pg->next = (void *)get_zeroed_page(GFP_KERNEL);
681493762fcSSteven Rostedt 		if (!pg->next)
682318e0a73SSteven Rostedt 			goto out_free;
683493762fcSSteven Rostedt 		pg = pg->next;
684493762fcSSteven Rostedt 	}
685493762fcSSteven Rostedt 
686493762fcSSteven Rostedt 	return 0;
687318e0a73SSteven Rostedt 
688318e0a73SSteven Rostedt  out_free:
689318e0a73SSteven Rostedt 	pg = stat->start;
690318e0a73SSteven Rostedt 	while (pg) {
691318e0a73SSteven Rostedt 		unsigned long tmp = (unsigned long)pg;
692318e0a73SSteven Rostedt 
693318e0a73SSteven Rostedt 		pg = pg->next;
694318e0a73SSteven Rostedt 		free_page(tmp);
695318e0a73SSteven Rostedt 	}
696318e0a73SSteven Rostedt 
697318e0a73SSteven Rostedt 	free_page((unsigned long)stat->pages);
698318e0a73SSteven Rostedt 	stat->pages = NULL;
699318e0a73SSteven Rostedt 	stat->start = NULL;
700318e0a73SSteven Rostedt 
701318e0a73SSteven Rostedt 	return -ENOMEM;
702493762fcSSteven Rostedt }
703493762fcSSteven Rostedt 
704cafb168aSSteven Rostedt static int ftrace_profile_init_cpu(int cpu)
705493762fcSSteven Rostedt {
706cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
707493762fcSSteven Rostedt 	int size;
708493762fcSSteven Rostedt 
709cafb168aSSteven Rostedt 	stat = &per_cpu(ftrace_profile_stats, cpu);
710cafb168aSSteven Rostedt 
711cafb168aSSteven Rostedt 	if (stat->hash) {
712493762fcSSteven Rostedt 		/* If the profile is already created, simply reset it */
713cafb168aSSteven Rostedt 		ftrace_profile_reset(stat);
714493762fcSSteven Rostedt 		return 0;
715493762fcSSteven Rostedt 	}
716493762fcSSteven Rostedt 
717493762fcSSteven Rostedt 	/*
718493762fcSSteven Rostedt 	 * We are profiling all functions, but usually only a few thousand
719493762fcSSteven Rostedt 	 * functions are hit. We'll make a hash of 1024 items.
720493762fcSSteven Rostedt 	 */
721493762fcSSteven Rostedt 	size = FTRACE_PROFILE_HASH_SIZE;
722493762fcSSteven Rostedt 
723cafb168aSSteven Rostedt 	stat->hash = kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL);
724493762fcSSteven Rostedt 
725cafb168aSSteven Rostedt 	if (!stat->hash)
726493762fcSSteven Rostedt 		return -ENOMEM;
727493762fcSSteven Rostedt 
728cafb168aSSteven Rostedt 	if (!ftrace_profile_bits) {
729493762fcSSteven Rostedt 		size--;
730493762fcSSteven Rostedt 
731493762fcSSteven Rostedt 		for (; size; size >>= 1)
732493762fcSSteven Rostedt 			ftrace_profile_bits++;
733cafb168aSSteven Rostedt 	}
734493762fcSSteven Rostedt 
735318e0a73SSteven Rostedt 	/* Preallocate the function profiling pages */
736cafb168aSSteven Rostedt 	if (ftrace_profile_pages_init(stat) < 0) {
737cafb168aSSteven Rostedt 		kfree(stat->hash);
738cafb168aSSteven Rostedt 		stat->hash = NULL;
739493762fcSSteven Rostedt 		return -ENOMEM;
740493762fcSSteven Rostedt 	}
741493762fcSSteven Rostedt 
742493762fcSSteven Rostedt 	return 0;
743493762fcSSteven Rostedt }
744493762fcSSteven Rostedt 
745cafb168aSSteven Rostedt static int ftrace_profile_init(void)
746cafb168aSSteven Rostedt {
747cafb168aSSteven Rostedt 	int cpu;
748cafb168aSSteven Rostedt 	int ret = 0;
749cafb168aSSteven Rostedt 
750cafb168aSSteven Rostedt 	for_each_online_cpu(cpu) {
751cafb168aSSteven Rostedt 		ret = ftrace_profile_init_cpu(cpu);
752cafb168aSSteven Rostedt 		if (ret)
753cafb168aSSteven Rostedt 			break;
754cafb168aSSteven Rostedt 	}
755cafb168aSSteven Rostedt 
756cafb168aSSteven Rostedt 	return ret;
757cafb168aSSteven Rostedt }
758cafb168aSSteven Rostedt 
759493762fcSSteven Rostedt /* interrupts must be disabled */
760cafb168aSSteven Rostedt static struct ftrace_profile *
761cafb168aSSteven Rostedt ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)
762493762fcSSteven Rostedt {
763493762fcSSteven Rostedt 	struct ftrace_profile *rec;
764493762fcSSteven Rostedt 	struct hlist_head *hhd;
765493762fcSSteven Rostedt 	struct hlist_node *n;
766493762fcSSteven Rostedt 	unsigned long key;
767493762fcSSteven Rostedt 
768493762fcSSteven Rostedt 	key = hash_long(ip, ftrace_profile_bits);
769cafb168aSSteven Rostedt 	hhd = &stat->hash[key];
770493762fcSSteven Rostedt 
771493762fcSSteven Rostedt 	if (hlist_empty(hhd))
772493762fcSSteven Rostedt 		return NULL;
773493762fcSSteven Rostedt 
774493762fcSSteven Rostedt 	hlist_for_each_entry_rcu(rec, n, hhd, node) {
775493762fcSSteven Rostedt 		if (rec->ip == ip)
776493762fcSSteven Rostedt 			return rec;
777493762fcSSteven Rostedt 	}
778493762fcSSteven Rostedt 
779493762fcSSteven Rostedt 	return NULL;
780493762fcSSteven Rostedt }
781493762fcSSteven Rostedt 
782cafb168aSSteven Rostedt static void ftrace_add_profile(struct ftrace_profile_stat *stat,
783cafb168aSSteven Rostedt 			       struct ftrace_profile *rec)
784493762fcSSteven Rostedt {
785493762fcSSteven Rostedt 	unsigned long key;
786493762fcSSteven Rostedt 
787493762fcSSteven Rostedt 	key = hash_long(rec->ip, ftrace_profile_bits);
788cafb168aSSteven Rostedt 	hlist_add_head_rcu(&rec->node, &stat->hash[key]);
789493762fcSSteven Rostedt }
790493762fcSSteven Rostedt 
791318e0a73SSteven Rostedt /*
792318e0a73SSteven Rostedt  * The memory is already allocated, this simply finds a new record to use.
793318e0a73SSteven Rostedt  */
794493762fcSSteven Rostedt static struct ftrace_profile *
795318e0a73SSteven Rostedt ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)
796493762fcSSteven Rostedt {
797493762fcSSteven Rostedt 	struct ftrace_profile *rec = NULL;
798493762fcSSteven Rostedt 
799318e0a73SSteven Rostedt 	/* prevent recursion (from NMIs) */
800cafb168aSSteven Rostedt 	if (atomic_inc_return(&stat->disabled) != 1)
801493762fcSSteven Rostedt 		goto out;
802493762fcSSteven Rostedt 
803493762fcSSteven Rostedt 	/*
804318e0a73SSteven Rostedt 	 * Try to find the function again since an NMI
805318e0a73SSteven Rostedt 	 * could have added it
806493762fcSSteven Rostedt 	 */
807cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, ip);
808493762fcSSteven Rostedt 	if (rec)
809cafb168aSSteven Rostedt 		goto out;
810493762fcSSteven Rostedt 
811cafb168aSSteven Rostedt 	if (stat->pages->index == PROFILES_PER_PAGE) {
812cafb168aSSteven Rostedt 		if (!stat->pages->next)
813cafb168aSSteven Rostedt 			goto out;
814cafb168aSSteven Rostedt 		stat->pages = stat->pages->next;
815493762fcSSteven Rostedt 	}
816493762fcSSteven Rostedt 
817cafb168aSSteven Rostedt 	rec = &stat->pages->records[stat->pages->index++];
818493762fcSSteven Rostedt 	rec->ip = ip;
819cafb168aSSteven Rostedt 	ftrace_add_profile(stat, rec);
820493762fcSSteven Rostedt 
821493762fcSSteven Rostedt  out:
822cafb168aSSteven Rostedt 	atomic_dec(&stat->disabled);
823493762fcSSteven Rostedt 
824493762fcSSteven Rostedt 	return rec;
825493762fcSSteven Rostedt }
826493762fcSSteven Rostedt 
827493762fcSSteven Rostedt static void
8282f5f6ad9SSteven Rostedt function_profile_call(unsigned long ip, unsigned long parent_ip,
829a1e2e31dSSteven Rostedt 		      struct ftrace_ops *ops, struct pt_regs *regs)
830493762fcSSteven Rostedt {
831cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
832493762fcSSteven Rostedt 	struct ftrace_profile *rec;
833493762fcSSteven Rostedt 	unsigned long flags;
834493762fcSSteven Rostedt 
835493762fcSSteven Rostedt 	if (!ftrace_profile_enabled)
836493762fcSSteven Rostedt 		return;
837493762fcSSteven Rostedt 
838493762fcSSteven Rostedt 	local_irq_save(flags);
839cafb168aSSteven Rostedt 
840cafb168aSSteven Rostedt 	stat = &__get_cpu_var(ftrace_profile_stats);
8410f6ce3deSSteven Rostedt 	if (!stat->hash || !ftrace_profile_enabled)
842cafb168aSSteven Rostedt 		goto out;
843cafb168aSSteven Rostedt 
844cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, ip);
845493762fcSSteven Rostedt 	if (!rec) {
846318e0a73SSteven Rostedt 		rec = ftrace_profile_alloc(stat, ip);
847493762fcSSteven Rostedt 		if (!rec)
848493762fcSSteven Rostedt 			goto out;
849493762fcSSteven Rostedt 	}
850493762fcSSteven Rostedt 
851493762fcSSteven Rostedt 	rec->counter++;
852493762fcSSteven Rostedt  out:
853493762fcSSteven Rostedt 	local_irq_restore(flags);
854493762fcSSteven Rostedt }
855493762fcSSteven Rostedt 
8560706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
8570706f1c4SSteven Rostedt static int profile_graph_entry(struct ftrace_graph_ent *trace)
8580706f1c4SSteven Rostedt {
859a1e2e31dSSteven Rostedt 	function_profile_call(trace->func, 0, NULL, NULL);
8600706f1c4SSteven Rostedt 	return 1;
8610706f1c4SSteven Rostedt }
8620706f1c4SSteven Rostedt 
8630706f1c4SSteven Rostedt static void profile_graph_return(struct ftrace_graph_ret *trace)
8640706f1c4SSteven Rostedt {
865cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
866a2a16d6aSSteven Rostedt 	unsigned long long calltime;
8670706f1c4SSteven Rostedt 	struct ftrace_profile *rec;
868cafb168aSSteven Rostedt 	unsigned long flags;
8690706f1c4SSteven Rostedt 
8700706f1c4SSteven Rostedt 	local_irq_save(flags);
871cafb168aSSteven Rostedt 	stat = &__get_cpu_var(ftrace_profile_stats);
8720f6ce3deSSteven Rostedt 	if (!stat->hash || !ftrace_profile_enabled)
873cafb168aSSteven Rostedt 		goto out;
874cafb168aSSteven Rostedt 
87537e44bc5SSteven Rostedt 	/* If the calltime was zero'd ignore it */
87637e44bc5SSteven Rostedt 	if (!trace->calltime)
87737e44bc5SSteven Rostedt 		goto out;
87837e44bc5SSteven Rostedt 
879a2a16d6aSSteven Rostedt 	calltime = trace->rettime - trace->calltime;
880a2a16d6aSSteven Rostedt 
881a2a16d6aSSteven Rostedt 	if (!(trace_flags & TRACE_ITER_GRAPH_TIME)) {
882a2a16d6aSSteven Rostedt 		int index;
883a2a16d6aSSteven Rostedt 
884a2a16d6aSSteven Rostedt 		index = trace->depth;
885a2a16d6aSSteven Rostedt 
886a2a16d6aSSteven Rostedt 		/* Append this call time to the parent time to subtract */
887a2a16d6aSSteven Rostedt 		if (index)
888a2a16d6aSSteven Rostedt 			current->ret_stack[index - 1].subtime += calltime;
889a2a16d6aSSteven Rostedt 
890a2a16d6aSSteven Rostedt 		if (current->ret_stack[index].subtime < calltime)
891a2a16d6aSSteven Rostedt 			calltime -= current->ret_stack[index].subtime;
892a2a16d6aSSteven Rostedt 		else
893a2a16d6aSSteven Rostedt 			calltime = 0;
894a2a16d6aSSteven Rostedt 	}
895a2a16d6aSSteven Rostedt 
896cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, trace->func);
897e330b3bcSChase Douglas 	if (rec) {
898a2a16d6aSSteven Rostedt 		rec->time += calltime;
899e330b3bcSChase Douglas 		rec->time_squared += calltime * calltime;
900e330b3bcSChase Douglas 	}
901a2a16d6aSSteven Rostedt 
902cafb168aSSteven Rostedt  out:
9030706f1c4SSteven Rostedt 	local_irq_restore(flags);
9040706f1c4SSteven Rostedt }
9050706f1c4SSteven Rostedt 
9060706f1c4SSteven Rostedt static int register_ftrace_profiler(void)
9070706f1c4SSteven Rostedt {
9080706f1c4SSteven Rostedt 	return register_ftrace_graph(&profile_graph_return,
9090706f1c4SSteven Rostedt 				     &profile_graph_entry);
9100706f1c4SSteven Rostedt }
9110706f1c4SSteven Rostedt 
9120706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void)
9130706f1c4SSteven Rostedt {
9140706f1c4SSteven Rostedt 	unregister_ftrace_graph();
9150706f1c4SSteven Rostedt }
9160706f1c4SSteven Rostedt #else
917bd38c0e6SPaul McQuade static struct ftrace_ops ftrace_profile_ops __read_mostly = {
918493762fcSSteven Rostedt 	.func		= function_profile_call,
9194740974aSSteven Rostedt 	.flags		= FTRACE_OPS_FL_RECURSION_SAFE,
920493762fcSSteven Rostedt };
921493762fcSSteven Rostedt 
9220706f1c4SSteven Rostedt static int register_ftrace_profiler(void)
9230706f1c4SSteven Rostedt {
9240706f1c4SSteven Rostedt 	return register_ftrace_function(&ftrace_profile_ops);
9250706f1c4SSteven Rostedt }
9260706f1c4SSteven Rostedt 
9270706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void)
9280706f1c4SSteven Rostedt {
9290706f1c4SSteven Rostedt 	unregister_ftrace_function(&ftrace_profile_ops);
9300706f1c4SSteven Rostedt }
9310706f1c4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
9320706f1c4SSteven Rostedt 
933493762fcSSteven Rostedt static ssize_t
934493762fcSSteven Rostedt ftrace_profile_write(struct file *filp, const char __user *ubuf,
935493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
936493762fcSSteven Rostedt {
937493762fcSSteven Rostedt 	unsigned long val;
938493762fcSSteven Rostedt 	int ret;
939493762fcSSteven Rostedt 
94022fe9b54SPeter Huewe 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
94122fe9b54SPeter Huewe 	if (ret)
942493762fcSSteven Rostedt 		return ret;
943493762fcSSteven Rostedt 
944493762fcSSteven Rostedt 	val = !!val;
945493762fcSSteven Rostedt 
946493762fcSSteven Rostedt 	mutex_lock(&ftrace_profile_lock);
947493762fcSSteven Rostedt 	if (ftrace_profile_enabled ^ val) {
948493762fcSSteven Rostedt 		if (val) {
949493762fcSSteven Rostedt 			ret = ftrace_profile_init();
950493762fcSSteven Rostedt 			if (ret < 0) {
951493762fcSSteven Rostedt 				cnt = ret;
952493762fcSSteven Rostedt 				goto out;
953493762fcSSteven Rostedt 			}
954493762fcSSteven Rostedt 
9550706f1c4SSteven Rostedt 			ret = register_ftrace_profiler();
9560706f1c4SSteven Rostedt 			if (ret < 0) {
9570706f1c4SSteven Rostedt 				cnt = ret;
9580706f1c4SSteven Rostedt 				goto out;
9590706f1c4SSteven Rostedt 			}
960493762fcSSteven Rostedt 			ftrace_profile_enabled = 1;
961493762fcSSteven Rostedt 		} else {
962493762fcSSteven Rostedt 			ftrace_profile_enabled = 0;
9630f6ce3deSSteven Rostedt 			/*
9640f6ce3deSSteven Rostedt 			 * unregister_ftrace_profiler calls stop_machine
9650f6ce3deSSteven Rostedt 			 * so this acts like an synchronize_sched.
9660f6ce3deSSteven Rostedt 			 */
9670706f1c4SSteven Rostedt 			unregister_ftrace_profiler();
968493762fcSSteven Rostedt 		}
969493762fcSSteven Rostedt 	}
970493762fcSSteven Rostedt  out:
971493762fcSSteven Rostedt 	mutex_unlock(&ftrace_profile_lock);
972493762fcSSteven Rostedt 
973cf8517cfSJiri Olsa 	*ppos += cnt;
974493762fcSSteven Rostedt 
975493762fcSSteven Rostedt 	return cnt;
976493762fcSSteven Rostedt }
977493762fcSSteven Rostedt 
978493762fcSSteven Rostedt static ssize_t
979493762fcSSteven Rostedt ftrace_profile_read(struct file *filp, char __user *ubuf,
980493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
981493762fcSSteven Rostedt {
982fb9fb015SSteven Rostedt 	char buf[64];		/* big enough to hold a number */
983493762fcSSteven Rostedt 	int r;
984493762fcSSteven Rostedt 
985493762fcSSteven Rostedt 	r = sprintf(buf, "%u\n", ftrace_profile_enabled);
986493762fcSSteven Rostedt 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
987493762fcSSteven Rostedt }
988493762fcSSteven Rostedt 
989493762fcSSteven Rostedt static const struct file_operations ftrace_profile_fops = {
990493762fcSSteven Rostedt 	.open		= tracing_open_generic,
991493762fcSSteven Rostedt 	.read		= ftrace_profile_read,
992493762fcSSteven Rostedt 	.write		= ftrace_profile_write,
9936038f373SArnd Bergmann 	.llseek		= default_llseek,
994493762fcSSteven Rostedt };
995493762fcSSteven Rostedt 
996cafb168aSSteven Rostedt /* used to initialize the real stat files */
997cafb168aSSteven Rostedt static struct tracer_stat function_stats __initdata = {
998cafb168aSSteven Rostedt 	.name		= "functions",
999cafb168aSSteven Rostedt 	.stat_start	= function_stat_start,
1000cafb168aSSteven Rostedt 	.stat_next	= function_stat_next,
1001cafb168aSSteven Rostedt 	.stat_cmp	= function_stat_cmp,
1002cafb168aSSteven Rostedt 	.stat_headers	= function_stat_headers,
1003cafb168aSSteven Rostedt 	.stat_show	= function_stat_show
1004cafb168aSSteven Rostedt };
1005cafb168aSSteven Rostedt 
10066ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
1007493762fcSSteven Rostedt {
1008cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
1009493762fcSSteven Rostedt 	struct dentry *entry;
1010cafb168aSSteven Rostedt 	char *name;
1011493762fcSSteven Rostedt 	int ret;
1012cafb168aSSteven Rostedt 	int cpu;
1013493762fcSSteven Rostedt 
1014cafb168aSSteven Rostedt 	for_each_possible_cpu(cpu) {
1015cafb168aSSteven Rostedt 		stat = &per_cpu(ftrace_profile_stats, cpu);
1016cafb168aSSteven Rostedt 
1017cafb168aSSteven Rostedt 		/* allocate enough for function name + cpu number */
1018cafb168aSSteven Rostedt 		name = kmalloc(32, GFP_KERNEL);
1019cafb168aSSteven Rostedt 		if (!name) {
1020cafb168aSSteven Rostedt 			/*
1021cafb168aSSteven Rostedt 			 * The files created are permanent, if something happens
1022cafb168aSSteven Rostedt 			 * we still do not free memory.
1023cafb168aSSteven Rostedt 			 */
1024cafb168aSSteven Rostedt 			WARN(1,
1025cafb168aSSteven Rostedt 			     "Could not allocate stat file for cpu %d\n",
1026cafb168aSSteven Rostedt 			     cpu);
1027493762fcSSteven Rostedt 			return;
1028493762fcSSteven Rostedt 		}
1029cafb168aSSteven Rostedt 		stat->stat = function_stats;
1030cafb168aSSteven Rostedt 		snprintf(name, 32, "function%d", cpu);
1031cafb168aSSteven Rostedt 		stat->stat.name = name;
1032cafb168aSSteven Rostedt 		ret = register_stat_tracer(&stat->stat);
1033cafb168aSSteven Rostedt 		if (ret) {
1034cafb168aSSteven Rostedt 			WARN(1,
1035cafb168aSSteven Rostedt 			     "Could not register function stat for cpu %d\n",
1036cafb168aSSteven Rostedt 			     cpu);
1037cafb168aSSteven Rostedt 			kfree(name);
1038cafb168aSSteven Rostedt 			return;
1039cafb168aSSteven Rostedt 		}
1040cafb168aSSteven Rostedt 	}
1041493762fcSSteven Rostedt 
1042493762fcSSteven Rostedt 	entry = debugfs_create_file("function_profile_enabled", 0644,
1043493762fcSSteven Rostedt 				    d_tracer, NULL, &ftrace_profile_fops);
1044493762fcSSteven Rostedt 	if (!entry)
1045493762fcSSteven Rostedt 		pr_warning("Could not create debugfs "
1046493762fcSSteven Rostedt 			   "'function_profile_enabled' entry\n");
1047493762fcSSteven Rostedt }
1048493762fcSSteven Rostedt 
1049493762fcSSteven Rostedt #else /* CONFIG_FUNCTION_PROFILER */
10506ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
1051493762fcSSteven Rostedt {
1052493762fcSSteven Rostedt }
1053493762fcSSteven Rostedt #endif /* CONFIG_FUNCTION_PROFILER */
1054493762fcSSteven Rostedt 
105573d3fd96SIngo Molnar static struct pid * const ftrace_swapper_pid = &init_struct_pid;
105673d3fd96SIngo Molnar 
10573d083395SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE
105873d3fd96SIngo Molnar 
105999ecdc43SSteven Rostedt #ifndef CONFIG_FTRACE_MCOUNT_RECORD
1060cb7be3b2SSteven Rostedt # error Dynamic ftrace depends on MCOUNT_RECORD
106199ecdc43SSteven Rostedt #endif
106299ecdc43SSteven Rostedt 
10638fc0c701SSteven Rostedt static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly;
10648fc0c701SSteven Rostedt 
1065b6887d79SSteven Rostedt struct ftrace_func_probe {
10668fc0c701SSteven Rostedt 	struct hlist_node	node;
1067b6887d79SSteven Rostedt 	struct ftrace_probe_ops	*ops;
10688fc0c701SSteven Rostedt 	unsigned long		flags;
10698fc0c701SSteven Rostedt 	unsigned long		ip;
10708fc0c701SSteven Rostedt 	void			*data;
10717818b388SSteven Rostedt (Red Hat) 	struct list_head	free_list;
10728fc0c701SSteven Rostedt };
10738fc0c701SSteven Rostedt 
1074b448c4e3SSteven Rostedt struct ftrace_func_entry {
1075b448c4e3SSteven Rostedt 	struct hlist_node hlist;
1076b448c4e3SSteven Rostedt 	unsigned long ip;
1077b448c4e3SSteven Rostedt };
1078b448c4e3SSteven Rostedt 
1079b448c4e3SSteven Rostedt struct ftrace_hash {
1080b448c4e3SSteven Rostedt 	unsigned long		size_bits;
1081b448c4e3SSteven Rostedt 	struct hlist_head	*buckets;
1082b448c4e3SSteven Rostedt 	unsigned long		count;
108307fd5515SSteven Rostedt 	struct rcu_head		rcu;
1084b448c4e3SSteven Rostedt };
1085b448c4e3SSteven Rostedt 
108633dc9b12SSteven Rostedt /*
108733dc9b12SSteven Rostedt  * We make these constant because no one should touch them,
108833dc9b12SSteven Rostedt  * but they are used as the default "empty hash", to avoid allocating
108933dc9b12SSteven Rostedt  * it all the time. These are in a read only section such that if
109033dc9b12SSteven Rostedt  * anyone does try to modify it, it will cause an exception.
109133dc9b12SSteven Rostedt  */
109233dc9b12SSteven Rostedt static const struct hlist_head empty_buckets[1];
109333dc9b12SSteven Rostedt static const struct ftrace_hash empty_hash = {
109433dc9b12SSteven Rostedt 	.buckets = (struct hlist_head *)empty_buckets,
1095b448c4e3SSteven Rostedt };
109633dc9b12SSteven Rostedt #define EMPTY_HASH	((struct ftrace_hash *)&empty_hash)
10975072c59fSSteven Rostedt 
10982b499381SSteven Rostedt static struct ftrace_ops global_ops = {
1099f45948e8SSteven Rostedt 	.func			= ftrace_stub,
110033dc9b12SSteven Rostedt 	.notrace_hash		= EMPTY_HASH,
110133dc9b12SSteven Rostedt 	.filter_hash		= EMPTY_HASH,
11024740974aSSteven Rostedt 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE,
1103f45948e8SSteven Rostedt };
1104f45948e8SSteven Rostedt 
110541c52c0dSSteven Rostedt static DEFINE_MUTEX(ftrace_regex_lock);
11063d083395SSteven Rostedt 
11073c1720f0SSteven Rostedt struct ftrace_page {
11083c1720f0SSteven Rostedt 	struct ftrace_page	*next;
1109a7900875SSteven Rostedt 	struct dyn_ftrace	*records;
1110431aa3fbSSteven Rostedt 	int			index;
1111a7900875SSteven Rostedt 	int			size;
1112aa5e5ceaSDavid Miller };
11133c1720f0SSteven Rostedt 
111485ae32aeSSteven Rostedt static struct ftrace_page *ftrace_new_pgs;
111585ae32aeSSteven Rostedt 
1116a7900875SSteven Rostedt #define ENTRY_SIZE sizeof(struct dyn_ftrace)
1117a7900875SSteven Rostedt #define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
11183c1720f0SSteven Rostedt 
11193c1720f0SSteven Rostedt /* estimate from running different kernels */
11203c1720f0SSteven Rostedt #define NR_TO_INIT		10000
11213c1720f0SSteven Rostedt 
11223c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages_start;
11233c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages;
11243c1720f0SSteven Rostedt 
112506a51d93SSteven Rostedt static bool ftrace_hash_empty(struct ftrace_hash *hash)
112606a51d93SSteven Rostedt {
112706a51d93SSteven Rostedt 	return !hash || !hash->count;
112806a51d93SSteven Rostedt }
112906a51d93SSteven Rostedt 
1130b448c4e3SSteven Rostedt static struct ftrace_func_entry *
1131b448c4e3SSteven Rostedt ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
1132b448c4e3SSteven Rostedt {
1133b448c4e3SSteven Rostedt 	unsigned long key;
1134b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1135b448c4e3SSteven Rostedt 	struct hlist_head *hhd;
1136b448c4e3SSteven Rostedt 	struct hlist_node *n;
1137b448c4e3SSteven Rostedt 
113806a51d93SSteven Rostedt 	if (ftrace_hash_empty(hash))
1139b448c4e3SSteven Rostedt 		return NULL;
1140b448c4e3SSteven Rostedt 
1141b448c4e3SSteven Rostedt 	if (hash->size_bits > 0)
1142b448c4e3SSteven Rostedt 		key = hash_long(ip, hash->size_bits);
1143b448c4e3SSteven Rostedt 	else
1144b448c4e3SSteven Rostedt 		key = 0;
1145b448c4e3SSteven Rostedt 
1146b448c4e3SSteven Rostedt 	hhd = &hash->buckets[key];
1147b448c4e3SSteven Rostedt 
1148b448c4e3SSteven Rostedt 	hlist_for_each_entry_rcu(entry, n, hhd, hlist) {
1149b448c4e3SSteven Rostedt 		if (entry->ip == ip)
1150b448c4e3SSteven Rostedt 			return entry;
1151b448c4e3SSteven Rostedt 	}
1152b448c4e3SSteven Rostedt 	return NULL;
1153b448c4e3SSteven Rostedt }
1154b448c4e3SSteven Rostedt 
115533dc9b12SSteven Rostedt static void __add_hash_entry(struct ftrace_hash *hash,
115633dc9b12SSteven Rostedt 			     struct ftrace_func_entry *entry)
115733dc9b12SSteven Rostedt {
115833dc9b12SSteven Rostedt 	struct hlist_head *hhd;
115933dc9b12SSteven Rostedt 	unsigned long key;
116033dc9b12SSteven Rostedt 
116133dc9b12SSteven Rostedt 	if (hash->size_bits)
116233dc9b12SSteven Rostedt 		key = hash_long(entry->ip, hash->size_bits);
116333dc9b12SSteven Rostedt 	else
116433dc9b12SSteven Rostedt 		key = 0;
116533dc9b12SSteven Rostedt 
116633dc9b12SSteven Rostedt 	hhd = &hash->buckets[key];
116733dc9b12SSteven Rostedt 	hlist_add_head(&entry->hlist, hhd);
116833dc9b12SSteven Rostedt 	hash->count++;
116933dc9b12SSteven Rostedt }
117033dc9b12SSteven Rostedt 
1171b448c4e3SSteven Rostedt static int add_hash_entry(struct ftrace_hash *hash, unsigned long ip)
1172b448c4e3SSteven Rostedt {
1173b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1174b448c4e3SSteven Rostedt 
1175b448c4e3SSteven Rostedt 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
1176b448c4e3SSteven Rostedt 	if (!entry)
1177b448c4e3SSteven Rostedt 		return -ENOMEM;
1178b448c4e3SSteven Rostedt 
1179b448c4e3SSteven Rostedt 	entry->ip = ip;
118033dc9b12SSteven Rostedt 	__add_hash_entry(hash, entry);
1181b448c4e3SSteven Rostedt 
1182b448c4e3SSteven Rostedt 	return 0;
1183b448c4e3SSteven Rostedt }
1184b448c4e3SSteven Rostedt 
1185b448c4e3SSteven Rostedt static void
118633dc9b12SSteven Rostedt free_hash_entry(struct ftrace_hash *hash,
118733dc9b12SSteven Rostedt 		  struct ftrace_func_entry *entry)
118833dc9b12SSteven Rostedt {
118933dc9b12SSteven Rostedt 	hlist_del(&entry->hlist);
119033dc9b12SSteven Rostedt 	kfree(entry);
119133dc9b12SSteven Rostedt 	hash->count--;
119233dc9b12SSteven Rostedt }
119333dc9b12SSteven Rostedt 
119433dc9b12SSteven Rostedt static void
1195b448c4e3SSteven Rostedt remove_hash_entry(struct ftrace_hash *hash,
1196b448c4e3SSteven Rostedt 		  struct ftrace_func_entry *entry)
1197b448c4e3SSteven Rostedt {
1198b448c4e3SSteven Rostedt 	hlist_del(&entry->hlist);
1199b448c4e3SSteven Rostedt 	hash->count--;
1200b448c4e3SSteven Rostedt }
1201b448c4e3SSteven Rostedt 
1202b448c4e3SSteven Rostedt static void ftrace_hash_clear(struct ftrace_hash *hash)
1203b448c4e3SSteven Rostedt {
1204b448c4e3SSteven Rostedt 	struct hlist_head *hhd;
1205b448c4e3SSteven Rostedt 	struct hlist_node *tp, *tn;
1206b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1207b448c4e3SSteven Rostedt 	int size = 1 << hash->size_bits;
1208b448c4e3SSteven Rostedt 	int i;
1209b448c4e3SSteven Rostedt 
121033dc9b12SSteven Rostedt 	if (!hash->count)
121133dc9b12SSteven Rostedt 		return;
121233dc9b12SSteven Rostedt 
1213b448c4e3SSteven Rostedt 	for (i = 0; i < size; i++) {
1214b448c4e3SSteven Rostedt 		hhd = &hash->buckets[i];
1215b448c4e3SSteven Rostedt 		hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist)
121633dc9b12SSteven Rostedt 			free_hash_entry(hash, entry);
1217b448c4e3SSteven Rostedt 	}
1218b448c4e3SSteven Rostedt 	FTRACE_WARN_ON(hash->count);
1219b448c4e3SSteven Rostedt }
1220b448c4e3SSteven Rostedt 
122133dc9b12SSteven Rostedt static void free_ftrace_hash(struct ftrace_hash *hash)
122233dc9b12SSteven Rostedt {
122333dc9b12SSteven Rostedt 	if (!hash || hash == EMPTY_HASH)
122433dc9b12SSteven Rostedt 		return;
122533dc9b12SSteven Rostedt 	ftrace_hash_clear(hash);
122633dc9b12SSteven Rostedt 	kfree(hash->buckets);
122733dc9b12SSteven Rostedt 	kfree(hash);
122833dc9b12SSteven Rostedt }
122933dc9b12SSteven Rostedt 
123007fd5515SSteven Rostedt static void __free_ftrace_hash_rcu(struct rcu_head *rcu)
123107fd5515SSteven Rostedt {
123207fd5515SSteven Rostedt 	struct ftrace_hash *hash;
123307fd5515SSteven Rostedt 
123407fd5515SSteven Rostedt 	hash = container_of(rcu, struct ftrace_hash, rcu);
123507fd5515SSteven Rostedt 	free_ftrace_hash(hash);
123607fd5515SSteven Rostedt }
123707fd5515SSteven Rostedt 
123807fd5515SSteven Rostedt static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
123907fd5515SSteven Rostedt {
124007fd5515SSteven Rostedt 	if (!hash || hash == EMPTY_HASH)
124107fd5515SSteven Rostedt 		return;
124207fd5515SSteven Rostedt 	call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu);
124307fd5515SSteven Rostedt }
124407fd5515SSteven Rostedt 
12455500fa51SJiri Olsa void ftrace_free_filter(struct ftrace_ops *ops)
12465500fa51SJiri Olsa {
12475500fa51SJiri Olsa 	free_ftrace_hash(ops->filter_hash);
12485500fa51SJiri Olsa 	free_ftrace_hash(ops->notrace_hash);
12495500fa51SJiri Olsa }
12505500fa51SJiri Olsa 
125133dc9b12SSteven Rostedt static struct ftrace_hash *alloc_ftrace_hash(int size_bits)
125233dc9b12SSteven Rostedt {
125333dc9b12SSteven Rostedt 	struct ftrace_hash *hash;
125433dc9b12SSteven Rostedt 	int size;
125533dc9b12SSteven Rostedt 
125633dc9b12SSteven Rostedt 	hash = kzalloc(sizeof(*hash), GFP_KERNEL);
125733dc9b12SSteven Rostedt 	if (!hash)
125833dc9b12SSteven Rostedt 		return NULL;
125933dc9b12SSteven Rostedt 
126033dc9b12SSteven Rostedt 	size = 1 << size_bits;
126147b0edcbSThomas Meyer 	hash->buckets = kcalloc(size, sizeof(*hash->buckets), GFP_KERNEL);
126233dc9b12SSteven Rostedt 
126333dc9b12SSteven Rostedt 	if (!hash->buckets) {
126433dc9b12SSteven Rostedt 		kfree(hash);
126533dc9b12SSteven Rostedt 		return NULL;
126633dc9b12SSteven Rostedt 	}
126733dc9b12SSteven Rostedt 
126833dc9b12SSteven Rostedt 	hash->size_bits = size_bits;
126933dc9b12SSteven Rostedt 
127033dc9b12SSteven Rostedt 	return hash;
127133dc9b12SSteven Rostedt }
127233dc9b12SSteven Rostedt 
127333dc9b12SSteven Rostedt static struct ftrace_hash *
127433dc9b12SSteven Rostedt alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
127533dc9b12SSteven Rostedt {
127633dc9b12SSteven Rostedt 	struct ftrace_func_entry *entry;
127733dc9b12SSteven Rostedt 	struct ftrace_hash *new_hash;
127833dc9b12SSteven Rostedt 	struct hlist_node *tp;
127933dc9b12SSteven Rostedt 	int size;
128033dc9b12SSteven Rostedt 	int ret;
128133dc9b12SSteven Rostedt 	int i;
128233dc9b12SSteven Rostedt 
128333dc9b12SSteven Rostedt 	new_hash = alloc_ftrace_hash(size_bits);
128433dc9b12SSteven Rostedt 	if (!new_hash)
128533dc9b12SSteven Rostedt 		return NULL;
128633dc9b12SSteven Rostedt 
128733dc9b12SSteven Rostedt 	/* Empty hash? */
128806a51d93SSteven Rostedt 	if (ftrace_hash_empty(hash))
128933dc9b12SSteven Rostedt 		return new_hash;
129033dc9b12SSteven Rostedt 
129133dc9b12SSteven Rostedt 	size = 1 << hash->size_bits;
129233dc9b12SSteven Rostedt 	for (i = 0; i < size; i++) {
129333dc9b12SSteven Rostedt 		hlist_for_each_entry(entry, tp, &hash->buckets[i], hlist) {
129433dc9b12SSteven Rostedt 			ret = add_hash_entry(new_hash, entry->ip);
129533dc9b12SSteven Rostedt 			if (ret < 0)
129633dc9b12SSteven Rostedt 				goto free_hash;
129733dc9b12SSteven Rostedt 		}
129833dc9b12SSteven Rostedt 	}
129933dc9b12SSteven Rostedt 
130033dc9b12SSteven Rostedt 	FTRACE_WARN_ON(new_hash->count != hash->count);
130133dc9b12SSteven Rostedt 
130233dc9b12SSteven Rostedt 	return new_hash;
130333dc9b12SSteven Rostedt 
130433dc9b12SSteven Rostedt  free_hash:
130533dc9b12SSteven Rostedt 	free_ftrace_hash(new_hash);
130633dc9b12SSteven Rostedt 	return NULL;
130733dc9b12SSteven Rostedt }
130833dc9b12SSteven Rostedt 
130941fb61c2SSteven Rostedt static void
131041fb61c2SSteven Rostedt ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash);
131141fb61c2SSteven Rostedt static void
131241fb61c2SSteven Rostedt ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash);
131341fb61c2SSteven Rostedt 
131433dc9b12SSteven Rostedt static int
131541fb61c2SSteven Rostedt ftrace_hash_move(struct ftrace_ops *ops, int enable,
131641fb61c2SSteven Rostedt 		 struct ftrace_hash **dst, struct ftrace_hash *src)
131733dc9b12SSteven Rostedt {
131833dc9b12SSteven Rostedt 	struct ftrace_func_entry *entry;
131933dc9b12SSteven Rostedt 	struct hlist_node *tp, *tn;
132033dc9b12SSteven Rostedt 	struct hlist_head *hhd;
132107fd5515SSteven Rostedt 	struct ftrace_hash *old_hash;
132207fd5515SSteven Rostedt 	struct ftrace_hash *new_hash;
132333dc9b12SSteven Rostedt 	unsigned long key;
132433dc9b12SSteven Rostedt 	int size = src->count;
132533dc9b12SSteven Rostedt 	int bits = 0;
132641fb61c2SSteven Rostedt 	int ret;
132733dc9b12SSteven Rostedt 	int i;
132833dc9b12SSteven Rostedt 
132933dc9b12SSteven Rostedt 	/*
133041fb61c2SSteven Rostedt 	 * Remove the current set, update the hash and add
133141fb61c2SSteven Rostedt 	 * them back.
133241fb61c2SSteven Rostedt 	 */
133341fb61c2SSteven Rostedt 	ftrace_hash_rec_disable(ops, enable);
133441fb61c2SSteven Rostedt 
133541fb61c2SSteven Rostedt 	/*
133633dc9b12SSteven Rostedt 	 * If the new source is empty, just free dst and assign it
133733dc9b12SSteven Rostedt 	 * the empty_hash.
133833dc9b12SSteven Rostedt 	 */
133933dc9b12SSteven Rostedt 	if (!src->count) {
134007fd5515SSteven Rostedt 		free_ftrace_hash_rcu(*dst);
134107fd5515SSteven Rostedt 		rcu_assign_pointer(*dst, EMPTY_HASH);
1342d4d34b98SSteven Rostedt 		/* still need to update the function records */
1343d4d34b98SSteven Rostedt 		ret = 0;
1344d4d34b98SSteven Rostedt 		goto out;
134533dc9b12SSteven Rostedt 	}
134633dc9b12SSteven Rostedt 
134733dc9b12SSteven Rostedt 	/*
134833dc9b12SSteven Rostedt 	 * Make the hash size about 1/2 the # found
134933dc9b12SSteven Rostedt 	 */
135033dc9b12SSteven Rostedt 	for (size /= 2; size; size >>= 1)
135133dc9b12SSteven Rostedt 		bits++;
135233dc9b12SSteven Rostedt 
135333dc9b12SSteven Rostedt 	/* Don't allocate too much */
135433dc9b12SSteven Rostedt 	if (bits > FTRACE_HASH_MAX_BITS)
135533dc9b12SSteven Rostedt 		bits = FTRACE_HASH_MAX_BITS;
135633dc9b12SSteven Rostedt 
135741fb61c2SSteven Rostedt 	ret = -ENOMEM;
135807fd5515SSteven Rostedt 	new_hash = alloc_ftrace_hash(bits);
135907fd5515SSteven Rostedt 	if (!new_hash)
136041fb61c2SSteven Rostedt 		goto out;
136133dc9b12SSteven Rostedt 
136233dc9b12SSteven Rostedt 	size = 1 << src->size_bits;
136333dc9b12SSteven Rostedt 	for (i = 0; i < size; i++) {
136433dc9b12SSteven Rostedt 		hhd = &src->buckets[i];
136533dc9b12SSteven Rostedt 		hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) {
136633dc9b12SSteven Rostedt 			if (bits > 0)
136733dc9b12SSteven Rostedt 				key = hash_long(entry->ip, bits);
136833dc9b12SSteven Rostedt 			else
136933dc9b12SSteven Rostedt 				key = 0;
137033dc9b12SSteven Rostedt 			remove_hash_entry(src, entry);
137107fd5515SSteven Rostedt 			__add_hash_entry(new_hash, entry);
137233dc9b12SSteven Rostedt 		}
137333dc9b12SSteven Rostedt 	}
137433dc9b12SSteven Rostedt 
137507fd5515SSteven Rostedt 	old_hash = *dst;
137607fd5515SSteven Rostedt 	rcu_assign_pointer(*dst, new_hash);
137707fd5515SSteven Rostedt 	free_ftrace_hash_rcu(old_hash);
137807fd5515SSteven Rostedt 
137941fb61c2SSteven Rostedt 	ret = 0;
138041fb61c2SSteven Rostedt  out:
138141fb61c2SSteven Rostedt 	/*
138241fb61c2SSteven Rostedt 	 * Enable regardless of ret:
138341fb61c2SSteven Rostedt 	 *  On success, we enable the new hash.
138441fb61c2SSteven Rostedt 	 *  On failure, we re-enable the original hash.
138541fb61c2SSteven Rostedt 	 */
138641fb61c2SSteven Rostedt 	ftrace_hash_rec_enable(ops, enable);
138741fb61c2SSteven Rostedt 
138841fb61c2SSteven Rostedt 	return ret;
138933dc9b12SSteven Rostedt }
139033dc9b12SSteven Rostedt 
1391265c831cSSteven Rostedt /*
1392b848914cSSteven Rostedt  * Test the hashes for this ops to see if we want to call
1393b848914cSSteven Rostedt  * the ops->func or not.
1394b848914cSSteven Rostedt  *
1395b848914cSSteven Rostedt  * It's a match if the ip is in the ops->filter_hash or
1396b848914cSSteven Rostedt  * the filter_hash does not exist or is empty,
1397b848914cSSteven Rostedt  *  AND
1398b848914cSSteven Rostedt  * the ip is not in the ops->notrace_hash.
1399cdbe61bfSSteven Rostedt  *
1400cdbe61bfSSteven Rostedt  * This needs to be called with preemption disabled as
1401cdbe61bfSSteven Rostedt  * the hashes are freed with call_rcu_sched().
1402b848914cSSteven Rostedt  */
1403b848914cSSteven Rostedt static int
1404b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
1405b848914cSSteven Rostedt {
1406b848914cSSteven Rostedt 	struct ftrace_hash *filter_hash;
1407b848914cSSteven Rostedt 	struct ftrace_hash *notrace_hash;
1408b848914cSSteven Rostedt 	int ret;
1409b848914cSSteven Rostedt 
1410b848914cSSteven Rostedt 	filter_hash = rcu_dereference_raw(ops->filter_hash);
1411b848914cSSteven Rostedt 	notrace_hash = rcu_dereference_raw(ops->notrace_hash);
1412b848914cSSteven Rostedt 
141306a51d93SSteven Rostedt 	if ((ftrace_hash_empty(filter_hash) ||
1414b848914cSSteven Rostedt 	     ftrace_lookup_ip(filter_hash, ip)) &&
141506a51d93SSteven Rostedt 	    (ftrace_hash_empty(notrace_hash) ||
1416b848914cSSteven Rostedt 	     !ftrace_lookup_ip(notrace_hash, ip)))
1417b848914cSSteven Rostedt 		ret = 1;
1418b848914cSSteven Rostedt 	else
1419b848914cSSteven Rostedt 		ret = 0;
1420b848914cSSteven Rostedt 
1421b848914cSSteven Rostedt 	return ret;
1422b848914cSSteven Rostedt }
1423b848914cSSteven Rostedt 
1424b848914cSSteven Rostedt /*
1425265c831cSSteven Rostedt  * This is a double for. Do not use 'break' to break out of the loop,
1426265c831cSSteven Rostedt  * you must use a goto.
1427265c831cSSteven Rostedt  */
1428265c831cSSteven Rostedt #define do_for_each_ftrace_rec(pg, rec)					\
1429265c831cSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {		\
1430265c831cSSteven Rostedt 		int _____i;						\
1431265c831cSSteven Rostedt 		for (_____i = 0; _____i < pg->index; _____i++) {	\
1432265c831cSSteven Rostedt 			rec = &pg->records[_____i];
1433265c831cSSteven Rostedt 
1434265c831cSSteven Rostedt #define while_for_each_ftrace_rec()		\
1435265c831cSSteven Rostedt 		}				\
1436265c831cSSteven Rostedt 	}
1437ecea656dSAbhishek Sagar 
14385855feadSSteven Rostedt 
14395855feadSSteven Rostedt static int ftrace_cmp_recs(const void *a, const void *b)
14405855feadSSteven Rostedt {
1441a650e02aSSteven Rostedt 	const struct dyn_ftrace *key = a;
1442a650e02aSSteven Rostedt 	const struct dyn_ftrace *rec = b;
14435855feadSSteven Rostedt 
1444a650e02aSSteven Rostedt 	if (key->flags < rec->ip)
14455855feadSSteven Rostedt 		return -1;
1446a650e02aSSteven Rostedt 	if (key->ip >= rec->ip + MCOUNT_INSN_SIZE)
1447a650e02aSSteven Rostedt 		return 1;
1448a650e02aSSteven Rostedt 	return 0;
1449a650e02aSSteven Rostedt }
1450a650e02aSSteven Rostedt 
1451f0cf973aSSteven Rostedt static unsigned long ftrace_location_range(unsigned long start, unsigned long end)
1452a650e02aSSteven Rostedt {
1453a650e02aSSteven Rostedt 	struct ftrace_page *pg;
1454a650e02aSSteven Rostedt 	struct dyn_ftrace *rec;
1455a650e02aSSteven Rostedt 	struct dyn_ftrace key;
1456a650e02aSSteven Rostedt 
1457a650e02aSSteven Rostedt 	key.ip = start;
1458a650e02aSSteven Rostedt 	key.flags = end;	/* overload flags, as it is unsigned long */
1459a650e02aSSteven Rostedt 
1460a650e02aSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {
1461a650e02aSSteven Rostedt 		if (end < pg->records[0].ip ||
1462a650e02aSSteven Rostedt 		    start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
1463a650e02aSSteven Rostedt 			continue;
1464a650e02aSSteven Rostedt 		rec = bsearch(&key, pg->records, pg->index,
1465a650e02aSSteven Rostedt 			      sizeof(struct dyn_ftrace),
1466a650e02aSSteven Rostedt 			      ftrace_cmp_recs);
1467a650e02aSSteven Rostedt 		if (rec)
1468f0cf973aSSteven Rostedt 			return rec->ip;
1469a650e02aSSteven Rostedt 	}
1470a650e02aSSteven Rostedt 
14715855feadSSteven Rostedt 	return 0;
14725855feadSSteven Rostedt }
14735855feadSSteven Rostedt 
1474c88fd863SSteven Rostedt /**
1475c88fd863SSteven Rostedt  * ftrace_location - return true if the ip giving is a traced location
1476c88fd863SSteven Rostedt  * @ip: the instruction pointer to check
1477c88fd863SSteven Rostedt  *
1478f0cf973aSSteven Rostedt  * Returns rec->ip if @ip given is a pointer to a ftrace location.
1479c88fd863SSteven Rostedt  * That is, the instruction that is either a NOP or call to
1480c88fd863SSteven Rostedt  * the function tracer. It checks the ftrace internal tables to
1481c88fd863SSteven Rostedt  * determine if the address belongs or not.
1482c88fd863SSteven Rostedt  */
1483f0cf973aSSteven Rostedt unsigned long ftrace_location(unsigned long ip)
1484c88fd863SSteven Rostedt {
1485a650e02aSSteven Rostedt 	return ftrace_location_range(ip, ip);
14865855feadSSteven Rostedt }
1487c88fd863SSteven Rostedt 
1488a650e02aSSteven Rostedt /**
1489a650e02aSSteven Rostedt  * ftrace_text_reserved - return true if range contains an ftrace location
1490a650e02aSSteven Rostedt  * @start: start of range to search
1491a650e02aSSteven Rostedt  * @end: end of range to search (inclusive). @end points to the last byte to check.
1492a650e02aSSteven Rostedt  *
1493a650e02aSSteven Rostedt  * Returns 1 if @start and @end contains a ftrace location.
1494a650e02aSSteven Rostedt  * That is, the instruction that is either a NOP or call to
1495a650e02aSSteven Rostedt  * the function tracer. It checks the ftrace internal tables to
1496a650e02aSSteven Rostedt  * determine if the address belongs or not.
1497a650e02aSSteven Rostedt  */
1498a650e02aSSteven Rostedt int ftrace_text_reserved(void *start, void *end)
1499a650e02aSSteven Rostedt {
1500f0cf973aSSteven Rostedt 	unsigned long ret;
1501f0cf973aSSteven Rostedt 
1502f0cf973aSSteven Rostedt 	ret = ftrace_location_range((unsigned long)start,
1503a650e02aSSteven Rostedt 				    (unsigned long)end);
1504f0cf973aSSteven Rostedt 
1505f0cf973aSSteven Rostedt 	return (int)!!ret;
1506c88fd863SSteven Rostedt }
1507c88fd863SSteven Rostedt 
1508ed926f9bSSteven Rostedt static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1509ed926f9bSSteven Rostedt 				     int filter_hash,
1510ed926f9bSSteven Rostedt 				     bool inc)
1511ed926f9bSSteven Rostedt {
1512ed926f9bSSteven Rostedt 	struct ftrace_hash *hash;
1513ed926f9bSSteven Rostedt 	struct ftrace_hash *other_hash;
1514ed926f9bSSteven Rostedt 	struct ftrace_page *pg;
1515ed926f9bSSteven Rostedt 	struct dyn_ftrace *rec;
1516ed926f9bSSteven Rostedt 	int count = 0;
1517ed926f9bSSteven Rostedt 	int all = 0;
1518ed926f9bSSteven Rostedt 
1519ed926f9bSSteven Rostedt 	/* Only update if the ops has been registered */
1520ed926f9bSSteven Rostedt 	if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
1521ed926f9bSSteven Rostedt 		return;
1522ed926f9bSSteven Rostedt 
1523ed926f9bSSteven Rostedt 	/*
1524ed926f9bSSteven Rostedt 	 * In the filter_hash case:
1525ed926f9bSSteven Rostedt 	 *   If the count is zero, we update all records.
1526ed926f9bSSteven Rostedt 	 *   Otherwise we just update the items in the hash.
1527ed926f9bSSteven Rostedt 	 *
1528ed926f9bSSteven Rostedt 	 * In the notrace_hash case:
1529ed926f9bSSteven Rostedt 	 *   We enable the update in the hash.
1530ed926f9bSSteven Rostedt 	 *   As disabling notrace means enabling the tracing,
1531ed926f9bSSteven Rostedt 	 *   and enabling notrace means disabling, the inc variable
1532ed926f9bSSteven Rostedt 	 *   gets inversed.
1533ed926f9bSSteven Rostedt 	 */
1534ed926f9bSSteven Rostedt 	if (filter_hash) {
1535ed926f9bSSteven Rostedt 		hash = ops->filter_hash;
1536ed926f9bSSteven Rostedt 		other_hash = ops->notrace_hash;
153706a51d93SSteven Rostedt 		if (ftrace_hash_empty(hash))
1538ed926f9bSSteven Rostedt 			all = 1;
1539ed926f9bSSteven Rostedt 	} else {
1540ed926f9bSSteven Rostedt 		inc = !inc;
1541ed926f9bSSteven Rostedt 		hash = ops->notrace_hash;
1542ed926f9bSSteven Rostedt 		other_hash = ops->filter_hash;
1543ed926f9bSSteven Rostedt 		/*
1544ed926f9bSSteven Rostedt 		 * If the notrace hash has no items,
1545ed926f9bSSteven Rostedt 		 * then there's nothing to do.
1546ed926f9bSSteven Rostedt 		 */
154706a51d93SSteven Rostedt 		if (ftrace_hash_empty(hash))
1548ed926f9bSSteven Rostedt 			return;
1549ed926f9bSSteven Rostedt 	}
1550ed926f9bSSteven Rostedt 
1551ed926f9bSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
1552ed926f9bSSteven Rostedt 		int in_other_hash = 0;
1553ed926f9bSSteven Rostedt 		int in_hash = 0;
1554ed926f9bSSteven Rostedt 		int match = 0;
1555ed926f9bSSteven Rostedt 
1556ed926f9bSSteven Rostedt 		if (all) {
1557ed926f9bSSteven Rostedt 			/*
1558ed926f9bSSteven Rostedt 			 * Only the filter_hash affects all records.
1559ed926f9bSSteven Rostedt 			 * Update if the record is not in the notrace hash.
1560ed926f9bSSteven Rostedt 			 */
1561b848914cSSteven Rostedt 			if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip))
1562ed926f9bSSteven Rostedt 				match = 1;
1563ed926f9bSSteven Rostedt 		} else {
156406a51d93SSteven Rostedt 			in_hash = !!ftrace_lookup_ip(hash, rec->ip);
156506a51d93SSteven Rostedt 			in_other_hash = !!ftrace_lookup_ip(other_hash, rec->ip);
1566ed926f9bSSteven Rostedt 
1567ed926f9bSSteven Rostedt 			/*
1568ed926f9bSSteven Rostedt 			 *
1569ed926f9bSSteven Rostedt 			 */
1570ed926f9bSSteven Rostedt 			if (filter_hash && in_hash && !in_other_hash)
1571ed926f9bSSteven Rostedt 				match = 1;
1572ed926f9bSSteven Rostedt 			else if (!filter_hash && in_hash &&
157306a51d93SSteven Rostedt 				 (in_other_hash || ftrace_hash_empty(other_hash)))
1574ed926f9bSSteven Rostedt 				match = 1;
1575ed926f9bSSteven Rostedt 		}
1576ed926f9bSSteven Rostedt 		if (!match)
1577ed926f9bSSteven Rostedt 			continue;
1578ed926f9bSSteven Rostedt 
1579ed926f9bSSteven Rostedt 		if (inc) {
1580ed926f9bSSteven Rostedt 			rec->flags++;
1581ed926f9bSSteven Rostedt 			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX))
1582ed926f9bSSteven Rostedt 				return;
158308f6fba5SSteven Rostedt 			/*
158408f6fba5SSteven Rostedt 			 * If any ops wants regs saved for this function
158508f6fba5SSteven Rostedt 			 * then all ops will get saved regs.
158608f6fba5SSteven Rostedt 			 */
158708f6fba5SSteven Rostedt 			if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
158808f6fba5SSteven Rostedt 				rec->flags |= FTRACE_FL_REGS;
1589ed926f9bSSteven Rostedt 		} else {
1590ed926f9bSSteven Rostedt 			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0))
1591ed926f9bSSteven Rostedt 				return;
1592ed926f9bSSteven Rostedt 			rec->flags--;
1593ed926f9bSSteven Rostedt 		}
1594ed926f9bSSteven Rostedt 		count++;
1595ed926f9bSSteven Rostedt 		/* Shortcut, if we handled all records, we are done. */
1596ed926f9bSSteven Rostedt 		if (!all && count == hash->count)
1597ed926f9bSSteven Rostedt 			return;
1598ed926f9bSSteven Rostedt 	} while_for_each_ftrace_rec();
1599ed926f9bSSteven Rostedt }
1600ed926f9bSSteven Rostedt 
1601ed926f9bSSteven Rostedt static void ftrace_hash_rec_disable(struct ftrace_ops *ops,
1602ed926f9bSSteven Rostedt 				    int filter_hash)
1603ed926f9bSSteven Rostedt {
1604ed926f9bSSteven Rostedt 	__ftrace_hash_rec_update(ops, filter_hash, 0);
1605ed926f9bSSteven Rostedt }
1606ed926f9bSSteven Rostedt 
1607ed926f9bSSteven Rostedt static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
1608ed926f9bSSteven Rostedt 				   int filter_hash)
1609ed926f9bSSteven Rostedt {
1610ed926f9bSSteven Rostedt 	__ftrace_hash_rec_update(ops, filter_hash, 1);
1611ed926f9bSSteven Rostedt }
1612ed926f9bSSteven Rostedt 
161305736a42SSteven Rostedt static void print_ip_ins(const char *fmt, unsigned char *p)
161405736a42SSteven Rostedt {
161505736a42SSteven Rostedt 	int i;
161605736a42SSteven Rostedt 
161705736a42SSteven Rostedt 	printk(KERN_CONT "%s", fmt);
161805736a42SSteven Rostedt 
161905736a42SSteven Rostedt 	for (i = 0; i < MCOUNT_INSN_SIZE; i++)
162005736a42SSteven Rostedt 		printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
162105736a42SSteven Rostedt }
162205736a42SSteven Rostedt 
1623c88fd863SSteven Rostedt /**
1624c88fd863SSteven Rostedt  * ftrace_bug - report and shutdown function tracer
1625c88fd863SSteven Rostedt  * @failed: The failed type (EFAULT, EINVAL, EPERM)
1626c88fd863SSteven Rostedt  * @ip: The address that failed
1627c88fd863SSteven Rostedt  *
1628c88fd863SSteven Rostedt  * The arch code that enables or disables the function tracing
1629c88fd863SSteven Rostedt  * can call ftrace_bug() when it has detected a problem in
1630c88fd863SSteven Rostedt  * modifying the code. @failed should be one of either:
1631c88fd863SSteven Rostedt  * EFAULT - if the problem happens on reading the @ip address
1632c88fd863SSteven Rostedt  * EINVAL - if what is read at @ip is not what was expected
1633c88fd863SSteven Rostedt  * EPERM - if the problem happens on writting to the @ip address
1634c88fd863SSteven Rostedt  */
1635c88fd863SSteven Rostedt void ftrace_bug(int failed, unsigned long ip)
16363c1720f0SSteven Rostedt {
1637b17e8a37SSteven Rostedt 	switch (failed) {
1638593eb8a2SSteven Rostedt 	case -EFAULT:
16396912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
164005736a42SSteven Rostedt 		pr_info("ftrace faulted on modifying ");
164105736a42SSteven Rostedt 		print_ip_sym(ip);
164205736a42SSteven Rostedt 		break;
1643593eb8a2SSteven Rostedt 	case -EINVAL:
16446912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
164505736a42SSteven Rostedt 		pr_info("ftrace failed to modify ");
164605736a42SSteven Rostedt 		print_ip_sym(ip);
164705736a42SSteven Rostedt 		print_ip_ins(" actual: ", (unsigned char *)ip);
164805736a42SSteven Rostedt 		printk(KERN_CONT "\n");
164905736a42SSteven Rostedt 		break;
1650593eb8a2SSteven Rostedt 	case -EPERM:
16516912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
1652593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on writing ");
1653593eb8a2SSteven Rostedt 		print_ip_sym(ip);
1654593eb8a2SSteven Rostedt 		break;
1655593eb8a2SSteven Rostedt 	default:
16566912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
1657593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on unknown error ");
1658593eb8a2SSteven Rostedt 		print_ip_sym(ip);
165905736a42SSteven Rostedt 	}
1660b17e8a37SSteven Rostedt }
166105736a42SSteven Rostedt 
1662c88fd863SSteven Rostedt static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
16633d083395SSteven Rostedt {
166464fbcd16SXiao Guangrong 	unsigned long flag = 0UL;
1665e7d3737eSFrederic Weisbecker 
16663d083395SSteven Rostedt 	/*
166730fb6aa7SJiri Olsa 	 * If we are updating calls:
16683d083395SSteven Rostedt 	 *
1669ed926f9bSSteven Rostedt 	 *   If the record has a ref count, then we need to enable it
1670ed926f9bSSteven Rostedt 	 *   because someone is using it.
16713d083395SSteven Rostedt 	 *
1672ed926f9bSSteven Rostedt 	 *   Otherwise we make sure its disabled.
1673ed926f9bSSteven Rostedt 	 *
167430fb6aa7SJiri Olsa 	 * If we are disabling calls, then disable all records that
1675ed926f9bSSteven Rostedt 	 * are enabled.
16763d083395SSteven Rostedt 	 */
1677c88fd863SSteven Rostedt 	if (enable && (rec->flags & ~FTRACE_FL_MASK))
167864fbcd16SXiao Guangrong 		flag = FTRACE_FL_ENABLED;
16793d083395SSteven Rostedt 
168008f6fba5SSteven Rostedt 	/*
168108f6fba5SSteven Rostedt 	 * If enabling and the REGS flag does not match the REGS_EN, then
168208f6fba5SSteven Rostedt 	 * do not ignore this record. Set flags to fail the compare against
168308f6fba5SSteven Rostedt 	 * ENABLED.
168408f6fba5SSteven Rostedt 	 */
168508f6fba5SSteven Rostedt 	if (flag &&
168608f6fba5SSteven Rostedt 	    (!(rec->flags & FTRACE_FL_REGS) != !(rec->flags & FTRACE_FL_REGS_EN)))
168708f6fba5SSteven Rostedt 		flag |= FTRACE_FL_REGS;
168808f6fba5SSteven Rostedt 
168964fbcd16SXiao Guangrong 	/* If the state of this record hasn't changed, then do nothing */
169064fbcd16SXiao Guangrong 	if ((rec->flags & FTRACE_FL_ENABLED) == flag)
1691c88fd863SSteven Rostedt 		return FTRACE_UPDATE_IGNORE;
169264fbcd16SXiao Guangrong 
169364fbcd16SXiao Guangrong 	if (flag) {
169408f6fba5SSteven Rostedt 		/* Save off if rec is being enabled (for return value) */
169508f6fba5SSteven Rostedt 		flag ^= rec->flags & FTRACE_FL_ENABLED;
169608f6fba5SSteven Rostedt 
169708f6fba5SSteven Rostedt 		if (update) {
169864fbcd16SXiao Guangrong 			rec->flags |= FTRACE_FL_ENABLED;
169908f6fba5SSteven Rostedt 			if (flag & FTRACE_FL_REGS) {
170008f6fba5SSteven Rostedt 				if (rec->flags & FTRACE_FL_REGS)
170108f6fba5SSteven Rostedt 					rec->flags |= FTRACE_FL_REGS_EN;
170208f6fba5SSteven Rostedt 				else
170308f6fba5SSteven Rostedt 					rec->flags &= ~FTRACE_FL_REGS_EN;
170408f6fba5SSteven Rostedt 			}
170564fbcd16SXiao Guangrong 		}
170664fbcd16SXiao Guangrong 
170708f6fba5SSteven Rostedt 		/*
170808f6fba5SSteven Rostedt 		 * If this record is being updated from a nop, then
170908f6fba5SSteven Rostedt 		 *   return UPDATE_MAKE_CALL.
171008f6fba5SSteven Rostedt 		 * Otherwise, if the EN flag is set, then return
171108f6fba5SSteven Rostedt 		 *   UPDATE_MODIFY_CALL_REGS to tell the caller to convert
171208f6fba5SSteven Rostedt 		 *   from the non-save regs, to a save regs function.
171308f6fba5SSteven Rostedt 		 * Otherwise,
171408f6fba5SSteven Rostedt 		 *   return UPDATE_MODIFY_CALL to tell the caller to convert
171508f6fba5SSteven Rostedt 		 *   from the save regs, to a non-save regs function.
171608f6fba5SSteven Rostedt 		 */
171708f6fba5SSteven Rostedt 		if (flag & FTRACE_FL_ENABLED)
171808f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MAKE_CALL;
171908f6fba5SSteven Rostedt 		else if (rec->flags & FTRACE_FL_REGS_EN)
172008f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MODIFY_CALL_REGS;
172108f6fba5SSteven Rostedt 		else
172208f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MODIFY_CALL;
172308f6fba5SSteven Rostedt 	}
172408f6fba5SSteven Rostedt 
172508f6fba5SSteven Rostedt 	if (update) {
172608f6fba5SSteven Rostedt 		/* If there's no more users, clear all flags */
172708f6fba5SSteven Rostedt 		if (!(rec->flags & ~FTRACE_FL_MASK))
172808f6fba5SSteven Rostedt 			rec->flags = 0;
172908f6fba5SSteven Rostedt 		else
173008f6fba5SSteven Rostedt 			/* Just disable the record (keep REGS state) */
173164fbcd16SXiao Guangrong 			rec->flags &= ~FTRACE_FL_ENABLED;
173208f6fba5SSteven Rostedt 	}
1733c88fd863SSteven Rostedt 
1734c88fd863SSteven Rostedt 	return FTRACE_UPDATE_MAKE_NOP;
1735c88fd863SSteven Rostedt }
1736c88fd863SSteven Rostedt 
1737c88fd863SSteven Rostedt /**
1738c88fd863SSteven Rostedt  * ftrace_update_record, set a record that now is tracing or not
1739c88fd863SSteven Rostedt  * @rec: the record to update
1740c88fd863SSteven Rostedt  * @enable: set to 1 if the record is tracing, zero to force disable
1741c88fd863SSteven Rostedt  *
1742c88fd863SSteven Rostedt  * The records that represent all functions that can be traced need
1743c88fd863SSteven Rostedt  * to be updated when tracing has been enabled.
1744c88fd863SSteven Rostedt  */
1745c88fd863SSteven Rostedt int ftrace_update_record(struct dyn_ftrace *rec, int enable)
1746c88fd863SSteven Rostedt {
1747c88fd863SSteven Rostedt 	return ftrace_check_record(rec, enable, 1);
1748c88fd863SSteven Rostedt }
1749c88fd863SSteven Rostedt 
1750c88fd863SSteven Rostedt /**
1751c88fd863SSteven Rostedt  * ftrace_test_record, check if the record has been enabled or not
1752c88fd863SSteven Rostedt  * @rec: the record to test
1753c88fd863SSteven Rostedt  * @enable: set to 1 to check if enabled, 0 if it is disabled
1754c88fd863SSteven Rostedt  *
1755c88fd863SSteven Rostedt  * The arch code may need to test if a record is already set to
1756c88fd863SSteven Rostedt  * tracing to determine how to modify the function code that it
1757c88fd863SSteven Rostedt  * represents.
1758c88fd863SSteven Rostedt  */
1759c88fd863SSteven Rostedt int ftrace_test_record(struct dyn_ftrace *rec, int enable)
1760c88fd863SSteven Rostedt {
1761c88fd863SSteven Rostedt 	return ftrace_check_record(rec, enable, 0);
1762c88fd863SSteven Rostedt }
1763c88fd863SSteven Rostedt 
1764c88fd863SSteven Rostedt static int
1765c88fd863SSteven Rostedt __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
1766c88fd863SSteven Rostedt {
176708f6fba5SSteven Rostedt 	unsigned long ftrace_old_addr;
1768c88fd863SSteven Rostedt 	unsigned long ftrace_addr;
1769c88fd863SSteven Rostedt 	int ret;
1770c88fd863SSteven Rostedt 
1771c88fd863SSteven Rostedt 	ret = ftrace_update_record(rec, enable);
1772c88fd863SSteven Rostedt 
177308f6fba5SSteven Rostedt 	if (rec->flags & FTRACE_FL_REGS)
177408f6fba5SSteven Rostedt 		ftrace_addr = (unsigned long)FTRACE_REGS_ADDR;
177508f6fba5SSteven Rostedt 	else
177608f6fba5SSteven Rostedt 		ftrace_addr = (unsigned long)FTRACE_ADDR;
177708f6fba5SSteven Rostedt 
1778c88fd863SSteven Rostedt 	switch (ret) {
1779c88fd863SSteven Rostedt 	case FTRACE_UPDATE_IGNORE:
1780c88fd863SSteven Rostedt 		return 0;
1781c88fd863SSteven Rostedt 
1782c88fd863SSteven Rostedt 	case FTRACE_UPDATE_MAKE_CALL:
1783c88fd863SSteven Rostedt 		return ftrace_make_call(rec, ftrace_addr);
1784c88fd863SSteven Rostedt 
1785c88fd863SSteven Rostedt 	case FTRACE_UPDATE_MAKE_NOP:
1786e7d3737eSFrederic Weisbecker 		return ftrace_make_nop(NULL, rec, ftrace_addr);
178708f6fba5SSteven Rostedt 
178808f6fba5SSteven Rostedt 	case FTRACE_UPDATE_MODIFY_CALL_REGS:
178908f6fba5SSteven Rostedt 	case FTRACE_UPDATE_MODIFY_CALL:
179008f6fba5SSteven Rostedt 		if (rec->flags & FTRACE_FL_REGS)
179108f6fba5SSteven Rostedt 			ftrace_old_addr = (unsigned long)FTRACE_ADDR;
179208f6fba5SSteven Rostedt 		else
179308f6fba5SSteven Rostedt 			ftrace_old_addr = (unsigned long)FTRACE_REGS_ADDR;
179408f6fba5SSteven Rostedt 
179508f6fba5SSteven Rostedt 		return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr);
17963d083395SSteven Rostedt 	}
17973d083395SSteven Rostedt 
1798c88fd863SSteven Rostedt 	return -1; /* unknow ftrace bug */
1799c88fd863SSteven Rostedt }
1800c88fd863SSteven Rostedt 
1801e4f5d544SSteven Rostedt void __weak ftrace_replace_code(int enable)
18023d083395SSteven Rostedt {
18033d083395SSteven Rostedt 	struct dyn_ftrace *rec;
18043d083395SSteven Rostedt 	struct ftrace_page *pg;
18056a24a244SSteven Rostedt 	int failed;
18063d083395SSteven Rostedt 
180745a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
180845a4a237SSteven Rostedt 		return;
180945a4a237SSteven Rostedt 
1810265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
1811e4f5d544SSteven Rostedt 		failed = __ftrace_replace_code(rec, enable);
1812fa9d13cfSZhaolei 		if (failed) {
181331e88909SSteven Rostedt 			ftrace_bug(failed, rec->ip);
18144377245aSSteven Rostedt 			/* Stop processing */
18154377245aSSteven Rostedt 			return;
18164377245aSSteven Rostedt 		}
1817265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
18183d083395SSteven Rostedt }
18193c1720f0SSteven Rostedt 
1820c88fd863SSteven Rostedt struct ftrace_rec_iter {
1821c88fd863SSteven Rostedt 	struct ftrace_page	*pg;
1822c88fd863SSteven Rostedt 	int			index;
1823c88fd863SSteven Rostedt };
1824c88fd863SSteven Rostedt 
1825c88fd863SSteven Rostedt /**
1826c88fd863SSteven Rostedt  * ftrace_rec_iter_start, start up iterating over traced functions
1827c88fd863SSteven Rostedt  *
1828c88fd863SSteven Rostedt  * Returns an iterator handle that is used to iterate over all
1829c88fd863SSteven Rostedt  * the records that represent address locations where functions
1830c88fd863SSteven Rostedt  * are traced.
1831c88fd863SSteven Rostedt  *
1832c88fd863SSteven Rostedt  * May return NULL if no records are available.
1833c88fd863SSteven Rostedt  */
1834c88fd863SSteven Rostedt struct ftrace_rec_iter *ftrace_rec_iter_start(void)
1835c88fd863SSteven Rostedt {
1836c88fd863SSteven Rostedt 	/*
1837c88fd863SSteven Rostedt 	 * We only use a single iterator.
1838c88fd863SSteven Rostedt 	 * Protected by the ftrace_lock mutex.
1839c88fd863SSteven Rostedt 	 */
1840c88fd863SSteven Rostedt 	static struct ftrace_rec_iter ftrace_rec_iter;
1841c88fd863SSteven Rostedt 	struct ftrace_rec_iter *iter = &ftrace_rec_iter;
1842c88fd863SSteven Rostedt 
1843c88fd863SSteven Rostedt 	iter->pg = ftrace_pages_start;
1844c88fd863SSteven Rostedt 	iter->index = 0;
1845c88fd863SSteven Rostedt 
1846c88fd863SSteven Rostedt 	/* Could have empty pages */
1847c88fd863SSteven Rostedt 	while (iter->pg && !iter->pg->index)
1848c88fd863SSteven Rostedt 		iter->pg = iter->pg->next;
1849c88fd863SSteven Rostedt 
1850c88fd863SSteven Rostedt 	if (!iter->pg)
1851c88fd863SSteven Rostedt 		return NULL;
1852c88fd863SSteven Rostedt 
1853c88fd863SSteven Rostedt 	return iter;
1854c88fd863SSteven Rostedt }
1855c88fd863SSteven Rostedt 
1856c88fd863SSteven Rostedt /**
1857c88fd863SSteven Rostedt  * ftrace_rec_iter_next, get the next record to process.
1858c88fd863SSteven Rostedt  * @iter: The handle to the iterator.
1859c88fd863SSteven Rostedt  *
1860c88fd863SSteven Rostedt  * Returns the next iterator after the given iterator @iter.
1861c88fd863SSteven Rostedt  */
1862c88fd863SSteven Rostedt struct ftrace_rec_iter *ftrace_rec_iter_next(struct ftrace_rec_iter *iter)
1863c88fd863SSteven Rostedt {
1864c88fd863SSteven Rostedt 	iter->index++;
1865c88fd863SSteven Rostedt 
1866c88fd863SSteven Rostedt 	if (iter->index >= iter->pg->index) {
1867c88fd863SSteven Rostedt 		iter->pg = iter->pg->next;
1868c88fd863SSteven Rostedt 		iter->index = 0;
1869c88fd863SSteven Rostedt 
1870c88fd863SSteven Rostedt 		/* Could have empty pages */
1871c88fd863SSteven Rostedt 		while (iter->pg && !iter->pg->index)
1872c88fd863SSteven Rostedt 			iter->pg = iter->pg->next;
1873c88fd863SSteven Rostedt 	}
1874c88fd863SSteven Rostedt 
1875c88fd863SSteven Rostedt 	if (!iter->pg)
1876c88fd863SSteven Rostedt 		return NULL;
1877c88fd863SSteven Rostedt 
1878c88fd863SSteven Rostedt 	return iter;
1879c88fd863SSteven Rostedt }
1880c88fd863SSteven Rostedt 
1881c88fd863SSteven Rostedt /**
1882c88fd863SSteven Rostedt  * ftrace_rec_iter_record, get the record at the iterator location
1883c88fd863SSteven Rostedt  * @iter: The current iterator location
1884c88fd863SSteven Rostedt  *
1885c88fd863SSteven Rostedt  * Returns the record that the current @iter is at.
1886c88fd863SSteven Rostedt  */
1887c88fd863SSteven Rostedt struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter)
1888c88fd863SSteven Rostedt {
1889c88fd863SSteven Rostedt 	return &iter->pg->records[iter->index];
1890c88fd863SSteven Rostedt }
1891c88fd863SSteven Rostedt 
18923b47bfc1SSteven Rostedt static int
189331e88909SSteven Rostedt ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
18943c1720f0SSteven Rostedt {
189537ad5084SSteven Rostedt 	unsigned long ip;
1896492a7ea5SAbhishek Sagar 	int ret;
189737ad5084SSteven Rostedt 
1898492a7ea5SAbhishek Sagar 	ip = rec->ip;
18993c1720f0SSteven Rostedt 
190045a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
190145a4a237SSteven Rostedt 		return 0;
190245a4a237SSteven Rostedt 
190325aac9dcSShaohua Li 	ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
19043d083395SSteven Rostedt 	if (ret) {
190531e88909SSteven Rostedt 		ftrace_bug(ret, ip);
19063d083395SSteven Rostedt 		return 0;
1907d61f82d0SSteven Rostedt 	}
1908d61f82d0SSteven Rostedt 	return 1;
19093d083395SSteven Rostedt }
19103d083395SSteven Rostedt 
1911000ab691SSteven Rostedt /*
1912000ab691SSteven Rostedt  * archs can override this function if they must do something
1913000ab691SSteven Rostedt  * before the modifying code is performed.
1914000ab691SSteven Rostedt  */
1915000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_prepare(void)
1916000ab691SSteven Rostedt {
1917000ab691SSteven Rostedt 	return 0;
1918000ab691SSteven Rostedt }
1919000ab691SSteven Rostedt 
1920000ab691SSteven Rostedt /*
1921000ab691SSteven Rostedt  * archs can override this function if they must do something
1922000ab691SSteven Rostedt  * after the modifying code is performed.
1923000ab691SSteven Rostedt  */
1924000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_post_process(void)
1925000ab691SSteven Rostedt {
1926000ab691SSteven Rostedt 	return 0;
1927000ab691SSteven Rostedt }
1928000ab691SSteven Rostedt 
19298ed3e2cfSSteven Rostedt void ftrace_modify_all_code(int command)
19308ed3e2cfSSteven Rostedt {
19318ed3e2cfSSteven Rostedt 	if (command & FTRACE_UPDATE_CALLS)
19328ed3e2cfSSteven Rostedt 		ftrace_replace_code(1);
19338ed3e2cfSSteven Rostedt 	else if (command & FTRACE_DISABLE_CALLS)
19348ed3e2cfSSteven Rostedt 		ftrace_replace_code(0);
19358ed3e2cfSSteven Rostedt 
19368ed3e2cfSSteven Rostedt 	if (command & FTRACE_UPDATE_TRACE_FUNC)
19378ed3e2cfSSteven Rostedt 		ftrace_update_ftrace_func(ftrace_trace_function);
19388ed3e2cfSSteven Rostedt 
19398ed3e2cfSSteven Rostedt 	if (command & FTRACE_START_FUNC_RET)
19408ed3e2cfSSteven Rostedt 		ftrace_enable_ftrace_graph_caller();
19418ed3e2cfSSteven Rostedt 	else if (command & FTRACE_STOP_FUNC_RET)
19428ed3e2cfSSteven Rostedt 		ftrace_disable_ftrace_graph_caller();
19438ed3e2cfSSteven Rostedt }
19448ed3e2cfSSteven Rostedt 
19453d083395SSteven Rostedt static int __ftrace_modify_code(void *data)
19463d083395SSteven Rostedt {
19473d083395SSteven Rostedt 	int *command = data;
19483d083395SSteven Rostedt 
19498ed3e2cfSSteven Rostedt 	ftrace_modify_all_code(*command);
19505a45cfe1SSteven Rostedt 
1951c88fd863SSteven Rostedt 	return 0;
1952c88fd863SSteven Rostedt }
1953c88fd863SSteven Rostedt 
1954c88fd863SSteven Rostedt /**
1955c88fd863SSteven Rostedt  * ftrace_run_stop_machine, go back to the stop machine method
1956c88fd863SSteven Rostedt  * @command: The command to tell ftrace what to do
1957c88fd863SSteven Rostedt  *
1958c88fd863SSteven Rostedt  * If an arch needs to fall back to the stop machine method, the
1959c88fd863SSteven Rostedt  * it can call this function.
1960c88fd863SSteven Rostedt  */
1961c88fd863SSteven Rostedt void ftrace_run_stop_machine(int command)
1962c88fd863SSteven Rostedt {
1963c88fd863SSteven Rostedt 	stop_machine(__ftrace_modify_code, &command, NULL);
1964c88fd863SSteven Rostedt }
1965c88fd863SSteven Rostedt 
1966c88fd863SSteven Rostedt /**
1967c88fd863SSteven Rostedt  * arch_ftrace_update_code, modify the code to trace or not trace
1968c88fd863SSteven Rostedt  * @command: The command that needs to be done
1969c88fd863SSteven Rostedt  *
1970c88fd863SSteven Rostedt  * Archs can override this function if it does not need to
1971c88fd863SSteven Rostedt  * run stop_machine() to modify code.
1972c88fd863SSteven Rostedt  */
1973c88fd863SSteven Rostedt void __weak arch_ftrace_update_code(int command)
1974c88fd863SSteven Rostedt {
1975c88fd863SSteven Rostedt 	ftrace_run_stop_machine(command);
1976c88fd863SSteven Rostedt }
1977c88fd863SSteven Rostedt 
1978c88fd863SSteven Rostedt static void ftrace_run_update_code(int command)
1979c88fd863SSteven Rostedt {
1980c88fd863SSteven Rostedt 	int ret;
1981c88fd863SSteven Rostedt 
1982c88fd863SSteven Rostedt 	ret = ftrace_arch_code_modify_prepare();
1983c88fd863SSteven Rostedt 	FTRACE_WARN_ON(ret);
1984c88fd863SSteven Rostedt 	if (ret)
1985c88fd863SSteven Rostedt 		return;
1986c88fd863SSteven Rostedt 	/*
1987c88fd863SSteven Rostedt 	 * Do not call function tracer while we update the code.
1988c88fd863SSteven Rostedt 	 * We are in stop machine.
1989c88fd863SSteven Rostedt 	 */
1990c88fd863SSteven Rostedt 	function_trace_stop++;
1991c88fd863SSteven Rostedt 
1992c88fd863SSteven Rostedt 	/*
1993c88fd863SSteven Rostedt 	 * By default we use stop_machine() to modify the code.
1994c88fd863SSteven Rostedt 	 * But archs can do what ever they want as long as it
1995c88fd863SSteven Rostedt 	 * is safe. The stop_machine() is the safest, but also
1996c88fd863SSteven Rostedt 	 * produces the most overhead.
1997c88fd863SSteven Rostedt 	 */
1998c88fd863SSteven Rostedt 	arch_ftrace_update_code(command);
1999c88fd863SSteven Rostedt 
20006331c28cSSteven Rostedt 	function_trace_stop--;
20016331c28cSSteven Rostedt 
2002000ab691SSteven Rostedt 	ret = ftrace_arch_code_modify_post_process();
2003000ab691SSteven Rostedt 	FTRACE_WARN_ON(ret);
20043d083395SSteven Rostedt }
20053d083395SSteven Rostedt 
20063d083395SSteven Rostedt static ftrace_func_t saved_ftrace_func;
200760a7ecf4SSteven Rostedt static int ftrace_start_up;
2008b848914cSSteven Rostedt static int global_start_up;
2009df4fc315SSteven Rostedt 
2010df4fc315SSteven Rostedt static void ftrace_startup_enable(int command)
2011df4fc315SSteven Rostedt {
2012df4fc315SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
2013df4fc315SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
2014df4fc315SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
2015df4fc315SSteven Rostedt 	}
2016df4fc315SSteven Rostedt 
2017df4fc315SSteven Rostedt 	if (!command || !ftrace_enabled)
2018df4fc315SSteven Rostedt 		return;
2019df4fc315SSteven Rostedt 
2020df4fc315SSteven Rostedt 	ftrace_run_update_code(command);
2021df4fc315SSteven Rostedt }
20223d083395SSteven Rostedt 
2023a1cd6173SSteven Rostedt static int ftrace_startup(struct ftrace_ops *ops, int command)
20243d083395SSteven Rostedt {
2025b848914cSSteven Rostedt 	bool hash_enable = true;
2026b848914cSSteven Rostedt 
20274eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
2028a1cd6173SSteven Rostedt 		return -ENODEV;
20294eebcc81SSteven Rostedt 
203060a7ecf4SSteven Rostedt 	ftrace_start_up++;
203130fb6aa7SJiri Olsa 	command |= FTRACE_UPDATE_CALLS;
20323d083395SSteven Rostedt 
2033b848914cSSteven Rostedt 	/* ops marked global share the filter hashes */
2034b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
2035b848914cSSteven Rostedt 		ops = &global_ops;
2036b848914cSSteven Rostedt 		/* Don't update hash if global is already set */
2037b848914cSSteven Rostedt 		if (global_start_up)
2038b848914cSSteven Rostedt 			hash_enable = false;
2039b848914cSSteven Rostedt 		global_start_up++;
2040b848914cSSteven Rostedt 	}
2041b848914cSSteven Rostedt 
2042ed926f9bSSteven Rostedt 	ops->flags |= FTRACE_OPS_FL_ENABLED;
2043b848914cSSteven Rostedt 	if (hash_enable)
2044ed926f9bSSteven Rostedt 		ftrace_hash_rec_enable(ops, 1);
2045ed926f9bSSteven Rostedt 
2046df4fc315SSteven Rostedt 	ftrace_startup_enable(command);
2047a1cd6173SSteven Rostedt 
2048a1cd6173SSteven Rostedt 	return 0;
20493d083395SSteven Rostedt }
20503d083395SSteven Rostedt 
2051bd69c30bSSteven Rostedt static void ftrace_shutdown(struct ftrace_ops *ops, int command)
20523d083395SSteven Rostedt {
2053b848914cSSteven Rostedt 	bool hash_disable = true;
2054b848914cSSteven Rostedt 
20554eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
20564eebcc81SSteven Rostedt 		return;
20574eebcc81SSteven Rostedt 
205860a7ecf4SSteven Rostedt 	ftrace_start_up--;
20599ea1a153SFrederic Weisbecker 	/*
20609ea1a153SFrederic Weisbecker 	 * Just warn in case of unbalance, no need to kill ftrace, it's not
20619ea1a153SFrederic Weisbecker 	 * critical but the ftrace_call callers may be never nopped again after
20629ea1a153SFrederic Weisbecker 	 * further ftrace uses.
20639ea1a153SFrederic Weisbecker 	 */
20649ea1a153SFrederic Weisbecker 	WARN_ON_ONCE(ftrace_start_up < 0);
20659ea1a153SFrederic Weisbecker 
2066b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
2067b848914cSSteven Rostedt 		ops = &global_ops;
2068b848914cSSteven Rostedt 		global_start_up--;
2069b848914cSSteven Rostedt 		WARN_ON_ONCE(global_start_up < 0);
2070b848914cSSteven Rostedt 		/* Don't update hash if global still has users */
2071b848914cSSteven Rostedt 		if (global_start_up) {
2072b848914cSSteven Rostedt 			WARN_ON_ONCE(!ftrace_start_up);
2073b848914cSSteven Rostedt 			hash_disable = false;
2074b848914cSSteven Rostedt 		}
2075b848914cSSteven Rostedt 	}
2076b848914cSSteven Rostedt 
2077b848914cSSteven Rostedt 	if (hash_disable)
2078ed926f9bSSteven Rostedt 		ftrace_hash_rec_disable(ops, 1);
2079ed926f9bSSteven Rostedt 
2080b848914cSSteven Rostedt 	if (ops != &global_ops || !global_start_up)
2081ed926f9bSSteven Rostedt 		ops->flags &= ~FTRACE_OPS_FL_ENABLED;
2082b848914cSSteven Rostedt 
208330fb6aa7SJiri Olsa 	command |= FTRACE_UPDATE_CALLS;
2084d61f82d0SSteven Rostedt 
2085d61f82d0SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
2086d61f82d0SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
2087d61f82d0SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
2088d61f82d0SSteven Rostedt 	}
2089d61f82d0SSteven Rostedt 
2090d61f82d0SSteven Rostedt 	if (!command || !ftrace_enabled)
2091e6ea44e9SSteven Rostedt 		return;
20923d083395SSteven Rostedt 
2093d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
20943d083395SSteven Rostedt }
20953d083395SSteven Rostedt 
2096e309b41dSIngo Molnar static void ftrace_startup_sysctl(void)
2097b0fc494fSSteven Rostedt {
20984eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
20994eebcc81SSteven Rostedt 		return;
21004eebcc81SSteven Rostedt 
2101d61f82d0SSteven Rostedt 	/* Force update next time */
2102d61f82d0SSteven Rostedt 	saved_ftrace_func = NULL;
210360a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if we want ftrace running */
210460a7ecf4SSteven Rostedt 	if (ftrace_start_up)
210530fb6aa7SJiri Olsa 		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
2106b0fc494fSSteven Rostedt }
2107b0fc494fSSteven Rostedt 
2108e309b41dSIngo Molnar static void ftrace_shutdown_sysctl(void)
2109b0fc494fSSteven Rostedt {
21104eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
21114eebcc81SSteven Rostedt 		return;
21124eebcc81SSteven Rostedt 
211360a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if ftrace is running */
211460a7ecf4SSteven Rostedt 	if (ftrace_start_up)
211579e406d7SSteven Rostedt 		ftrace_run_update_code(FTRACE_DISABLE_CALLS);
2116b0fc494fSSteven Rostedt }
2117b0fc494fSSteven Rostedt 
21183d083395SSteven Rostedt static cycle_t		ftrace_update_time;
21193d083395SSteven Rostedt static unsigned long	ftrace_update_cnt;
21203d083395SSteven Rostedt unsigned long		ftrace_update_tot_cnt;
21213d083395SSteven Rostedt 
2122f7bc8b61SSteven Rostedt static int ops_traces_mod(struct ftrace_ops *ops)
2123f7bc8b61SSteven Rostedt {
2124f7bc8b61SSteven Rostedt 	struct ftrace_hash *hash;
2125f7bc8b61SSteven Rostedt 
2126f7bc8b61SSteven Rostedt 	hash = ops->filter_hash;
212706a51d93SSteven Rostedt 	return ftrace_hash_empty(hash);
2128f7bc8b61SSteven Rostedt }
2129f7bc8b61SSteven Rostedt 
213031e88909SSteven Rostedt static int ftrace_update_code(struct module *mod)
21313d083395SSteven Rostedt {
213285ae32aeSSteven Rostedt 	struct ftrace_page *pg;
2133e94142a6SLai Jiangshan 	struct dyn_ftrace *p;
2134f22f9a89SAbhishek Sagar 	cycle_t start, stop;
2135f7bc8b61SSteven Rostedt 	unsigned long ref = 0;
213685ae32aeSSteven Rostedt 	int i;
2137f7bc8b61SSteven Rostedt 
2138f7bc8b61SSteven Rostedt 	/*
2139f7bc8b61SSteven Rostedt 	 * When adding a module, we need to check if tracers are
2140f7bc8b61SSteven Rostedt 	 * currently enabled and if they are set to trace all functions.
2141f7bc8b61SSteven Rostedt 	 * If they are, we need to enable the module functions as well
2142f7bc8b61SSteven Rostedt 	 * as update the reference counts for those function records.
2143f7bc8b61SSteven Rostedt 	 */
2144f7bc8b61SSteven Rostedt 	if (mod) {
2145f7bc8b61SSteven Rostedt 		struct ftrace_ops *ops;
2146f7bc8b61SSteven Rostedt 
2147f7bc8b61SSteven Rostedt 		for (ops = ftrace_ops_list;
2148f7bc8b61SSteven Rostedt 		     ops != &ftrace_list_end; ops = ops->next) {
2149f7bc8b61SSteven Rostedt 			if (ops->flags & FTRACE_OPS_FL_ENABLED &&
2150f7bc8b61SSteven Rostedt 			    ops_traces_mod(ops))
2151f7bc8b61SSteven Rostedt 				ref++;
2152f7bc8b61SSteven Rostedt 		}
2153f7bc8b61SSteven Rostedt 	}
21543d083395SSteven Rostedt 
2155750ed1a4SIngo Molnar 	start = ftrace_now(raw_smp_processor_id());
21563d083395SSteven Rostedt 	ftrace_update_cnt = 0;
21573d083395SSteven Rostedt 
215885ae32aeSSteven Rostedt 	for (pg = ftrace_new_pgs; pg; pg = pg->next) {
2159f22f9a89SAbhishek Sagar 
216085ae32aeSSteven Rostedt 		for (i = 0; i < pg->index; i++) {
216108f5ac90SSteven Rostedt 			/* If something went wrong, bail without enabling anything */
216208f5ac90SSteven Rostedt 			if (unlikely(ftrace_disabled))
216308f5ac90SSteven Rostedt 				return -1;
21643d083395SSteven Rostedt 
216585ae32aeSSteven Rostedt 			p = &pg->records[i];
2166f7bc8b61SSteven Rostedt 			p->flags = ref;
2167f22f9a89SAbhishek Sagar 
21685cb084bbSJiri Olsa 			/*
216925985edcSLucas De Marchi 			 * Do the initial record conversion from mcount jump
21705cb084bbSJiri Olsa 			 * to the NOP instructions.
21715cb084bbSJiri Olsa 			 */
217232082309SSteven Rostedt 			if (!ftrace_code_disable(mod, p))
2173d2c8c3eaSSteven Rostedt 				break;
21745cb084bbSJiri Olsa 
21753d083395SSteven Rostedt 			ftrace_update_cnt++;
21765cb084bbSJiri Olsa 
21775cb084bbSJiri Olsa 			/*
21785cb084bbSJiri Olsa 			 * If the tracing is enabled, go ahead and enable the record.
21795cb084bbSJiri Olsa 			 *
21805cb084bbSJiri Olsa 			 * The reason not to enable the record immediatelly is the
21815cb084bbSJiri Olsa 			 * inherent check of ftrace_make_nop/ftrace_make_call for
21825cb084bbSJiri Olsa 			 * correct previous instructions.  Making first the NOP
21835cb084bbSJiri Olsa 			 * conversion puts the module to the correct state, thus
21845cb084bbSJiri Olsa 			 * passing the ftrace_make_call check.
21855cb084bbSJiri Olsa 			 */
2186f7bc8b61SSteven Rostedt 			if (ftrace_start_up && ref) {
21875cb084bbSJiri Olsa 				int failed = __ftrace_replace_code(p, 1);
218832082309SSteven Rostedt 				if (failed)
21895cb084bbSJiri Olsa 					ftrace_bug(failed, p->ip);
21905cb084bbSJiri Olsa 			}
21915cb084bbSJiri Olsa 		}
219285ae32aeSSteven Rostedt 	}
219385ae32aeSSteven Rostedt 
219485ae32aeSSteven Rostedt 	ftrace_new_pgs = NULL;
21953d083395SSteven Rostedt 
2196750ed1a4SIngo Molnar 	stop = ftrace_now(raw_smp_processor_id());
21973d083395SSteven Rostedt 	ftrace_update_time = stop - start;
21983d083395SSteven Rostedt 	ftrace_update_tot_cnt += ftrace_update_cnt;
21993d083395SSteven Rostedt 
220016444a8aSArnaldo Carvalho de Melo 	return 0;
220116444a8aSArnaldo Carvalho de Melo }
220216444a8aSArnaldo Carvalho de Melo 
2203a7900875SSteven Rostedt static int ftrace_allocate_records(struct ftrace_page *pg, int count)
22043c1720f0SSteven Rostedt {
2205a7900875SSteven Rostedt 	int order;
22063c1720f0SSteven Rostedt 	int cnt;
22073c1720f0SSteven Rostedt 
2208a7900875SSteven Rostedt 	if (WARN_ON(!count))
2209a7900875SSteven Rostedt 		return -EINVAL;
2210a7900875SSteven Rostedt 
2211a7900875SSteven Rostedt 	order = get_count_order(DIV_ROUND_UP(count, ENTRIES_PER_PAGE));
22123c1720f0SSteven Rostedt 
22133c1720f0SSteven Rostedt 	/*
2214a7900875SSteven Rostedt 	 * We want to fill as much as possible. No more than a page
2215a7900875SSteven Rostedt 	 * may be empty.
22163c1720f0SSteven Rostedt 	 */
2217a7900875SSteven Rostedt 	while ((PAGE_SIZE << order) / ENTRY_SIZE >= count + ENTRIES_PER_PAGE)
2218a7900875SSteven Rostedt 		order--;
22193c1720f0SSteven Rostedt 
2220a7900875SSteven Rostedt  again:
2221a7900875SSteven Rostedt 	pg->records = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
2222a7900875SSteven Rostedt 
2223a7900875SSteven Rostedt 	if (!pg->records) {
2224a7900875SSteven Rostedt 		/* if we can't allocate this size, try something smaller */
2225a7900875SSteven Rostedt 		if (!order)
2226a7900875SSteven Rostedt 			return -ENOMEM;
2227a7900875SSteven Rostedt 		order >>= 1;
2228a7900875SSteven Rostedt 		goto again;
2229a7900875SSteven Rostedt 	}
2230a7900875SSteven Rostedt 
2231a7900875SSteven Rostedt 	cnt = (PAGE_SIZE << order) / ENTRY_SIZE;
2232a7900875SSteven Rostedt 	pg->size = cnt;
2233a7900875SSteven Rostedt 
2234a7900875SSteven Rostedt 	if (cnt > count)
2235a7900875SSteven Rostedt 		cnt = count;
2236a7900875SSteven Rostedt 
2237a7900875SSteven Rostedt 	return cnt;
2238a7900875SSteven Rostedt }
2239a7900875SSteven Rostedt 
2240a7900875SSteven Rostedt static struct ftrace_page *
2241a7900875SSteven Rostedt ftrace_allocate_pages(unsigned long num_to_init)
2242a7900875SSteven Rostedt {
2243a7900875SSteven Rostedt 	struct ftrace_page *start_pg;
2244a7900875SSteven Rostedt 	struct ftrace_page *pg;
2245a7900875SSteven Rostedt 	int order;
2246a7900875SSteven Rostedt 	int cnt;
2247a7900875SSteven Rostedt 
2248a7900875SSteven Rostedt 	if (!num_to_init)
2249a7900875SSteven Rostedt 		return 0;
2250a7900875SSteven Rostedt 
2251a7900875SSteven Rostedt 	start_pg = pg = kzalloc(sizeof(*pg), GFP_KERNEL);
2252a7900875SSteven Rostedt 	if (!pg)
2253a7900875SSteven Rostedt 		return NULL;
2254a7900875SSteven Rostedt 
2255a7900875SSteven Rostedt 	/*
2256a7900875SSteven Rostedt 	 * Try to allocate as much as possible in one continues
2257a7900875SSteven Rostedt 	 * location that fills in all of the space. We want to
2258a7900875SSteven Rostedt 	 * waste as little space as possible.
2259a7900875SSteven Rostedt 	 */
2260a7900875SSteven Rostedt 	for (;;) {
2261a7900875SSteven Rostedt 		cnt = ftrace_allocate_records(pg, num_to_init);
2262a7900875SSteven Rostedt 		if (cnt < 0)
2263a7900875SSteven Rostedt 			goto free_pages;
2264a7900875SSteven Rostedt 
2265a7900875SSteven Rostedt 		num_to_init -= cnt;
2266a7900875SSteven Rostedt 		if (!num_to_init)
2267a7900875SSteven Rostedt 			break;
2268a7900875SSteven Rostedt 
2269a7900875SSteven Rostedt 		pg->next = kzalloc(sizeof(*pg), GFP_KERNEL);
2270a7900875SSteven Rostedt 		if (!pg->next)
2271a7900875SSteven Rostedt 			goto free_pages;
2272a7900875SSteven Rostedt 
2273a7900875SSteven Rostedt 		pg = pg->next;
2274a7900875SSteven Rostedt 	}
2275a7900875SSteven Rostedt 
2276a7900875SSteven Rostedt 	return start_pg;
2277a7900875SSteven Rostedt 
2278a7900875SSteven Rostedt  free_pages:
2279a7900875SSteven Rostedt 	while (start_pg) {
2280a7900875SSteven Rostedt 		order = get_count_order(pg->size / ENTRIES_PER_PAGE);
2281a7900875SSteven Rostedt 		free_pages((unsigned long)pg->records, order);
2282a7900875SSteven Rostedt 		start_pg = pg->next;
2283a7900875SSteven Rostedt 		kfree(pg);
2284a7900875SSteven Rostedt 		pg = start_pg;
2285a7900875SSteven Rostedt 	}
2286a7900875SSteven Rostedt 	pr_info("ftrace: FAILED to allocate memory for functions\n");
2287a7900875SSteven Rostedt 	return NULL;
2288a7900875SSteven Rostedt }
2289a7900875SSteven Rostedt 
2290a7900875SSteven Rostedt static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
2291a7900875SSteven Rostedt {
2292a7900875SSteven Rostedt 	int cnt;
2293a7900875SSteven Rostedt 
2294a7900875SSteven Rostedt 	if (!num_to_init) {
2295a7900875SSteven Rostedt 		pr_info("ftrace: No functions to be traced?\n");
2296a7900875SSteven Rostedt 		return -1;
2297a7900875SSteven Rostedt 	}
22983c1720f0SSteven Rostedt 
229968bf21aaSSteven Rostedt 	cnt = num_to_init / ENTRIES_PER_PAGE;
230008f5ac90SSteven Rostedt 	pr_info("ftrace: allocating %ld entries in %d pages\n",
23015821e1b7Swalimis 		num_to_init, cnt + 1);
23023c1720f0SSteven Rostedt 
23033c1720f0SSteven Rostedt 	return 0;
23043c1720f0SSteven Rostedt }
23053c1720f0SSteven Rostedt 
23065072c59fSSteven Rostedt #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
23075072c59fSSteven Rostedt 
23085072c59fSSteven Rostedt struct ftrace_iterator {
230998c4fd04SSteven Rostedt 	loff_t				pos;
23102bccfffdSSteven Rostedt 	loff_t				func_pos;
23115072c59fSSteven Rostedt 	struct ftrace_page		*pg;
23124aeb6967SSteven Rostedt 	struct dyn_ftrace		*func;
23134aeb6967SSteven Rostedt 	struct ftrace_func_probe	*probe;
23144aeb6967SSteven Rostedt 	struct trace_parser		parser;
23151cf41dd7SSteven Rostedt 	struct ftrace_hash		*hash;
231633dc9b12SSteven Rostedt 	struct ftrace_ops		*ops;
23178fc0c701SSteven Rostedt 	int				hidx;
2318431aa3fbSSteven Rostedt 	int				idx;
23195072c59fSSteven Rostedt 	unsigned			flags;
23205072c59fSSteven Rostedt };
23215072c59fSSteven Rostedt 
2322e309b41dSIngo Molnar static void *
23234aeb6967SSteven Rostedt t_hash_next(struct seq_file *m, loff_t *pos)
23248fc0c701SSteven Rostedt {
23258fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
23264aeb6967SSteven Rostedt 	struct hlist_node *hnd = NULL;
23278fc0c701SSteven Rostedt 	struct hlist_head *hhd;
23288fc0c701SSteven Rostedt 
23298fc0c701SSteven Rostedt 	(*pos)++;
233098c4fd04SSteven Rostedt 	iter->pos = *pos;
23318fc0c701SSteven Rostedt 
23324aeb6967SSteven Rostedt 	if (iter->probe)
23334aeb6967SSteven Rostedt 		hnd = &iter->probe->node;
23348fc0c701SSteven Rostedt  retry:
23358fc0c701SSteven Rostedt 	if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
23368fc0c701SSteven Rostedt 		return NULL;
23378fc0c701SSteven Rostedt 
23388fc0c701SSteven Rostedt 	hhd = &ftrace_func_hash[iter->hidx];
23398fc0c701SSteven Rostedt 
23408fc0c701SSteven Rostedt 	if (hlist_empty(hhd)) {
23418fc0c701SSteven Rostedt 		iter->hidx++;
23428fc0c701SSteven Rostedt 		hnd = NULL;
23438fc0c701SSteven Rostedt 		goto retry;
23448fc0c701SSteven Rostedt 	}
23458fc0c701SSteven Rostedt 
23468fc0c701SSteven Rostedt 	if (!hnd)
23478fc0c701SSteven Rostedt 		hnd = hhd->first;
23488fc0c701SSteven Rostedt 	else {
23498fc0c701SSteven Rostedt 		hnd = hnd->next;
23508fc0c701SSteven Rostedt 		if (!hnd) {
23518fc0c701SSteven Rostedt 			iter->hidx++;
23528fc0c701SSteven Rostedt 			goto retry;
23538fc0c701SSteven Rostedt 		}
23548fc0c701SSteven Rostedt 	}
23558fc0c701SSteven Rostedt 
23564aeb6967SSteven Rostedt 	if (WARN_ON_ONCE(!hnd))
23574aeb6967SSteven Rostedt 		return NULL;
23584aeb6967SSteven Rostedt 
23594aeb6967SSteven Rostedt 	iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node);
23604aeb6967SSteven Rostedt 
23614aeb6967SSteven Rostedt 	return iter;
23628fc0c701SSteven Rostedt }
23638fc0c701SSteven Rostedt 
23648fc0c701SSteven Rostedt static void *t_hash_start(struct seq_file *m, loff_t *pos)
23658fc0c701SSteven Rostedt {
23668fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
23678fc0c701SSteven Rostedt 	void *p = NULL;
2368d82d6244SLi Zefan 	loff_t l;
2369d82d6244SLi Zefan 
237069a3083cSSteven Rostedt 	if (!(iter->flags & FTRACE_ITER_DO_HASH))
237169a3083cSSteven Rostedt 		return NULL;
237269a3083cSSteven Rostedt 
23732bccfffdSSteven Rostedt 	if (iter->func_pos > *pos)
23742bccfffdSSteven Rostedt 		return NULL;
23758fc0c701SSteven Rostedt 
2376d82d6244SLi Zefan 	iter->hidx = 0;
23772bccfffdSSteven Rostedt 	for (l = 0; l <= (*pos - iter->func_pos); ) {
23784aeb6967SSteven Rostedt 		p = t_hash_next(m, &l);
2379d82d6244SLi Zefan 		if (!p)
2380d82d6244SLi Zefan 			break;
2381d82d6244SLi Zefan 	}
23824aeb6967SSteven Rostedt 	if (!p)
23834aeb6967SSteven Rostedt 		return NULL;
23844aeb6967SSteven Rostedt 
238598c4fd04SSteven Rostedt 	/* Only set this if we have an item */
238698c4fd04SSteven Rostedt 	iter->flags |= FTRACE_ITER_HASH;
238798c4fd04SSteven Rostedt 
23884aeb6967SSteven Rostedt 	return iter;
23898fc0c701SSteven Rostedt }
23908fc0c701SSteven Rostedt 
23914aeb6967SSteven Rostedt static int
23924aeb6967SSteven Rostedt t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
23938fc0c701SSteven Rostedt {
2394b6887d79SSteven Rostedt 	struct ftrace_func_probe *rec;
23958fc0c701SSteven Rostedt 
23964aeb6967SSteven Rostedt 	rec = iter->probe;
23974aeb6967SSteven Rostedt 	if (WARN_ON_ONCE(!rec))
23984aeb6967SSteven Rostedt 		return -EIO;
23998fc0c701SSteven Rostedt 
2400809dcf29SSteven Rostedt 	if (rec->ops->print)
2401809dcf29SSteven Rostedt 		return rec->ops->print(m, rec->ip, rec->ops, rec->data);
2402809dcf29SSteven Rostedt 
2403b375a11aSSteven Rostedt 	seq_printf(m, "%ps:%ps", (void *)rec->ip, (void *)rec->ops->func);
24048fc0c701SSteven Rostedt 
24058fc0c701SSteven Rostedt 	if (rec->data)
24068fc0c701SSteven Rostedt 		seq_printf(m, ":%p", rec->data);
24078fc0c701SSteven Rostedt 	seq_putc(m, '\n');
24088fc0c701SSteven Rostedt 
24098fc0c701SSteven Rostedt 	return 0;
24108fc0c701SSteven Rostedt }
24118fc0c701SSteven Rostedt 
24128fc0c701SSteven Rostedt static void *
24135072c59fSSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos)
24145072c59fSSteven Rostedt {
24155072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
2416fc13cb0cSSteven Rostedt 	struct ftrace_ops *ops = iter->ops;
24175072c59fSSteven Rostedt 	struct dyn_ftrace *rec = NULL;
24185072c59fSSteven Rostedt 
241945a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
242045a4a237SSteven Rostedt 		return NULL;
242145a4a237SSteven Rostedt 
24228fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
24234aeb6967SSteven Rostedt 		return t_hash_next(m, pos);
24248fc0c701SSteven Rostedt 
24255072c59fSSteven Rostedt 	(*pos)++;
24261106b699SJiri Olsa 	iter->pos = iter->func_pos = *pos;
24275072c59fSSteven Rostedt 
24280c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL)
242957c072c7SSteven Rostedt 		return t_hash_start(m, pos);
24300c75a3edSSteven Rostedt 
24315072c59fSSteven Rostedt  retry:
24325072c59fSSteven Rostedt 	if (iter->idx >= iter->pg->index) {
24335072c59fSSteven Rostedt 		if (iter->pg->next) {
24345072c59fSSteven Rostedt 			iter->pg = iter->pg->next;
24355072c59fSSteven Rostedt 			iter->idx = 0;
24365072c59fSSteven Rostedt 			goto retry;
24375072c59fSSteven Rostedt 		}
24385072c59fSSteven Rostedt 	} else {
24395072c59fSSteven Rostedt 		rec = &iter->pg->records[iter->idx++];
244032082309SSteven Rostedt 		if (((iter->flags & FTRACE_ITER_FILTER) &&
2441f45948e8SSteven Rostedt 		     !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) ||
24420183fb1cSSteven Rostedt 
244341c52c0dSSteven Rostedt 		    ((iter->flags & FTRACE_ITER_NOTRACE) &&
2444647bcd03SSteven Rostedt 		     !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) ||
2445647bcd03SSteven Rostedt 
2446647bcd03SSteven Rostedt 		    ((iter->flags & FTRACE_ITER_ENABLED) &&
2447647bcd03SSteven Rostedt 		     !(rec->flags & ~FTRACE_FL_MASK))) {
2448647bcd03SSteven Rostedt 
24495072c59fSSteven Rostedt 			rec = NULL;
24505072c59fSSteven Rostedt 			goto retry;
24515072c59fSSteven Rostedt 		}
24525072c59fSSteven Rostedt 	}
24535072c59fSSteven Rostedt 
24544aeb6967SSteven Rostedt 	if (!rec)
245557c072c7SSteven Rostedt 		return t_hash_start(m, pos);
24564aeb6967SSteven Rostedt 
24574aeb6967SSteven Rostedt 	iter->func = rec;
24584aeb6967SSteven Rostedt 
24594aeb6967SSteven Rostedt 	return iter;
24605072c59fSSteven Rostedt }
24615072c59fSSteven Rostedt 
246298c4fd04SSteven Rostedt static void reset_iter_read(struct ftrace_iterator *iter)
246398c4fd04SSteven Rostedt {
246498c4fd04SSteven Rostedt 	iter->pos = 0;
246598c4fd04SSteven Rostedt 	iter->func_pos = 0;
246670f77b3fSDan Carpenter 	iter->flags &= ~(FTRACE_ITER_PRINTALL | FTRACE_ITER_HASH);
24675072c59fSSteven Rostedt }
24685072c59fSSteven Rostedt 
24695072c59fSSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos)
24705072c59fSSteven Rostedt {
24715072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
2472fc13cb0cSSteven Rostedt 	struct ftrace_ops *ops = iter->ops;
24735072c59fSSteven Rostedt 	void *p = NULL;
2474694ce0a5SLi Zefan 	loff_t l;
24755072c59fSSteven Rostedt 
24768fc0c701SSteven Rostedt 	mutex_lock(&ftrace_lock);
247745a4a237SSteven Rostedt 
247845a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
247945a4a237SSteven Rostedt 		return NULL;
248045a4a237SSteven Rostedt 
24810c75a3edSSteven Rostedt 	/*
248298c4fd04SSteven Rostedt 	 * If an lseek was done, then reset and start from beginning.
248398c4fd04SSteven Rostedt 	 */
248498c4fd04SSteven Rostedt 	if (*pos < iter->pos)
248598c4fd04SSteven Rostedt 		reset_iter_read(iter);
248698c4fd04SSteven Rostedt 
248798c4fd04SSteven Rostedt 	/*
24880c75a3edSSteven Rostedt 	 * For set_ftrace_filter reading, if we have the filter
24890c75a3edSSteven Rostedt 	 * off, we can short cut and just print out that all
24900c75a3edSSteven Rostedt 	 * functions are enabled.
24910c75a3edSSteven Rostedt 	 */
249206a51d93SSteven Rostedt 	if (iter->flags & FTRACE_ITER_FILTER &&
249306a51d93SSteven Rostedt 	    ftrace_hash_empty(ops->filter_hash)) {
24940c75a3edSSteven Rostedt 		if (*pos > 0)
24958fc0c701SSteven Rostedt 			return t_hash_start(m, pos);
24960c75a3edSSteven Rostedt 		iter->flags |= FTRACE_ITER_PRINTALL;
2497df091625SChris Wright 		/* reset in case of seek/pread */
2498df091625SChris Wright 		iter->flags &= ~FTRACE_ITER_HASH;
24990c75a3edSSteven Rostedt 		return iter;
25000c75a3edSSteven Rostedt 	}
25010c75a3edSSteven Rostedt 
25028fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
25038fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
25048fc0c701SSteven Rostedt 
250598c4fd04SSteven Rostedt 	/*
250698c4fd04SSteven Rostedt 	 * Unfortunately, we need to restart at ftrace_pages_start
250798c4fd04SSteven Rostedt 	 * every time we let go of the ftrace_mutex. This is because
250898c4fd04SSteven Rostedt 	 * those pointers can change without the lock.
250998c4fd04SSteven Rostedt 	 */
2510694ce0a5SLi Zefan 	iter->pg = ftrace_pages_start;
2511694ce0a5SLi Zefan 	iter->idx = 0;
2512694ce0a5SLi Zefan 	for (l = 0; l <= *pos; ) {
2513694ce0a5SLi Zefan 		p = t_next(m, p, &l);
2514694ce0a5SLi Zefan 		if (!p)
2515694ce0a5SLi Zefan 			break;
251650cdaf08SLiming Wang 	}
25175821e1b7Swalimis 
251869a3083cSSteven Rostedt 	if (!p)
25198fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
25208fc0c701SSteven Rostedt 
25214aeb6967SSteven Rostedt 	return iter;
25225072c59fSSteven Rostedt }
25235072c59fSSteven Rostedt 
25245072c59fSSteven Rostedt static void t_stop(struct seq_file *m, void *p)
25255072c59fSSteven Rostedt {
25268fc0c701SSteven Rostedt 	mutex_unlock(&ftrace_lock);
25275072c59fSSteven Rostedt }
25285072c59fSSteven Rostedt 
25295072c59fSSteven Rostedt static int t_show(struct seq_file *m, void *v)
25305072c59fSSteven Rostedt {
25310c75a3edSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
25324aeb6967SSteven Rostedt 	struct dyn_ftrace *rec;
25335072c59fSSteven Rostedt 
25348fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
25354aeb6967SSteven Rostedt 		return t_hash_show(m, iter);
25368fc0c701SSteven Rostedt 
25370c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL) {
25380c75a3edSSteven Rostedt 		seq_printf(m, "#### all functions enabled ####\n");
25390c75a3edSSteven Rostedt 		return 0;
25400c75a3edSSteven Rostedt 	}
25410c75a3edSSteven Rostedt 
25424aeb6967SSteven Rostedt 	rec = iter->func;
25434aeb6967SSteven Rostedt 
25445072c59fSSteven Rostedt 	if (!rec)
25455072c59fSSteven Rostedt 		return 0;
25465072c59fSSteven Rostedt 
2547647bcd03SSteven Rostedt 	seq_printf(m, "%ps", (void *)rec->ip);
2548647bcd03SSteven Rostedt 	if (iter->flags & FTRACE_ITER_ENABLED)
254908f6fba5SSteven Rostedt 		seq_printf(m, " (%ld)%s",
255008f6fba5SSteven Rostedt 			   rec->flags & ~FTRACE_FL_MASK,
255108f6fba5SSteven Rostedt 			   rec->flags & FTRACE_FL_REGS ? " R" : "");
2552647bcd03SSteven Rostedt 	seq_printf(m, "\n");
25535072c59fSSteven Rostedt 
25545072c59fSSteven Rostedt 	return 0;
25555072c59fSSteven Rostedt }
25565072c59fSSteven Rostedt 
255788e9d34cSJames Morris static const struct seq_operations show_ftrace_seq_ops = {
25585072c59fSSteven Rostedt 	.start = t_start,
25595072c59fSSteven Rostedt 	.next = t_next,
25605072c59fSSteven Rostedt 	.stop = t_stop,
25615072c59fSSteven Rostedt 	.show = t_show,
25625072c59fSSteven Rostedt };
25635072c59fSSteven Rostedt 
2564e309b41dSIngo Molnar static int
25655072c59fSSteven Rostedt ftrace_avail_open(struct inode *inode, struct file *file)
25665072c59fSSteven Rostedt {
25675072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
25685072c59fSSteven Rostedt 
25694eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
25704eebcc81SSteven Rostedt 		return -ENODEV;
25714eebcc81SSteven Rostedt 
257250e18b94SJiri Olsa 	iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
257350e18b94SJiri Olsa 	if (iter) {
25745072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
2575fc13cb0cSSteven Rostedt 		iter->ops = &global_ops;
25764bf39a94SIngo Molnar 	}
25775072c59fSSteven Rostedt 
257850e18b94SJiri Olsa 	return iter ? 0 : -ENOMEM;
25795072c59fSSteven Rostedt }
25805072c59fSSteven Rostedt 
2581647bcd03SSteven Rostedt static int
2582647bcd03SSteven Rostedt ftrace_enabled_open(struct inode *inode, struct file *file)
2583647bcd03SSteven Rostedt {
2584647bcd03SSteven Rostedt 	struct ftrace_iterator *iter;
2585647bcd03SSteven Rostedt 
2586647bcd03SSteven Rostedt 	if (unlikely(ftrace_disabled))
2587647bcd03SSteven Rostedt 		return -ENODEV;
2588647bcd03SSteven Rostedt 
258950e18b94SJiri Olsa 	iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
259050e18b94SJiri Olsa 	if (iter) {
2591647bcd03SSteven Rostedt 		iter->pg = ftrace_pages_start;
2592647bcd03SSteven Rostedt 		iter->flags = FTRACE_ITER_ENABLED;
2593fc13cb0cSSteven Rostedt 		iter->ops = &global_ops;
2594647bcd03SSteven Rostedt 	}
2595647bcd03SSteven Rostedt 
259650e18b94SJiri Olsa 	return iter ? 0 : -ENOMEM;
2597647bcd03SSteven Rostedt }
2598647bcd03SSteven Rostedt 
25991cf41dd7SSteven Rostedt static void ftrace_filter_reset(struct ftrace_hash *hash)
26005072c59fSSteven Rostedt {
260152baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
26021cf41dd7SSteven Rostedt 	ftrace_hash_clear(hash);
260352baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
26045072c59fSSteven Rostedt }
26055072c59fSSteven Rostedt 
2606fc13cb0cSSteven Rostedt /**
2607fc13cb0cSSteven Rostedt  * ftrace_regex_open - initialize function tracer filter files
2608fc13cb0cSSteven Rostedt  * @ops: The ftrace_ops that hold the hash filters
2609fc13cb0cSSteven Rostedt  * @flag: The type of filter to process
2610fc13cb0cSSteven Rostedt  * @inode: The inode, usually passed in to your open routine
2611fc13cb0cSSteven Rostedt  * @file: The file, usually passed in to your open routine
2612fc13cb0cSSteven Rostedt  *
2613fc13cb0cSSteven Rostedt  * ftrace_regex_open() initializes the filter files for the
2614fc13cb0cSSteven Rostedt  * @ops. Depending on @flag it may process the filter hash or
2615fc13cb0cSSteven Rostedt  * the notrace hash of @ops. With this called from the open
2616fc13cb0cSSteven Rostedt  * routine, you can use ftrace_filter_write() for the write
2617fc13cb0cSSteven Rostedt  * routine if @flag has FTRACE_ITER_FILTER set, or
2618fc13cb0cSSteven Rostedt  * ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set.
2619fc13cb0cSSteven Rostedt  * ftrace_regex_lseek() should be used as the lseek routine, and
2620fc13cb0cSSteven Rostedt  * release must call ftrace_regex_release().
2621fc13cb0cSSteven Rostedt  */
2622fc13cb0cSSteven Rostedt int
2623f45948e8SSteven Rostedt ftrace_regex_open(struct ftrace_ops *ops, int flag,
26241cf41dd7SSteven Rostedt 		  struct inode *inode, struct file *file)
26255072c59fSSteven Rostedt {
26265072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
2627f45948e8SSteven Rostedt 	struct ftrace_hash *hash;
26285072c59fSSteven Rostedt 	int ret = 0;
26295072c59fSSteven Rostedt 
26304eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
26314eebcc81SSteven Rostedt 		return -ENODEV;
26324eebcc81SSteven Rostedt 
26335072c59fSSteven Rostedt 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
26345072c59fSSteven Rostedt 	if (!iter)
26355072c59fSSteven Rostedt 		return -ENOMEM;
26365072c59fSSteven Rostedt 
2637689fd8b6S[email protected] 	if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) {
2638689fd8b6S[email protected] 		kfree(iter);
2639689fd8b6S[email protected] 		return -ENOMEM;
2640689fd8b6S[email protected] 	}
2641689fd8b6S[email protected] 
2642f45948e8SSteven Rostedt 	if (flag & FTRACE_ITER_NOTRACE)
2643f45948e8SSteven Rostedt 		hash = ops->notrace_hash;
2644f45948e8SSteven Rostedt 	else
2645f45948e8SSteven Rostedt 		hash = ops->filter_hash;
2646f45948e8SSteven Rostedt 
264733dc9b12SSteven Rostedt 	iter->ops = ops;
264833dc9b12SSteven Rostedt 	iter->flags = flag;
264933dc9b12SSteven Rostedt 
265033dc9b12SSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
265133dc9b12SSteven Rostedt 		mutex_lock(&ftrace_lock);
265233dc9b12SSteven Rostedt 		iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
265333dc9b12SSteven Rostedt 		mutex_unlock(&ftrace_lock);
265433dc9b12SSteven Rostedt 
265533dc9b12SSteven Rostedt 		if (!iter->hash) {
265633dc9b12SSteven Rostedt 			trace_parser_put(&iter->parser);
265733dc9b12SSteven Rostedt 			kfree(iter);
265833dc9b12SSteven Rostedt 			return -ENOMEM;
265933dc9b12SSteven Rostedt 		}
266033dc9b12SSteven Rostedt 	}
26611cf41dd7SSteven Rostedt 
266241c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
266333dc9b12SSteven Rostedt 
26645072c59fSSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
26658650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC))
266633dc9b12SSteven Rostedt 		ftrace_filter_reset(iter->hash);
26675072c59fSSteven Rostedt 
26685072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
26695072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
26705072c59fSSteven Rostedt 
26715072c59fSSteven Rostedt 		ret = seq_open(file, &show_ftrace_seq_ops);
26725072c59fSSteven Rostedt 		if (!ret) {
26735072c59fSSteven Rostedt 			struct seq_file *m = file->private_data;
26745072c59fSSteven Rostedt 			m->private = iter;
267579fe249cSLi Zefan 		} else {
267633dc9b12SSteven Rostedt 			/* Failed */
267733dc9b12SSteven Rostedt 			free_ftrace_hash(iter->hash);
267879fe249cSLi Zefan 			trace_parser_put(&iter->parser);
26795072c59fSSteven Rostedt 			kfree(iter);
268079fe249cSLi Zefan 		}
26815072c59fSSteven Rostedt 	} else
26825072c59fSSteven Rostedt 		file->private_data = iter;
268341c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
26845072c59fSSteven Rostedt 
26855072c59fSSteven Rostedt 	return ret;
26865072c59fSSteven Rostedt }
26875072c59fSSteven Rostedt 
268841c52c0dSSteven Rostedt static int
268941c52c0dSSteven Rostedt ftrace_filter_open(struct inode *inode, struct file *file)
269041c52c0dSSteven Rostedt {
269169a3083cSSteven Rostedt 	return ftrace_regex_open(&global_ops,
269269a3083cSSteven Rostedt 			FTRACE_ITER_FILTER | FTRACE_ITER_DO_HASH,
26931cf41dd7SSteven Rostedt 			inode, file);
269441c52c0dSSteven Rostedt }
269541c52c0dSSteven Rostedt 
269641c52c0dSSteven Rostedt static int
269741c52c0dSSteven Rostedt ftrace_notrace_open(struct inode *inode, struct file *file)
269841c52c0dSSteven Rostedt {
2699f45948e8SSteven Rostedt 	return ftrace_regex_open(&global_ops, FTRACE_ITER_NOTRACE,
27001cf41dd7SSteven Rostedt 				 inode, file);
270141c52c0dSSteven Rostedt }
270241c52c0dSSteven Rostedt 
2703fc13cb0cSSteven Rostedt loff_t
2704965c8e59SAndrew Morton ftrace_regex_lseek(struct file *file, loff_t offset, int whence)
27055072c59fSSteven Rostedt {
27065072c59fSSteven Rostedt 	loff_t ret;
27075072c59fSSteven Rostedt 
27085072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ)
2709965c8e59SAndrew Morton 		ret = seq_lseek(file, offset, whence);
27105072c59fSSteven Rostedt 	else
27115072c59fSSteven Rostedt 		file->f_pos = ret = 1;
27125072c59fSSteven Rostedt 
27135072c59fSSteven Rostedt 	return ret;
27145072c59fSSteven Rostedt }
27155072c59fSSteven Rostedt 
271664e7c440SSteven Rostedt static int ftrace_match(char *str, char *regex, int len, int type)
27179f4801e3SSteven Rostedt {
27189f4801e3SSteven Rostedt 	int matched = 0;
2719751e9983SLi Zefan 	int slen;
27209f4801e3SSteven Rostedt 
27219f4801e3SSteven Rostedt 	switch (type) {
27229f4801e3SSteven Rostedt 	case MATCH_FULL:
27239f4801e3SSteven Rostedt 		if (strcmp(str, regex) == 0)
27249f4801e3SSteven Rostedt 			matched = 1;
27259f4801e3SSteven Rostedt 		break;
27269f4801e3SSteven Rostedt 	case MATCH_FRONT_ONLY:
27279f4801e3SSteven Rostedt 		if (strncmp(str, regex, len) == 0)
27289f4801e3SSteven Rostedt 			matched = 1;
27299f4801e3SSteven Rostedt 		break;
27309f4801e3SSteven Rostedt 	case MATCH_MIDDLE_ONLY:
27319f4801e3SSteven Rostedt 		if (strstr(str, regex))
27329f4801e3SSteven Rostedt 			matched = 1;
27339f4801e3SSteven Rostedt 		break;
27349f4801e3SSteven Rostedt 	case MATCH_END_ONLY:
2735751e9983SLi Zefan 		slen = strlen(str);
2736751e9983SLi Zefan 		if (slen >= len && memcmp(str + slen - len, regex, len) == 0)
27379f4801e3SSteven Rostedt 			matched = 1;
27389f4801e3SSteven Rostedt 		break;
27399f4801e3SSteven Rostedt 	}
27409f4801e3SSteven Rostedt 
27419f4801e3SSteven Rostedt 	return matched;
27429f4801e3SSteven Rostedt }
27439f4801e3SSteven Rostedt 
2744b448c4e3SSteven Rostedt static int
27451cf41dd7SSteven Rostedt enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not)
274664e7c440SSteven Rostedt {
2747b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
2748b448c4e3SSteven Rostedt 	int ret = 0;
2749b448c4e3SSteven Rostedt 
27501cf41dd7SSteven Rostedt 	entry = ftrace_lookup_ip(hash, rec->ip);
2751b448c4e3SSteven Rostedt 	if (not) {
2752b448c4e3SSteven Rostedt 		/* Do nothing if it doesn't exist */
2753b448c4e3SSteven Rostedt 		if (!entry)
2754b448c4e3SSteven Rostedt 			return 0;
2755b448c4e3SSteven Rostedt 
275633dc9b12SSteven Rostedt 		free_hash_entry(hash, entry);
2757b448c4e3SSteven Rostedt 	} else {
2758b448c4e3SSteven Rostedt 		/* Do nothing if it exists */
2759b448c4e3SSteven Rostedt 		if (entry)
2760b448c4e3SSteven Rostedt 			return 0;
2761b448c4e3SSteven Rostedt 
2762b448c4e3SSteven Rostedt 		ret = add_hash_entry(hash, rec->ip);
2763b448c4e3SSteven Rostedt 	}
2764b448c4e3SSteven Rostedt 	return ret;
2765996e87beSSteven Rostedt }
2766996e87beSSteven Rostedt 
276764e7c440SSteven Rostedt static int
2768b9df92d2SSteven Rostedt ftrace_match_record(struct dyn_ftrace *rec, char *mod,
2769b9df92d2SSteven Rostedt 		    char *regex, int len, int type)
277064e7c440SSteven Rostedt {
277164e7c440SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
2772b9df92d2SSteven Rostedt 	char *modname;
277364e7c440SSteven Rostedt 
2774b9df92d2SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
2775b9df92d2SSteven Rostedt 
2776b9df92d2SSteven Rostedt 	if (mod) {
2777b9df92d2SSteven Rostedt 		/* module lookup requires matching the module */
2778b9df92d2SSteven Rostedt 		if (!modname || strcmp(modname, mod))
2779b9df92d2SSteven Rostedt 			return 0;
2780b9df92d2SSteven Rostedt 
2781b9df92d2SSteven Rostedt 		/* blank search means to match all funcs in the mod */
2782b9df92d2SSteven Rostedt 		if (!len)
2783b9df92d2SSteven Rostedt 			return 1;
2784b9df92d2SSteven Rostedt 	}
2785b9df92d2SSteven Rostedt 
278664e7c440SSteven Rostedt 	return ftrace_match(str, regex, len, type);
278764e7c440SSteven Rostedt }
278864e7c440SSteven Rostedt 
27891cf41dd7SSteven Rostedt static int
27901cf41dd7SSteven Rostedt match_records(struct ftrace_hash *hash, char *buff,
27911cf41dd7SSteven Rostedt 	      int len, char *mod, int not)
27929f4801e3SSteven Rostedt {
2793b9df92d2SSteven Rostedt 	unsigned search_len = 0;
27949f4801e3SSteven Rostedt 	struct ftrace_page *pg;
27959f4801e3SSteven Rostedt 	struct dyn_ftrace *rec;
2796b9df92d2SSteven Rostedt 	int type = MATCH_FULL;
2797b9df92d2SSteven Rostedt 	char *search = buff;
2798311d16daSLi Zefan 	int found = 0;
2799b448c4e3SSteven Rostedt 	int ret;
28009f4801e3SSteven Rostedt 
2801b9df92d2SSteven Rostedt 	if (len) {
28023f6fe06dSFrederic Weisbecker 		type = filter_parse_regex(buff, len, &search, &not);
28039f4801e3SSteven Rostedt 		search_len = strlen(search);
2804b9df92d2SSteven Rostedt 	}
2805b9df92d2SSteven Rostedt 
280652baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
2807b9df92d2SSteven Rostedt 
2808b9df92d2SSteven Rostedt 	if (unlikely(ftrace_disabled))
2809b9df92d2SSteven Rostedt 		goto out_unlock;
2810b9df92d2SSteven Rostedt 
2811265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
2812b9df92d2SSteven Rostedt 		if (ftrace_match_record(rec, mod, search, search_len, type)) {
28131cf41dd7SSteven Rostedt 			ret = enter_record(hash, rec, not);
2814b448c4e3SSteven Rostedt 			if (ret < 0) {
2815b448c4e3SSteven Rostedt 				found = ret;
2816b448c4e3SSteven Rostedt 				goto out_unlock;
2817b448c4e3SSteven Rostedt 			}
2818311d16daSLi Zefan 			found = 1;
28195072c59fSSteven Rostedt 		}
2820265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
2821b9df92d2SSteven Rostedt  out_unlock:
282252baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2823311d16daSLi Zefan 
2824311d16daSLi Zefan 	return found;
28255072c59fSSteven Rostedt }
28265072c59fSSteven Rostedt 
282764e7c440SSteven Rostedt static int
28281cf41dd7SSteven Rostedt ftrace_match_records(struct ftrace_hash *hash, char *buff, int len)
282964e7c440SSteven Rostedt {
28301cf41dd7SSteven Rostedt 	return match_records(hash, buff, len, NULL, 0);
283164e7c440SSteven Rostedt }
283264e7c440SSteven Rostedt 
28331cf41dd7SSteven Rostedt static int
28341cf41dd7SSteven Rostedt ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod)
283564e7c440SSteven Rostedt {
283664e7c440SSteven Rostedt 	int not = 0;
28376a24a244SSteven Rostedt 
283864e7c440SSteven Rostedt 	/* blank or '*' mean the same */
283964e7c440SSteven Rostedt 	if (strcmp(buff, "*") == 0)
284064e7c440SSteven Rostedt 		buff[0] = 0;
284164e7c440SSteven Rostedt 
284264e7c440SSteven Rostedt 	/* handle the case of 'dont filter this module' */
284364e7c440SSteven Rostedt 	if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) {
284464e7c440SSteven Rostedt 		buff[0] = 0;
284564e7c440SSteven Rostedt 		not = 1;
284664e7c440SSteven Rostedt 	}
284764e7c440SSteven Rostedt 
28481cf41dd7SSteven Rostedt 	return match_records(hash, buff, strlen(buff), mod, not);
284964e7c440SSteven Rostedt }
285064e7c440SSteven Rostedt 
2851f6180773SSteven Rostedt /*
2852f6180773SSteven Rostedt  * We register the module command as a template to show others how
2853f6180773SSteven Rostedt  * to register the a command as well.
2854f6180773SSteven Rostedt  */
2855f6180773SSteven Rostedt 
2856f6180773SSteven Rostedt static int
285743dd61c9SSteven Rostedt ftrace_mod_callback(struct ftrace_hash *hash,
285843dd61c9SSteven Rostedt 		    char *func, char *cmd, char *param, int enable)
2859f6180773SSteven Rostedt {
2860f6180773SSteven Rostedt 	char *mod;
2861b448c4e3SSteven Rostedt 	int ret = -EINVAL;
2862f6180773SSteven Rostedt 
2863f6180773SSteven Rostedt 	/*
2864f6180773SSteven Rostedt 	 * cmd == 'mod' because we only registered this func
2865f6180773SSteven Rostedt 	 * for the 'mod' ftrace_func_command.
2866f6180773SSteven Rostedt 	 * But if you register one func with multiple commands,
2867f6180773SSteven Rostedt 	 * you can tell which command was used by the cmd
2868f6180773SSteven Rostedt 	 * parameter.
2869f6180773SSteven Rostedt 	 */
2870f6180773SSteven Rostedt 
2871f6180773SSteven Rostedt 	/* we must have a module name */
2872f6180773SSteven Rostedt 	if (!param)
2873b448c4e3SSteven Rostedt 		return ret;
2874f6180773SSteven Rostedt 
2875f6180773SSteven Rostedt 	mod = strsep(&param, ":");
2876f6180773SSteven Rostedt 	if (!strlen(mod))
2877b448c4e3SSteven Rostedt 		return ret;
2878f6180773SSteven Rostedt 
28791cf41dd7SSteven Rostedt 	ret = ftrace_match_module_records(hash, func, mod);
2880b448c4e3SSteven Rostedt 	if (!ret)
2881b448c4e3SSteven Rostedt 		ret = -EINVAL;
2882b448c4e3SSteven Rostedt 	if (ret < 0)
2883b448c4e3SSteven Rostedt 		return ret;
2884b448c4e3SSteven Rostedt 
2885f6180773SSteven Rostedt 	return 0;
2886f6180773SSteven Rostedt }
2887f6180773SSteven Rostedt 
2888f6180773SSteven Rostedt static struct ftrace_func_command ftrace_mod_cmd = {
2889f6180773SSteven Rostedt 	.name			= "mod",
2890f6180773SSteven Rostedt 	.func			= ftrace_mod_callback,
2891f6180773SSteven Rostedt };
2892f6180773SSteven Rostedt 
2893f6180773SSteven Rostedt static int __init ftrace_mod_cmd_init(void)
2894f6180773SSteven Rostedt {
2895f6180773SSteven Rostedt 	return register_ftrace_command(&ftrace_mod_cmd);
2896f6180773SSteven Rostedt }
28976f415672SSteven Rostedt core_initcall(ftrace_mod_cmd_init);
2898f6180773SSteven Rostedt 
28992f5f6ad9SSteven Rostedt static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
2900a1e2e31dSSteven Rostedt 				      struct ftrace_ops *op, struct pt_regs *pt_regs)
290159df055fSSteven Rostedt {
2902b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
290359df055fSSteven Rostedt 	struct hlist_head *hhd;
290459df055fSSteven Rostedt 	struct hlist_node *n;
290559df055fSSteven Rostedt 	unsigned long key;
290659df055fSSteven Rostedt 
290759df055fSSteven Rostedt 	key = hash_long(ip, FTRACE_HASH_BITS);
290859df055fSSteven Rostedt 
290959df055fSSteven Rostedt 	hhd = &ftrace_func_hash[key];
291059df055fSSteven Rostedt 
291159df055fSSteven Rostedt 	if (hlist_empty(hhd))
291259df055fSSteven Rostedt 		return;
291359df055fSSteven Rostedt 
291459df055fSSteven Rostedt 	/*
291559df055fSSteven Rostedt 	 * Disable preemption for these calls to prevent a RCU grace
291659df055fSSteven Rostedt 	 * period. This syncs the hash iteration and freeing of items
291759df055fSSteven Rostedt 	 * on the hash. rcu_read_lock is too dangerous here.
291859df055fSSteven Rostedt 	 */
29195168ae50SSteven Rostedt 	preempt_disable_notrace();
292059df055fSSteven Rostedt 	hlist_for_each_entry_rcu(entry, n, hhd, node) {
292159df055fSSteven Rostedt 		if (entry->ip == ip)
292259df055fSSteven Rostedt 			entry->ops->func(ip, parent_ip, &entry->data);
292359df055fSSteven Rostedt 	}
29245168ae50SSteven Rostedt 	preempt_enable_notrace();
292559df055fSSteven Rostedt }
292659df055fSSteven Rostedt 
2927b6887d79SSteven Rostedt static struct ftrace_ops trace_probe_ops __read_mostly =
292859df055fSSteven Rostedt {
2929b6887d79SSteven Rostedt 	.func		= function_trace_probe_call,
293059df055fSSteven Rostedt };
293159df055fSSteven Rostedt 
2932b6887d79SSteven Rostedt static int ftrace_probe_registered;
293359df055fSSteven Rostedt 
2934b6887d79SSteven Rostedt static void __enable_ftrace_function_probe(void)
293559df055fSSteven Rostedt {
2936b848914cSSteven Rostedt 	int ret;
293759df055fSSteven Rostedt 	int i;
293859df055fSSteven Rostedt 
2939b6887d79SSteven Rostedt 	if (ftrace_probe_registered)
294059df055fSSteven Rostedt 		return;
294159df055fSSteven Rostedt 
294259df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
294359df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
294459df055fSSteven Rostedt 		if (hhd->first)
294559df055fSSteven Rostedt 			break;
294659df055fSSteven Rostedt 	}
294759df055fSSteven Rostedt 	/* Nothing registered? */
294859df055fSSteven Rostedt 	if (i == FTRACE_FUNC_HASHSIZE)
294959df055fSSteven Rostedt 		return;
295059df055fSSteven Rostedt 
2951b848914cSSteven Rostedt 	ret = __register_ftrace_function(&trace_probe_ops);
2952b848914cSSteven Rostedt 	if (!ret)
2953a1cd6173SSteven Rostedt 		ret = ftrace_startup(&trace_probe_ops, 0);
2954b848914cSSteven Rostedt 
2955b6887d79SSteven Rostedt 	ftrace_probe_registered = 1;
295659df055fSSteven Rostedt }
295759df055fSSteven Rostedt 
2958b6887d79SSteven Rostedt static void __disable_ftrace_function_probe(void)
295959df055fSSteven Rostedt {
2960b848914cSSteven Rostedt 	int ret;
296159df055fSSteven Rostedt 	int i;
296259df055fSSteven Rostedt 
2963b6887d79SSteven Rostedt 	if (!ftrace_probe_registered)
296459df055fSSteven Rostedt 		return;
296559df055fSSteven Rostedt 
296659df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
296759df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
296859df055fSSteven Rostedt 		if (hhd->first)
296959df055fSSteven Rostedt 			return;
297059df055fSSteven Rostedt 	}
297159df055fSSteven Rostedt 
297259df055fSSteven Rostedt 	/* no more funcs left */
2973b848914cSSteven Rostedt 	ret = __unregister_ftrace_function(&trace_probe_ops);
2974b848914cSSteven Rostedt 	if (!ret)
2975b848914cSSteven Rostedt 		ftrace_shutdown(&trace_probe_ops, 0);
2976b848914cSSteven Rostedt 
2977b6887d79SSteven Rostedt 	ftrace_probe_registered = 0;
297859df055fSSteven Rostedt }
297959df055fSSteven Rostedt 
298059df055fSSteven Rostedt 
29817818b388SSteven Rostedt (Red Hat) static void ftrace_free_entry(struct ftrace_func_probe *entry)
298259df055fSSteven Rostedt {
298359df055fSSteven Rostedt 	if (entry->ops->free)
2984e67efb93SSteven Rostedt (Red Hat) 		entry->ops->free(entry->ops, entry->ip, &entry->data);
298559df055fSSteven Rostedt 	kfree(entry);
298659df055fSSteven Rostedt }
298759df055fSSteven Rostedt 
298859df055fSSteven Rostedt int
2989b6887d79SSteven Rostedt register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
299059df055fSSteven Rostedt 			      void *data)
299159df055fSSteven Rostedt {
2992b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
2993e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
2994e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
299559df055fSSteven Rostedt 	struct ftrace_page *pg;
299659df055fSSteven Rostedt 	struct dyn_ftrace *rec;
299759df055fSSteven Rostedt 	int type, len, not;
29986a24a244SSteven Rostedt 	unsigned long key;
299959df055fSSteven Rostedt 	int count = 0;
300059df055fSSteven Rostedt 	char *search;
3001e1df4cb6SSteven Rostedt (Red Hat) 	int ret;
300259df055fSSteven Rostedt 
30033f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(glob, strlen(glob), &search, &not);
300459df055fSSteven Rostedt 	len = strlen(search);
300559df055fSSteven Rostedt 
3006b6887d79SSteven Rostedt 	/* we do not support '!' for function probes */
300759df055fSSteven Rostedt 	if (WARN_ON(not))
300859df055fSSteven Rostedt 		return -EINVAL;
300959df055fSSteven Rostedt 
301059df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
301159df055fSSteven Rostedt 
3012e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3013e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash) {
3014e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENOMEM;
301545a4a237SSteven Rostedt 		goto out_unlock;
3016e1df4cb6SSteven Rostedt (Red Hat) 	}
3017e1df4cb6SSteven Rostedt (Red Hat) 
3018e1df4cb6SSteven Rostedt (Red Hat) 	if (unlikely(ftrace_disabled)) {
3019e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENODEV;
3020e1df4cb6SSteven Rostedt (Red Hat) 		goto out_unlock;
3021e1df4cb6SSteven Rostedt (Red Hat) 	}
302245a4a237SSteven Rostedt 
302359df055fSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
302459df055fSSteven Rostedt 
3025b9df92d2SSteven Rostedt 		if (!ftrace_match_record(rec, NULL, search, len, type))
302659df055fSSteven Rostedt 			continue;
302759df055fSSteven Rostedt 
302859df055fSSteven Rostedt 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
302959df055fSSteven Rostedt 		if (!entry) {
3030b6887d79SSteven Rostedt 			/* If we did not process any, then return error */
303159df055fSSteven Rostedt 			if (!count)
303259df055fSSteven Rostedt 				count = -ENOMEM;
303359df055fSSteven Rostedt 			goto out_unlock;
303459df055fSSteven Rostedt 		}
303559df055fSSteven Rostedt 
303659df055fSSteven Rostedt 		count++;
303759df055fSSteven Rostedt 
303859df055fSSteven Rostedt 		entry->data = data;
303959df055fSSteven Rostedt 
304059df055fSSteven Rostedt 		/*
304159df055fSSteven Rostedt 		 * The caller might want to do something special
304259df055fSSteven Rostedt 		 * for each function we find. We call the callback
304359df055fSSteven Rostedt 		 * to give the caller an opportunity to do so.
304459df055fSSteven Rostedt 		 */
3045e67efb93SSteven Rostedt (Red Hat) 		if (ops->init) {
3046e67efb93SSteven Rostedt (Red Hat) 			if (ops->init(ops, rec->ip, &entry->data) < 0) {
304759df055fSSteven Rostedt 				/* caller does not like this func */
304859df055fSSteven Rostedt 				kfree(entry);
304959df055fSSteven Rostedt 				continue;
305059df055fSSteven Rostedt 			}
305159df055fSSteven Rostedt 		}
305259df055fSSteven Rostedt 
3053e1df4cb6SSteven Rostedt (Red Hat) 		ret = enter_record(hash, rec, 0);
3054e1df4cb6SSteven Rostedt (Red Hat) 		if (ret < 0) {
3055e1df4cb6SSteven Rostedt (Red Hat) 			kfree(entry);
3056e1df4cb6SSteven Rostedt (Red Hat) 			count = ret;
3057e1df4cb6SSteven Rostedt (Red Hat) 			goto out_unlock;
3058e1df4cb6SSteven Rostedt (Red Hat) 		}
3059e1df4cb6SSteven Rostedt (Red Hat) 
306059df055fSSteven Rostedt 		entry->ops = ops;
306159df055fSSteven Rostedt 		entry->ip = rec->ip;
306259df055fSSteven Rostedt 
306359df055fSSteven Rostedt 		key = hash_long(entry->ip, FTRACE_HASH_BITS);
306459df055fSSteven Rostedt 		hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]);
306559df055fSSteven Rostedt 
306659df055fSSteven Rostedt 	} while_for_each_ftrace_rec();
3067e1df4cb6SSteven Rostedt (Red Hat) 
3068e1df4cb6SSteven Rostedt (Red Hat) 	ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3069e1df4cb6SSteven Rostedt (Red Hat) 	if (ret < 0)
3070e1df4cb6SSteven Rostedt (Red Hat) 		count = ret;
3071e1df4cb6SSteven Rostedt (Red Hat) 
3072b6887d79SSteven Rostedt 	__enable_ftrace_function_probe();
307359df055fSSteven Rostedt 
307459df055fSSteven Rostedt  out_unlock:
307559df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
3076e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
307759df055fSSteven Rostedt 
307859df055fSSteven Rostedt 	return count;
307959df055fSSteven Rostedt }
308059df055fSSteven Rostedt 
308159df055fSSteven Rostedt enum {
3082b6887d79SSteven Rostedt 	PROBE_TEST_FUNC		= 1,
3083b6887d79SSteven Rostedt 	PROBE_TEST_DATA		= 2
308459df055fSSteven Rostedt };
308559df055fSSteven Rostedt 
308659df055fSSteven Rostedt static void
3087b6887d79SSteven Rostedt __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
308859df055fSSteven Rostedt 				  void *data, int flags)
308959df055fSSteven Rostedt {
3090e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_func_entry *rec_entry;
3091b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
30927818b388SSteven Rostedt (Red Hat) 	struct ftrace_func_probe *p;
3093e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
30947818b388SSteven Rostedt (Red Hat) 	struct list_head free_list;
3095e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
309659df055fSSteven Rostedt 	struct hlist_node *n, *tmp;
309759df055fSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
309859df055fSSteven Rostedt 	int type = MATCH_FULL;
309959df055fSSteven Rostedt 	int i, len = 0;
310059df055fSSteven Rostedt 	char *search;
310159df055fSSteven Rostedt 
3102b36461daSAtsushi Tsuji 	if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
310359df055fSSteven Rostedt 		glob = NULL;
3104b36461daSAtsushi Tsuji 	else if (glob) {
310559df055fSSteven Rostedt 		int not;
310659df055fSSteven Rostedt 
31073f6fe06dSFrederic Weisbecker 		type = filter_parse_regex(glob, strlen(glob), &search, &not);
310859df055fSSteven Rostedt 		len = strlen(search);
310959df055fSSteven Rostedt 
3110b6887d79SSteven Rostedt 		/* we do not support '!' for function probes */
311159df055fSSteven Rostedt 		if (WARN_ON(not))
311259df055fSSteven Rostedt 			return;
311359df055fSSteven Rostedt 	}
311459df055fSSteven Rostedt 
311559df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
3116e1df4cb6SSteven Rostedt (Red Hat) 
3117e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3118e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash)
3119e1df4cb6SSteven Rostedt (Red Hat) 		/* Hmm, should report this somehow */
3120e1df4cb6SSteven Rostedt (Red Hat) 		goto out_unlock;
3121e1df4cb6SSteven Rostedt (Red Hat) 
31227818b388SSteven Rostedt (Red Hat) 	INIT_LIST_HEAD(&free_list);
31237818b388SSteven Rostedt (Red Hat) 
312459df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
312559df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
312659df055fSSteven Rostedt 
312759df055fSSteven Rostedt 		hlist_for_each_entry_safe(entry, n, tmp, hhd, node) {
312859df055fSSteven Rostedt 
312959df055fSSteven Rostedt 			/* break up if statements for readability */
3130b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_FUNC) && entry->ops != ops)
313159df055fSSteven Rostedt 				continue;
313259df055fSSteven Rostedt 
3133b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_DATA) && entry->data != data)
313459df055fSSteven Rostedt 				continue;
313559df055fSSteven Rostedt 
313659df055fSSteven Rostedt 			/* do this last, since it is the most expensive */
313759df055fSSteven Rostedt 			if (glob) {
313859df055fSSteven Rostedt 				kallsyms_lookup(entry->ip, NULL, NULL,
313959df055fSSteven Rostedt 						NULL, str);
314059df055fSSteven Rostedt 				if (!ftrace_match(str, glob, len, type))
314159df055fSSteven Rostedt 					continue;
314259df055fSSteven Rostedt 			}
314359df055fSSteven Rostedt 
3144e1df4cb6SSteven Rostedt (Red Hat) 			rec_entry = ftrace_lookup_ip(hash, entry->ip);
3145e1df4cb6SSteven Rostedt (Red Hat) 			/* It is possible more than one entry had this ip */
3146e1df4cb6SSteven Rostedt (Red Hat) 			if (rec_entry)
3147e1df4cb6SSteven Rostedt (Red Hat) 				free_hash_entry(hash, rec_entry);
3148e1df4cb6SSteven Rostedt (Red Hat) 
3149740466bcSSteven Rostedt (Red Hat) 			hlist_del_rcu(&entry->node);
31507818b388SSteven Rostedt (Red Hat) 			list_add(&entry->free_list, &free_list);
315159df055fSSteven Rostedt 		}
315259df055fSSteven Rostedt 	}
3153b6887d79SSteven Rostedt 	__disable_ftrace_function_probe();
3154e1df4cb6SSteven Rostedt (Red Hat) 	/*
3155e1df4cb6SSteven Rostedt (Red Hat) 	 * Remove after the disable is called. Otherwise, if the last
3156e1df4cb6SSteven Rostedt (Red Hat) 	 * probe is removed, a null hash means *all enabled*.
3157e1df4cb6SSteven Rostedt (Red Hat) 	 */
3158e1df4cb6SSteven Rostedt (Red Hat) 	ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
31597818b388SSteven Rostedt (Red Hat) 	synchronize_sched();
31607818b388SSteven Rostedt (Red Hat) 	list_for_each_entry_safe(entry, p, &free_list, free_list) {
31617818b388SSteven Rostedt (Red Hat) 		list_del(&entry->free_list);
31627818b388SSteven Rostedt (Red Hat) 		ftrace_free_entry(entry);
31637818b388SSteven Rostedt (Red Hat) 	}
31647818b388SSteven Rostedt (Red Hat) 
3165e1df4cb6SSteven Rostedt (Red Hat)  out_unlock:
316659df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
3167e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
316859df055fSSteven Rostedt }
316959df055fSSteven Rostedt 
317059df055fSSteven Rostedt void
3171b6887d79SSteven Rostedt unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
317259df055fSSteven Rostedt 				void *data)
317359df055fSSteven Rostedt {
3174b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, data,
3175b6887d79SSteven Rostedt 					  PROBE_TEST_FUNC | PROBE_TEST_DATA);
317659df055fSSteven Rostedt }
317759df055fSSteven Rostedt 
317859df055fSSteven Rostedt void
3179b6887d79SSteven Rostedt unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops)
318059df055fSSteven Rostedt {
3181b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC);
318259df055fSSteven Rostedt }
318359df055fSSteven Rostedt 
3184b6887d79SSteven Rostedt void unregister_ftrace_function_probe_all(char *glob)
318559df055fSSteven Rostedt {
3186b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, NULL, NULL, 0);
318759df055fSSteven Rostedt }
318859df055fSSteven Rostedt 
3189f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands);
3190f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex);
3191f6180773SSteven Rostedt 
3192f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd)
3193f6180773SSteven Rostedt {
3194f6180773SSteven Rostedt 	struct ftrace_func_command *p;
3195f6180773SSteven Rostedt 	int ret = 0;
3196f6180773SSteven Rostedt 
3197f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3198f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3199f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3200f6180773SSteven Rostedt 			ret = -EBUSY;
3201f6180773SSteven Rostedt 			goto out_unlock;
3202f6180773SSteven Rostedt 		}
3203f6180773SSteven Rostedt 	}
3204f6180773SSteven Rostedt 	list_add(&cmd->list, &ftrace_commands);
3205f6180773SSteven Rostedt  out_unlock:
3206f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3207f6180773SSteven Rostedt 
3208f6180773SSteven Rostedt 	return ret;
3209f6180773SSteven Rostedt }
3210f6180773SSteven Rostedt 
3211f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd)
3212f6180773SSteven Rostedt {
3213f6180773SSteven Rostedt 	struct ftrace_func_command *p, *n;
3214f6180773SSteven Rostedt 	int ret = -ENODEV;
3215f6180773SSteven Rostedt 
3216f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3217f6180773SSteven Rostedt 	list_for_each_entry_safe(p, n, &ftrace_commands, list) {
3218f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3219f6180773SSteven Rostedt 			ret = 0;
3220f6180773SSteven Rostedt 			list_del_init(&p->list);
3221f6180773SSteven Rostedt 			goto out_unlock;
3222f6180773SSteven Rostedt 		}
3223f6180773SSteven Rostedt 	}
3224f6180773SSteven Rostedt  out_unlock:
3225f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3226f6180773SSteven Rostedt 
3227f6180773SSteven Rostedt 	return ret;
3228f6180773SSteven Rostedt }
3229f6180773SSteven Rostedt 
323033dc9b12SSteven Rostedt static int ftrace_process_regex(struct ftrace_hash *hash,
323133dc9b12SSteven Rostedt 				char *buff, int len, int enable)
323264e7c440SSteven Rostedt {
3233f6180773SSteven Rostedt 	char *func, *command, *next = buff;
32346a24a244SSteven Rostedt 	struct ftrace_func_command *p;
32350aff1c0cSGuoWen Li 	int ret = -EINVAL;
323664e7c440SSteven Rostedt 
323764e7c440SSteven Rostedt 	func = strsep(&next, ":");
323864e7c440SSteven Rostedt 
323964e7c440SSteven Rostedt 	if (!next) {
32401cf41dd7SSteven Rostedt 		ret = ftrace_match_records(hash, func, len);
3241b448c4e3SSteven Rostedt 		if (!ret)
3242b448c4e3SSteven Rostedt 			ret = -EINVAL;
3243b448c4e3SSteven Rostedt 		if (ret < 0)
3244311d16daSLi Zefan 			return ret;
3245b448c4e3SSteven Rostedt 		return 0;
324664e7c440SSteven Rostedt 	}
324764e7c440SSteven Rostedt 
3248f6180773SSteven Rostedt 	/* command found */
324964e7c440SSteven Rostedt 
325064e7c440SSteven Rostedt 	command = strsep(&next, ":");
325164e7c440SSteven Rostedt 
3252f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3253f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3254f6180773SSteven Rostedt 		if (strcmp(p->name, command) == 0) {
325543dd61c9SSteven Rostedt 			ret = p->func(hash, func, command, next, enable);
3256f6180773SSteven Rostedt 			goto out_unlock;
325764e7c440SSteven Rostedt 		}
3258f6180773SSteven Rostedt 	}
3259f6180773SSteven Rostedt  out_unlock:
3260f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
326164e7c440SSteven Rostedt 
3262f6180773SSteven Rostedt 	return ret;
326364e7c440SSteven Rostedt }
326464e7c440SSteven Rostedt 
3265e309b41dSIngo Molnar static ssize_t
326641c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf,
326741c52c0dSSteven Rostedt 		   size_t cnt, loff_t *ppos, int enable)
32685072c59fSSteven Rostedt {
32695072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
3270689fd8b6S[email protected] 	struct trace_parser *parser;
3271689fd8b6S[email protected] 	ssize_t ret, read;
32725072c59fSSteven Rostedt 
32734ba7978eSLi Zefan 	if (!cnt)
32745072c59fSSteven Rostedt 		return 0;
32755072c59fSSteven Rostedt 
327641c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
32775072c59fSSteven Rostedt 
327845a4a237SSteven Rostedt 	ret = -ENODEV;
327945a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
328045a4a237SSteven Rostedt 		goto out_unlock;
328145a4a237SSteven Rostedt 
32825072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
32835072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
32845072c59fSSteven Rostedt 		iter = m->private;
32855072c59fSSteven Rostedt 	} else
32865072c59fSSteven Rostedt 		iter = file->private_data;
32875072c59fSSteven Rostedt 
3288689fd8b6S[email protected] 	parser = &iter->parser;
3289689fd8b6S[email protected] 	read = trace_get_user(parser, ubuf, cnt, ppos);
32905072c59fSSteven Rostedt 
32914ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded(parser) &&
3292689fd8b6S[email protected] 	    !trace_parser_cont(parser)) {
329333dc9b12SSteven Rostedt 		ret = ftrace_process_regex(iter->hash, parser->buffer,
3294689fd8b6S[email protected] 					   parser->idx, enable);
3295313254a9SLi Zefan 		trace_parser_clear(parser);
32965072c59fSSteven Rostedt 		if (ret)
3297ed146b25SLi Zefan 			goto out_unlock;
32985072c59fSSteven Rostedt 	}
32995072c59fSSteven Rostedt 
33005072c59fSSteven Rostedt 	ret = read;
3301ed146b25SLi Zefan out_unlock:
330241c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
3303ed146b25SLi Zefan 
33045072c59fSSteven Rostedt 	return ret;
33055072c59fSSteven Rostedt }
33065072c59fSSteven Rostedt 
3307fc13cb0cSSteven Rostedt ssize_t
330841c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf,
330941c52c0dSSteven Rostedt 		    size_t cnt, loff_t *ppos)
331041c52c0dSSteven Rostedt {
331141c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
331241c52c0dSSteven Rostedt }
331341c52c0dSSteven Rostedt 
3314fc13cb0cSSteven Rostedt ssize_t
331541c52c0dSSteven Rostedt ftrace_notrace_write(struct file *file, const char __user *ubuf,
331641c52c0dSSteven Rostedt 		     size_t cnt, loff_t *ppos)
331741c52c0dSSteven Rostedt {
331841c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 0);
331941c52c0dSSteven Rostedt }
332041c52c0dSSteven Rostedt 
332133dc9b12SSteven Rostedt static int
3322647664eaSMasami Hiramatsu ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
3323647664eaSMasami Hiramatsu {
3324647664eaSMasami Hiramatsu 	struct ftrace_func_entry *entry;
3325647664eaSMasami Hiramatsu 
3326647664eaSMasami Hiramatsu 	if (!ftrace_location(ip))
3327647664eaSMasami Hiramatsu 		return -EINVAL;
3328647664eaSMasami Hiramatsu 
3329647664eaSMasami Hiramatsu 	if (remove) {
3330647664eaSMasami Hiramatsu 		entry = ftrace_lookup_ip(hash, ip);
3331647664eaSMasami Hiramatsu 		if (!entry)
3332647664eaSMasami Hiramatsu 			return -ENOENT;
3333647664eaSMasami Hiramatsu 		free_hash_entry(hash, entry);
3334647664eaSMasami Hiramatsu 		return 0;
3335647664eaSMasami Hiramatsu 	}
3336647664eaSMasami Hiramatsu 
3337647664eaSMasami Hiramatsu 	return add_hash_entry(hash, ip);
3338647664eaSMasami Hiramatsu }
3339647664eaSMasami Hiramatsu 
3340647664eaSMasami Hiramatsu static int
3341647664eaSMasami Hiramatsu ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
3342647664eaSMasami Hiramatsu 		unsigned long ip, int remove, int reset, int enable)
334341c52c0dSSteven Rostedt {
334433dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3345f45948e8SSteven Rostedt 	struct ftrace_hash *hash;
334633dc9b12SSteven Rostedt 	int ret;
3347f45948e8SSteven Rostedt 
3348936e074bSSteven Rostedt 	/* All global ops uses the global ops filters */
3349936e074bSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL)
3350936e074bSSteven Rostedt 		ops = &global_ops;
3351936e074bSSteven Rostedt 
335241c52c0dSSteven Rostedt 	if (unlikely(ftrace_disabled))
335333dc9b12SSteven Rostedt 		return -ENODEV;
335441c52c0dSSteven Rostedt 
3355f45948e8SSteven Rostedt 	if (enable)
335633dc9b12SSteven Rostedt 		orig_hash = &ops->filter_hash;
3357f45948e8SSteven Rostedt 	else
335833dc9b12SSteven Rostedt 		orig_hash = &ops->notrace_hash;
335933dc9b12SSteven Rostedt 
336033dc9b12SSteven Rostedt 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
336133dc9b12SSteven Rostedt 	if (!hash)
336233dc9b12SSteven Rostedt 		return -ENOMEM;
3363f45948e8SSteven Rostedt 
336441c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
336541c52c0dSSteven Rostedt 	if (reset)
33661cf41dd7SSteven Rostedt 		ftrace_filter_reset(hash);
3367ac483c44SJiri Olsa 	if (buf && !ftrace_match_records(hash, buf, len)) {
3368ac483c44SJiri Olsa 		ret = -EINVAL;
3369ac483c44SJiri Olsa 		goto out_regex_unlock;
3370ac483c44SJiri Olsa 	}
3371647664eaSMasami Hiramatsu 	if (ip) {
3372647664eaSMasami Hiramatsu 		ret = ftrace_match_addr(hash, ip, remove);
3373647664eaSMasami Hiramatsu 		if (ret < 0)
3374647664eaSMasami Hiramatsu 			goto out_regex_unlock;
3375647664eaSMasami Hiramatsu 	}
337633dc9b12SSteven Rostedt 
337733dc9b12SSteven Rostedt 	mutex_lock(&ftrace_lock);
337841fb61c2SSteven Rostedt 	ret = ftrace_hash_move(ops, enable, orig_hash, hash);
3379072126f4SSteven Rostedt 	if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED
3380072126f4SSteven Rostedt 	    && ftrace_enabled)
338130fb6aa7SJiri Olsa 		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
3382072126f4SSteven Rostedt 
338333dc9b12SSteven Rostedt 	mutex_unlock(&ftrace_lock);
338433dc9b12SSteven Rostedt 
3385ac483c44SJiri Olsa  out_regex_unlock:
338641c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
338733dc9b12SSteven Rostedt 
338833dc9b12SSteven Rostedt 	free_ftrace_hash(hash);
338933dc9b12SSteven Rostedt 	return ret;
339041c52c0dSSteven Rostedt }
339141c52c0dSSteven Rostedt 
3392647664eaSMasami Hiramatsu static int
3393647664eaSMasami Hiramatsu ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
3394647664eaSMasami Hiramatsu 		int reset, int enable)
3395647664eaSMasami Hiramatsu {
3396647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, 0, 0, ip, remove, reset, enable);
3397647664eaSMasami Hiramatsu }
3398647664eaSMasami Hiramatsu 
3399647664eaSMasami Hiramatsu /**
3400647664eaSMasami Hiramatsu  * ftrace_set_filter_ip - set a function to filter on in ftrace by address
3401647664eaSMasami Hiramatsu  * @ops - the ops to set the filter with
3402647664eaSMasami Hiramatsu  * @ip - the address to add to or remove from the filter.
3403647664eaSMasami Hiramatsu  * @remove - non zero to remove the ip from the filter
3404647664eaSMasami Hiramatsu  * @reset - non zero to reset all filters before applying this filter.
3405647664eaSMasami Hiramatsu  *
3406647664eaSMasami Hiramatsu  * Filters denote which functions should be enabled when tracing is enabled
3407647664eaSMasami Hiramatsu  * If @ip is NULL, it failes to update filter.
3408647664eaSMasami Hiramatsu  */
3409647664eaSMasami Hiramatsu int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
3410647664eaSMasami Hiramatsu 			 int remove, int reset)
3411647664eaSMasami Hiramatsu {
3412647664eaSMasami Hiramatsu 	return ftrace_set_addr(ops, ip, remove, reset, 1);
3413647664eaSMasami Hiramatsu }
3414647664eaSMasami Hiramatsu EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
3415647664eaSMasami Hiramatsu 
3416647664eaSMasami Hiramatsu static int
3417647664eaSMasami Hiramatsu ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
3418647664eaSMasami Hiramatsu 		 int reset, int enable)
3419647664eaSMasami Hiramatsu {
3420647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, buf, len, 0, 0, reset, enable);
3421647664eaSMasami Hiramatsu }
3422647664eaSMasami Hiramatsu 
342377a2b37dSSteven Rostedt /**
342477a2b37dSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3425936e074bSSteven Rostedt  * @ops - the ops to set the filter with
342677a2b37dSSteven Rostedt  * @buf - the string that holds the function filter text.
342777a2b37dSSteven Rostedt  * @len - the length of the string.
342877a2b37dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
342977a2b37dSSteven Rostedt  *
343077a2b37dSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
343177a2b37dSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
343277a2b37dSSteven Rostedt  */
3433ac483c44SJiri Olsa int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
3434936e074bSSteven Rostedt 		       int len, int reset)
343577a2b37dSSteven Rostedt {
3436ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 1);
343741c52c0dSSteven Rostedt }
3438936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_filter);
34394eebcc81SSteven Rostedt 
344041c52c0dSSteven Rostedt /**
344141c52c0dSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3442936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
344341c52c0dSSteven Rostedt  * @buf - the string that holds the function notrace text.
344441c52c0dSSteven Rostedt  * @len - the length of the string.
344541c52c0dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
344641c52c0dSSteven Rostedt  *
344741c52c0dSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
344841c52c0dSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
344941c52c0dSSteven Rostedt  * for tracing.
345041c52c0dSSteven Rostedt  */
3451ac483c44SJiri Olsa int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
3452936e074bSSteven Rostedt 			int len, int reset)
3453936e074bSSteven Rostedt {
3454ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 0);
3455936e074bSSteven Rostedt }
3456936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_notrace);
3457936e074bSSteven Rostedt /**
3458936e074bSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3459936e074bSSteven Rostedt  * @ops - the ops to set the filter with
3460936e074bSSteven Rostedt  * @buf - the string that holds the function filter text.
3461936e074bSSteven Rostedt  * @len - the length of the string.
3462936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3463936e074bSSteven Rostedt  *
3464936e074bSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
3465936e074bSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
3466936e074bSSteven Rostedt  */
3467936e074bSSteven Rostedt void ftrace_set_global_filter(unsigned char *buf, int len, int reset)
3468936e074bSSteven Rostedt {
3469936e074bSSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 1);
3470936e074bSSteven Rostedt }
3471936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_filter);
3472936e074bSSteven Rostedt 
3473936e074bSSteven Rostedt /**
3474936e074bSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3475936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
3476936e074bSSteven Rostedt  * @buf - the string that holds the function notrace text.
3477936e074bSSteven Rostedt  * @len - the length of the string.
3478936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3479936e074bSSteven Rostedt  *
3480936e074bSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
3481936e074bSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
3482936e074bSSteven Rostedt  * for tracing.
3483936e074bSSteven Rostedt  */
3484936e074bSSteven Rostedt void ftrace_set_global_notrace(unsigned char *buf, int len, int reset)
348541c52c0dSSteven Rostedt {
3486f45948e8SSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 0);
348777a2b37dSSteven Rostedt }
3488936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_notrace);
348977a2b37dSSteven Rostedt 
34902af15d6aSSteven Rostedt /*
34912af15d6aSSteven Rostedt  * command line interface to allow users to set filters on boot up.
34922af15d6aSSteven Rostedt  */
34932af15d6aSSteven Rostedt #define FTRACE_FILTER_SIZE		COMMAND_LINE_SIZE
34942af15d6aSSteven Rostedt static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
34952af15d6aSSteven Rostedt static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;
34962af15d6aSSteven Rostedt 
34972af15d6aSSteven Rostedt static int __init set_ftrace_notrace(char *str)
34982af15d6aSSteven Rostedt {
34999607a869SChen Gang 	strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
35002af15d6aSSteven Rostedt 	return 1;
35012af15d6aSSteven Rostedt }
35022af15d6aSSteven Rostedt __setup("ftrace_notrace=", set_ftrace_notrace);
35032af15d6aSSteven Rostedt 
35042af15d6aSSteven Rostedt static int __init set_ftrace_filter(char *str)
35052af15d6aSSteven Rostedt {
35069607a869SChen Gang 	strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
35072af15d6aSSteven Rostedt 	return 1;
35082af15d6aSSteven Rostedt }
35092af15d6aSSteven Rostedt __setup("ftrace_filter=", set_ftrace_filter);
35102af15d6aSSteven Rostedt 
3511369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3512f6060f46SLai Jiangshan static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
3513801c29fdSSteven Rostedt static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
3514801c29fdSSteven Rostedt 
3515369bc18fSStefan Assmann static int __init set_graph_function(char *str)
3516369bc18fSStefan Assmann {
351706f43d66SFrederic Weisbecker 	strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
3518369bc18fSStefan Assmann 	return 1;
3519369bc18fSStefan Assmann }
3520369bc18fSStefan Assmann __setup("ftrace_graph_filter=", set_graph_function);
3521369bc18fSStefan Assmann 
3522369bc18fSStefan Assmann static void __init set_ftrace_early_graph(char *buf)
3523369bc18fSStefan Assmann {
3524369bc18fSStefan Assmann 	int ret;
3525369bc18fSStefan Assmann 	char *func;
3526369bc18fSStefan Assmann 
3527369bc18fSStefan Assmann 	while (buf) {
3528369bc18fSStefan Assmann 		func = strsep(&buf, ",");
3529369bc18fSStefan Assmann 		/* we allow only one expression at a time */
3530369bc18fSStefan Assmann 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3531369bc18fSStefan Assmann 				      func);
3532369bc18fSStefan Assmann 		if (ret)
3533369bc18fSStefan Assmann 			printk(KERN_DEBUG "ftrace: function %s not "
3534369bc18fSStefan Assmann 					  "traceable\n", func);
3535369bc18fSStefan Assmann 	}
3536369bc18fSStefan Assmann }
3537369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3538369bc18fSStefan Assmann 
35392a85a37fSSteven Rostedt void __init
35402a85a37fSSteven Rostedt ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable)
35412af15d6aSSteven Rostedt {
35422af15d6aSSteven Rostedt 	char *func;
35432af15d6aSSteven Rostedt 
35442af15d6aSSteven Rostedt 	while (buf) {
35452af15d6aSSteven Rostedt 		func = strsep(&buf, ",");
3546f45948e8SSteven Rostedt 		ftrace_set_regex(ops, func, strlen(func), 0, enable);
35472af15d6aSSteven Rostedt 	}
35482af15d6aSSteven Rostedt }
35492af15d6aSSteven Rostedt 
35502af15d6aSSteven Rostedt static void __init set_ftrace_early_filters(void)
35512af15d6aSSteven Rostedt {
35522af15d6aSSteven Rostedt 	if (ftrace_filter_buf[0])
35532a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_filter_buf, 1);
35542af15d6aSSteven Rostedt 	if (ftrace_notrace_buf[0])
35552a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_notrace_buf, 0);
3556369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3557369bc18fSStefan Assmann 	if (ftrace_graph_buf[0])
3558369bc18fSStefan Assmann 		set_ftrace_early_graph(ftrace_graph_buf);
3559369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
35602af15d6aSSteven Rostedt }
35612af15d6aSSteven Rostedt 
3562fc13cb0cSSteven Rostedt int ftrace_regex_release(struct inode *inode, struct file *file)
35635072c59fSSteven Rostedt {
35645072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
35655072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
356633dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3567689fd8b6S[email protected] 	struct trace_parser *parser;
3568ed926f9bSSteven Rostedt 	int filter_hash;
356933dc9b12SSteven Rostedt 	int ret;
35705072c59fSSteven Rostedt 
357141c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
35725072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
35735072c59fSSteven Rostedt 		iter = m->private;
35745072c59fSSteven Rostedt 
35755072c59fSSteven Rostedt 		seq_release(inode, file);
35765072c59fSSteven Rostedt 	} else
35775072c59fSSteven Rostedt 		iter = file->private_data;
35785072c59fSSteven Rostedt 
3579689fd8b6S[email protected] 	parser = &iter->parser;
3580689fd8b6S[email protected] 	if (trace_parser_loaded(parser)) {
3581689fd8b6S[email protected] 		parser->buffer[parser->idx] = 0;
35821cf41dd7SSteven Rostedt 		ftrace_match_records(iter->hash, parser->buffer, parser->idx);
35835072c59fSSteven Rostedt 	}
35845072c59fSSteven Rostedt 
3585058e297dSSteven Rostedt 	trace_parser_put(parser);
3586058e297dSSteven Rostedt 
3587058e297dSSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
3588ed926f9bSSteven Rostedt 		filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
3589ed926f9bSSteven Rostedt 
3590ed926f9bSSteven Rostedt 		if (filter_hash)
359133dc9b12SSteven Rostedt 			orig_hash = &iter->ops->filter_hash;
3592ed926f9bSSteven Rostedt 		else
3593ed926f9bSSteven Rostedt 			orig_hash = &iter->ops->notrace_hash;
359433dc9b12SSteven Rostedt 
3595e6ea44e9SSteven Rostedt 		mutex_lock(&ftrace_lock);
359641fb61c2SSteven Rostedt 		ret = ftrace_hash_move(iter->ops, filter_hash,
359741fb61c2SSteven Rostedt 				       orig_hash, iter->hash);
359841fb61c2SSteven Rostedt 		if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED)
3599ed926f9bSSteven Rostedt 		    && ftrace_enabled)
360030fb6aa7SJiri Olsa 			ftrace_run_update_code(FTRACE_UPDATE_CALLS);
360141fb61c2SSteven Rostedt 
3602e6ea44e9SSteven Rostedt 		mutex_unlock(&ftrace_lock);
3603058e297dSSteven Rostedt 	}
360433dc9b12SSteven Rostedt 	free_ftrace_hash(iter->hash);
360533dc9b12SSteven Rostedt 	kfree(iter);
3606689fd8b6S[email protected] 
360741c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
36085072c59fSSteven Rostedt 	return 0;
36095072c59fSSteven Rostedt }
36105072c59fSSteven Rostedt 
36115e2336a0SSteven Rostedt static const struct file_operations ftrace_avail_fops = {
36125072c59fSSteven Rostedt 	.open = ftrace_avail_open,
36135072c59fSSteven Rostedt 	.read = seq_read,
36145072c59fSSteven Rostedt 	.llseek = seq_lseek,
36153be04b47SLi Zefan 	.release = seq_release_private,
36165072c59fSSteven Rostedt };
36175072c59fSSteven Rostedt 
3618647bcd03SSteven Rostedt static const struct file_operations ftrace_enabled_fops = {
3619647bcd03SSteven Rostedt 	.open = ftrace_enabled_open,
3620647bcd03SSteven Rostedt 	.read = seq_read,
3621647bcd03SSteven Rostedt 	.llseek = seq_lseek,
3622647bcd03SSteven Rostedt 	.release = seq_release_private,
3623647bcd03SSteven Rostedt };
3624647bcd03SSteven Rostedt 
36255e2336a0SSteven Rostedt static const struct file_operations ftrace_filter_fops = {
36265072c59fSSteven Rostedt 	.open = ftrace_filter_open,
3627850a80cfSLai Jiangshan 	.read = seq_read,
36285072c59fSSteven Rostedt 	.write = ftrace_filter_write,
362998c4fd04SSteven Rostedt 	.llseek = ftrace_regex_lseek,
36301cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
36315072c59fSSteven Rostedt };
36325072c59fSSteven Rostedt 
36335e2336a0SSteven Rostedt static const struct file_operations ftrace_notrace_fops = {
363441c52c0dSSteven Rostedt 	.open = ftrace_notrace_open,
3635850a80cfSLai Jiangshan 	.read = seq_read,
363641c52c0dSSteven Rostedt 	.write = ftrace_notrace_write,
363741c52c0dSSteven Rostedt 	.llseek = ftrace_regex_lseek,
36381cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
363941c52c0dSSteven Rostedt };
364041c52c0dSSteven Rostedt 
3641ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3642ea4e2bc4SSteven Rostedt 
3643ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock);
3644ea4e2bc4SSteven Rostedt 
3645ea4e2bc4SSteven Rostedt int ftrace_graph_count;
3646c7c6b1feSLi Zefan int ftrace_graph_filter_enabled;
3647ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
3648ea4e2bc4SSteven Rostedt 
3649ea4e2bc4SSteven Rostedt static void *
365085951842SLi Zefan __g_next(struct seq_file *m, loff_t *pos)
3651ea4e2bc4SSteven Rostedt {
365285951842SLi Zefan 	if (*pos >= ftrace_graph_count)
3653ea4e2bc4SSteven Rostedt 		return NULL;
3654a4ec5e0cSLi Zefan 	return &ftrace_graph_funcs[*pos];
365585951842SLi Zefan }
3656ea4e2bc4SSteven Rostedt 
365785951842SLi Zefan static void *
365885951842SLi Zefan g_next(struct seq_file *m, void *v, loff_t *pos)
365985951842SLi Zefan {
366085951842SLi Zefan 	(*pos)++;
366185951842SLi Zefan 	return __g_next(m, pos);
3662ea4e2bc4SSteven Rostedt }
3663ea4e2bc4SSteven Rostedt 
3664ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos)
3665ea4e2bc4SSteven Rostedt {
3666ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3667ea4e2bc4SSteven Rostedt 
3668f9349a8fSFrederic Weisbecker 	/* Nothing, tell g_show to print all functions are enabled */
3669c7c6b1feSLi Zefan 	if (!ftrace_graph_filter_enabled && !*pos)
3670f9349a8fSFrederic Weisbecker 		return (void *)1;
3671f9349a8fSFrederic Weisbecker 
367285951842SLi Zefan 	return __g_next(m, pos);
3673ea4e2bc4SSteven Rostedt }
3674ea4e2bc4SSteven Rostedt 
3675ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p)
3676ea4e2bc4SSteven Rostedt {
3677ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3678ea4e2bc4SSteven Rostedt }
3679ea4e2bc4SSteven Rostedt 
3680ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v)
3681ea4e2bc4SSteven Rostedt {
3682ea4e2bc4SSteven Rostedt 	unsigned long *ptr = v;
3683ea4e2bc4SSteven Rostedt 
3684ea4e2bc4SSteven Rostedt 	if (!ptr)
3685ea4e2bc4SSteven Rostedt 		return 0;
3686ea4e2bc4SSteven Rostedt 
3687f9349a8fSFrederic Weisbecker 	if (ptr == (unsigned long *)1) {
3688f9349a8fSFrederic Weisbecker 		seq_printf(m, "#### all functions enabled ####\n");
3689f9349a8fSFrederic Weisbecker 		return 0;
3690f9349a8fSFrederic Weisbecker 	}
3691f9349a8fSFrederic Weisbecker 
3692b375a11aSSteven Rostedt 	seq_printf(m, "%ps\n", (void *)*ptr);
3693ea4e2bc4SSteven Rostedt 
3694ea4e2bc4SSteven Rostedt 	return 0;
3695ea4e2bc4SSteven Rostedt }
3696ea4e2bc4SSteven Rostedt 
369788e9d34cSJames Morris static const struct seq_operations ftrace_graph_seq_ops = {
3698ea4e2bc4SSteven Rostedt 	.start = g_start,
3699ea4e2bc4SSteven Rostedt 	.next = g_next,
3700ea4e2bc4SSteven Rostedt 	.stop = g_stop,
3701ea4e2bc4SSteven Rostedt 	.show = g_show,
3702ea4e2bc4SSteven Rostedt };
3703ea4e2bc4SSteven Rostedt 
3704ea4e2bc4SSteven Rostedt static int
3705ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file)
3706ea4e2bc4SSteven Rostedt {
3707ea4e2bc4SSteven Rostedt 	int ret = 0;
3708ea4e2bc4SSteven Rostedt 
3709ea4e2bc4SSteven Rostedt 	if (unlikely(ftrace_disabled))
3710ea4e2bc4SSteven Rostedt 		return -ENODEV;
3711ea4e2bc4SSteven Rostedt 
3712ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3713ea4e2bc4SSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
37148650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC)) {
3715c7c6b1feSLi Zefan 		ftrace_graph_filter_enabled = 0;
3716ea4e2bc4SSteven Rostedt 		ftrace_graph_count = 0;
3717ea4e2bc4SSteven Rostedt 		memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
3718ea4e2bc4SSteven Rostedt 	}
3719ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3720ea4e2bc4SSteven Rostedt 
3721a4ec5e0cSLi Zefan 	if (file->f_mode & FMODE_READ)
3722a4ec5e0cSLi Zefan 		ret = seq_open(file, &ftrace_graph_seq_ops);
3723a4ec5e0cSLi Zefan 
3724ea4e2bc4SSteven Rostedt 	return ret;
3725ea4e2bc4SSteven Rostedt }
3726ea4e2bc4SSteven Rostedt 
3727ea4e2bc4SSteven Rostedt static int
372887827111SLi Zefan ftrace_graph_release(struct inode *inode, struct file *file)
372987827111SLi Zefan {
373087827111SLi Zefan 	if (file->f_mode & FMODE_READ)
373187827111SLi Zefan 		seq_release(inode, file);
373287827111SLi Zefan 	return 0;
373387827111SLi Zefan }
373487827111SLi Zefan 
373587827111SLi Zefan static int
3736f9349a8fSFrederic Weisbecker ftrace_set_func(unsigned long *array, int *idx, char *buffer)
3737ea4e2bc4SSteven Rostedt {
3738ea4e2bc4SSteven Rostedt 	struct dyn_ftrace *rec;
3739ea4e2bc4SSteven Rostedt 	struct ftrace_page *pg;
3740f9349a8fSFrederic Weisbecker 	int search_len;
3741c7c6b1feSLi Zefan 	int fail = 1;
3742f9349a8fSFrederic Weisbecker 	int type, not;
3743f9349a8fSFrederic Weisbecker 	char *search;
3744f9349a8fSFrederic Weisbecker 	bool exists;
3745f9349a8fSFrederic Weisbecker 	int i;
3746ea4e2bc4SSteven Rostedt 
3747f9349a8fSFrederic Weisbecker 	/* decode regex */
37483f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
3749c7c6b1feSLi Zefan 	if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS)
3750c7c6b1feSLi Zefan 		return -EBUSY;
3751f9349a8fSFrederic Weisbecker 
3752f9349a8fSFrederic Weisbecker 	search_len = strlen(search);
3753f9349a8fSFrederic Weisbecker 
375452baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
375545a4a237SSteven Rostedt 
375645a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled)) {
375745a4a237SSteven Rostedt 		mutex_unlock(&ftrace_lock);
375845a4a237SSteven Rostedt 		return -ENODEV;
375945a4a237SSteven Rostedt 	}
376045a4a237SSteven Rostedt 
3761265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
3762ea4e2bc4SSteven Rostedt 
3763b9df92d2SSteven Rostedt 		if (ftrace_match_record(rec, NULL, search, search_len, type)) {
3764c7c6b1feSLi Zefan 			/* if it is in the array */
3765f9349a8fSFrederic Weisbecker 			exists = false;
3766c7c6b1feSLi Zefan 			for (i = 0; i < *idx; i++) {
3767f9349a8fSFrederic Weisbecker 				if (array[i] == rec->ip) {
3768f9349a8fSFrederic Weisbecker 					exists = true;
3769faec2ec5SLiming Wang 					break;
3770faec2ec5SLiming Wang 				}
3771c7c6b1feSLi Zefan 			}
3772c7c6b1feSLi Zefan 
3773c7c6b1feSLi Zefan 			if (!not) {
3774c7c6b1feSLi Zefan 				fail = 0;
3775c7c6b1feSLi Zefan 				if (!exists) {
3776f9349a8fSFrederic Weisbecker 					array[(*idx)++] = rec->ip;
3777c7c6b1feSLi Zefan 					if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
3778c7c6b1feSLi Zefan 						goto out;
3779c7c6b1feSLi Zefan 				}
3780c7c6b1feSLi Zefan 			} else {
3781c7c6b1feSLi Zefan 				if (exists) {
3782c7c6b1feSLi Zefan 					array[i] = array[--(*idx)];
3783c7c6b1feSLi Zefan 					array[*idx] = 0;
3784c7c6b1feSLi Zefan 					fail = 0;
3785c7c6b1feSLi Zefan 				}
3786c7c6b1feSLi Zefan 			}
3787f9349a8fSFrederic Weisbecker 		}
3788265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
3789c7c6b1feSLi Zefan out:
379052baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
3791ea4e2bc4SSteven Rostedt 
3792c7c6b1feSLi Zefan 	if (fail)
3793c7c6b1feSLi Zefan 		return -EINVAL;
3794c7c6b1feSLi Zefan 
3795*9f50afccSNamhyung Kim 	ftrace_graph_filter_enabled = !!(*idx);
3796*9f50afccSNamhyung Kim 
3797c7c6b1feSLi Zefan 	return 0;
3798ea4e2bc4SSteven Rostedt }
3799ea4e2bc4SSteven Rostedt 
3800ea4e2bc4SSteven Rostedt static ssize_t
3801ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf,
3802ea4e2bc4SSteven Rostedt 		   size_t cnt, loff_t *ppos)
3803ea4e2bc4SSteven Rostedt {
3804689fd8b6S[email protected] 	struct trace_parser parser;
38054ba7978eSLi Zefan 	ssize_t read, ret;
3806ea4e2bc4SSteven Rostedt 
3807c7c6b1feSLi Zefan 	if (!cnt)
3808ea4e2bc4SSteven Rostedt 		return 0;
3809ea4e2bc4SSteven Rostedt 
3810ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3811ea4e2bc4SSteven Rostedt 
3812689fd8b6S[email protected] 	if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
3813689fd8b6S[email protected] 		ret = -ENOMEM;
38141eb90f13SLi Zefan 		goto out_unlock;
3815ea4e2bc4SSteven Rostedt 	}
3816ea4e2bc4SSteven Rostedt 
3817689fd8b6S[email protected] 	read = trace_get_user(&parser, ubuf, cnt, ppos);
3818689fd8b6S[email protected] 
38194ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded((&parser))) {
3820689fd8b6S[email protected] 		parser.buffer[parser.idx] = 0;
3821ea4e2bc4SSteven Rostedt 
3822f9349a8fSFrederic Weisbecker 		/* we allow only one expression at a time */
3823a4ec5e0cSLi Zefan 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3824689fd8b6S[email protected] 					parser.buffer);
3825ea4e2bc4SSteven Rostedt 		if (ret)
38261eb90f13SLi Zefan 			goto out_free;
3827689fd8b6S[email protected] 	}
3828ea4e2bc4SSteven Rostedt 
3829ea4e2bc4SSteven Rostedt 	ret = read;
38301eb90f13SLi Zefan 
38311eb90f13SLi Zefan out_free:
3832689fd8b6S[email protected] 	trace_parser_put(&parser);
38331eb90f13SLi Zefan out_unlock:
3834ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3835ea4e2bc4SSteven Rostedt 
3836ea4e2bc4SSteven Rostedt 	return ret;
3837ea4e2bc4SSteven Rostedt }
3838ea4e2bc4SSteven Rostedt 
3839ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = {
3840ea4e2bc4SSteven Rostedt 	.open		= ftrace_graph_open,
3841850a80cfSLai Jiangshan 	.read		= seq_read,
3842ea4e2bc4SSteven Rostedt 	.write		= ftrace_graph_write,
384387827111SLi Zefan 	.release	= ftrace_graph_release,
38446038f373SArnd Bergmann 	.llseek		= seq_lseek,
3845ea4e2bc4SSteven Rostedt };
3846ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3847ea4e2bc4SSteven Rostedt 
3848df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
38495072c59fSSteven Rostedt {
38505072c59fSSteven Rostedt 
38515452af66SFrederic Weisbecker 	trace_create_file("available_filter_functions", 0444,
38525072c59fSSteven Rostedt 			d_tracer, NULL, &ftrace_avail_fops);
38535072c59fSSteven Rostedt 
3854647bcd03SSteven Rostedt 	trace_create_file("enabled_functions", 0444,
3855647bcd03SSteven Rostedt 			d_tracer, NULL, &ftrace_enabled_fops);
3856647bcd03SSteven Rostedt 
38575452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_filter", 0644, d_tracer,
38585072c59fSSteven Rostedt 			NULL, &ftrace_filter_fops);
385941c52c0dSSteven Rostedt 
38605452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_notrace", 0644, d_tracer,
386141c52c0dSSteven Rostedt 				    NULL, &ftrace_notrace_fops);
3862ad90c0e3SSteven Rostedt 
3863ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
38645452af66SFrederic Weisbecker 	trace_create_file("set_graph_function", 0444, d_tracer,
3865ea4e2bc4SSteven Rostedt 				    NULL,
3866ea4e2bc4SSteven Rostedt 				    &ftrace_graph_fops);
3867ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3868ea4e2bc4SSteven Rostedt 
38695072c59fSSteven Rostedt 	return 0;
38705072c59fSSteven Rostedt }
38715072c59fSSteven Rostedt 
38729fd49328SSteven Rostedt static int ftrace_cmp_ips(const void *a, const void *b)
387368950619SSteven Rostedt {
38749fd49328SSteven Rostedt 	const unsigned long *ipa = a;
38759fd49328SSteven Rostedt 	const unsigned long *ipb = b;
387668950619SSteven Rostedt 
38779fd49328SSteven Rostedt 	if (*ipa > *ipb)
38789fd49328SSteven Rostedt 		return 1;
38799fd49328SSteven Rostedt 	if (*ipa < *ipb)
38809fd49328SSteven Rostedt 		return -1;
38819fd49328SSteven Rostedt 	return 0;
38829fd49328SSteven Rostedt }
38839fd49328SSteven Rostedt 
38849fd49328SSteven Rostedt static void ftrace_swap_ips(void *a, void *b, int size)
38859fd49328SSteven Rostedt {
38869fd49328SSteven Rostedt 	unsigned long *ipa = a;
38879fd49328SSteven Rostedt 	unsigned long *ipb = b;
38889fd49328SSteven Rostedt 	unsigned long t;
38899fd49328SSteven Rostedt 
38909fd49328SSteven Rostedt 	t = *ipa;
38919fd49328SSteven Rostedt 	*ipa = *ipb;
38929fd49328SSteven Rostedt 	*ipb = t;
389368950619SSteven Rostedt }
389468950619SSteven Rostedt 
38955cb084bbSJiri Olsa static int ftrace_process_locs(struct module *mod,
389631e88909SSteven Rostedt 			       unsigned long *start,
389768bf21aaSSteven Rostedt 			       unsigned long *end)
389868bf21aaSSteven Rostedt {
3899706c81f8SSteven Rostedt 	struct ftrace_page *start_pg;
3900a7900875SSteven Rostedt 	struct ftrace_page *pg;
3901706c81f8SSteven Rostedt 	struct dyn_ftrace *rec;
3902a7900875SSteven Rostedt 	unsigned long count;
390368bf21aaSSteven Rostedt 	unsigned long *p;
390468bf21aaSSteven Rostedt 	unsigned long addr;
39054376cac6SSteven Rostedt 	unsigned long flags = 0; /* Shut up gcc */
3906a7900875SSteven Rostedt 	int ret = -ENOMEM;
3907a7900875SSteven Rostedt 
3908a7900875SSteven Rostedt 	count = end - start;
3909a7900875SSteven Rostedt 
3910a7900875SSteven Rostedt 	if (!count)
3911a7900875SSteven Rostedt 		return 0;
3912a7900875SSteven Rostedt 
39139fd49328SSteven Rostedt 	sort(start, count, sizeof(*start),
39149fd49328SSteven Rostedt 	     ftrace_cmp_ips, ftrace_swap_ips);
39159fd49328SSteven Rostedt 
3916706c81f8SSteven Rostedt 	start_pg = ftrace_allocate_pages(count);
3917706c81f8SSteven Rostedt 	if (!start_pg)
3918a7900875SSteven Rostedt 		return -ENOMEM;
391968bf21aaSSteven Rostedt 
3920e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
3921a7900875SSteven Rostedt 
392232082309SSteven Rostedt 	/*
392332082309SSteven Rostedt 	 * Core and each module needs their own pages, as
392432082309SSteven Rostedt 	 * modules will free them when they are removed.
392532082309SSteven Rostedt 	 * Force a new page to be allocated for modules.
392632082309SSteven Rostedt 	 */
3927a7900875SSteven Rostedt 	if (!mod) {
3928a7900875SSteven Rostedt 		WARN_ON(ftrace_pages || ftrace_pages_start);
3929a7900875SSteven Rostedt 		/* First initialization */
3930706c81f8SSteven Rostedt 		ftrace_pages = ftrace_pages_start = start_pg;
3931a7900875SSteven Rostedt 	} else {
393232082309SSteven Rostedt 		if (!ftrace_pages)
3933a7900875SSteven Rostedt 			goto out;
393432082309SSteven Rostedt 
3935a7900875SSteven Rostedt 		if (WARN_ON(ftrace_pages->next)) {
3936a7900875SSteven Rostedt 			/* Hmm, we have free pages? */
3937a7900875SSteven Rostedt 			while (ftrace_pages->next)
393832082309SSteven Rostedt 				ftrace_pages = ftrace_pages->next;
393932082309SSteven Rostedt 		}
3940a7900875SSteven Rostedt 
3941706c81f8SSteven Rostedt 		ftrace_pages->next = start_pg;
394232082309SSteven Rostedt 	}
394332082309SSteven Rostedt 
394468bf21aaSSteven Rostedt 	p = start;
3945706c81f8SSteven Rostedt 	pg = start_pg;
394668bf21aaSSteven Rostedt 	while (p < end) {
394768bf21aaSSteven Rostedt 		addr = ftrace_call_adjust(*p++);
394820e5227eSSteven Rostedt 		/*
394920e5227eSSteven Rostedt 		 * Some architecture linkers will pad between
395020e5227eSSteven Rostedt 		 * the different mcount_loc sections of different
395120e5227eSSteven Rostedt 		 * object files to satisfy alignments.
395220e5227eSSteven Rostedt 		 * Skip any NULL pointers.
395320e5227eSSteven Rostedt 		 */
395420e5227eSSteven Rostedt 		if (!addr)
395520e5227eSSteven Rostedt 			continue;
3956706c81f8SSteven Rostedt 
3957706c81f8SSteven Rostedt 		if (pg->index == pg->size) {
3958706c81f8SSteven Rostedt 			/* We should have allocated enough */
3959706c81f8SSteven Rostedt 			if (WARN_ON(!pg->next))
3960a7900875SSteven Rostedt 				break;
3961706c81f8SSteven Rostedt 			pg = pg->next;
396268bf21aaSSteven Rostedt 		}
396368bf21aaSSteven Rostedt 
3964706c81f8SSteven Rostedt 		rec = &pg->records[pg->index++];
3965706c81f8SSteven Rostedt 		rec->ip = addr;
3966706c81f8SSteven Rostedt 	}
3967706c81f8SSteven Rostedt 
3968706c81f8SSteven Rostedt 	/* We should have used all pages */
3969706c81f8SSteven Rostedt 	WARN_ON(pg->next);
3970706c81f8SSteven Rostedt 
3971706c81f8SSteven Rostedt 	/* Assign the last page to ftrace_pages */
3972706c81f8SSteven Rostedt 	ftrace_pages = pg;
3973706c81f8SSteven Rostedt 
397485ae32aeSSteven Rostedt 	/* These new locations need to be initialized */
3975706c81f8SSteven Rostedt 	ftrace_new_pgs = start_pg;
397685ae32aeSSteven Rostedt 
3977a4f18ed1SSteven Rostedt 	/*
39784376cac6SSteven Rostedt 	 * We only need to disable interrupts on start up
39794376cac6SSteven Rostedt 	 * because we are modifying code that an interrupt
39804376cac6SSteven Rostedt 	 * may execute, and the modification is not atomic.
39814376cac6SSteven Rostedt 	 * But for modules, nothing runs the code we modify
39824376cac6SSteven Rostedt 	 * until we are finished with it, and there's no
39834376cac6SSteven Rostedt 	 * reason to cause large interrupt latencies while we do it.
3984a4f18ed1SSteven Rostedt 	 */
39854376cac6SSteven Rostedt 	if (!mod)
3986a4f18ed1SSteven Rostedt 		local_irq_save(flags);
398731e88909SSteven Rostedt 	ftrace_update_code(mod);
39884376cac6SSteven Rostedt 	if (!mod)
3989a4f18ed1SSteven Rostedt 		local_irq_restore(flags);
3990a7900875SSteven Rostedt 	ret = 0;
3991a7900875SSteven Rostedt  out:
3992e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
399368bf21aaSSteven Rostedt 
3994a7900875SSteven Rostedt 	return ret;
399568bf21aaSSteven Rostedt }
399668bf21aaSSteven Rostedt 
399793eb677dSSteven Rostedt #ifdef CONFIG_MODULES
399832082309SSteven Rostedt 
399932082309SSteven Rostedt #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)
400032082309SSteven Rostedt 
4001e7247a15S[email protected] void ftrace_release_mod(struct module *mod)
400293eb677dSSteven Rostedt {
400393eb677dSSteven Rostedt 	struct dyn_ftrace *rec;
400432082309SSteven Rostedt 	struct ftrace_page **last_pg;
400593eb677dSSteven Rostedt 	struct ftrace_page *pg;
4006a7900875SSteven Rostedt 	int order;
400793eb677dSSteven Rostedt 
400893eb677dSSteven Rostedt 	mutex_lock(&ftrace_lock);
400945a4a237SSteven Rostedt 
401045a4a237SSteven Rostedt 	if (ftrace_disabled)
401145a4a237SSteven Rostedt 		goto out_unlock;
401245a4a237SSteven Rostedt 
401332082309SSteven Rostedt 	/*
401432082309SSteven Rostedt 	 * Each module has its own ftrace_pages, remove
401532082309SSteven Rostedt 	 * them from the list.
401632082309SSteven Rostedt 	 */
401732082309SSteven Rostedt 	last_pg = &ftrace_pages_start;
401832082309SSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = *last_pg) {
401932082309SSteven Rostedt 		rec = &pg->records[0];
4020e7247a15S[email protected] 		if (within_module_core(rec->ip, mod)) {
402193eb677dSSteven Rostedt 			/*
402232082309SSteven Rostedt 			 * As core pages are first, the first
402332082309SSteven Rostedt 			 * page should never be a module page.
402493eb677dSSteven Rostedt 			 */
402532082309SSteven Rostedt 			if (WARN_ON(pg == ftrace_pages_start))
402632082309SSteven Rostedt 				goto out_unlock;
402732082309SSteven Rostedt 
402832082309SSteven Rostedt 			/* Check if we are deleting the last page */
402932082309SSteven Rostedt 			if (pg == ftrace_pages)
403032082309SSteven Rostedt 				ftrace_pages = next_to_ftrace_page(last_pg);
403132082309SSteven Rostedt 
403232082309SSteven Rostedt 			*last_pg = pg->next;
4033a7900875SSteven Rostedt 			order = get_count_order(pg->size / ENTRIES_PER_PAGE);
4034a7900875SSteven Rostedt 			free_pages((unsigned long)pg->records, order);
4035a7900875SSteven Rostedt 			kfree(pg);
403632082309SSteven Rostedt 		} else
403732082309SSteven Rostedt 			last_pg = &pg->next;
403893eb677dSSteven Rostedt 	}
403945a4a237SSteven Rostedt  out_unlock:
404093eb677dSSteven Rostedt 	mutex_unlock(&ftrace_lock);
404193eb677dSSteven Rostedt }
404293eb677dSSteven Rostedt 
404393eb677dSSteven Rostedt static void ftrace_init_module(struct module *mod,
404431e88909SSteven Rostedt 			       unsigned long *start, unsigned long *end)
404590d595feSSteven Rostedt {
404600fd61aeSSteven Rostedt 	if (ftrace_disabled || start == end)
4047fed1939cSSteven Rostedt 		return;
40485cb084bbSJiri Olsa 	ftrace_process_locs(mod, start, end);
404990d595feSSteven Rostedt }
405090d595feSSteven Rostedt 
40518c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
405293eb677dSSteven Rostedt 				      unsigned long val, void *data)
405393eb677dSSteven Rostedt {
405493eb677dSSteven Rostedt 	struct module *mod = data;
405593eb677dSSteven Rostedt 
40568c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_COMING)
405793eb677dSSteven Rostedt 		ftrace_init_module(mod, mod->ftrace_callsites,
405893eb677dSSteven Rostedt 				   mod->ftrace_callsites +
405993eb677dSSteven Rostedt 				   mod->num_ftrace_callsites);
40608c189ea6SSteven Rostedt (Red Hat) 	return 0;
406193eb677dSSteven Rostedt }
406293eb677dSSteven Rostedt 
40638c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
40648c189ea6SSteven Rostedt (Red Hat) 				     unsigned long val, void *data)
40658c189ea6SSteven Rostedt (Red Hat) {
40668c189ea6SSteven Rostedt (Red Hat) 	struct module *mod = data;
40678c189ea6SSteven Rostedt (Red Hat) 
40688c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_GOING)
40698c189ea6SSteven Rostedt (Red Hat) 		ftrace_release_mod(mod);
40708c189ea6SSteven Rostedt (Red Hat) 
407193eb677dSSteven Rostedt 	return 0;
407293eb677dSSteven Rostedt }
407393eb677dSSteven Rostedt #else
40748c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
40758c189ea6SSteven Rostedt (Red Hat) 				      unsigned long val, void *data)
40768c189ea6SSteven Rostedt (Red Hat) {
40778c189ea6SSteven Rostedt (Red Hat) 	return 0;
40788c189ea6SSteven Rostedt (Red Hat) }
40798c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
408093eb677dSSteven Rostedt 				     unsigned long val, void *data)
408193eb677dSSteven Rostedt {
408293eb677dSSteven Rostedt 	return 0;
408393eb677dSSteven Rostedt }
408493eb677dSSteven Rostedt #endif /* CONFIG_MODULES */
408593eb677dSSteven Rostedt 
40868c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_enter_nb = {
40878c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_enter,
4088c1bf08acSSteven Rostedt 	.priority = INT_MAX,	/* Run before anything that can use kprobes */
408993eb677dSSteven Rostedt };
409093eb677dSSteven Rostedt 
40918c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_exit_nb = {
40928c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_exit,
40938c189ea6SSteven Rostedt (Red Hat) 	.priority = INT_MIN,	/* Run after anything that can remove kprobes */
40948c189ea6SSteven Rostedt (Red Hat) };
40958c189ea6SSteven Rostedt (Red Hat) 
409668bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[];
409768bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[];
409868bf21aaSSteven Rostedt 
409968bf21aaSSteven Rostedt void __init ftrace_init(void)
410068bf21aaSSteven Rostedt {
410168bf21aaSSteven Rostedt 	unsigned long count, addr, flags;
410268bf21aaSSteven Rostedt 	int ret;
410368bf21aaSSteven Rostedt 
410468bf21aaSSteven Rostedt 	/* Keep the ftrace pointer to the stub */
410568bf21aaSSteven Rostedt 	addr = (unsigned long)ftrace_stub;
410668bf21aaSSteven Rostedt 
410768bf21aaSSteven Rostedt 	local_irq_save(flags);
410868bf21aaSSteven Rostedt 	ftrace_dyn_arch_init(&addr);
410968bf21aaSSteven Rostedt 	local_irq_restore(flags);
411068bf21aaSSteven Rostedt 
411168bf21aaSSteven Rostedt 	/* ftrace_dyn_arch_init places the return code in addr */
411268bf21aaSSteven Rostedt 	if (addr)
411368bf21aaSSteven Rostedt 		goto failed;
411468bf21aaSSteven Rostedt 
411568bf21aaSSteven Rostedt 	count = __stop_mcount_loc - __start_mcount_loc;
411668bf21aaSSteven Rostedt 
411768bf21aaSSteven Rostedt 	ret = ftrace_dyn_table_alloc(count);
411868bf21aaSSteven Rostedt 	if (ret)
411968bf21aaSSteven Rostedt 		goto failed;
412068bf21aaSSteven Rostedt 
412168bf21aaSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled = 1;
412268bf21aaSSteven Rostedt 
41235cb084bbSJiri Olsa 	ret = ftrace_process_locs(NULL,
412431e88909SSteven Rostedt 				  __start_mcount_loc,
412568bf21aaSSteven Rostedt 				  __stop_mcount_loc);
412668bf21aaSSteven Rostedt 
41278c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_enter_nb);
412824ed0c4bSMing Lei 	if (ret)
41298c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module enter notifier\n");
41308c189ea6SSteven Rostedt (Red Hat) 
41318c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_exit_nb);
41328c189ea6SSteven Rostedt (Red Hat) 	if (ret)
41338c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module exit notifier\n");
413493eb677dSSteven Rostedt 
41352af15d6aSSteven Rostedt 	set_ftrace_early_filters();
41362af15d6aSSteven Rostedt 
413768bf21aaSSteven Rostedt 	return;
413868bf21aaSSteven Rostedt  failed:
413968bf21aaSSteven Rostedt 	ftrace_disabled = 1;
414068bf21aaSSteven Rostedt }
414168bf21aaSSteven Rostedt 
41423d083395SSteven Rostedt #else
41430b6e4d56SFrederic Weisbecker 
41442b499381SSteven Rostedt static struct ftrace_ops global_ops = {
4145bd69c30bSSteven Rostedt 	.func			= ftrace_stub,
41464740974aSSteven Rostedt 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE,
4147bd69c30bSSteven Rostedt };
4148bd69c30bSSteven Rostedt 
41490b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void)
41500b6e4d56SFrederic Weisbecker {
41510b6e4d56SFrederic Weisbecker 	ftrace_enabled = 1;
41520b6e4d56SFrederic Weisbecker 	return 0;
41530b6e4d56SFrederic Weisbecker }
41546f415672SSteven Rostedt core_initcall(ftrace_nodyn_init);
41550b6e4d56SFrederic Weisbecker 
4156df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
4157df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { }
41585a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */
41593b6cfdb1SSteven Rostedt # define ftrace_startup(ops, command)			\
41603b6cfdb1SSteven Rostedt 	({						\
41613b6cfdb1SSteven Rostedt 		(ops)->flags |= FTRACE_OPS_FL_ENABLED;	\
41623b6cfdb1SSteven Rostedt 		0;					\
41633b6cfdb1SSteven Rostedt 	})
4164bd69c30bSSteven Rostedt # define ftrace_shutdown(ops, command)	do { } while (0)
4165b0fc494fSSteven Rostedt # define ftrace_startup_sysctl()	do { } while (0)
4166b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl()	do { } while (0)
4167b848914cSSteven Rostedt 
4168b848914cSSteven Rostedt static inline int
4169b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
4170b848914cSSteven Rostedt {
4171b848914cSSteven Rostedt 	return 1;
4172b848914cSSteven Rostedt }
4173b848914cSSteven Rostedt 
41743d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */
41753d083395SSteven Rostedt 
4176b848914cSSteven Rostedt static void
41772f5f6ad9SSteven Rostedt ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
4178a1e2e31dSSteven Rostedt 			struct ftrace_ops *op, struct pt_regs *regs)
4179e248491aSJiri Olsa {
4180e248491aSJiri Olsa 	if (unlikely(trace_recursion_test(TRACE_CONTROL_BIT)))
4181e248491aSJiri Olsa 		return;
4182e248491aSJiri Olsa 
4183e248491aSJiri Olsa 	/*
4184e248491aSJiri Olsa 	 * Some of the ops may be dynamically allocated,
4185e248491aSJiri Olsa 	 * they must be freed after a synchronize_sched().
4186e248491aSJiri Olsa 	 */
4187e248491aSJiri Olsa 	preempt_disable_notrace();
4188e248491aSJiri Olsa 	trace_recursion_set(TRACE_CONTROL_BIT);
41890a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_control_list) {
4190e248491aSJiri Olsa 		if (!ftrace_function_local_disabled(op) &&
4191e248491aSJiri Olsa 		    ftrace_ops_test(op, ip))
4192a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
41930a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4194e248491aSJiri Olsa 	trace_recursion_clear(TRACE_CONTROL_BIT);
4195e248491aSJiri Olsa 	preempt_enable_notrace();
4196e248491aSJiri Olsa }
4197e248491aSJiri Olsa 
4198e248491aSJiri Olsa static struct ftrace_ops control_ops = {
4199e248491aSJiri Olsa 	.func = ftrace_ops_control_func,
42004740974aSSteven Rostedt 	.flags = FTRACE_OPS_FL_RECURSION_SAFE,
4201e248491aSJiri Olsa };
4202e248491aSJiri Olsa 
42032f5f6ad9SSteven Rostedt static inline void
42042f5f6ad9SSteven Rostedt __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4205a1e2e31dSSteven Rostedt 		       struct ftrace_ops *ignored, struct pt_regs *regs)
4206b848914cSSteven Rostedt {
4207cdbe61bfSSteven Rostedt 	struct ftrace_ops *op;
4208edc15cafSSteven Rostedt 	int bit;
4209b848914cSSteven Rostedt 
4210ccf3672dSSteven Rostedt 	if (function_trace_stop)
4211ccf3672dSSteven Rostedt 		return;
4212ccf3672dSSteven Rostedt 
4213edc15cafSSteven Rostedt 	bit = trace_test_and_set_recursion(TRACE_LIST_START, TRACE_LIST_MAX);
4214edc15cafSSteven Rostedt 	if (bit < 0)
4215b1cff0adSSteven Rostedt 		return;
4216b1cff0adSSteven Rostedt 
4217cdbe61bfSSteven Rostedt 	/*
4218cdbe61bfSSteven Rostedt 	 * Some of the ops may be dynamically allocated,
4219cdbe61bfSSteven Rostedt 	 * they must be freed after a synchronize_sched().
4220cdbe61bfSSteven Rostedt 	 */
4221cdbe61bfSSteven Rostedt 	preempt_disable_notrace();
42220a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_ops_list) {
4223b848914cSSteven Rostedt 		if (ftrace_ops_test(op, ip))
4224a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
42250a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4226cdbe61bfSSteven Rostedt 	preempt_enable_notrace();
4227edc15cafSSteven Rostedt 	trace_clear_recursion(bit);
4228b848914cSSteven Rostedt }
4229b848914cSSteven Rostedt 
42302f5f6ad9SSteven Rostedt /*
42312f5f6ad9SSteven Rostedt  * Some archs only support passing ip and parent_ip. Even though
42322f5f6ad9SSteven Rostedt  * the list function ignores the op parameter, we do not want any
42332f5f6ad9SSteven Rostedt  * C side effects, where a function is called without the caller
42342f5f6ad9SSteven Rostedt  * sending a third parameter.
4235a1e2e31dSSteven Rostedt  * Archs are to support both the regs and ftrace_ops at the same time.
4236a1e2e31dSSteven Rostedt  * If they support ftrace_ops, it is assumed they support regs.
4237a1e2e31dSSteven Rostedt  * If call backs want to use regs, they must either check for regs
423806aeaaeaSMasami Hiramatsu  * being NULL, or CONFIG_DYNAMIC_FTRACE_WITH_REGS.
423906aeaaeaSMasami Hiramatsu  * Note, CONFIG_DYNAMIC_FTRACE_WITH_REGS expects a full regs to be saved.
4240a1e2e31dSSteven Rostedt  * An architecture can pass partial regs with ftrace_ops and still
4241a1e2e31dSSteven Rostedt  * set the ARCH_SUPPORT_FTARCE_OPS.
42422f5f6ad9SSteven Rostedt  */
42432f5f6ad9SSteven Rostedt #if ARCH_SUPPORTS_FTRACE_OPS
42442f5f6ad9SSteven Rostedt static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4245a1e2e31dSSteven Rostedt 				 struct ftrace_ops *op, struct pt_regs *regs)
42462f5f6ad9SSteven Rostedt {
4247a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, regs);
42482f5f6ad9SSteven Rostedt }
42492f5f6ad9SSteven Rostedt #else
42502f5f6ad9SSteven Rostedt static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip)
42512f5f6ad9SSteven Rostedt {
4252a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, NULL);
42532f5f6ad9SSteven Rostedt }
42542f5f6ad9SSteven Rostedt #endif
42552f5f6ad9SSteven Rostedt 
4256e32d8956SSteven Rostedt static void clear_ftrace_swapper(void)
4257e32d8956SSteven Rostedt {
4258e32d8956SSteven Rostedt 	struct task_struct *p;
4259e32d8956SSteven Rostedt 	int cpu;
4260e32d8956SSteven Rostedt 
4261e32d8956SSteven Rostedt 	get_online_cpus();
4262e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4263e32d8956SSteven Rostedt 		p = idle_task(cpu);
4264e32d8956SSteven Rostedt 		clear_tsk_trace_trace(p);
4265e32d8956SSteven Rostedt 	}
4266e32d8956SSteven Rostedt 	put_online_cpus();
4267e32d8956SSteven Rostedt }
4268e32d8956SSteven Rostedt 
4269e32d8956SSteven Rostedt static void set_ftrace_swapper(void)
4270e32d8956SSteven Rostedt {
4271e32d8956SSteven Rostedt 	struct task_struct *p;
4272e32d8956SSteven Rostedt 	int cpu;
4273e32d8956SSteven Rostedt 
4274e32d8956SSteven Rostedt 	get_online_cpus();
4275e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4276e32d8956SSteven Rostedt 		p = idle_task(cpu);
4277e32d8956SSteven Rostedt 		set_tsk_trace_trace(p);
4278e32d8956SSteven Rostedt 	}
4279e32d8956SSteven Rostedt 	put_online_cpus();
4280e32d8956SSteven Rostedt }
4281e32d8956SSteven Rostedt 
4282e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid)
4283978f3a45SSteven Rostedt {
4284978f3a45SSteven Rostedt 	struct task_struct *p;
4285978f3a45SSteven Rostedt 
4286229c4ef8SOleg Nesterov 	rcu_read_lock();
4287e32d8956SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4288978f3a45SSteven Rostedt 		clear_tsk_trace_trace(p);
4289e32d8956SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4290229c4ef8SOleg Nesterov 	rcu_read_unlock();
4291229c4ef8SOleg Nesterov 
4292e32d8956SSteven Rostedt 	put_pid(pid);
4293978f3a45SSteven Rostedt }
4294978f3a45SSteven Rostedt 
4295e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid)
4296978f3a45SSteven Rostedt {
4297978f3a45SSteven Rostedt 	struct task_struct *p;
4298978f3a45SSteven Rostedt 
4299229c4ef8SOleg Nesterov 	rcu_read_lock();
4300978f3a45SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4301978f3a45SSteven Rostedt 		set_tsk_trace_trace(p);
4302978f3a45SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4303229c4ef8SOleg Nesterov 	rcu_read_unlock();
4304978f3a45SSteven Rostedt }
4305978f3a45SSteven Rostedt 
4306756d17eeS[email protected] static void clear_ftrace_pid_task(struct pid *pid)
4307e32d8956SSteven Rostedt {
4308756d17eeS[email protected] 	if (pid == ftrace_swapper_pid)
4309e32d8956SSteven Rostedt 		clear_ftrace_swapper();
4310e32d8956SSteven Rostedt 	else
4311756d17eeS[email protected] 		clear_ftrace_pid(pid);
4312e32d8956SSteven Rostedt }
4313e32d8956SSteven Rostedt 
4314e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid)
4315e32d8956SSteven Rostedt {
4316e32d8956SSteven Rostedt 	if (pid == ftrace_swapper_pid)
4317e32d8956SSteven Rostedt 		set_ftrace_swapper();
4318e32d8956SSteven Rostedt 	else
4319e32d8956SSteven Rostedt 		set_ftrace_pid(pid);
4320e32d8956SSteven Rostedt }
4321e32d8956SSteven Rostedt 
4322756d17eeS[email protected] static int ftrace_pid_add(int p)
4323756d17eeS[email protected] {
4324756d17eeS[email protected] 	struct pid *pid;
4325756d17eeS[email protected] 	struct ftrace_pid *fpid;
4326756d17eeS[email protected] 	int ret = -EINVAL;
4327756d17eeS[email protected] 
4328756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4329756d17eeS[email protected] 
4330756d17eeS[email protected] 	if (!p)
4331756d17eeS[email protected] 		pid = ftrace_swapper_pid;
4332756d17eeS[email protected] 	else
4333756d17eeS[email protected] 		pid = find_get_pid(p);
4334756d17eeS[email protected] 
4335756d17eeS[email protected] 	if (!pid)
4336756d17eeS[email protected] 		goto out;
4337756d17eeS[email protected] 
4338756d17eeS[email protected] 	ret = 0;
4339756d17eeS[email protected] 
4340756d17eeS[email protected] 	list_for_each_entry(fpid, &ftrace_pids, list)
4341756d17eeS[email protected] 		if (fpid->pid == pid)
4342756d17eeS[email protected] 			goto out_put;
4343756d17eeS[email protected] 
4344756d17eeS[email protected] 	ret = -ENOMEM;
4345756d17eeS[email protected] 
4346756d17eeS[email protected] 	fpid = kmalloc(sizeof(*fpid), GFP_KERNEL);
4347756d17eeS[email protected] 	if (!fpid)
4348756d17eeS[email protected] 		goto out_put;
4349756d17eeS[email protected] 
4350756d17eeS[email protected] 	list_add(&fpid->list, &ftrace_pids);
4351756d17eeS[email protected] 	fpid->pid = pid;
4352756d17eeS[email protected] 
4353756d17eeS[email protected] 	set_ftrace_pid_task(pid);
4354756d17eeS[email protected] 
4355756d17eeS[email protected] 	ftrace_update_pid_func();
4356756d17eeS[email protected] 	ftrace_startup_enable(0);
4357756d17eeS[email protected] 
4358756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4359756d17eeS[email protected] 	return 0;
4360756d17eeS[email protected] 
4361756d17eeS[email protected] out_put:
4362756d17eeS[email protected] 	if (pid != ftrace_swapper_pid)
4363756d17eeS[email protected] 		put_pid(pid);
4364756d17eeS[email protected] 
4365756d17eeS[email protected] out:
4366756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4367756d17eeS[email protected] 	return ret;
4368756d17eeS[email protected] }
4369756d17eeS[email protected] 
4370756d17eeS[email protected] static void ftrace_pid_reset(void)
4371756d17eeS[email protected] {
4372756d17eeS[email protected] 	struct ftrace_pid *fpid, *safe;
4373756d17eeS[email protected] 
4374756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4375756d17eeS[email protected] 	list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) {
4376756d17eeS[email protected] 		struct pid *pid = fpid->pid;
4377756d17eeS[email protected] 
4378756d17eeS[email protected] 		clear_ftrace_pid_task(pid);
4379756d17eeS[email protected] 
4380756d17eeS[email protected] 		list_del(&fpid->list);
4381756d17eeS[email protected] 		kfree(fpid);
4382756d17eeS[email protected] 	}
4383756d17eeS[email protected] 
4384756d17eeS[email protected] 	ftrace_update_pid_func();
4385756d17eeS[email protected] 	ftrace_startup_enable(0);
4386756d17eeS[email protected] 
4387756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4388756d17eeS[email protected] }
4389756d17eeS[email protected] 
4390756d17eeS[email protected] static void *fpid_start(struct seq_file *m, loff_t *pos)
4391756d17eeS[email protected] {
4392756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4393756d17eeS[email protected] 
4394756d17eeS[email protected] 	if (list_empty(&ftrace_pids) && (!*pos))
4395756d17eeS[email protected] 		return (void *) 1;
4396756d17eeS[email protected] 
4397756d17eeS[email protected] 	return seq_list_start(&ftrace_pids, *pos);
4398756d17eeS[email protected] }
4399756d17eeS[email protected] 
4400756d17eeS[email protected] static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
4401756d17eeS[email protected] {
4402756d17eeS[email protected] 	if (v == (void *)1)
4403756d17eeS[email protected] 		return NULL;
4404756d17eeS[email protected] 
4405756d17eeS[email protected] 	return seq_list_next(v, &ftrace_pids, pos);
4406756d17eeS[email protected] }
4407756d17eeS[email protected] 
4408756d17eeS[email protected] static void fpid_stop(struct seq_file *m, void *p)
4409756d17eeS[email protected] {
4410756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4411756d17eeS[email protected] }
4412756d17eeS[email protected] 
4413756d17eeS[email protected] static int fpid_show(struct seq_file *m, void *v)
4414756d17eeS[email protected] {
4415756d17eeS[email protected] 	const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list);
4416756d17eeS[email protected] 
4417756d17eeS[email protected] 	if (v == (void *)1) {
4418756d17eeS[email protected] 		seq_printf(m, "no pid\n");
4419756d17eeS[email protected] 		return 0;
4420756d17eeS[email protected] 	}
4421756d17eeS[email protected] 
4422756d17eeS[email protected] 	if (fpid->pid == ftrace_swapper_pid)
4423756d17eeS[email protected] 		seq_printf(m, "swapper tasks\n");
4424756d17eeS[email protected] 	else
4425756d17eeS[email protected] 		seq_printf(m, "%u\n", pid_vnr(fpid->pid));
4426756d17eeS[email protected] 
4427756d17eeS[email protected] 	return 0;
4428756d17eeS[email protected] }
4429756d17eeS[email protected] 
4430756d17eeS[email protected] static const struct seq_operations ftrace_pid_sops = {
4431756d17eeS[email protected] 	.start = fpid_start,
4432756d17eeS[email protected] 	.next = fpid_next,
4433756d17eeS[email protected] 	.stop = fpid_stop,
4434756d17eeS[email protected] 	.show = fpid_show,
4435756d17eeS[email protected] };
4436756d17eeS[email protected] 
4437756d17eeS[email protected] static int
4438756d17eeS[email protected] ftrace_pid_open(struct inode *inode, struct file *file)
4439756d17eeS[email protected] {
4440756d17eeS[email protected] 	int ret = 0;
4441756d17eeS[email protected] 
4442756d17eeS[email protected] 	if ((file->f_mode & FMODE_WRITE) &&
4443756d17eeS[email protected] 	    (file->f_flags & O_TRUNC))
4444756d17eeS[email protected] 		ftrace_pid_reset();
4445756d17eeS[email protected] 
4446756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4447756d17eeS[email protected] 		ret = seq_open(file, &ftrace_pid_sops);
4448756d17eeS[email protected] 
4449756d17eeS[email protected] 	return ret;
4450756d17eeS[email protected] }
4451756d17eeS[email protected] 
4452df4fc315SSteven Rostedt static ssize_t
4453df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf,
4454df4fc315SSteven Rostedt 		   size_t cnt, loff_t *ppos)
4455df4fc315SSteven Rostedt {
4456457dc928SIngo Molnar 	char buf[64], *tmp;
4457df4fc315SSteven Rostedt 	long val;
4458df4fc315SSteven Rostedt 	int ret;
4459df4fc315SSteven Rostedt 
4460df4fc315SSteven Rostedt 	if (cnt >= sizeof(buf))
4461df4fc315SSteven Rostedt 		return -EINVAL;
4462df4fc315SSteven Rostedt 
4463df4fc315SSteven Rostedt 	if (copy_from_user(&buf, ubuf, cnt))
4464df4fc315SSteven Rostedt 		return -EFAULT;
4465df4fc315SSteven Rostedt 
4466df4fc315SSteven Rostedt 	buf[cnt] = 0;
4467df4fc315SSteven Rostedt 
4468756d17eeS[email protected] 	/*
4469756d17eeS[email protected] 	 * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid"
4470756d17eeS[email protected] 	 * to clean the filter quietly.
4471756d17eeS[email protected] 	 */
4472457dc928SIngo Molnar 	tmp = strstrip(buf);
4473457dc928SIngo Molnar 	if (strlen(tmp) == 0)
4474756d17eeS[email protected] 		return 1;
4475756d17eeS[email protected] 
4476bcd83ea6SDaniel Walter 	ret = kstrtol(tmp, 10, &val);
4477df4fc315SSteven Rostedt 	if (ret < 0)
4478df4fc315SSteven Rostedt 		return ret;
4479df4fc315SSteven Rostedt 
4480756d17eeS[email protected] 	ret = ftrace_pid_add(val);
4481978f3a45SSteven Rostedt 
4482756d17eeS[email protected] 	return ret ? ret : cnt;
4483e32d8956SSteven Rostedt }
4484978f3a45SSteven Rostedt 
4485756d17eeS[email protected] static int
4486756d17eeS[email protected] ftrace_pid_release(struct inode *inode, struct file *file)
4487756d17eeS[email protected] {
4488756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4489756d17eeS[email protected] 		seq_release(inode, file);
4490978f3a45SSteven Rostedt 
4491756d17eeS[email protected] 	return 0;
4492df4fc315SSteven Rostedt }
4493df4fc315SSteven Rostedt 
44945e2336a0SSteven Rostedt static const struct file_operations ftrace_pid_fops = {
4495756d17eeS[email protected] 	.open		= ftrace_pid_open,
4496df4fc315SSteven Rostedt 	.write		= ftrace_pid_write,
4497756d17eeS[email protected] 	.read		= seq_read,
4498756d17eeS[email protected] 	.llseek		= seq_lseek,
4499756d17eeS[email protected] 	.release	= ftrace_pid_release,
4500df4fc315SSteven Rostedt };
4501df4fc315SSteven Rostedt 
4502df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void)
4503df4fc315SSteven Rostedt {
4504df4fc315SSteven Rostedt 	struct dentry *d_tracer;
4505df4fc315SSteven Rostedt 
4506df4fc315SSteven Rostedt 	d_tracer = tracing_init_dentry();
4507df4fc315SSteven Rostedt 	if (!d_tracer)
4508df4fc315SSteven Rostedt 		return 0;
4509df4fc315SSteven Rostedt 
4510df4fc315SSteven Rostedt 	ftrace_init_dyn_debugfs(d_tracer);
4511df4fc315SSteven Rostedt 
45125452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_pid", 0644, d_tracer,
4513df4fc315SSteven Rostedt 			    NULL, &ftrace_pid_fops);
4514493762fcSSteven Rostedt 
4515493762fcSSteven Rostedt 	ftrace_profile_debugfs(d_tracer);
4516493762fcSSteven Rostedt 
4517df4fc315SSteven Rostedt 	return 0;
4518df4fc315SSteven Rostedt }
4519df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs);
4520df4fc315SSteven Rostedt 
45213d083395SSteven Rostedt /**
452281adbdc0SSteven Rostedt  * ftrace_kill - kill ftrace
4523a2bb6a3dSSteven Rostedt  *
4524a2bb6a3dSSteven Rostedt  * This function should be used by panic code. It stops ftrace
4525a2bb6a3dSSteven Rostedt  * but in a not so nice way. If you need to simply kill ftrace
4526a2bb6a3dSSteven Rostedt  * from a non-atomic section, use ftrace_kill.
4527a2bb6a3dSSteven Rostedt  */
452881adbdc0SSteven Rostedt void ftrace_kill(void)
4529a2bb6a3dSSteven Rostedt {
4530a2bb6a3dSSteven Rostedt 	ftrace_disabled = 1;
4531a2bb6a3dSSteven Rostedt 	ftrace_enabled = 0;
4532a2bb6a3dSSteven Rostedt 	clear_ftrace_function();
4533a2bb6a3dSSteven Rostedt }
4534a2bb6a3dSSteven Rostedt 
4535a2bb6a3dSSteven Rostedt /**
4536e0a413f6SSteven Rostedt  * Test if ftrace is dead or not.
4537e0a413f6SSteven Rostedt  */
4538e0a413f6SSteven Rostedt int ftrace_is_dead(void)
4539e0a413f6SSteven Rostedt {
4540e0a413f6SSteven Rostedt 	return ftrace_disabled;
4541e0a413f6SSteven Rostedt }
4542e0a413f6SSteven Rostedt 
4543e0a413f6SSteven Rostedt /**
45443d083395SSteven Rostedt  * register_ftrace_function - register a function for profiling
45453d083395SSteven Rostedt  * @ops - ops structure that holds the function for profiling.
45463d083395SSteven Rostedt  *
45473d083395SSteven Rostedt  * Register a function to be called by all functions in the
45483d083395SSteven Rostedt  * kernel.
45493d083395SSteven Rostedt  *
45503d083395SSteven Rostedt  * Note: @ops->func and all the functions it calls must be labeled
45513d083395SSteven Rostedt  *       with "notrace", otherwise it will go into a
45523d083395SSteven Rostedt  *       recursive loop.
45533d083395SSteven Rostedt  */
45543d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops)
45553d083395SSteven Rostedt {
455645a4a237SSteven Rostedt 	int ret = -1;
45574eebcc81SSteven Rostedt 
4558e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4559e7d3737eSFrederic Weisbecker 
4560b0fc494fSSteven Rostedt 	ret = __register_ftrace_function(ops);
4561b848914cSSteven Rostedt 	if (!ret)
4562a1cd6173SSteven Rostedt 		ret = ftrace_startup(ops, 0);
4563b848914cSSteven Rostedt 
4564e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
45658d240dd8SBorislav Petkov 
4566b0fc494fSSteven Rostedt 	return ret;
45673d083395SSteven Rostedt }
4568cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(register_ftrace_function);
45693d083395SSteven Rostedt 
45703d083395SSteven Rostedt /**
457132632920SUwe Kleine-Koenig  * unregister_ftrace_function - unregister a function for profiling.
45723d083395SSteven Rostedt  * @ops - ops structure that holds the function to unregister
45733d083395SSteven Rostedt  *
45743d083395SSteven Rostedt  * Unregister a function that was added to be called by ftrace profiling.
45753d083395SSteven Rostedt  */
45763d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops)
45773d083395SSteven Rostedt {
45783d083395SSteven Rostedt 	int ret;
45793d083395SSteven Rostedt 
4580e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
45813d083395SSteven Rostedt 	ret = __unregister_ftrace_function(ops);
4582b848914cSSteven Rostedt 	if (!ret)
4583b848914cSSteven Rostedt 		ftrace_shutdown(ops, 0);
4584e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4585b0fc494fSSteven Rostedt 
4586b0fc494fSSteven Rostedt 	return ret;
4587b0fc494fSSteven Rostedt }
4588cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(unregister_ftrace_function);
4589b0fc494fSSteven Rostedt 
4590e309b41dSIngo Molnar int
4591b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write,
45928d65af78SAlexey Dobriyan 		     void __user *buffer, size_t *lenp,
4593b0fc494fSSteven Rostedt 		     loff_t *ppos)
4594b0fc494fSSteven Rostedt {
459545a4a237SSteven Rostedt 	int ret = -ENODEV;
45964eebcc81SSteven Rostedt 
4597e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4598b0fc494fSSteven Rostedt 
459945a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
460045a4a237SSteven Rostedt 		goto out;
460145a4a237SSteven Rostedt 
46028d65af78SAlexey Dobriyan 	ret = proc_dointvec(table, write, buffer, lenp, ppos);
4603b0fc494fSSteven Rostedt 
4604a32c7765SLi Zefan 	if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
4605b0fc494fSSteven Rostedt 		goto out;
4606b0fc494fSSteven Rostedt 
4607a32c7765SLi Zefan 	last_ftrace_enabled = !!ftrace_enabled;
4608b0fc494fSSteven Rostedt 
4609b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
4610b0fc494fSSteven Rostedt 
4611b0fc494fSSteven Rostedt 		ftrace_startup_sysctl();
4612b0fc494fSSteven Rostedt 
4613b0fc494fSSteven Rostedt 		/* we are starting ftrace again */
4614b848914cSSteven Rostedt 		if (ftrace_ops_list != &ftrace_list_end) {
4615b848914cSSteven Rostedt 			if (ftrace_ops_list->next == &ftrace_list_end)
4616b848914cSSteven Rostedt 				ftrace_trace_function = ftrace_ops_list->func;
4617b0fc494fSSteven Rostedt 			else
4618b848914cSSteven Rostedt 				ftrace_trace_function = ftrace_ops_list_func;
4619b0fc494fSSteven Rostedt 		}
4620b0fc494fSSteven Rostedt 
4621b0fc494fSSteven Rostedt 	} else {
4622b0fc494fSSteven Rostedt 		/* stopping ftrace calls (just send to ftrace_stub) */
4623b0fc494fSSteven Rostedt 		ftrace_trace_function = ftrace_stub;
4624b0fc494fSSteven Rostedt 
4625b0fc494fSSteven Rostedt 		ftrace_shutdown_sysctl();
4626b0fc494fSSteven Rostedt 	}
4627b0fc494fSSteven Rostedt 
4628b0fc494fSSteven Rostedt  out:
4629e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
46303d083395SSteven Rostedt 	return ret;
463116444a8aSArnaldo Carvalho de Melo }
4632f17845e5SIngo Molnar 
4633fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER
4634e7d3737eSFrederic Weisbecker 
4635597af815SSteven Rostedt static int ftrace_graph_active;
46364a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier;
4637f201ae23SFrederic Weisbecker 
4638e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
4639e49dc19cSSteven Rostedt {
4640e49dc19cSSteven Rostedt 	return 0;
4641e49dc19cSSteven Rostedt }
4642e49dc19cSSteven Rostedt 
4643287b6e68SFrederic Weisbecker /* The callbacks that hook a function */
4644287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return =
4645287b6e68SFrederic Weisbecker 			(trace_func_graph_ret_t)ftrace_stub;
4646e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
4647f201ae23SFrederic Weisbecker 
4648f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
4649f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
4650f201ae23SFrederic Weisbecker {
4651f201ae23SFrederic Weisbecker 	int i;
4652f201ae23SFrederic Weisbecker 	int ret = 0;
4653f201ae23SFrederic Weisbecker 	unsigned long flags;
4654f201ae23SFrederic Weisbecker 	int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE;
4655f201ae23SFrederic Weisbecker 	struct task_struct *g, *t;
4656f201ae23SFrederic Weisbecker 
4657f201ae23SFrederic Weisbecker 	for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
4658f201ae23SFrederic Weisbecker 		ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
4659f201ae23SFrederic Weisbecker 					* sizeof(struct ftrace_ret_stack),
4660f201ae23SFrederic Weisbecker 					GFP_KERNEL);
4661f201ae23SFrederic Weisbecker 		if (!ret_stack_list[i]) {
4662f201ae23SFrederic Weisbecker 			start = 0;
4663f201ae23SFrederic Weisbecker 			end = i;
4664f201ae23SFrederic Weisbecker 			ret = -ENOMEM;
4665f201ae23SFrederic Weisbecker 			goto free;
4666f201ae23SFrederic Weisbecker 		}
4667f201ae23SFrederic Weisbecker 	}
4668f201ae23SFrederic Weisbecker 
4669f201ae23SFrederic Weisbecker 	read_lock_irqsave(&tasklist_lock, flags);
4670f201ae23SFrederic Weisbecker 	do_each_thread(g, t) {
4671f201ae23SFrederic Weisbecker 		if (start == end) {
4672f201ae23SFrederic Weisbecker 			ret = -EAGAIN;
4673f201ae23SFrederic Weisbecker 			goto unlock;
4674f201ae23SFrederic Weisbecker 		}
4675f201ae23SFrederic Weisbecker 
4676f201ae23SFrederic Weisbecker 		if (t->ret_stack == NULL) {
4677380c4b14SFrederic Weisbecker 			atomic_set(&t->tracing_graph_pause, 0);
4678f201ae23SFrederic Weisbecker 			atomic_set(&t->trace_overrun, 0);
467926c01624SSteven Rostedt 			t->curr_ret_stack = -1;
468026c01624SSteven Rostedt 			/* Make sure the tasks see the -1 first: */
468126c01624SSteven Rostedt 			smp_wmb();
468226c01624SSteven Rostedt 			t->ret_stack = ret_stack_list[start++];
4683f201ae23SFrederic Weisbecker 		}
4684f201ae23SFrederic Weisbecker 	} while_each_thread(g, t);
4685f201ae23SFrederic Weisbecker 
4686f201ae23SFrederic Weisbecker unlock:
4687f201ae23SFrederic Weisbecker 	read_unlock_irqrestore(&tasklist_lock, flags);
4688f201ae23SFrederic Weisbecker free:
4689f201ae23SFrederic Weisbecker 	for (i = start; i < end; i++)
4690f201ae23SFrederic Weisbecker 		kfree(ret_stack_list[i]);
4691f201ae23SFrederic Weisbecker 	return ret;
4692f201ae23SFrederic Weisbecker }
4693f201ae23SFrederic Weisbecker 
46948aef2d28SSteven Rostedt static void
469538516ab5SSteven Rostedt ftrace_graph_probe_sched_switch(void *ignore,
469638516ab5SSteven Rostedt 			struct task_struct *prev, struct task_struct *next)
46978aef2d28SSteven Rostedt {
46988aef2d28SSteven Rostedt 	unsigned long long timestamp;
46998aef2d28SSteven Rostedt 	int index;
47008aef2d28SSteven Rostedt 
4701be6f164aSSteven Rostedt 	/*
4702be6f164aSSteven Rostedt 	 * Does the user want to count the time a function was asleep.
4703be6f164aSSteven Rostedt 	 * If so, do not update the time stamps.
4704be6f164aSSteven Rostedt 	 */
4705be6f164aSSteven Rostedt 	if (trace_flags & TRACE_ITER_SLEEP_TIME)
4706be6f164aSSteven Rostedt 		return;
4707be6f164aSSteven Rostedt 
47088aef2d28SSteven Rostedt 	timestamp = trace_clock_local();
47098aef2d28SSteven Rostedt 
47108aef2d28SSteven Rostedt 	prev->ftrace_timestamp = timestamp;
47118aef2d28SSteven Rostedt 
47128aef2d28SSteven Rostedt 	/* only process tasks that we timestamped */
47138aef2d28SSteven Rostedt 	if (!next->ftrace_timestamp)
47148aef2d28SSteven Rostedt 		return;
47158aef2d28SSteven Rostedt 
47168aef2d28SSteven Rostedt 	/*
47178aef2d28SSteven Rostedt 	 * Update all the counters in next to make up for the
47188aef2d28SSteven Rostedt 	 * time next was sleeping.
47198aef2d28SSteven Rostedt 	 */
47208aef2d28SSteven Rostedt 	timestamp -= next->ftrace_timestamp;
47218aef2d28SSteven Rostedt 
47228aef2d28SSteven Rostedt 	for (index = next->curr_ret_stack; index >= 0; index--)
47238aef2d28SSteven Rostedt 		next->ret_stack[index].calltime += timestamp;
47248aef2d28SSteven Rostedt }
47258aef2d28SSteven Rostedt 
4726f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */
4727fb52607aSFrederic Weisbecker static int start_graph_tracing(void)
4728f201ae23SFrederic Weisbecker {
4729f201ae23SFrederic Weisbecker 	struct ftrace_ret_stack **ret_stack_list;
47305b058bcdSFrederic Weisbecker 	int ret, cpu;
4731f201ae23SFrederic Weisbecker 
4732f201ae23SFrederic Weisbecker 	ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
4733f201ae23SFrederic Weisbecker 				sizeof(struct ftrace_ret_stack *),
4734f201ae23SFrederic Weisbecker 				GFP_KERNEL);
4735f201ae23SFrederic Weisbecker 
4736f201ae23SFrederic Weisbecker 	if (!ret_stack_list)
4737f201ae23SFrederic Weisbecker 		return -ENOMEM;
4738f201ae23SFrederic Weisbecker 
47395b058bcdSFrederic Weisbecker 	/* The cpu_boot init_task->ret_stack will never be freed */
4740179c498aSSteven Rostedt 	for_each_online_cpu(cpu) {
4741179c498aSSteven Rostedt 		if (!idle_task(cpu)->ret_stack)
4742868baf07SSteven Rostedt 			ftrace_graph_init_idle_task(idle_task(cpu), cpu);
4743179c498aSSteven Rostedt 	}
47445b058bcdSFrederic Weisbecker 
4745f201ae23SFrederic Weisbecker 	do {
4746f201ae23SFrederic Weisbecker 		ret = alloc_retstack_tasklist(ret_stack_list);
4747f201ae23SFrederic Weisbecker 	} while (ret == -EAGAIN);
4748f201ae23SFrederic Weisbecker 
47498aef2d28SSteven Rostedt 	if (!ret) {
475038516ab5SSteven Rostedt 		ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
47518aef2d28SSteven Rostedt 		if (ret)
47528aef2d28SSteven Rostedt 			pr_info("ftrace_graph: Couldn't activate tracepoint"
47538aef2d28SSteven Rostedt 				" probe to kernel_sched_switch\n");
47548aef2d28SSteven Rostedt 	}
47558aef2d28SSteven Rostedt 
4756f201ae23SFrederic Weisbecker 	kfree(ret_stack_list);
4757f201ae23SFrederic Weisbecker 	return ret;
4758f201ae23SFrederic Weisbecker }
4759f201ae23SFrederic Weisbecker 
47604a2b8ddaSFrederic Weisbecker /*
47614a2b8ddaSFrederic Weisbecker  * Hibernation protection.
47624a2b8ddaSFrederic Weisbecker  * The state of the current task is too much unstable during
47634a2b8ddaSFrederic Weisbecker  * suspend/restore to disk. We want to protect against that.
47644a2b8ddaSFrederic Weisbecker  */
47654a2b8ddaSFrederic Weisbecker static int
47664a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
47674a2b8ddaSFrederic Weisbecker 							void *unused)
47684a2b8ddaSFrederic Weisbecker {
47694a2b8ddaSFrederic Weisbecker 	switch (state) {
47704a2b8ddaSFrederic Weisbecker 	case PM_HIBERNATION_PREPARE:
47714a2b8ddaSFrederic Weisbecker 		pause_graph_tracing();
47724a2b8ddaSFrederic Weisbecker 		break;
47734a2b8ddaSFrederic Weisbecker 
47744a2b8ddaSFrederic Weisbecker 	case PM_POST_HIBERNATION:
47754a2b8ddaSFrederic Weisbecker 		unpause_graph_tracing();
47764a2b8ddaSFrederic Weisbecker 		break;
47774a2b8ddaSFrederic Weisbecker 	}
47784a2b8ddaSFrederic Weisbecker 	return NOTIFY_DONE;
47794a2b8ddaSFrederic Weisbecker }
47804a2b8ddaSFrederic Weisbecker 
4781287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc,
4782287b6e68SFrederic Weisbecker 			trace_func_graph_ent_t entryfunc)
478315e6cb36SFrederic Weisbecker {
4784e7d3737eSFrederic Weisbecker 	int ret = 0;
4785e7d3737eSFrederic Weisbecker 
4786e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4787e7d3737eSFrederic Weisbecker 
478805ce5818SSteven Rostedt 	/* we currently allow only one tracer registered at a time */
4789597af815SSteven Rostedt 	if (ftrace_graph_active) {
479005ce5818SSteven Rostedt 		ret = -EBUSY;
479105ce5818SSteven Rostedt 		goto out;
479205ce5818SSteven Rostedt 	}
479305ce5818SSteven Rostedt 
47944a2b8ddaSFrederic Weisbecker 	ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call;
47954a2b8ddaSFrederic Weisbecker 	register_pm_notifier(&ftrace_suspend_notifier);
47964a2b8ddaSFrederic Weisbecker 
4797597af815SSteven Rostedt 	ftrace_graph_active++;
4798fb52607aSFrederic Weisbecker 	ret = start_graph_tracing();
4799f201ae23SFrederic Weisbecker 	if (ret) {
4800597af815SSteven Rostedt 		ftrace_graph_active--;
4801f201ae23SFrederic Weisbecker 		goto out;
4802f201ae23SFrederic Weisbecker 	}
4803e53a6319SSteven Rostedt 
4804287b6e68SFrederic Weisbecker 	ftrace_graph_return = retfunc;
4805287b6e68SFrederic Weisbecker 	ftrace_graph_entry = entryfunc;
4806e53a6319SSteven Rostedt 
4807a1cd6173SSteven Rostedt 	ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
4808e7d3737eSFrederic Weisbecker 
4809e7d3737eSFrederic Weisbecker out:
4810e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4811e7d3737eSFrederic Weisbecker 	return ret;
481215e6cb36SFrederic Weisbecker }
481315e6cb36SFrederic Weisbecker 
4814fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void)
481515e6cb36SFrederic Weisbecker {
4816e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4817e7d3737eSFrederic Weisbecker 
4818597af815SSteven Rostedt 	if (unlikely(!ftrace_graph_active))
48192aad1b76SSteven Rostedt 		goto out;
48202aad1b76SSteven Rostedt 
4821597af815SSteven Rostedt 	ftrace_graph_active--;
4822287b6e68SFrederic Weisbecker 	ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
4823e49dc19cSSteven Rostedt 	ftrace_graph_entry = ftrace_graph_entry_stub;
4824bd69c30bSSteven Rostedt 	ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
48254a2b8ddaSFrederic Weisbecker 	unregister_pm_notifier(&ftrace_suspend_notifier);
482638516ab5SSteven Rostedt 	unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
4827e7d3737eSFrederic Weisbecker 
48282aad1b76SSteven Rostedt  out:
4829e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
483015e6cb36SFrederic Weisbecker }
4831f201ae23SFrederic Weisbecker 
4832868baf07SSteven Rostedt static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
4833868baf07SSteven Rostedt 
4834868baf07SSteven Rostedt static void
4835868baf07SSteven Rostedt graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
4836868baf07SSteven Rostedt {
4837868baf07SSteven Rostedt 	atomic_set(&t->tracing_graph_pause, 0);
4838868baf07SSteven Rostedt 	atomic_set(&t->trace_overrun, 0);
4839868baf07SSteven Rostedt 	t->ftrace_timestamp = 0;
484025985edcSLucas De Marchi 	/* make curr_ret_stack visible before we add the ret_stack */
4841868baf07SSteven Rostedt 	smp_wmb();
4842868baf07SSteven Rostedt 	t->ret_stack = ret_stack;
4843868baf07SSteven Rostedt }
4844868baf07SSteven Rostedt 
4845868baf07SSteven Rostedt /*
4846868baf07SSteven Rostedt  * Allocate a return stack for the idle task. May be the first
4847868baf07SSteven Rostedt  * time through, or it may be done by CPU hotplug online.
4848868baf07SSteven Rostedt  */
4849868baf07SSteven Rostedt void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
4850868baf07SSteven Rostedt {
4851868baf07SSteven Rostedt 	t->curr_ret_stack = -1;
4852868baf07SSteven Rostedt 	/*
4853868baf07SSteven Rostedt 	 * The idle task has no parent, it either has its own
4854868baf07SSteven Rostedt 	 * stack or no stack at all.
4855868baf07SSteven Rostedt 	 */
4856868baf07SSteven Rostedt 	if (t->ret_stack)
4857868baf07SSteven Rostedt 		WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
4858868baf07SSteven Rostedt 
4859868baf07SSteven Rostedt 	if (ftrace_graph_active) {
4860868baf07SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
4861868baf07SSteven Rostedt 
4862868baf07SSteven Rostedt 		ret_stack = per_cpu(idle_ret_stack, cpu);
4863868baf07SSteven Rostedt 		if (!ret_stack) {
4864868baf07SSteven Rostedt 			ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4865868baf07SSteven Rostedt 					    * sizeof(struct ftrace_ret_stack),
4866868baf07SSteven Rostedt 					    GFP_KERNEL);
4867868baf07SSteven Rostedt 			if (!ret_stack)
4868868baf07SSteven Rostedt 				return;
4869868baf07SSteven Rostedt 			per_cpu(idle_ret_stack, cpu) = ret_stack;
4870868baf07SSteven Rostedt 		}
4871868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
4872868baf07SSteven Rostedt 	}
4873868baf07SSteven Rostedt }
4874868baf07SSteven Rostedt 
4875f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */
4876fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t)
4877f201ae23SFrederic Weisbecker {
487884047e36SSteven Rostedt 	/* Make sure we do not use the parent ret_stack */
487984047e36SSteven Rostedt 	t->ret_stack = NULL;
4880ea14eb71SSteven Rostedt 	t->curr_ret_stack = -1;
488184047e36SSteven Rostedt 
4882597af815SSteven Rostedt 	if (ftrace_graph_active) {
488382310a32SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
488482310a32SSteven Rostedt 
488582310a32SSteven Rostedt 		ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4886f201ae23SFrederic Weisbecker 				* sizeof(struct ftrace_ret_stack),
4887f201ae23SFrederic Weisbecker 				GFP_KERNEL);
488882310a32SSteven Rostedt 		if (!ret_stack)
4889f201ae23SFrederic Weisbecker 			return;
4890868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
489184047e36SSteven Rostedt 	}
4892f201ae23SFrederic Weisbecker }
4893f201ae23SFrederic Weisbecker 
4894fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t)
4895f201ae23SFrederic Weisbecker {
4896eae849caSFrederic Weisbecker 	struct ftrace_ret_stack	*ret_stack = t->ret_stack;
4897eae849caSFrederic Weisbecker 
4898f201ae23SFrederic Weisbecker 	t->ret_stack = NULL;
4899eae849caSFrederic Weisbecker 	/* NULL must become visible to IRQs before we free it: */
4900eae849caSFrederic Weisbecker 	barrier();
4901eae849caSFrederic Weisbecker 
4902eae849caSFrederic Weisbecker 	kfree(ret_stack);
4903f201ae23SFrederic Weisbecker }
490414a866c5SSteven Rostedt 
490514a866c5SSteven Rostedt void ftrace_graph_stop(void)
490614a866c5SSteven Rostedt {
490714a866c5SSteven Rostedt 	ftrace_stop();
490814a866c5SSteven Rostedt }
490915e6cb36SFrederic Weisbecker #endif
4910