xref: /linux-6.15/kernel/trace/ftrace.c (revision 20079ebe)
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_enabled __read_mostly;
490fb9fb015SSteven Rostedt 
491fb9fb015SSteven Rostedt /* ftrace_profile_lock - synchronize the enable and disable of the profiler */
492493762fcSSteven Rostedt static DEFINE_MUTEX(ftrace_profile_lock);
493493762fcSSteven Rostedt 
494cafb168aSSteven Rostedt static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats);
495493762fcSSteven Rostedt 
496*20079ebeSNamhyung Kim #define FTRACE_PROFILE_HASH_BITS 10
497*20079ebeSNamhyung Kim #define FTRACE_PROFILE_HASH_SIZE (1 << FTRACE_PROFILE_HASH_BITS)
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 
728318e0a73SSteven Rostedt 	/* Preallocate the function profiling pages */
729cafb168aSSteven Rostedt 	if (ftrace_profile_pages_init(stat) < 0) {
730cafb168aSSteven Rostedt 		kfree(stat->hash);
731cafb168aSSteven Rostedt 		stat->hash = NULL;
732493762fcSSteven Rostedt 		return -ENOMEM;
733493762fcSSteven Rostedt 	}
734493762fcSSteven Rostedt 
735493762fcSSteven Rostedt 	return 0;
736493762fcSSteven Rostedt }
737493762fcSSteven Rostedt 
738cafb168aSSteven Rostedt static int ftrace_profile_init(void)
739cafb168aSSteven Rostedt {
740cafb168aSSteven Rostedt 	int cpu;
741cafb168aSSteven Rostedt 	int ret = 0;
742cafb168aSSteven Rostedt 
743cafb168aSSteven Rostedt 	for_each_online_cpu(cpu) {
744cafb168aSSteven Rostedt 		ret = ftrace_profile_init_cpu(cpu);
745cafb168aSSteven Rostedt 		if (ret)
746cafb168aSSteven Rostedt 			break;
747cafb168aSSteven Rostedt 	}
748cafb168aSSteven Rostedt 
749cafb168aSSteven Rostedt 	return ret;
750cafb168aSSteven Rostedt }
751cafb168aSSteven Rostedt 
752493762fcSSteven Rostedt /* interrupts must be disabled */
753cafb168aSSteven Rostedt static struct ftrace_profile *
754cafb168aSSteven Rostedt ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)
755493762fcSSteven Rostedt {
756493762fcSSteven Rostedt 	struct ftrace_profile *rec;
757493762fcSSteven Rostedt 	struct hlist_head *hhd;
758493762fcSSteven Rostedt 	struct hlist_node *n;
759493762fcSSteven Rostedt 	unsigned long key;
760493762fcSSteven Rostedt 
761*20079ebeSNamhyung Kim 	key = hash_long(ip, FTRACE_PROFILE_HASH_BITS);
762cafb168aSSteven Rostedt 	hhd = &stat->hash[key];
763493762fcSSteven Rostedt 
764493762fcSSteven Rostedt 	if (hlist_empty(hhd))
765493762fcSSteven Rostedt 		return NULL;
766493762fcSSteven Rostedt 
767493762fcSSteven Rostedt 	hlist_for_each_entry_rcu(rec, n, hhd, node) {
768493762fcSSteven Rostedt 		if (rec->ip == ip)
769493762fcSSteven Rostedt 			return rec;
770493762fcSSteven Rostedt 	}
771493762fcSSteven Rostedt 
772493762fcSSteven Rostedt 	return NULL;
773493762fcSSteven Rostedt }
774493762fcSSteven Rostedt 
775cafb168aSSteven Rostedt static void ftrace_add_profile(struct ftrace_profile_stat *stat,
776cafb168aSSteven Rostedt 			       struct ftrace_profile *rec)
777493762fcSSteven Rostedt {
778493762fcSSteven Rostedt 	unsigned long key;
779493762fcSSteven Rostedt 
780*20079ebeSNamhyung Kim 	key = hash_long(rec->ip, FTRACE_PROFILE_HASH_BITS);
781cafb168aSSteven Rostedt 	hlist_add_head_rcu(&rec->node, &stat->hash[key]);
782493762fcSSteven Rostedt }
783493762fcSSteven Rostedt 
784318e0a73SSteven Rostedt /*
785318e0a73SSteven Rostedt  * The memory is already allocated, this simply finds a new record to use.
786318e0a73SSteven Rostedt  */
787493762fcSSteven Rostedt static struct ftrace_profile *
788318e0a73SSteven Rostedt ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)
789493762fcSSteven Rostedt {
790493762fcSSteven Rostedt 	struct ftrace_profile *rec = NULL;
791493762fcSSteven Rostedt 
792318e0a73SSteven Rostedt 	/* prevent recursion (from NMIs) */
793cafb168aSSteven Rostedt 	if (atomic_inc_return(&stat->disabled) != 1)
794493762fcSSteven Rostedt 		goto out;
795493762fcSSteven Rostedt 
796493762fcSSteven Rostedt 	/*
797318e0a73SSteven Rostedt 	 * Try to find the function again since an NMI
798318e0a73SSteven Rostedt 	 * could have added it
799493762fcSSteven Rostedt 	 */
800cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, ip);
801493762fcSSteven Rostedt 	if (rec)
802cafb168aSSteven Rostedt 		goto out;
803493762fcSSteven Rostedt 
804cafb168aSSteven Rostedt 	if (stat->pages->index == PROFILES_PER_PAGE) {
805cafb168aSSteven Rostedt 		if (!stat->pages->next)
806cafb168aSSteven Rostedt 			goto out;
807cafb168aSSteven Rostedt 		stat->pages = stat->pages->next;
808493762fcSSteven Rostedt 	}
809493762fcSSteven Rostedt 
810cafb168aSSteven Rostedt 	rec = &stat->pages->records[stat->pages->index++];
811493762fcSSteven Rostedt 	rec->ip = ip;
812cafb168aSSteven Rostedt 	ftrace_add_profile(stat, rec);
813493762fcSSteven Rostedt 
814493762fcSSteven Rostedt  out:
815cafb168aSSteven Rostedt 	atomic_dec(&stat->disabled);
816493762fcSSteven Rostedt 
817493762fcSSteven Rostedt 	return rec;
818493762fcSSteven Rostedt }
819493762fcSSteven Rostedt 
820493762fcSSteven Rostedt static void
8212f5f6ad9SSteven Rostedt function_profile_call(unsigned long ip, unsigned long parent_ip,
822a1e2e31dSSteven Rostedt 		      struct ftrace_ops *ops, struct pt_regs *regs)
823493762fcSSteven Rostedt {
824cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
825493762fcSSteven Rostedt 	struct ftrace_profile *rec;
826493762fcSSteven Rostedt 	unsigned long flags;
827493762fcSSteven Rostedt 
828493762fcSSteven Rostedt 	if (!ftrace_profile_enabled)
829493762fcSSteven Rostedt 		return;
830493762fcSSteven Rostedt 
831493762fcSSteven Rostedt 	local_irq_save(flags);
832cafb168aSSteven Rostedt 
833cafb168aSSteven Rostedt 	stat = &__get_cpu_var(ftrace_profile_stats);
8340f6ce3deSSteven Rostedt 	if (!stat->hash || !ftrace_profile_enabled)
835cafb168aSSteven Rostedt 		goto out;
836cafb168aSSteven Rostedt 
837cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, ip);
838493762fcSSteven Rostedt 	if (!rec) {
839318e0a73SSteven Rostedt 		rec = ftrace_profile_alloc(stat, ip);
840493762fcSSteven Rostedt 		if (!rec)
841493762fcSSteven Rostedt 			goto out;
842493762fcSSteven Rostedt 	}
843493762fcSSteven Rostedt 
844493762fcSSteven Rostedt 	rec->counter++;
845493762fcSSteven Rostedt  out:
846493762fcSSteven Rostedt 	local_irq_restore(flags);
847493762fcSSteven Rostedt }
848493762fcSSteven Rostedt 
8490706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
8500706f1c4SSteven Rostedt static int profile_graph_entry(struct ftrace_graph_ent *trace)
8510706f1c4SSteven Rostedt {
852a1e2e31dSSteven Rostedt 	function_profile_call(trace->func, 0, NULL, NULL);
8530706f1c4SSteven Rostedt 	return 1;
8540706f1c4SSteven Rostedt }
8550706f1c4SSteven Rostedt 
8560706f1c4SSteven Rostedt static void profile_graph_return(struct ftrace_graph_ret *trace)
8570706f1c4SSteven Rostedt {
858cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
859a2a16d6aSSteven Rostedt 	unsigned long long calltime;
8600706f1c4SSteven Rostedt 	struct ftrace_profile *rec;
861cafb168aSSteven Rostedt 	unsigned long flags;
8620706f1c4SSteven Rostedt 
8630706f1c4SSteven Rostedt 	local_irq_save(flags);
864cafb168aSSteven Rostedt 	stat = &__get_cpu_var(ftrace_profile_stats);
8650f6ce3deSSteven Rostedt 	if (!stat->hash || !ftrace_profile_enabled)
866cafb168aSSteven Rostedt 		goto out;
867cafb168aSSteven Rostedt 
86837e44bc5SSteven Rostedt 	/* If the calltime was zero'd ignore it */
86937e44bc5SSteven Rostedt 	if (!trace->calltime)
87037e44bc5SSteven Rostedt 		goto out;
87137e44bc5SSteven Rostedt 
872a2a16d6aSSteven Rostedt 	calltime = trace->rettime - trace->calltime;
873a2a16d6aSSteven Rostedt 
874a2a16d6aSSteven Rostedt 	if (!(trace_flags & TRACE_ITER_GRAPH_TIME)) {
875a2a16d6aSSteven Rostedt 		int index;
876a2a16d6aSSteven Rostedt 
877a2a16d6aSSteven Rostedt 		index = trace->depth;
878a2a16d6aSSteven Rostedt 
879a2a16d6aSSteven Rostedt 		/* Append this call time to the parent time to subtract */
880a2a16d6aSSteven Rostedt 		if (index)
881a2a16d6aSSteven Rostedt 			current->ret_stack[index - 1].subtime += calltime;
882a2a16d6aSSteven Rostedt 
883a2a16d6aSSteven Rostedt 		if (current->ret_stack[index].subtime < calltime)
884a2a16d6aSSteven Rostedt 			calltime -= current->ret_stack[index].subtime;
885a2a16d6aSSteven Rostedt 		else
886a2a16d6aSSteven Rostedt 			calltime = 0;
887a2a16d6aSSteven Rostedt 	}
888a2a16d6aSSteven Rostedt 
889cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, trace->func);
890e330b3bcSChase Douglas 	if (rec) {
891a2a16d6aSSteven Rostedt 		rec->time += calltime;
892e330b3bcSChase Douglas 		rec->time_squared += calltime * calltime;
893e330b3bcSChase Douglas 	}
894a2a16d6aSSteven Rostedt 
895cafb168aSSteven Rostedt  out:
8960706f1c4SSteven Rostedt 	local_irq_restore(flags);
8970706f1c4SSteven Rostedt }
8980706f1c4SSteven Rostedt 
8990706f1c4SSteven Rostedt static int register_ftrace_profiler(void)
9000706f1c4SSteven Rostedt {
9010706f1c4SSteven Rostedt 	return register_ftrace_graph(&profile_graph_return,
9020706f1c4SSteven Rostedt 				     &profile_graph_entry);
9030706f1c4SSteven Rostedt }
9040706f1c4SSteven Rostedt 
9050706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void)
9060706f1c4SSteven Rostedt {
9070706f1c4SSteven Rostedt 	unregister_ftrace_graph();
9080706f1c4SSteven Rostedt }
9090706f1c4SSteven Rostedt #else
910bd38c0e6SPaul McQuade static struct ftrace_ops ftrace_profile_ops __read_mostly = {
911493762fcSSteven Rostedt 	.func		= function_profile_call,
9124740974aSSteven Rostedt 	.flags		= FTRACE_OPS_FL_RECURSION_SAFE,
913493762fcSSteven Rostedt };
914493762fcSSteven Rostedt 
9150706f1c4SSteven Rostedt static int register_ftrace_profiler(void)
9160706f1c4SSteven Rostedt {
9170706f1c4SSteven Rostedt 	return register_ftrace_function(&ftrace_profile_ops);
9180706f1c4SSteven Rostedt }
9190706f1c4SSteven Rostedt 
9200706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void)
9210706f1c4SSteven Rostedt {
9220706f1c4SSteven Rostedt 	unregister_ftrace_function(&ftrace_profile_ops);
9230706f1c4SSteven Rostedt }
9240706f1c4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
9250706f1c4SSteven Rostedt 
926493762fcSSteven Rostedt static ssize_t
927493762fcSSteven Rostedt ftrace_profile_write(struct file *filp, const char __user *ubuf,
928493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
929493762fcSSteven Rostedt {
930493762fcSSteven Rostedt 	unsigned long val;
931493762fcSSteven Rostedt 	int ret;
932493762fcSSteven Rostedt 
93322fe9b54SPeter Huewe 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
93422fe9b54SPeter Huewe 	if (ret)
935493762fcSSteven Rostedt 		return ret;
936493762fcSSteven Rostedt 
937493762fcSSteven Rostedt 	val = !!val;
938493762fcSSteven Rostedt 
939493762fcSSteven Rostedt 	mutex_lock(&ftrace_profile_lock);
940493762fcSSteven Rostedt 	if (ftrace_profile_enabled ^ val) {
941493762fcSSteven Rostedt 		if (val) {
942493762fcSSteven Rostedt 			ret = ftrace_profile_init();
943493762fcSSteven Rostedt 			if (ret < 0) {
944493762fcSSteven Rostedt 				cnt = ret;
945493762fcSSteven Rostedt 				goto out;
946493762fcSSteven Rostedt 			}
947493762fcSSteven Rostedt 
9480706f1c4SSteven Rostedt 			ret = register_ftrace_profiler();
9490706f1c4SSteven Rostedt 			if (ret < 0) {
9500706f1c4SSteven Rostedt 				cnt = ret;
9510706f1c4SSteven Rostedt 				goto out;
9520706f1c4SSteven Rostedt 			}
953493762fcSSteven Rostedt 			ftrace_profile_enabled = 1;
954493762fcSSteven Rostedt 		} else {
955493762fcSSteven Rostedt 			ftrace_profile_enabled = 0;
9560f6ce3deSSteven Rostedt 			/*
9570f6ce3deSSteven Rostedt 			 * unregister_ftrace_profiler calls stop_machine
9580f6ce3deSSteven Rostedt 			 * so this acts like an synchronize_sched.
9590f6ce3deSSteven Rostedt 			 */
9600706f1c4SSteven Rostedt 			unregister_ftrace_profiler();
961493762fcSSteven Rostedt 		}
962493762fcSSteven Rostedt 	}
963493762fcSSteven Rostedt  out:
964493762fcSSteven Rostedt 	mutex_unlock(&ftrace_profile_lock);
965493762fcSSteven Rostedt 
966cf8517cfSJiri Olsa 	*ppos += cnt;
967493762fcSSteven Rostedt 
968493762fcSSteven Rostedt 	return cnt;
969493762fcSSteven Rostedt }
970493762fcSSteven Rostedt 
971493762fcSSteven Rostedt static ssize_t
972493762fcSSteven Rostedt ftrace_profile_read(struct file *filp, char __user *ubuf,
973493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
974493762fcSSteven Rostedt {
975fb9fb015SSteven Rostedt 	char buf[64];		/* big enough to hold a number */
976493762fcSSteven Rostedt 	int r;
977493762fcSSteven Rostedt 
978493762fcSSteven Rostedt 	r = sprintf(buf, "%u\n", ftrace_profile_enabled);
979493762fcSSteven Rostedt 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
980493762fcSSteven Rostedt }
981493762fcSSteven Rostedt 
982493762fcSSteven Rostedt static const struct file_operations ftrace_profile_fops = {
983493762fcSSteven Rostedt 	.open		= tracing_open_generic,
984493762fcSSteven Rostedt 	.read		= ftrace_profile_read,
985493762fcSSteven Rostedt 	.write		= ftrace_profile_write,
9866038f373SArnd Bergmann 	.llseek		= default_llseek,
987493762fcSSteven Rostedt };
988493762fcSSteven Rostedt 
989cafb168aSSteven Rostedt /* used to initialize the real stat files */
990cafb168aSSteven Rostedt static struct tracer_stat function_stats __initdata = {
991cafb168aSSteven Rostedt 	.name		= "functions",
992cafb168aSSteven Rostedt 	.stat_start	= function_stat_start,
993cafb168aSSteven Rostedt 	.stat_next	= function_stat_next,
994cafb168aSSteven Rostedt 	.stat_cmp	= function_stat_cmp,
995cafb168aSSteven Rostedt 	.stat_headers	= function_stat_headers,
996cafb168aSSteven Rostedt 	.stat_show	= function_stat_show
997cafb168aSSteven Rostedt };
998cafb168aSSteven Rostedt 
9996ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
1000493762fcSSteven Rostedt {
1001cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
1002493762fcSSteven Rostedt 	struct dentry *entry;
1003cafb168aSSteven Rostedt 	char *name;
1004493762fcSSteven Rostedt 	int ret;
1005cafb168aSSteven Rostedt 	int cpu;
1006493762fcSSteven Rostedt 
1007cafb168aSSteven Rostedt 	for_each_possible_cpu(cpu) {
1008cafb168aSSteven Rostedt 		stat = &per_cpu(ftrace_profile_stats, cpu);
1009cafb168aSSteven Rostedt 
1010cafb168aSSteven Rostedt 		/* allocate enough for function name + cpu number */
1011cafb168aSSteven Rostedt 		name = kmalloc(32, GFP_KERNEL);
1012cafb168aSSteven Rostedt 		if (!name) {
1013cafb168aSSteven Rostedt 			/*
1014cafb168aSSteven Rostedt 			 * The files created are permanent, if something happens
1015cafb168aSSteven Rostedt 			 * we still do not free memory.
1016cafb168aSSteven Rostedt 			 */
1017cafb168aSSteven Rostedt 			WARN(1,
1018cafb168aSSteven Rostedt 			     "Could not allocate stat file for cpu %d\n",
1019cafb168aSSteven Rostedt 			     cpu);
1020493762fcSSteven Rostedt 			return;
1021493762fcSSteven Rostedt 		}
1022cafb168aSSteven Rostedt 		stat->stat = function_stats;
1023cafb168aSSteven Rostedt 		snprintf(name, 32, "function%d", cpu);
1024cafb168aSSteven Rostedt 		stat->stat.name = name;
1025cafb168aSSteven Rostedt 		ret = register_stat_tracer(&stat->stat);
1026cafb168aSSteven Rostedt 		if (ret) {
1027cafb168aSSteven Rostedt 			WARN(1,
1028cafb168aSSteven Rostedt 			     "Could not register function stat for cpu %d\n",
1029cafb168aSSteven Rostedt 			     cpu);
1030cafb168aSSteven Rostedt 			kfree(name);
1031cafb168aSSteven Rostedt 			return;
1032cafb168aSSteven Rostedt 		}
1033cafb168aSSteven Rostedt 	}
1034493762fcSSteven Rostedt 
1035493762fcSSteven Rostedt 	entry = debugfs_create_file("function_profile_enabled", 0644,
1036493762fcSSteven Rostedt 				    d_tracer, NULL, &ftrace_profile_fops);
1037493762fcSSteven Rostedt 	if (!entry)
1038493762fcSSteven Rostedt 		pr_warning("Could not create debugfs "
1039493762fcSSteven Rostedt 			   "'function_profile_enabled' entry\n");
1040493762fcSSteven Rostedt }
1041493762fcSSteven Rostedt 
1042493762fcSSteven Rostedt #else /* CONFIG_FUNCTION_PROFILER */
10436ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
1044493762fcSSteven Rostedt {
1045493762fcSSteven Rostedt }
1046493762fcSSteven Rostedt #endif /* CONFIG_FUNCTION_PROFILER */
1047493762fcSSteven Rostedt 
104873d3fd96SIngo Molnar static struct pid * const ftrace_swapper_pid = &init_struct_pid;
104973d3fd96SIngo Molnar 
10503d083395SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE
105173d3fd96SIngo Molnar 
105299ecdc43SSteven Rostedt #ifndef CONFIG_FTRACE_MCOUNT_RECORD
1053cb7be3b2SSteven Rostedt # error Dynamic ftrace depends on MCOUNT_RECORD
105499ecdc43SSteven Rostedt #endif
105599ecdc43SSteven Rostedt 
10568fc0c701SSteven Rostedt static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly;
10578fc0c701SSteven Rostedt 
1058b6887d79SSteven Rostedt struct ftrace_func_probe {
10598fc0c701SSteven Rostedt 	struct hlist_node	node;
1060b6887d79SSteven Rostedt 	struct ftrace_probe_ops	*ops;
10618fc0c701SSteven Rostedt 	unsigned long		flags;
10628fc0c701SSteven Rostedt 	unsigned long		ip;
10638fc0c701SSteven Rostedt 	void			*data;
10647818b388SSteven Rostedt (Red Hat) 	struct list_head	free_list;
10658fc0c701SSteven Rostedt };
10668fc0c701SSteven Rostedt 
1067b448c4e3SSteven Rostedt struct ftrace_func_entry {
1068b448c4e3SSteven Rostedt 	struct hlist_node hlist;
1069b448c4e3SSteven Rostedt 	unsigned long ip;
1070b448c4e3SSteven Rostedt };
1071b448c4e3SSteven Rostedt 
1072b448c4e3SSteven Rostedt struct ftrace_hash {
1073b448c4e3SSteven Rostedt 	unsigned long		size_bits;
1074b448c4e3SSteven Rostedt 	struct hlist_head	*buckets;
1075b448c4e3SSteven Rostedt 	unsigned long		count;
107607fd5515SSteven Rostedt 	struct rcu_head		rcu;
1077b448c4e3SSteven Rostedt };
1078b448c4e3SSteven Rostedt 
107933dc9b12SSteven Rostedt /*
108033dc9b12SSteven Rostedt  * We make these constant because no one should touch them,
108133dc9b12SSteven Rostedt  * but they are used as the default "empty hash", to avoid allocating
108233dc9b12SSteven Rostedt  * it all the time. These are in a read only section such that if
108333dc9b12SSteven Rostedt  * anyone does try to modify it, it will cause an exception.
108433dc9b12SSteven Rostedt  */
108533dc9b12SSteven Rostedt static const struct hlist_head empty_buckets[1];
108633dc9b12SSteven Rostedt static const struct ftrace_hash empty_hash = {
108733dc9b12SSteven Rostedt 	.buckets = (struct hlist_head *)empty_buckets,
1088b448c4e3SSteven Rostedt };
108933dc9b12SSteven Rostedt #define EMPTY_HASH	((struct ftrace_hash *)&empty_hash)
10905072c59fSSteven Rostedt 
10912b499381SSteven Rostedt static struct ftrace_ops global_ops = {
1092f45948e8SSteven Rostedt 	.func			= ftrace_stub,
109333dc9b12SSteven Rostedt 	.notrace_hash		= EMPTY_HASH,
109433dc9b12SSteven Rostedt 	.filter_hash		= EMPTY_HASH,
10954740974aSSteven Rostedt 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE,
1096f45948e8SSteven Rostedt };
1097f45948e8SSteven Rostedt 
109841c52c0dSSteven Rostedt static DEFINE_MUTEX(ftrace_regex_lock);
10993d083395SSteven Rostedt 
11003c1720f0SSteven Rostedt struct ftrace_page {
11013c1720f0SSteven Rostedt 	struct ftrace_page	*next;
1102a7900875SSteven Rostedt 	struct dyn_ftrace	*records;
1103431aa3fbSSteven Rostedt 	int			index;
1104a7900875SSteven Rostedt 	int			size;
1105aa5e5ceaSDavid Miller };
11063c1720f0SSteven Rostedt 
110785ae32aeSSteven Rostedt static struct ftrace_page *ftrace_new_pgs;
110885ae32aeSSteven Rostedt 
1109a7900875SSteven Rostedt #define ENTRY_SIZE sizeof(struct dyn_ftrace)
1110a7900875SSteven Rostedt #define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
11113c1720f0SSteven Rostedt 
11123c1720f0SSteven Rostedt /* estimate from running different kernels */
11133c1720f0SSteven Rostedt #define NR_TO_INIT		10000
11143c1720f0SSteven Rostedt 
11153c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages_start;
11163c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages;
11173c1720f0SSteven Rostedt 
111806a51d93SSteven Rostedt static bool ftrace_hash_empty(struct ftrace_hash *hash)
111906a51d93SSteven Rostedt {
112006a51d93SSteven Rostedt 	return !hash || !hash->count;
112106a51d93SSteven Rostedt }
112206a51d93SSteven Rostedt 
1123b448c4e3SSteven Rostedt static struct ftrace_func_entry *
1124b448c4e3SSteven Rostedt ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
1125b448c4e3SSteven Rostedt {
1126b448c4e3SSteven Rostedt 	unsigned long key;
1127b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1128b448c4e3SSteven Rostedt 	struct hlist_head *hhd;
1129b448c4e3SSteven Rostedt 	struct hlist_node *n;
1130b448c4e3SSteven Rostedt 
113106a51d93SSteven Rostedt 	if (ftrace_hash_empty(hash))
1132b448c4e3SSteven Rostedt 		return NULL;
1133b448c4e3SSteven Rostedt 
1134b448c4e3SSteven Rostedt 	if (hash->size_bits > 0)
1135b448c4e3SSteven Rostedt 		key = hash_long(ip, hash->size_bits);
1136b448c4e3SSteven Rostedt 	else
1137b448c4e3SSteven Rostedt 		key = 0;
1138b448c4e3SSteven Rostedt 
1139b448c4e3SSteven Rostedt 	hhd = &hash->buckets[key];
1140b448c4e3SSteven Rostedt 
1141b448c4e3SSteven Rostedt 	hlist_for_each_entry_rcu(entry, n, hhd, hlist) {
1142b448c4e3SSteven Rostedt 		if (entry->ip == ip)
1143b448c4e3SSteven Rostedt 			return entry;
1144b448c4e3SSteven Rostedt 	}
1145b448c4e3SSteven Rostedt 	return NULL;
1146b448c4e3SSteven Rostedt }
1147b448c4e3SSteven Rostedt 
114833dc9b12SSteven Rostedt static void __add_hash_entry(struct ftrace_hash *hash,
114933dc9b12SSteven Rostedt 			     struct ftrace_func_entry *entry)
115033dc9b12SSteven Rostedt {
115133dc9b12SSteven Rostedt 	struct hlist_head *hhd;
115233dc9b12SSteven Rostedt 	unsigned long key;
115333dc9b12SSteven Rostedt 
115433dc9b12SSteven Rostedt 	if (hash->size_bits)
115533dc9b12SSteven Rostedt 		key = hash_long(entry->ip, hash->size_bits);
115633dc9b12SSteven Rostedt 	else
115733dc9b12SSteven Rostedt 		key = 0;
115833dc9b12SSteven Rostedt 
115933dc9b12SSteven Rostedt 	hhd = &hash->buckets[key];
116033dc9b12SSteven Rostedt 	hlist_add_head(&entry->hlist, hhd);
116133dc9b12SSteven Rostedt 	hash->count++;
116233dc9b12SSteven Rostedt }
116333dc9b12SSteven Rostedt 
1164b448c4e3SSteven Rostedt static int add_hash_entry(struct ftrace_hash *hash, unsigned long ip)
1165b448c4e3SSteven Rostedt {
1166b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1167b448c4e3SSteven Rostedt 
1168b448c4e3SSteven Rostedt 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
1169b448c4e3SSteven Rostedt 	if (!entry)
1170b448c4e3SSteven Rostedt 		return -ENOMEM;
1171b448c4e3SSteven Rostedt 
1172b448c4e3SSteven Rostedt 	entry->ip = ip;
117333dc9b12SSteven Rostedt 	__add_hash_entry(hash, entry);
1174b448c4e3SSteven Rostedt 
1175b448c4e3SSteven Rostedt 	return 0;
1176b448c4e3SSteven Rostedt }
1177b448c4e3SSteven Rostedt 
1178b448c4e3SSteven Rostedt static void
117933dc9b12SSteven Rostedt free_hash_entry(struct ftrace_hash *hash,
118033dc9b12SSteven Rostedt 		  struct ftrace_func_entry *entry)
118133dc9b12SSteven Rostedt {
118233dc9b12SSteven Rostedt 	hlist_del(&entry->hlist);
118333dc9b12SSteven Rostedt 	kfree(entry);
118433dc9b12SSteven Rostedt 	hash->count--;
118533dc9b12SSteven Rostedt }
118633dc9b12SSteven Rostedt 
118733dc9b12SSteven Rostedt static void
1188b448c4e3SSteven Rostedt remove_hash_entry(struct ftrace_hash *hash,
1189b448c4e3SSteven Rostedt 		  struct ftrace_func_entry *entry)
1190b448c4e3SSteven Rostedt {
1191b448c4e3SSteven Rostedt 	hlist_del(&entry->hlist);
1192b448c4e3SSteven Rostedt 	hash->count--;
1193b448c4e3SSteven Rostedt }
1194b448c4e3SSteven Rostedt 
1195b448c4e3SSteven Rostedt static void ftrace_hash_clear(struct ftrace_hash *hash)
1196b448c4e3SSteven Rostedt {
1197b448c4e3SSteven Rostedt 	struct hlist_head *hhd;
1198b448c4e3SSteven Rostedt 	struct hlist_node *tp, *tn;
1199b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1200b448c4e3SSteven Rostedt 	int size = 1 << hash->size_bits;
1201b448c4e3SSteven Rostedt 	int i;
1202b448c4e3SSteven Rostedt 
120333dc9b12SSteven Rostedt 	if (!hash->count)
120433dc9b12SSteven Rostedt 		return;
120533dc9b12SSteven Rostedt 
1206b448c4e3SSteven Rostedt 	for (i = 0; i < size; i++) {
1207b448c4e3SSteven Rostedt 		hhd = &hash->buckets[i];
1208b448c4e3SSteven Rostedt 		hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist)
120933dc9b12SSteven Rostedt 			free_hash_entry(hash, entry);
1210b448c4e3SSteven Rostedt 	}
1211b448c4e3SSteven Rostedt 	FTRACE_WARN_ON(hash->count);
1212b448c4e3SSteven Rostedt }
1213b448c4e3SSteven Rostedt 
121433dc9b12SSteven Rostedt static void free_ftrace_hash(struct ftrace_hash *hash)
121533dc9b12SSteven Rostedt {
121633dc9b12SSteven Rostedt 	if (!hash || hash == EMPTY_HASH)
121733dc9b12SSteven Rostedt 		return;
121833dc9b12SSteven Rostedt 	ftrace_hash_clear(hash);
121933dc9b12SSteven Rostedt 	kfree(hash->buckets);
122033dc9b12SSteven Rostedt 	kfree(hash);
122133dc9b12SSteven Rostedt }
122233dc9b12SSteven Rostedt 
122307fd5515SSteven Rostedt static void __free_ftrace_hash_rcu(struct rcu_head *rcu)
122407fd5515SSteven Rostedt {
122507fd5515SSteven Rostedt 	struct ftrace_hash *hash;
122607fd5515SSteven Rostedt 
122707fd5515SSteven Rostedt 	hash = container_of(rcu, struct ftrace_hash, rcu);
122807fd5515SSteven Rostedt 	free_ftrace_hash(hash);
122907fd5515SSteven Rostedt }
123007fd5515SSteven Rostedt 
123107fd5515SSteven Rostedt static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
123207fd5515SSteven Rostedt {
123307fd5515SSteven Rostedt 	if (!hash || hash == EMPTY_HASH)
123407fd5515SSteven Rostedt 		return;
123507fd5515SSteven Rostedt 	call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu);
123607fd5515SSteven Rostedt }
123707fd5515SSteven Rostedt 
12385500fa51SJiri Olsa void ftrace_free_filter(struct ftrace_ops *ops)
12395500fa51SJiri Olsa {
12405500fa51SJiri Olsa 	free_ftrace_hash(ops->filter_hash);
12415500fa51SJiri Olsa 	free_ftrace_hash(ops->notrace_hash);
12425500fa51SJiri Olsa }
12435500fa51SJiri Olsa 
124433dc9b12SSteven Rostedt static struct ftrace_hash *alloc_ftrace_hash(int size_bits)
124533dc9b12SSteven Rostedt {
124633dc9b12SSteven Rostedt 	struct ftrace_hash *hash;
124733dc9b12SSteven Rostedt 	int size;
124833dc9b12SSteven Rostedt 
124933dc9b12SSteven Rostedt 	hash = kzalloc(sizeof(*hash), GFP_KERNEL);
125033dc9b12SSteven Rostedt 	if (!hash)
125133dc9b12SSteven Rostedt 		return NULL;
125233dc9b12SSteven Rostedt 
125333dc9b12SSteven Rostedt 	size = 1 << size_bits;
125447b0edcbSThomas Meyer 	hash->buckets = kcalloc(size, sizeof(*hash->buckets), GFP_KERNEL);
125533dc9b12SSteven Rostedt 
125633dc9b12SSteven Rostedt 	if (!hash->buckets) {
125733dc9b12SSteven Rostedt 		kfree(hash);
125833dc9b12SSteven Rostedt 		return NULL;
125933dc9b12SSteven Rostedt 	}
126033dc9b12SSteven Rostedt 
126133dc9b12SSteven Rostedt 	hash->size_bits = size_bits;
126233dc9b12SSteven Rostedt 
126333dc9b12SSteven Rostedt 	return hash;
126433dc9b12SSteven Rostedt }
126533dc9b12SSteven Rostedt 
126633dc9b12SSteven Rostedt static struct ftrace_hash *
126733dc9b12SSteven Rostedt alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
126833dc9b12SSteven Rostedt {
126933dc9b12SSteven Rostedt 	struct ftrace_func_entry *entry;
127033dc9b12SSteven Rostedt 	struct ftrace_hash *new_hash;
127133dc9b12SSteven Rostedt 	struct hlist_node *tp;
127233dc9b12SSteven Rostedt 	int size;
127333dc9b12SSteven Rostedt 	int ret;
127433dc9b12SSteven Rostedt 	int i;
127533dc9b12SSteven Rostedt 
127633dc9b12SSteven Rostedt 	new_hash = alloc_ftrace_hash(size_bits);
127733dc9b12SSteven Rostedt 	if (!new_hash)
127833dc9b12SSteven Rostedt 		return NULL;
127933dc9b12SSteven Rostedt 
128033dc9b12SSteven Rostedt 	/* Empty hash? */
128106a51d93SSteven Rostedt 	if (ftrace_hash_empty(hash))
128233dc9b12SSteven Rostedt 		return new_hash;
128333dc9b12SSteven Rostedt 
128433dc9b12SSteven Rostedt 	size = 1 << hash->size_bits;
128533dc9b12SSteven Rostedt 	for (i = 0; i < size; i++) {
128633dc9b12SSteven Rostedt 		hlist_for_each_entry(entry, tp, &hash->buckets[i], hlist) {
128733dc9b12SSteven Rostedt 			ret = add_hash_entry(new_hash, entry->ip);
128833dc9b12SSteven Rostedt 			if (ret < 0)
128933dc9b12SSteven Rostedt 				goto free_hash;
129033dc9b12SSteven Rostedt 		}
129133dc9b12SSteven Rostedt 	}
129233dc9b12SSteven Rostedt 
129333dc9b12SSteven Rostedt 	FTRACE_WARN_ON(new_hash->count != hash->count);
129433dc9b12SSteven Rostedt 
129533dc9b12SSteven Rostedt 	return new_hash;
129633dc9b12SSteven Rostedt 
129733dc9b12SSteven Rostedt  free_hash:
129833dc9b12SSteven Rostedt 	free_ftrace_hash(new_hash);
129933dc9b12SSteven Rostedt 	return NULL;
130033dc9b12SSteven Rostedt }
130133dc9b12SSteven Rostedt 
130241fb61c2SSteven Rostedt static void
130341fb61c2SSteven Rostedt ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash);
130441fb61c2SSteven Rostedt static void
130541fb61c2SSteven Rostedt ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash);
130641fb61c2SSteven Rostedt 
130733dc9b12SSteven Rostedt static int
130841fb61c2SSteven Rostedt ftrace_hash_move(struct ftrace_ops *ops, int enable,
130941fb61c2SSteven Rostedt 		 struct ftrace_hash **dst, struct ftrace_hash *src)
131033dc9b12SSteven Rostedt {
131133dc9b12SSteven Rostedt 	struct ftrace_func_entry *entry;
131233dc9b12SSteven Rostedt 	struct hlist_node *tp, *tn;
131333dc9b12SSteven Rostedt 	struct hlist_head *hhd;
131407fd5515SSteven Rostedt 	struct ftrace_hash *old_hash;
131507fd5515SSteven Rostedt 	struct ftrace_hash *new_hash;
131633dc9b12SSteven Rostedt 	int size = src->count;
131733dc9b12SSteven Rostedt 	int bits = 0;
131841fb61c2SSteven Rostedt 	int ret;
131933dc9b12SSteven Rostedt 	int i;
132033dc9b12SSteven Rostedt 
132133dc9b12SSteven Rostedt 	/*
132241fb61c2SSteven Rostedt 	 * Remove the current set, update the hash and add
132341fb61c2SSteven Rostedt 	 * them back.
132441fb61c2SSteven Rostedt 	 */
132541fb61c2SSteven Rostedt 	ftrace_hash_rec_disable(ops, enable);
132641fb61c2SSteven Rostedt 
132741fb61c2SSteven Rostedt 	/*
132833dc9b12SSteven Rostedt 	 * If the new source is empty, just free dst and assign it
132933dc9b12SSteven Rostedt 	 * the empty_hash.
133033dc9b12SSteven Rostedt 	 */
133133dc9b12SSteven Rostedt 	if (!src->count) {
133207fd5515SSteven Rostedt 		free_ftrace_hash_rcu(*dst);
133307fd5515SSteven Rostedt 		rcu_assign_pointer(*dst, EMPTY_HASH);
1334d4d34b98SSteven Rostedt 		/* still need to update the function records */
1335d4d34b98SSteven Rostedt 		ret = 0;
1336d4d34b98SSteven Rostedt 		goto out;
133733dc9b12SSteven Rostedt 	}
133833dc9b12SSteven Rostedt 
133933dc9b12SSteven Rostedt 	/*
134033dc9b12SSteven Rostedt 	 * Make the hash size about 1/2 the # found
134133dc9b12SSteven Rostedt 	 */
134233dc9b12SSteven Rostedt 	for (size /= 2; size; size >>= 1)
134333dc9b12SSteven Rostedt 		bits++;
134433dc9b12SSteven Rostedt 
134533dc9b12SSteven Rostedt 	/* Don't allocate too much */
134633dc9b12SSteven Rostedt 	if (bits > FTRACE_HASH_MAX_BITS)
134733dc9b12SSteven Rostedt 		bits = FTRACE_HASH_MAX_BITS;
134833dc9b12SSteven Rostedt 
134941fb61c2SSteven Rostedt 	ret = -ENOMEM;
135007fd5515SSteven Rostedt 	new_hash = alloc_ftrace_hash(bits);
135107fd5515SSteven Rostedt 	if (!new_hash)
135241fb61c2SSteven Rostedt 		goto out;
135333dc9b12SSteven Rostedt 
135433dc9b12SSteven Rostedt 	size = 1 << src->size_bits;
135533dc9b12SSteven Rostedt 	for (i = 0; i < size; i++) {
135633dc9b12SSteven Rostedt 		hhd = &src->buckets[i];
135733dc9b12SSteven Rostedt 		hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) {
135833dc9b12SSteven Rostedt 			remove_hash_entry(src, entry);
135907fd5515SSteven Rostedt 			__add_hash_entry(new_hash, entry);
136033dc9b12SSteven Rostedt 		}
136133dc9b12SSteven Rostedt 	}
136233dc9b12SSteven Rostedt 
136307fd5515SSteven Rostedt 	old_hash = *dst;
136407fd5515SSteven Rostedt 	rcu_assign_pointer(*dst, new_hash);
136507fd5515SSteven Rostedt 	free_ftrace_hash_rcu(old_hash);
136607fd5515SSteven Rostedt 
136741fb61c2SSteven Rostedt 	ret = 0;
136841fb61c2SSteven Rostedt  out:
136941fb61c2SSteven Rostedt 	/*
137041fb61c2SSteven Rostedt 	 * Enable regardless of ret:
137141fb61c2SSteven Rostedt 	 *  On success, we enable the new hash.
137241fb61c2SSteven Rostedt 	 *  On failure, we re-enable the original hash.
137341fb61c2SSteven Rostedt 	 */
137441fb61c2SSteven Rostedt 	ftrace_hash_rec_enable(ops, enable);
137541fb61c2SSteven Rostedt 
137641fb61c2SSteven Rostedt 	return ret;
137733dc9b12SSteven Rostedt }
137833dc9b12SSteven Rostedt 
1379265c831cSSteven Rostedt /*
1380b848914cSSteven Rostedt  * Test the hashes for this ops to see if we want to call
1381b848914cSSteven Rostedt  * the ops->func or not.
1382b848914cSSteven Rostedt  *
1383b848914cSSteven Rostedt  * It's a match if the ip is in the ops->filter_hash or
1384b848914cSSteven Rostedt  * the filter_hash does not exist or is empty,
1385b848914cSSteven Rostedt  *  AND
1386b848914cSSteven Rostedt  * the ip is not in the ops->notrace_hash.
1387cdbe61bfSSteven Rostedt  *
1388cdbe61bfSSteven Rostedt  * This needs to be called with preemption disabled as
1389cdbe61bfSSteven Rostedt  * the hashes are freed with call_rcu_sched().
1390b848914cSSteven Rostedt  */
1391b848914cSSteven Rostedt static int
1392b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
1393b848914cSSteven Rostedt {
1394b848914cSSteven Rostedt 	struct ftrace_hash *filter_hash;
1395b848914cSSteven Rostedt 	struct ftrace_hash *notrace_hash;
1396b848914cSSteven Rostedt 	int ret;
1397b848914cSSteven Rostedt 
1398b848914cSSteven Rostedt 	filter_hash = rcu_dereference_raw(ops->filter_hash);
1399b848914cSSteven Rostedt 	notrace_hash = rcu_dereference_raw(ops->notrace_hash);
1400b848914cSSteven Rostedt 
140106a51d93SSteven Rostedt 	if ((ftrace_hash_empty(filter_hash) ||
1402b848914cSSteven Rostedt 	     ftrace_lookup_ip(filter_hash, ip)) &&
140306a51d93SSteven Rostedt 	    (ftrace_hash_empty(notrace_hash) ||
1404b848914cSSteven Rostedt 	     !ftrace_lookup_ip(notrace_hash, ip)))
1405b848914cSSteven Rostedt 		ret = 1;
1406b848914cSSteven Rostedt 	else
1407b848914cSSteven Rostedt 		ret = 0;
1408b848914cSSteven Rostedt 
1409b848914cSSteven Rostedt 	return ret;
1410b848914cSSteven Rostedt }
1411b848914cSSteven Rostedt 
1412b848914cSSteven Rostedt /*
1413265c831cSSteven Rostedt  * This is a double for. Do not use 'break' to break out of the loop,
1414265c831cSSteven Rostedt  * you must use a goto.
1415265c831cSSteven Rostedt  */
1416265c831cSSteven Rostedt #define do_for_each_ftrace_rec(pg, rec)					\
1417265c831cSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {		\
1418265c831cSSteven Rostedt 		int _____i;						\
1419265c831cSSteven Rostedt 		for (_____i = 0; _____i < pg->index; _____i++) {	\
1420265c831cSSteven Rostedt 			rec = &pg->records[_____i];
1421265c831cSSteven Rostedt 
1422265c831cSSteven Rostedt #define while_for_each_ftrace_rec()		\
1423265c831cSSteven Rostedt 		}				\
1424265c831cSSteven Rostedt 	}
1425ecea656dSAbhishek Sagar 
14265855feadSSteven Rostedt 
14275855feadSSteven Rostedt static int ftrace_cmp_recs(const void *a, const void *b)
14285855feadSSteven Rostedt {
1429a650e02aSSteven Rostedt 	const struct dyn_ftrace *key = a;
1430a650e02aSSteven Rostedt 	const struct dyn_ftrace *rec = b;
14315855feadSSteven Rostedt 
1432a650e02aSSteven Rostedt 	if (key->flags < rec->ip)
14335855feadSSteven Rostedt 		return -1;
1434a650e02aSSteven Rostedt 	if (key->ip >= rec->ip + MCOUNT_INSN_SIZE)
1435a650e02aSSteven Rostedt 		return 1;
1436a650e02aSSteven Rostedt 	return 0;
1437a650e02aSSteven Rostedt }
1438a650e02aSSteven Rostedt 
1439f0cf973aSSteven Rostedt static unsigned long ftrace_location_range(unsigned long start, unsigned long end)
1440a650e02aSSteven Rostedt {
1441a650e02aSSteven Rostedt 	struct ftrace_page *pg;
1442a650e02aSSteven Rostedt 	struct dyn_ftrace *rec;
1443a650e02aSSteven Rostedt 	struct dyn_ftrace key;
1444a650e02aSSteven Rostedt 
1445a650e02aSSteven Rostedt 	key.ip = start;
1446a650e02aSSteven Rostedt 	key.flags = end;	/* overload flags, as it is unsigned long */
1447a650e02aSSteven Rostedt 
1448a650e02aSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {
1449a650e02aSSteven Rostedt 		if (end < pg->records[0].ip ||
1450a650e02aSSteven Rostedt 		    start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
1451a650e02aSSteven Rostedt 			continue;
1452a650e02aSSteven Rostedt 		rec = bsearch(&key, pg->records, pg->index,
1453a650e02aSSteven Rostedt 			      sizeof(struct dyn_ftrace),
1454a650e02aSSteven Rostedt 			      ftrace_cmp_recs);
1455a650e02aSSteven Rostedt 		if (rec)
1456f0cf973aSSteven Rostedt 			return rec->ip;
1457a650e02aSSteven Rostedt 	}
1458a650e02aSSteven Rostedt 
14595855feadSSteven Rostedt 	return 0;
14605855feadSSteven Rostedt }
14615855feadSSteven Rostedt 
1462c88fd863SSteven Rostedt /**
1463c88fd863SSteven Rostedt  * ftrace_location - return true if the ip giving is a traced location
1464c88fd863SSteven Rostedt  * @ip: the instruction pointer to check
1465c88fd863SSteven Rostedt  *
1466f0cf973aSSteven Rostedt  * Returns rec->ip if @ip given is a pointer to a ftrace location.
1467c88fd863SSteven Rostedt  * That is, the instruction that is either a NOP or call to
1468c88fd863SSteven Rostedt  * the function tracer. It checks the ftrace internal tables to
1469c88fd863SSteven Rostedt  * determine if the address belongs or not.
1470c88fd863SSteven Rostedt  */
1471f0cf973aSSteven Rostedt unsigned long ftrace_location(unsigned long ip)
1472c88fd863SSteven Rostedt {
1473a650e02aSSteven Rostedt 	return ftrace_location_range(ip, ip);
14745855feadSSteven Rostedt }
1475c88fd863SSteven Rostedt 
1476a650e02aSSteven Rostedt /**
1477a650e02aSSteven Rostedt  * ftrace_text_reserved - return true if range contains an ftrace location
1478a650e02aSSteven Rostedt  * @start: start of range to search
1479a650e02aSSteven Rostedt  * @end: end of range to search (inclusive). @end points to the last byte to check.
1480a650e02aSSteven Rostedt  *
1481a650e02aSSteven Rostedt  * Returns 1 if @start and @end contains a ftrace location.
1482a650e02aSSteven Rostedt  * That is, the instruction that is either a NOP or call to
1483a650e02aSSteven Rostedt  * the function tracer. It checks the ftrace internal tables to
1484a650e02aSSteven Rostedt  * determine if the address belongs or not.
1485a650e02aSSteven Rostedt  */
1486a650e02aSSteven Rostedt int ftrace_text_reserved(void *start, void *end)
1487a650e02aSSteven Rostedt {
1488f0cf973aSSteven Rostedt 	unsigned long ret;
1489f0cf973aSSteven Rostedt 
1490f0cf973aSSteven Rostedt 	ret = ftrace_location_range((unsigned long)start,
1491a650e02aSSteven Rostedt 				    (unsigned long)end);
1492f0cf973aSSteven Rostedt 
1493f0cf973aSSteven Rostedt 	return (int)!!ret;
1494c88fd863SSteven Rostedt }
1495c88fd863SSteven Rostedt 
1496ed926f9bSSteven Rostedt static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1497ed926f9bSSteven Rostedt 				     int filter_hash,
1498ed926f9bSSteven Rostedt 				     bool inc)
1499ed926f9bSSteven Rostedt {
1500ed926f9bSSteven Rostedt 	struct ftrace_hash *hash;
1501ed926f9bSSteven Rostedt 	struct ftrace_hash *other_hash;
1502ed926f9bSSteven Rostedt 	struct ftrace_page *pg;
1503ed926f9bSSteven Rostedt 	struct dyn_ftrace *rec;
1504ed926f9bSSteven Rostedt 	int count = 0;
1505ed926f9bSSteven Rostedt 	int all = 0;
1506ed926f9bSSteven Rostedt 
1507ed926f9bSSteven Rostedt 	/* Only update if the ops has been registered */
1508ed926f9bSSteven Rostedt 	if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
1509ed926f9bSSteven Rostedt 		return;
1510ed926f9bSSteven Rostedt 
1511ed926f9bSSteven Rostedt 	/*
1512ed926f9bSSteven Rostedt 	 * In the filter_hash case:
1513ed926f9bSSteven Rostedt 	 *   If the count is zero, we update all records.
1514ed926f9bSSteven Rostedt 	 *   Otherwise we just update the items in the hash.
1515ed926f9bSSteven Rostedt 	 *
1516ed926f9bSSteven Rostedt 	 * In the notrace_hash case:
1517ed926f9bSSteven Rostedt 	 *   We enable the update in the hash.
1518ed926f9bSSteven Rostedt 	 *   As disabling notrace means enabling the tracing,
1519ed926f9bSSteven Rostedt 	 *   and enabling notrace means disabling, the inc variable
1520ed926f9bSSteven Rostedt 	 *   gets inversed.
1521ed926f9bSSteven Rostedt 	 */
1522ed926f9bSSteven Rostedt 	if (filter_hash) {
1523ed926f9bSSteven Rostedt 		hash = ops->filter_hash;
1524ed926f9bSSteven Rostedt 		other_hash = ops->notrace_hash;
152506a51d93SSteven Rostedt 		if (ftrace_hash_empty(hash))
1526ed926f9bSSteven Rostedt 			all = 1;
1527ed926f9bSSteven Rostedt 	} else {
1528ed926f9bSSteven Rostedt 		inc = !inc;
1529ed926f9bSSteven Rostedt 		hash = ops->notrace_hash;
1530ed926f9bSSteven Rostedt 		other_hash = ops->filter_hash;
1531ed926f9bSSteven Rostedt 		/*
1532ed926f9bSSteven Rostedt 		 * If the notrace hash has no items,
1533ed926f9bSSteven Rostedt 		 * then there's nothing to do.
1534ed926f9bSSteven Rostedt 		 */
153506a51d93SSteven Rostedt 		if (ftrace_hash_empty(hash))
1536ed926f9bSSteven Rostedt 			return;
1537ed926f9bSSteven Rostedt 	}
1538ed926f9bSSteven Rostedt 
1539ed926f9bSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
1540ed926f9bSSteven Rostedt 		int in_other_hash = 0;
1541ed926f9bSSteven Rostedt 		int in_hash = 0;
1542ed926f9bSSteven Rostedt 		int match = 0;
1543ed926f9bSSteven Rostedt 
1544ed926f9bSSteven Rostedt 		if (all) {
1545ed926f9bSSteven Rostedt 			/*
1546ed926f9bSSteven Rostedt 			 * Only the filter_hash affects all records.
1547ed926f9bSSteven Rostedt 			 * Update if the record is not in the notrace hash.
1548ed926f9bSSteven Rostedt 			 */
1549b848914cSSteven Rostedt 			if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip))
1550ed926f9bSSteven Rostedt 				match = 1;
1551ed926f9bSSteven Rostedt 		} else {
155206a51d93SSteven Rostedt 			in_hash = !!ftrace_lookup_ip(hash, rec->ip);
155306a51d93SSteven Rostedt 			in_other_hash = !!ftrace_lookup_ip(other_hash, rec->ip);
1554ed926f9bSSteven Rostedt 
1555ed926f9bSSteven Rostedt 			/*
1556ed926f9bSSteven Rostedt 			 *
1557ed926f9bSSteven Rostedt 			 */
1558ed926f9bSSteven Rostedt 			if (filter_hash && in_hash && !in_other_hash)
1559ed926f9bSSteven Rostedt 				match = 1;
1560ed926f9bSSteven Rostedt 			else if (!filter_hash && in_hash &&
156106a51d93SSteven Rostedt 				 (in_other_hash || ftrace_hash_empty(other_hash)))
1562ed926f9bSSteven Rostedt 				match = 1;
1563ed926f9bSSteven Rostedt 		}
1564ed926f9bSSteven Rostedt 		if (!match)
1565ed926f9bSSteven Rostedt 			continue;
1566ed926f9bSSteven Rostedt 
1567ed926f9bSSteven Rostedt 		if (inc) {
1568ed926f9bSSteven Rostedt 			rec->flags++;
1569ed926f9bSSteven Rostedt 			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX))
1570ed926f9bSSteven Rostedt 				return;
157108f6fba5SSteven Rostedt 			/*
157208f6fba5SSteven Rostedt 			 * If any ops wants regs saved for this function
157308f6fba5SSteven Rostedt 			 * then all ops will get saved regs.
157408f6fba5SSteven Rostedt 			 */
157508f6fba5SSteven Rostedt 			if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
157608f6fba5SSteven Rostedt 				rec->flags |= FTRACE_FL_REGS;
1577ed926f9bSSteven Rostedt 		} else {
1578ed926f9bSSteven Rostedt 			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0))
1579ed926f9bSSteven Rostedt 				return;
1580ed926f9bSSteven Rostedt 			rec->flags--;
1581ed926f9bSSteven Rostedt 		}
1582ed926f9bSSteven Rostedt 		count++;
1583ed926f9bSSteven Rostedt 		/* Shortcut, if we handled all records, we are done. */
1584ed926f9bSSteven Rostedt 		if (!all && count == hash->count)
1585ed926f9bSSteven Rostedt 			return;
1586ed926f9bSSteven Rostedt 	} while_for_each_ftrace_rec();
1587ed926f9bSSteven Rostedt }
1588ed926f9bSSteven Rostedt 
1589ed926f9bSSteven Rostedt static void ftrace_hash_rec_disable(struct ftrace_ops *ops,
1590ed926f9bSSteven Rostedt 				    int filter_hash)
1591ed926f9bSSteven Rostedt {
1592ed926f9bSSteven Rostedt 	__ftrace_hash_rec_update(ops, filter_hash, 0);
1593ed926f9bSSteven Rostedt }
1594ed926f9bSSteven Rostedt 
1595ed926f9bSSteven Rostedt static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
1596ed926f9bSSteven Rostedt 				   int filter_hash)
1597ed926f9bSSteven Rostedt {
1598ed926f9bSSteven Rostedt 	__ftrace_hash_rec_update(ops, filter_hash, 1);
1599ed926f9bSSteven Rostedt }
1600ed926f9bSSteven Rostedt 
160105736a42SSteven Rostedt static void print_ip_ins(const char *fmt, unsigned char *p)
160205736a42SSteven Rostedt {
160305736a42SSteven Rostedt 	int i;
160405736a42SSteven Rostedt 
160505736a42SSteven Rostedt 	printk(KERN_CONT "%s", fmt);
160605736a42SSteven Rostedt 
160705736a42SSteven Rostedt 	for (i = 0; i < MCOUNT_INSN_SIZE; i++)
160805736a42SSteven Rostedt 		printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
160905736a42SSteven Rostedt }
161005736a42SSteven Rostedt 
1611c88fd863SSteven Rostedt /**
1612c88fd863SSteven Rostedt  * ftrace_bug - report and shutdown function tracer
1613c88fd863SSteven Rostedt  * @failed: The failed type (EFAULT, EINVAL, EPERM)
1614c88fd863SSteven Rostedt  * @ip: The address that failed
1615c88fd863SSteven Rostedt  *
1616c88fd863SSteven Rostedt  * The arch code that enables or disables the function tracing
1617c88fd863SSteven Rostedt  * can call ftrace_bug() when it has detected a problem in
1618c88fd863SSteven Rostedt  * modifying the code. @failed should be one of either:
1619c88fd863SSteven Rostedt  * EFAULT - if the problem happens on reading the @ip address
1620c88fd863SSteven Rostedt  * EINVAL - if what is read at @ip is not what was expected
1621c88fd863SSteven Rostedt  * EPERM - if the problem happens on writting to the @ip address
1622c88fd863SSteven Rostedt  */
1623c88fd863SSteven Rostedt void ftrace_bug(int failed, unsigned long ip)
16243c1720f0SSteven Rostedt {
1625b17e8a37SSteven Rostedt 	switch (failed) {
1626593eb8a2SSteven Rostedt 	case -EFAULT:
16276912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
162805736a42SSteven Rostedt 		pr_info("ftrace faulted on modifying ");
162905736a42SSteven Rostedt 		print_ip_sym(ip);
163005736a42SSteven Rostedt 		break;
1631593eb8a2SSteven Rostedt 	case -EINVAL:
16326912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
163305736a42SSteven Rostedt 		pr_info("ftrace failed to modify ");
163405736a42SSteven Rostedt 		print_ip_sym(ip);
163505736a42SSteven Rostedt 		print_ip_ins(" actual: ", (unsigned char *)ip);
163605736a42SSteven Rostedt 		printk(KERN_CONT "\n");
163705736a42SSteven Rostedt 		break;
1638593eb8a2SSteven Rostedt 	case -EPERM:
16396912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
1640593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on writing ");
1641593eb8a2SSteven Rostedt 		print_ip_sym(ip);
1642593eb8a2SSteven Rostedt 		break;
1643593eb8a2SSteven Rostedt 	default:
16446912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
1645593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on unknown error ");
1646593eb8a2SSteven Rostedt 		print_ip_sym(ip);
164705736a42SSteven Rostedt 	}
1648b17e8a37SSteven Rostedt }
164905736a42SSteven Rostedt 
1650c88fd863SSteven Rostedt static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
16513d083395SSteven Rostedt {
165264fbcd16SXiao Guangrong 	unsigned long flag = 0UL;
1653e7d3737eSFrederic Weisbecker 
16543d083395SSteven Rostedt 	/*
165530fb6aa7SJiri Olsa 	 * If we are updating calls:
16563d083395SSteven Rostedt 	 *
1657ed926f9bSSteven Rostedt 	 *   If the record has a ref count, then we need to enable it
1658ed926f9bSSteven Rostedt 	 *   because someone is using it.
16593d083395SSteven Rostedt 	 *
1660ed926f9bSSteven Rostedt 	 *   Otherwise we make sure its disabled.
1661ed926f9bSSteven Rostedt 	 *
166230fb6aa7SJiri Olsa 	 * If we are disabling calls, then disable all records that
1663ed926f9bSSteven Rostedt 	 * are enabled.
16643d083395SSteven Rostedt 	 */
1665c88fd863SSteven Rostedt 	if (enable && (rec->flags & ~FTRACE_FL_MASK))
166664fbcd16SXiao Guangrong 		flag = FTRACE_FL_ENABLED;
16673d083395SSteven Rostedt 
166808f6fba5SSteven Rostedt 	/*
166908f6fba5SSteven Rostedt 	 * If enabling and the REGS flag does not match the REGS_EN, then
167008f6fba5SSteven Rostedt 	 * do not ignore this record. Set flags to fail the compare against
167108f6fba5SSteven Rostedt 	 * ENABLED.
167208f6fba5SSteven Rostedt 	 */
167308f6fba5SSteven Rostedt 	if (flag &&
167408f6fba5SSteven Rostedt 	    (!(rec->flags & FTRACE_FL_REGS) != !(rec->flags & FTRACE_FL_REGS_EN)))
167508f6fba5SSteven Rostedt 		flag |= FTRACE_FL_REGS;
167608f6fba5SSteven Rostedt 
167764fbcd16SXiao Guangrong 	/* If the state of this record hasn't changed, then do nothing */
167864fbcd16SXiao Guangrong 	if ((rec->flags & FTRACE_FL_ENABLED) == flag)
1679c88fd863SSteven Rostedt 		return FTRACE_UPDATE_IGNORE;
168064fbcd16SXiao Guangrong 
168164fbcd16SXiao Guangrong 	if (flag) {
168208f6fba5SSteven Rostedt 		/* Save off if rec is being enabled (for return value) */
168308f6fba5SSteven Rostedt 		flag ^= rec->flags & FTRACE_FL_ENABLED;
168408f6fba5SSteven Rostedt 
168508f6fba5SSteven Rostedt 		if (update) {
168664fbcd16SXiao Guangrong 			rec->flags |= FTRACE_FL_ENABLED;
168708f6fba5SSteven Rostedt 			if (flag & FTRACE_FL_REGS) {
168808f6fba5SSteven Rostedt 				if (rec->flags & FTRACE_FL_REGS)
168908f6fba5SSteven Rostedt 					rec->flags |= FTRACE_FL_REGS_EN;
169008f6fba5SSteven Rostedt 				else
169108f6fba5SSteven Rostedt 					rec->flags &= ~FTRACE_FL_REGS_EN;
169208f6fba5SSteven Rostedt 			}
169364fbcd16SXiao Guangrong 		}
169464fbcd16SXiao Guangrong 
169508f6fba5SSteven Rostedt 		/*
169608f6fba5SSteven Rostedt 		 * If this record is being updated from a nop, then
169708f6fba5SSteven Rostedt 		 *   return UPDATE_MAKE_CALL.
169808f6fba5SSteven Rostedt 		 * Otherwise, if the EN flag is set, then return
169908f6fba5SSteven Rostedt 		 *   UPDATE_MODIFY_CALL_REGS to tell the caller to convert
170008f6fba5SSteven Rostedt 		 *   from the non-save regs, to a save regs function.
170108f6fba5SSteven Rostedt 		 * Otherwise,
170208f6fba5SSteven Rostedt 		 *   return UPDATE_MODIFY_CALL to tell the caller to convert
170308f6fba5SSteven Rostedt 		 *   from the save regs, to a non-save regs function.
170408f6fba5SSteven Rostedt 		 */
170508f6fba5SSteven Rostedt 		if (flag & FTRACE_FL_ENABLED)
170608f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MAKE_CALL;
170708f6fba5SSteven Rostedt 		else if (rec->flags & FTRACE_FL_REGS_EN)
170808f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MODIFY_CALL_REGS;
170908f6fba5SSteven Rostedt 		else
171008f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MODIFY_CALL;
171108f6fba5SSteven Rostedt 	}
171208f6fba5SSteven Rostedt 
171308f6fba5SSteven Rostedt 	if (update) {
171408f6fba5SSteven Rostedt 		/* If there's no more users, clear all flags */
171508f6fba5SSteven Rostedt 		if (!(rec->flags & ~FTRACE_FL_MASK))
171608f6fba5SSteven Rostedt 			rec->flags = 0;
171708f6fba5SSteven Rostedt 		else
171808f6fba5SSteven Rostedt 			/* Just disable the record (keep REGS state) */
171964fbcd16SXiao Guangrong 			rec->flags &= ~FTRACE_FL_ENABLED;
172008f6fba5SSteven Rostedt 	}
1721c88fd863SSteven Rostedt 
1722c88fd863SSteven Rostedt 	return FTRACE_UPDATE_MAKE_NOP;
1723c88fd863SSteven Rostedt }
1724c88fd863SSteven Rostedt 
1725c88fd863SSteven Rostedt /**
1726c88fd863SSteven Rostedt  * ftrace_update_record, set a record that now is tracing or not
1727c88fd863SSteven Rostedt  * @rec: the record to update
1728c88fd863SSteven Rostedt  * @enable: set to 1 if the record is tracing, zero to force disable
1729c88fd863SSteven Rostedt  *
1730c88fd863SSteven Rostedt  * The records that represent all functions that can be traced need
1731c88fd863SSteven Rostedt  * to be updated when tracing has been enabled.
1732c88fd863SSteven Rostedt  */
1733c88fd863SSteven Rostedt int ftrace_update_record(struct dyn_ftrace *rec, int enable)
1734c88fd863SSteven Rostedt {
1735c88fd863SSteven Rostedt 	return ftrace_check_record(rec, enable, 1);
1736c88fd863SSteven Rostedt }
1737c88fd863SSteven Rostedt 
1738c88fd863SSteven Rostedt /**
1739c88fd863SSteven Rostedt  * ftrace_test_record, check if the record has been enabled or not
1740c88fd863SSteven Rostedt  * @rec: the record to test
1741c88fd863SSteven Rostedt  * @enable: set to 1 to check if enabled, 0 if it is disabled
1742c88fd863SSteven Rostedt  *
1743c88fd863SSteven Rostedt  * The arch code may need to test if a record is already set to
1744c88fd863SSteven Rostedt  * tracing to determine how to modify the function code that it
1745c88fd863SSteven Rostedt  * represents.
1746c88fd863SSteven Rostedt  */
1747c88fd863SSteven Rostedt int ftrace_test_record(struct dyn_ftrace *rec, int enable)
1748c88fd863SSteven Rostedt {
1749c88fd863SSteven Rostedt 	return ftrace_check_record(rec, enable, 0);
1750c88fd863SSteven Rostedt }
1751c88fd863SSteven Rostedt 
1752c88fd863SSteven Rostedt static int
1753c88fd863SSteven Rostedt __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
1754c88fd863SSteven Rostedt {
175508f6fba5SSteven Rostedt 	unsigned long ftrace_old_addr;
1756c88fd863SSteven Rostedt 	unsigned long ftrace_addr;
1757c88fd863SSteven Rostedt 	int ret;
1758c88fd863SSteven Rostedt 
1759c88fd863SSteven Rostedt 	ret = ftrace_update_record(rec, enable);
1760c88fd863SSteven Rostedt 
176108f6fba5SSteven Rostedt 	if (rec->flags & FTRACE_FL_REGS)
176208f6fba5SSteven Rostedt 		ftrace_addr = (unsigned long)FTRACE_REGS_ADDR;
176308f6fba5SSteven Rostedt 	else
176408f6fba5SSteven Rostedt 		ftrace_addr = (unsigned long)FTRACE_ADDR;
176508f6fba5SSteven Rostedt 
1766c88fd863SSteven Rostedt 	switch (ret) {
1767c88fd863SSteven Rostedt 	case FTRACE_UPDATE_IGNORE:
1768c88fd863SSteven Rostedt 		return 0;
1769c88fd863SSteven Rostedt 
1770c88fd863SSteven Rostedt 	case FTRACE_UPDATE_MAKE_CALL:
1771c88fd863SSteven Rostedt 		return ftrace_make_call(rec, ftrace_addr);
1772c88fd863SSteven Rostedt 
1773c88fd863SSteven Rostedt 	case FTRACE_UPDATE_MAKE_NOP:
1774e7d3737eSFrederic Weisbecker 		return ftrace_make_nop(NULL, rec, ftrace_addr);
177508f6fba5SSteven Rostedt 
177608f6fba5SSteven Rostedt 	case FTRACE_UPDATE_MODIFY_CALL_REGS:
177708f6fba5SSteven Rostedt 	case FTRACE_UPDATE_MODIFY_CALL:
177808f6fba5SSteven Rostedt 		if (rec->flags & FTRACE_FL_REGS)
177908f6fba5SSteven Rostedt 			ftrace_old_addr = (unsigned long)FTRACE_ADDR;
178008f6fba5SSteven Rostedt 		else
178108f6fba5SSteven Rostedt 			ftrace_old_addr = (unsigned long)FTRACE_REGS_ADDR;
178208f6fba5SSteven Rostedt 
178308f6fba5SSteven Rostedt 		return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr);
17843d083395SSteven Rostedt 	}
17853d083395SSteven Rostedt 
1786c88fd863SSteven Rostedt 	return -1; /* unknow ftrace bug */
1787c88fd863SSteven Rostedt }
1788c88fd863SSteven Rostedt 
1789e4f5d544SSteven Rostedt void __weak ftrace_replace_code(int enable)
17903d083395SSteven Rostedt {
17913d083395SSteven Rostedt 	struct dyn_ftrace *rec;
17923d083395SSteven Rostedt 	struct ftrace_page *pg;
17936a24a244SSteven Rostedt 	int failed;
17943d083395SSteven Rostedt 
179545a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
179645a4a237SSteven Rostedt 		return;
179745a4a237SSteven Rostedt 
1798265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
1799e4f5d544SSteven Rostedt 		failed = __ftrace_replace_code(rec, enable);
1800fa9d13cfSZhaolei 		if (failed) {
180131e88909SSteven Rostedt 			ftrace_bug(failed, rec->ip);
18024377245aSSteven Rostedt 			/* Stop processing */
18034377245aSSteven Rostedt 			return;
18044377245aSSteven Rostedt 		}
1805265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
18063d083395SSteven Rostedt }
18073c1720f0SSteven Rostedt 
1808c88fd863SSteven Rostedt struct ftrace_rec_iter {
1809c88fd863SSteven Rostedt 	struct ftrace_page	*pg;
1810c88fd863SSteven Rostedt 	int			index;
1811c88fd863SSteven Rostedt };
1812c88fd863SSteven Rostedt 
1813c88fd863SSteven Rostedt /**
1814c88fd863SSteven Rostedt  * ftrace_rec_iter_start, start up iterating over traced functions
1815c88fd863SSteven Rostedt  *
1816c88fd863SSteven Rostedt  * Returns an iterator handle that is used to iterate over all
1817c88fd863SSteven Rostedt  * the records that represent address locations where functions
1818c88fd863SSteven Rostedt  * are traced.
1819c88fd863SSteven Rostedt  *
1820c88fd863SSteven Rostedt  * May return NULL if no records are available.
1821c88fd863SSteven Rostedt  */
1822c88fd863SSteven Rostedt struct ftrace_rec_iter *ftrace_rec_iter_start(void)
1823c88fd863SSteven Rostedt {
1824c88fd863SSteven Rostedt 	/*
1825c88fd863SSteven Rostedt 	 * We only use a single iterator.
1826c88fd863SSteven Rostedt 	 * Protected by the ftrace_lock mutex.
1827c88fd863SSteven Rostedt 	 */
1828c88fd863SSteven Rostedt 	static struct ftrace_rec_iter ftrace_rec_iter;
1829c88fd863SSteven Rostedt 	struct ftrace_rec_iter *iter = &ftrace_rec_iter;
1830c88fd863SSteven Rostedt 
1831c88fd863SSteven Rostedt 	iter->pg = ftrace_pages_start;
1832c88fd863SSteven Rostedt 	iter->index = 0;
1833c88fd863SSteven Rostedt 
1834c88fd863SSteven Rostedt 	/* Could have empty pages */
1835c88fd863SSteven Rostedt 	while (iter->pg && !iter->pg->index)
1836c88fd863SSteven Rostedt 		iter->pg = iter->pg->next;
1837c88fd863SSteven Rostedt 
1838c88fd863SSteven Rostedt 	if (!iter->pg)
1839c88fd863SSteven Rostedt 		return NULL;
1840c88fd863SSteven Rostedt 
1841c88fd863SSteven Rostedt 	return iter;
1842c88fd863SSteven Rostedt }
1843c88fd863SSteven Rostedt 
1844c88fd863SSteven Rostedt /**
1845c88fd863SSteven Rostedt  * ftrace_rec_iter_next, get the next record to process.
1846c88fd863SSteven Rostedt  * @iter: The handle to the iterator.
1847c88fd863SSteven Rostedt  *
1848c88fd863SSteven Rostedt  * Returns the next iterator after the given iterator @iter.
1849c88fd863SSteven Rostedt  */
1850c88fd863SSteven Rostedt struct ftrace_rec_iter *ftrace_rec_iter_next(struct ftrace_rec_iter *iter)
1851c88fd863SSteven Rostedt {
1852c88fd863SSteven Rostedt 	iter->index++;
1853c88fd863SSteven Rostedt 
1854c88fd863SSteven Rostedt 	if (iter->index >= iter->pg->index) {
1855c88fd863SSteven Rostedt 		iter->pg = iter->pg->next;
1856c88fd863SSteven Rostedt 		iter->index = 0;
1857c88fd863SSteven Rostedt 
1858c88fd863SSteven Rostedt 		/* Could have empty pages */
1859c88fd863SSteven Rostedt 		while (iter->pg && !iter->pg->index)
1860c88fd863SSteven Rostedt 			iter->pg = iter->pg->next;
1861c88fd863SSteven Rostedt 	}
1862c88fd863SSteven Rostedt 
1863c88fd863SSteven Rostedt 	if (!iter->pg)
1864c88fd863SSteven Rostedt 		return NULL;
1865c88fd863SSteven Rostedt 
1866c88fd863SSteven Rostedt 	return iter;
1867c88fd863SSteven Rostedt }
1868c88fd863SSteven Rostedt 
1869c88fd863SSteven Rostedt /**
1870c88fd863SSteven Rostedt  * ftrace_rec_iter_record, get the record at the iterator location
1871c88fd863SSteven Rostedt  * @iter: The current iterator location
1872c88fd863SSteven Rostedt  *
1873c88fd863SSteven Rostedt  * Returns the record that the current @iter is at.
1874c88fd863SSteven Rostedt  */
1875c88fd863SSteven Rostedt struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter)
1876c88fd863SSteven Rostedt {
1877c88fd863SSteven Rostedt 	return &iter->pg->records[iter->index];
1878c88fd863SSteven Rostedt }
1879c88fd863SSteven Rostedt 
18803b47bfc1SSteven Rostedt static int
188131e88909SSteven Rostedt ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
18823c1720f0SSteven Rostedt {
188337ad5084SSteven Rostedt 	unsigned long ip;
1884492a7ea5SAbhishek Sagar 	int ret;
188537ad5084SSteven Rostedt 
1886492a7ea5SAbhishek Sagar 	ip = rec->ip;
18873c1720f0SSteven Rostedt 
188845a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
188945a4a237SSteven Rostedt 		return 0;
189045a4a237SSteven Rostedt 
189125aac9dcSShaohua Li 	ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
18923d083395SSteven Rostedt 	if (ret) {
189331e88909SSteven Rostedt 		ftrace_bug(ret, ip);
18943d083395SSteven Rostedt 		return 0;
1895d61f82d0SSteven Rostedt 	}
1896d61f82d0SSteven Rostedt 	return 1;
18973d083395SSteven Rostedt }
18983d083395SSteven Rostedt 
1899000ab691SSteven Rostedt /*
1900000ab691SSteven Rostedt  * archs can override this function if they must do something
1901000ab691SSteven Rostedt  * before the modifying code is performed.
1902000ab691SSteven Rostedt  */
1903000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_prepare(void)
1904000ab691SSteven Rostedt {
1905000ab691SSteven Rostedt 	return 0;
1906000ab691SSteven Rostedt }
1907000ab691SSteven Rostedt 
1908000ab691SSteven Rostedt /*
1909000ab691SSteven Rostedt  * archs can override this function if they must do something
1910000ab691SSteven Rostedt  * after the modifying code is performed.
1911000ab691SSteven Rostedt  */
1912000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_post_process(void)
1913000ab691SSteven Rostedt {
1914000ab691SSteven Rostedt 	return 0;
1915000ab691SSteven Rostedt }
1916000ab691SSteven Rostedt 
19178ed3e2cfSSteven Rostedt void ftrace_modify_all_code(int command)
19188ed3e2cfSSteven Rostedt {
19198ed3e2cfSSteven Rostedt 	if (command & FTRACE_UPDATE_CALLS)
19208ed3e2cfSSteven Rostedt 		ftrace_replace_code(1);
19218ed3e2cfSSteven Rostedt 	else if (command & FTRACE_DISABLE_CALLS)
19228ed3e2cfSSteven Rostedt 		ftrace_replace_code(0);
19238ed3e2cfSSteven Rostedt 
19248ed3e2cfSSteven Rostedt 	if (command & FTRACE_UPDATE_TRACE_FUNC)
19258ed3e2cfSSteven Rostedt 		ftrace_update_ftrace_func(ftrace_trace_function);
19268ed3e2cfSSteven Rostedt 
19278ed3e2cfSSteven Rostedt 	if (command & FTRACE_START_FUNC_RET)
19288ed3e2cfSSteven Rostedt 		ftrace_enable_ftrace_graph_caller();
19298ed3e2cfSSteven Rostedt 	else if (command & FTRACE_STOP_FUNC_RET)
19308ed3e2cfSSteven Rostedt 		ftrace_disable_ftrace_graph_caller();
19318ed3e2cfSSteven Rostedt }
19328ed3e2cfSSteven Rostedt 
19333d083395SSteven Rostedt static int __ftrace_modify_code(void *data)
19343d083395SSteven Rostedt {
19353d083395SSteven Rostedt 	int *command = data;
19363d083395SSteven Rostedt 
19378ed3e2cfSSteven Rostedt 	ftrace_modify_all_code(*command);
19385a45cfe1SSteven Rostedt 
1939c88fd863SSteven Rostedt 	return 0;
1940c88fd863SSteven Rostedt }
1941c88fd863SSteven Rostedt 
1942c88fd863SSteven Rostedt /**
1943c88fd863SSteven Rostedt  * ftrace_run_stop_machine, go back to the stop machine method
1944c88fd863SSteven Rostedt  * @command: The command to tell ftrace what to do
1945c88fd863SSteven Rostedt  *
1946c88fd863SSteven Rostedt  * If an arch needs to fall back to the stop machine method, the
1947c88fd863SSteven Rostedt  * it can call this function.
1948c88fd863SSteven Rostedt  */
1949c88fd863SSteven Rostedt void ftrace_run_stop_machine(int command)
1950c88fd863SSteven Rostedt {
1951c88fd863SSteven Rostedt 	stop_machine(__ftrace_modify_code, &command, NULL);
1952c88fd863SSteven Rostedt }
1953c88fd863SSteven Rostedt 
1954c88fd863SSteven Rostedt /**
1955c88fd863SSteven Rostedt  * arch_ftrace_update_code, modify the code to trace or not trace
1956c88fd863SSteven Rostedt  * @command: The command that needs to be done
1957c88fd863SSteven Rostedt  *
1958c88fd863SSteven Rostedt  * Archs can override this function if it does not need to
1959c88fd863SSteven Rostedt  * run stop_machine() to modify code.
1960c88fd863SSteven Rostedt  */
1961c88fd863SSteven Rostedt void __weak arch_ftrace_update_code(int command)
1962c88fd863SSteven Rostedt {
1963c88fd863SSteven Rostedt 	ftrace_run_stop_machine(command);
1964c88fd863SSteven Rostedt }
1965c88fd863SSteven Rostedt 
1966c88fd863SSteven Rostedt static void ftrace_run_update_code(int command)
1967c88fd863SSteven Rostedt {
1968c88fd863SSteven Rostedt 	int ret;
1969c88fd863SSteven Rostedt 
1970c88fd863SSteven Rostedt 	ret = ftrace_arch_code_modify_prepare();
1971c88fd863SSteven Rostedt 	FTRACE_WARN_ON(ret);
1972c88fd863SSteven Rostedt 	if (ret)
1973c88fd863SSteven Rostedt 		return;
1974c88fd863SSteven Rostedt 	/*
1975c88fd863SSteven Rostedt 	 * Do not call function tracer while we update the code.
1976c88fd863SSteven Rostedt 	 * We are in stop machine.
1977c88fd863SSteven Rostedt 	 */
1978c88fd863SSteven Rostedt 	function_trace_stop++;
1979c88fd863SSteven Rostedt 
1980c88fd863SSteven Rostedt 	/*
1981c88fd863SSteven Rostedt 	 * By default we use stop_machine() to modify the code.
1982c88fd863SSteven Rostedt 	 * But archs can do what ever they want as long as it
1983c88fd863SSteven Rostedt 	 * is safe. The stop_machine() is the safest, but also
1984c88fd863SSteven Rostedt 	 * produces the most overhead.
1985c88fd863SSteven Rostedt 	 */
1986c88fd863SSteven Rostedt 	arch_ftrace_update_code(command);
1987c88fd863SSteven Rostedt 
19886331c28cSSteven Rostedt 	function_trace_stop--;
19896331c28cSSteven Rostedt 
1990000ab691SSteven Rostedt 	ret = ftrace_arch_code_modify_post_process();
1991000ab691SSteven Rostedt 	FTRACE_WARN_ON(ret);
19923d083395SSteven Rostedt }
19933d083395SSteven Rostedt 
19943d083395SSteven Rostedt static ftrace_func_t saved_ftrace_func;
199560a7ecf4SSteven Rostedt static int ftrace_start_up;
1996b848914cSSteven Rostedt static int global_start_up;
1997df4fc315SSteven Rostedt 
1998df4fc315SSteven Rostedt static void ftrace_startup_enable(int command)
1999df4fc315SSteven Rostedt {
2000df4fc315SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
2001df4fc315SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
2002df4fc315SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
2003df4fc315SSteven Rostedt 	}
2004df4fc315SSteven Rostedt 
2005df4fc315SSteven Rostedt 	if (!command || !ftrace_enabled)
2006df4fc315SSteven Rostedt 		return;
2007df4fc315SSteven Rostedt 
2008df4fc315SSteven Rostedt 	ftrace_run_update_code(command);
2009df4fc315SSteven Rostedt }
20103d083395SSteven Rostedt 
2011a1cd6173SSteven Rostedt static int ftrace_startup(struct ftrace_ops *ops, int command)
20123d083395SSteven Rostedt {
2013b848914cSSteven Rostedt 	bool hash_enable = true;
2014b848914cSSteven Rostedt 
20154eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
2016a1cd6173SSteven Rostedt 		return -ENODEV;
20174eebcc81SSteven Rostedt 
201860a7ecf4SSteven Rostedt 	ftrace_start_up++;
201930fb6aa7SJiri Olsa 	command |= FTRACE_UPDATE_CALLS;
20203d083395SSteven Rostedt 
2021b848914cSSteven Rostedt 	/* ops marked global share the filter hashes */
2022b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
2023b848914cSSteven Rostedt 		ops = &global_ops;
2024b848914cSSteven Rostedt 		/* Don't update hash if global is already set */
2025b848914cSSteven Rostedt 		if (global_start_up)
2026b848914cSSteven Rostedt 			hash_enable = false;
2027b848914cSSteven Rostedt 		global_start_up++;
2028b848914cSSteven Rostedt 	}
2029b848914cSSteven Rostedt 
2030ed926f9bSSteven Rostedt 	ops->flags |= FTRACE_OPS_FL_ENABLED;
2031b848914cSSteven Rostedt 	if (hash_enable)
2032ed926f9bSSteven Rostedt 		ftrace_hash_rec_enable(ops, 1);
2033ed926f9bSSteven Rostedt 
2034df4fc315SSteven Rostedt 	ftrace_startup_enable(command);
2035a1cd6173SSteven Rostedt 
2036a1cd6173SSteven Rostedt 	return 0;
20373d083395SSteven Rostedt }
20383d083395SSteven Rostedt 
2039bd69c30bSSteven Rostedt static void ftrace_shutdown(struct ftrace_ops *ops, int command)
20403d083395SSteven Rostedt {
2041b848914cSSteven Rostedt 	bool hash_disable = true;
2042b848914cSSteven Rostedt 
20434eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
20444eebcc81SSteven Rostedt 		return;
20454eebcc81SSteven Rostedt 
204660a7ecf4SSteven Rostedt 	ftrace_start_up--;
20479ea1a153SFrederic Weisbecker 	/*
20489ea1a153SFrederic Weisbecker 	 * Just warn in case of unbalance, no need to kill ftrace, it's not
20499ea1a153SFrederic Weisbecker 	 * critical but the ftrace_call callers may be never nopped again after
20509ea1a153SFrederic Weisbecker 	 * further ftrace uses.
20519ea1a153SFrederic Weisbecker 	 */
20529ea1a153SFrederic Weisbecker 	WARN_ON_ONCE(ftrace_start_up < 0);
20539ea1a153SFrederic Weisbecker 
2054b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
2055b848914cSSteven Rostedt 		ops = &global_ops;
2056b848914cSSteven Rostedt 		global_start_up--;
2057b848914cSSteven Rostedt 		WARN_ON_ONCE(global_start_up < 0);
2058b848914cSSteven Rostedt 		/* Don't update hash if global still has users */
2059b848914cSSteven Rostedt 		if (global_start_up) {
2060b848914cSSteven Rostedt 			WARN_ON_ONCE(!ftrace_start_up);
2061b848914cSSteven Rostedt 			hash_disable = false;
2062b848914cSSteven Rostedt 		}
2063b848914cSSteven Rostedt 	}
2064b848914cSSteven Rostedt 
2065b848914cSSteven Rostedt 	if (hash_disable)
2066ed926f9bSSteven Rostedt 		ftrace_hash_rec_disable(ops, 1);
2067ed926f9bSSteven Rostedt 
2068b848914cSSteven Rostedt 	if (ops != &global_ops || !global_start_up)
2069ed926f9bSSteven Rostedt 		ops->flags &= ~FTRACE_OPS_FL_ENABLED;
2070b848914cSSteven Rostedt 
207130fb6aa7SJiri Olsa 	command |= FTRACE_UPDATE_CALLS;
2072d61f82d0SSteven Rostedt 
2073d61f82d0SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
2074d61f82d0SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
2075d61f82d0SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
2076d61f82d0SSteven Rostedt 	}
2077d61f82d0SSteven Rostedt 
2078d61f82d0SSteven Rostedt 	if (!command || !ftrace_enabled)
2079e6ea44e9SSteven Rostedt 		return;
20803d083395SSteven Rostedt 
2081d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
20823d083395SSteven Rostedt }
20833d083395SSteven Rostedt 
2084e309b41dSIngo Molnar static void ftrace_startup_sysctl(void)
2085b0fc494fSSteven Rostedt {
20864eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
20874eebcc81SSteven Rostedt 		return;
20884eebcc81SSteven Rostedt 
2089d61f82d0SSteven Rostedt 	/* Force update next time */
2090d61f82d0SSteven Rostedt 	saved_ftrace_func = NULL;
209160a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if we want ftrace running */
209260a7ecf4SSteven Rostedt 	if (ftrace_start_up)
209330fb6aa7SJiri Olsa 		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
2094b0fc494fSSteven Rostedt }
2095b0fc494fSSteven Rostedt 
2096e309b41dSIngo Molnar static void ftrace_shutdown_sysctl(void)
2097b0fc494fSSteven Rostedt {
20984eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
20994eebcc81SSteven Rostedt 		return;
21004eebcc81SSteven Rostedt 
210160a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if ftrace is running */
210260a7ecf4SSteven Rostedt 	if (ftrace_start_up)
210379e406d7SSteven Rostedt 		ftrace_run_update_code(FTRACE_DISABLE_CALLS);
2104b0fc494fSSteven Rostedt }
2105b0fc494fSSteven Rostedt 
21063d083395SSteven Rostedt static cycle_t		ftrace_update_time;
21073d083395SSteven Rostedt static unsigned long	ftrace_update_cnt;
21083d083395SSteven Rostedt unsigned long		ftrace_update_tot_cnt;
21093d083395SSteven Rostedt 
2110f7bc8b61SSteven Rostedt static int ops_traces_mod(struct ftrace_ops *ops)
2111f7bc8b61SSteven Rostedt {
2112f7bc8b61SSteven Rostedt 	struct ftrace_hash *hash;
2113f7bc8b61SSteven Rostedt 
2114f7bc8b61SSteven Rostedt 	hash = ops->filter_hash;
211506a51d93SSteven Rostedt 	return ftrace_hash_empty(hash);
2116f7bc8b61SSteven Rostedt }
2117f7bc8b61SSteven Rostedt 
211831e88909SSteven Rostedt static int ftrace_update_code(struct module *mod)
21193d083395SSteven Rostedt {
212085ae32aeSSteven Rostedt 	struct ftrace_page *pg;
2121e94142a6SLai Jiangshan 	struct dyn_ftrace *p;
2122f22f9a89SAbhishek Sagar 	cycle_t start, stop;
2123f7bc8b61SSteven Rostedt 	unsigned long ref = 0;
212485ae32aeSSteven Rostedt 	int i;
2125f7bc8b61SSteven Rostedt 
2126f7bc8b61SSteven Rostedt 	/*
2127f7bc8b61SSteven Rostedt 	 * When adding a module, we need to check if tracers are
2128f7bc8b61SSteven Rostedt 	 * currently enabled and if they are set to trace all functions.
2129f7bc8b61SSteven Rostedt 	 * If they are, we need to enable the module functions as well
2130f7bc8b61SSteven Rostedt 	 * as update the reference counts for those function records.
2131f7bc8b61SSteven Rostedt 	 */
2132f7bc8b61SSteven Rostedt 	if (mod) {
2133f7bc8b61SSteven Rostedt 		struct ftrace_ops *ops;
2134f7bc8b61SSteven Rostedt 
2135f7bc8b61SSteven Rostedt 		for (ops = ftrace_ops_list;
2136f7bc8b61SSteven Rostedt 		     ops != &ftrace_list_end; ops = ops->next) {
2137f7bc8b61SSteven Rostedt 			if (ops->flags & FTRACE_OPS_FL_ENABLED &&
2138f7bc8b61SSteven Rostedt 			    ops_traces_mod(ops))
2139f7bc8b61SSteven Rostedt 				ref++;
2140f7bc8b61SSteven Rostedt 		}
2141f7bc8b61SSteven Rostedt 	}
21423d083395SSteven Rostedt 
2143750ed1a4SIngo Molnar 	start = ftrace_now(raw_smp_processor_id());
21443d083395SSteven Rostedt 	ftrace_update_cnt = 0;
21453d083395SSteven Rostedt 
214685ae32aeSSteven Rostedt 	for (pg = ftrace_new_pgs; pg; pg = pg->next) {
2147f22f9a89SAbhishek Sagar 
214885ae32aeSSteven Rostedt 		for (i = 0; i < pg->index; i++) {
214908f5ac90SSteven Rostedt 			/* If something went wrong, bail without enabling anything */
215008f5ac90SSteven Rostedt 			if (unlikely(ftrace_disabled))
215108f5ac90SSteven Rostedt 				return -1;
21523d083395SSteven Rostedt 
215385ae32aeSSteven Rostedt 			p = &pg->records[i];
2154f7bc8b61SSteven Rostedt 			p->flags = ref;
2155f22f9a89SAbhishek Sagar 
21565cb084bbSJiri Olsa 			/*
215725985edcSLucas De Marchi 			 * Do the initial record conversion from mcount jump
21585cb084bbSJiri Olsa 			 * to the NOP instructions.
21595cb084bbSJiri Olsa 			 */
216032082309SSteven Rostedt 			if (!ftrace_code_disable(mod, p))
2161d2c8c3eaSSteven Rostedt 				break;
21625cb084bbSJiri Olsa 
21633d083395SSteven Rostedt 			ftrace_update_cnt++;
21645cb084bbSJiri Olsa 
21655cb084bbSJiri Olsa 			/*
21665cb084bbSJiri Olsa 			 * If the tracing is enabled, go ahead and enable the record.
21675cb084bbSJiri Olsa 			 *
21685cb084bbSJiri Olsa 			 * The reason not to enable the record immediatelly is the
21695cb084bbSJiri Olsa 			 * inherent check of ftrace_make_nop/ftrace_make_call for
21705cb084bbSJiri Olsa 			 * correct previous instructions.  Making first the NOP
21715cb084bbSJiri Olsa 			 * conversion puts the module to the correct state, thus
21725cb084bbSJiri Olsa 			 * passing the ftrace_make_call check.
21735cb084bbSJiri Olsa 			 */
2174f7bc8b61SSteven Rostedt 			if (ftrace_start_up && ref) {
21755cb084bbSJiri Olsa 				int failed = __ftrace_replace_code(p, 1);
217632082309SSteven Rostedt 				if (failed)
21775cb084bbSJiri Olsa 					ftrace_bug(failed, p->ip);
21785cb084bbSJiri Olsa 			}
21795cb084bbSJiri Olsa 		}
218085ae32aeSSteven Rostedt 	}
218185ae32aeSSteven Rostedt 
218285ae32aeSSteven Rostedt 	ftrace_new_pgs = NULL;
21833d083395SSteven Rostedt 
2184750ed1a4SIngo Molnar 	stop = ftrace_now(raw_smp_processor_id());
21853d083395SSteven Rostedt 	ftrace_update_time = stop - start;
21863d083395SSteven Rostedt 	ftrace_update_tot_cnt += ftrace_update_cnt;
21873d083395SSteven Rostedt 
218816444a8aSArnaldo Carvalho de Melo 	return 0;
218916444a8aSArnaldo Carvalho de Melo }
219016444a8aSArnaldo Carvalho de Melo 
2191a7900875SSteven Rostedt static int ftrace_allocate_records(struct ftrace_page *pg, int count)
21923c1720f0SSteven Rostedt {
2193a7900875SSteven Rostedt 	int order;
21943c1720f0SSteven Rostedt 	int cnt;
21953c1720f0SSteven Rostedt 
2196a7900875SSteven Rostedt 	if (WARN_ON(!count))
2197a7900875SSteven Rostedt 		return -EINVAL;
2198a7900875SSteven Rostedt 
2199a7900875SSteven Rostedt 	order = get_count_order(DIV_ROUND_UP(count, ENTRIES_PER_PAGE));
22003c1720f0SSteven Rostedt 
22013c1720f0SSteven Rostedt 	/*
2202a7900875SSteven Rostedt 	 * We want to fill as much as possible. No more than a page
2203a7900875SSteven Rostedt 	 * may be empty.
22043c1720f0SSteven Rostedt 	 */
2205a7900875SSteven Rostedt 	while ((PAGE_SIZE << order) / ENTRY_SIZE >= count + ENTRIES_PER_PAGE)
2206a7900875SSteven Rostedt 		order--;
22073c1720f0SSteven Rostedt 
2208a7900875SSteven Rostedt  again:
2209a7900875SSteven Rostedt 	pg->records = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
2210a7900875SSteven Rostedt 
2211a7900875SSteven Rostedt 	if (!pg->records) {
2212a7900875SSteven Rostedt 		/* if we can't allocate this size, try something smaller */
2213a7900875SSteven Rostedt 		if (!order)
2214a7900875SSteven Rostedt 			return -ENOMEM;
2215a7900875SSteven Rostedt 		order >>= 1;
2216a7900875SSteven Rostedt 		goto again;
2217a7900875SSteven Rostedt 	}
2218a7900875SSteven Rostedt 
2219a7900875SSteven Rostedt 	cnt = (PAGE_SIZE << order) / ENTRY_SIZE;
2220a7900875SSteven Rostedt 	pg->size = cnt;
2221a7900875SSteven Rostedt 
2222a7900875SSteven Rostedt 	if (cnt > count)
2223a7900875SSteven Rostedt 		cnt = count;
2224a7900875SSteven Rostedt 
2225a7900875SSteven Rostedt 	return cnt;
2226a7900875SSteven Rostedt }
2227a7900875SSteven Rostedt 
2228a7900875SSteven Rostedt static struct ftrace_page *
2229a7900875SSteven Rostedt ftrace_allocate_pages(unsigned long num_to_init)
2230a7900875SSteven Rostedt {
2231a7900875SSteven Rostedt 	struct ftrace_page *start_pg;
2232a7900875SSteven Rostedt 	struct ftrace_page *pg;
2233a7900875SSteven Rostedt 	int order;
2234a7900875SSteven Rostedt 	int cnt;
2235a7900875SSteven Rostedt 
2236a7900875SSteven Rostedt 	if (!num_to_init)
2237a7900875SSteven Rostedt 		return 0;
2238a7900875SSteven Rostedt 
2239a7900875SSteven Rostedt 	start_pg = pg = kzalloc(sizeof(*pg), GFP_KERNEL);
2240a7900875SSteven Rostedt 	if (!pg)
2241a7900875SSteven Rostedt 		return NULL;
2242a7900875SSteven Rostedt 
2243a7900875SSteven Rostedt 	/*
2244a7900875SSteven Rostedt 	 * Try to allocate as much as possible in one continues
2245a7900875SSteven Rostedt 	 * location that fills in all of the space. We want to
2246a7900875SSteven Rostedt 	 * waste as little space as possible.
2247a7900875SSteven Rostedt 	 */
2248a7900875SSteven Rostedt 	for (;;) {
2249a7900875SSteven Rostedt 		cnt = ftrace_allocate_records(pg, num_to_init);
2250a7900875SSteven Rostedt 		if (cnt < 0)
2251a7900875SSteven Rostedt 			goto free_pages;
2252a7900875SSteven Rostedt 
2253a7900875SSteven Rostedt 		num_to_init -= cnt;
2254a7900875SSteven Rostedt 		if (!num_to_init)
2255a7900875SSteven Rostedt 			break;
2256a7900875SSteven Rostedt 
2257a7900875SSteven Rostedt 		pg->next = kzalloc(sizeof(*pg), GFP_KERNEL);
2258a7900875SSteven Rostedt 		if (!pg->next)
2259a7900875SSteven Rostedt 			goto free_pages;
2260a7900875SSteven Rostedt 
2261a7900875SSteven Rostedt 		pg = pg->next;
2262a7900875SSteven Rostedt 	}
2263a7900875SSteven Rostedt 
2264a7900875SSteven Rostedt 	return start_pg;
2265a7900875SSteven Rostedt 
2266a7900875SSteven Rostedt  free_pages:
2267a7900875SSteven Rostedt 	while (start_pg) {
2268a7900875SSteven Rostedt 		order = get_count_order(pg->size / ENTRIES_PER_PAGE);
2269a7900875SSteven Rostedt 		free_pages((unsigned long)pg->records, order);
2270a7900875SSteven Rostedt 		start_pg = pg->next;
2271a7900875SSteven Rostedt 		kfree(pg);
2272a7900875SSteven Rostedt 		pg = start_pg;
2273a7900875SSteven Rostedt 	}
2274a7900875SSteven Rostedt 	pr_info("ftrace: FAILED to allocate memory for functions\n");
2275a7900875SSteven Rostedt 	return NULL;
2276a7900875SSteven Rostedt }
2277a7900875SSteven Rostedt 
2278a7900875SSteven Rostedt static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
2279a7900875SSteven Rostedt {
2280a7900875SSteven Rostedt 	int cnt;
2281a7900875SSteven Rostedt 
2282a7900875SSteven Rostedt 	if (!num_to_init) {
2283a7900875SSteven Rostedt 		pr_info("ftrace: No functions to be traced?\n");
2284a7900875SSteven Rostedt 		return -1;
2285a7900875SSteven Rostedt 	}
22863c1720f0SSteven Rostedt 
228768bf21aaSSteven Rostedt 	cnt = num_to_init / ENTRIES_PER_PAGE;
228808f5ac90SSteven Rostedt 	pr_info("ftrace: allocating %ld entries in %d pages\n",
22895821e1b7Swalimis 		num_to_init, cnt + 1);
22903c1720f0SSteven Rostedt 
22913c1720f0SSteven Rostedt 	return 0;
22923c1720f0SSteven Rostedt }
22933c1720f0SSteven Rostedt 
22945072c59fSSteven Rostedt #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
22955072c59fSSteven Rostedt 
22965072c59fSSteven Rostedt struct ftrace_iterator {
229798c4fd04SSteven Rostedt 	loff_t				pos;
22982bccfffdSSteven Rostedt 	loff_t				func_pos;
22995072c59fSSteven Rostedt 	struct ftrace_page		*pg;
23004aeb6967SSteven Rostedt 	struct dyn_ftrace		*func;
23014aeb6967SSteven Rostedt 	struct ftrace_func_probe	*probe;
23024aeb6967SSteven Rostedt 	struct trace_parser		parser;
23031cf41dd7SSteven Rostedt 	struct ftrace_hash		*hash;
230433dc9b12SSteven Rostedt 	struct ftrace_ops		*ops;
23058fc0c701SSteven Rostedt 	int				hidx;
2306431aa3fbSSteven Rostedt 	int				idx;
23075072c59fSSteven Rostedt 	unsigned			flags;
23085072c59fSSteven Rostedt };
23095072c59fSSteven Rostedt 
2310e309b41dSIngo Molnar static void *
23114aeb6967SSteven Rostedt t_hash_next(struct seq_file *m, loff_t *pos)
23128fc0c701SSteven Rostedt {
23138fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
23144aeb6967SSteven Rostedt 	struct hlist_node *hnd = NULL;
23158fc0c701SSteven Rostedt 	struct hlist_head *hhd;
23168fc0c701SSteven Rostedt 
23178fc0c701SSteven Rostedt 	(*pos)++;
231898c4fd04SSteven Rostedt 	iter->pos = *pos;
23198fc0c701SSteven Rostedt 
23204aeb6967SSteven Rostedt 	if (iter->probe)
23214aeb6967SSteven Rostedt 		hnd = &iter->probe->node;
23228fc0c701SSteven Rostedt  retry:
23238fc0c701SSteven Rostedt 	if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
23248fc0c701SSteven Rostedt 		return NULL;
23258fc0c701SSteven Rostedt 
23268fc0c701SSteven Rostedt 	hhd = &ftrace_func_hash[iter->hidx];
23278fc0c701SSteven Rostedt 
23288fc0c701SSteven Rostedt 	if (hlist_empty(hhd)) {
23298fc0c701SSteven Rostedt 		iter->hidx++;
23308fc0c701SSteven Rostedt 		hnd = NULL;
23318fc0c701SSteven Rostedt 		goto retry;
23328fc0c701SSteven Rostedt 	}
23338fc0c701SSteven Rostedt 
23348fc0c701SSteven Rostedt 	if (!hnd)
23358fc0c701SSteven Rostedt 		hnd = hhd->first;
23368fc0c701SSteven Rostedt 	else {
23378fc0c701SSteven Rostedt 		hnd = hnd->next;
23388fc0c701SSteven Rostedt 		if (!hnd) {
23398fc0c701SSteven Rostedt 			iter->hidx++;
23408fc0c701SSteven Rostedt 			goto retry;
23418fc0c701SSteven Rostedt 		}
23428fc0c701SSteven Rostedt 	}
23438fc0c701SSteven Rostedt 
23444aeb6967SSteven Rostedt 	if (WARN_ON_ONCE(!hnd))
23454aeb6967SSteven Rostedt 		return NULL;
23464aeb6967SSteven Rostedt 
23474aeb6967SSteven Rostedt 	iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node);
23484aeb6967SSteven Rostedt 
23494aeb6967SSteven Rostedt 	return iter;
23508fc0c701SSteven Rostedt }
23518fc0c701SSteven Rostedt 
23528fc0c701SSteven Rostedt static void *t_hash_start(struct seq_file *m, loff_t *pos)
23538fc0c701SSteven Rostedt {
23548fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
23558fc0c701SSteven Rostedt 	void *p = NULL;
2356d82d6244SLi Zefan 	loff_t l;
2357d82d6244SLi Zefan 
235869a3083cSSteven Rostedt 	if (!(iter->flags & FTRACE_ITER_DO_HASH))
235969a3083cSSteven Rostedt 		return NULL;
236069a3083cSSteven Rostedt 
23612bccfffdSSteven Rostedt 	if (iter->func_pos > *pos)
23622bccfffdSSteven Rostedt 		return NULL;
23638fc0c701SSteven Rostedt 
2364d82d6244SLi Zefan 	iter->hidx = 0;
23652bccfffdSSteven Rostedt 	for (l = 0; l <= (*pos - iter->func_pos); ) {
23664aeb6967SSteven Rostedt 		p = t_hash_next(m, &l);
2367d82d6244SLi Zefan 		if (!p)
2368d82d6244SLi Zefan 			break;
2369d82d6244SLi Zefan 	}
23704aeb6967SSteven Rostedt 	if (!p)
23714aeb6967SSteven Rostedt 		return NULL;
23724aeb6967SSteven Rostedt 
237398c4fd04SSteven Rostedt 	/* Only set this if we have an item */
237498c4fd04SSteven Rostedt 	iter->flags |= FTRACE_ITER_HASH;
237598c4fd04SSteven Rostedt 
23764aeb6967SSteven Rostedt 	return iter;
23778fc0c701SSteven Rostedt }
23788fc0c701SSteven Rostedt 
23794aeb6967SSteven Rostedt static int
23804aeb6967SSteven Rostedt t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
23818fc0c701SSteven Rostedt {
2382b6887d79SSteven Rostedt 	struct ftrace_func_probe *rec;
23838fc0c701SSteven Rostedt 
23844aeb6967SSteven Rostedt 	rec = iter->probe;
23854aeb6967SSteven Rostedt 	if (WARN_ON_ONCE(!rec))
23864aeb6967SSteven Rostedt 		return -EIO;
23878fc0c701SSteven Rostedt 
2388809dcf29SSteven Rostedt 	if (rec->ops->print)
2389809dcf29SSteven Rostedt 		return rec->ops->print(m, rec->ip, rec->ops, rec->data);
2390809dcf29SSteven Rostedt 
2391b375a11aSSteven Rostedt 	seq_printf(m, "%ps:%ps", (void *)rec->ip, (void *)rec->ops->func);
23928fc0c701SSteven Rostedt 
23938fc0c701SSteven Rostedt 	if (rec->data)
23948fc0c701SSteven Rostedt 		seq_printf(m, ":%p", rec->data);
23958fc0c701SSteven Rostedt 	seq_putc(m, '\n');
23968fc0c701SSteven Rostedt 
23978fc0c701SSteven Rostedt 	return 0;
23988fc0c701SSteven Rostedt }
23998fc0c701SSteven Rostedt 
24008fc0c701SSteven Rostedt static void *
24015072c59fSSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos)
24025072c59fSSteven Rostedt {
24035072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
2404fc13cb0cSSteven Rostedt 	struct ftrace_ops *ops = iter->ops;
24055072c59fSSteven Rostedt 	struct dyn_ftrace *rec = NULL;
24065072c59fSSteven Rostedt 
240745a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
240845a4a237SSteven Rostedt 		return NULL;
240945a4a237SSteven Rostedt 
24108fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
24114aeb6967SSteven Rostedt 		return t_hash_next(m, pos);
24128fc0c701SSteven Rostedt 
24135072c59fSSteven Rostedt 	(*pos)++;
24141106b699SJiri Olsa 	iter->pos = iter->func_pos = *pos;
24155072c59fSSteven Rostedt 
24160c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL)
241757c072c7SSteven Rostedt 		return t_hash_start(m, pos);
24180c75a3edSSteven Rostedt 
24195072c59fSSteven Rostedt  retry:
24205072c59fSSteven Rostedt 	if (iter->idx >= iter->pg->index) {
24215072c59fSSteven Rostedt 		if (iter->pg->next) {
24225072c59fSSteven Rostedt 			iter->pg = iter->pg->next;
24235072c59fSSteven Rostedt 			iter->idx = 0;
24245072c59fSSteven Rostedt 			goto retry;
24255072c59fSSteven Rostedt 		}
24265072c59fSSteven Rostedt 	} else {
24275072c59fSSteven Rostedt 		rec = &iter->pg->records[iter->idx++];
242832082309SSteven Rostedt 		if (((iter->flags & FTRACE_ITER_FILTER) &&
2429f45948e8SSteven Rostedt 		     !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) ||
24300183fb1cSSteven Rostedt 
243141c52c0dSSteven Rostedt 		    ((iter->flags & FTRACE_ITER_NOTRACE) &&
2432647bcd03SSteven Rostedt 		     !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) ||
2433647bcd03SSteven Rostedt 
2434647bcd03SSteven Rostedt 		    ((iter->flags & FTRACE_ITER_ENABLED) &&
2435647bcd03SSteven Rostedt 		     !(rec->flags & ~FTRACE_FL_MASK))) {
2436647bcd03SSteven Rostedt 
24375072c59fSSteven Rostedt 			rec = NULL;
24385072c59fSSteven Rostedt 			goto retry;
24395072c59fSSteven Rostedt 		}
24405072c59fSSteven Rostedt 	}
24415072c59fSSteven Rostedt 
24424aeb6967SSteven Rostedt 	if (!rec)
244357c072c7SSteven Rostedt 		return t_hash_start(m, pos);
24444aeb6967SSteven Rostedt 
24454aeb6967SSteven Rostedt 	iter->func = rec;
24464aeb6967SSteven Rostedt 
24474aeb6967SSteven Rostedt 	return iter;
24485072c59fSSteven Rostedt }
24495072c59fSSteven Rostedt 
245098c4fd04SSteven Rostedt static void reset_iter_read(struct ftrace_iterator *iter)
245198c4fd04SSteven Rostedt {
245298c4fd04SSteven Rostedt 	iter->pos = 0;
245398c4fd04SSteven Rostedt 	iter->func_pos = 0;
245470f77b3fSDan Carpenter 	iter->flags &= ~(FTRACE_ITER_PRINTALL | FTRACE_ITER_HASH);
24555072c59fSSteven Rostedt }
24565072c59fSSteven Rostedt 
24575072c59fSSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos)
24585072c59fSSteven Rostedt {
24595072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
2460fc13cb0cSSteven Rostedt 	struct ftrace_ops *ops = iter->ops;
24615072c59fSSteven Rostedt 	void *p = NULL;
2462694ce0a5SLi Zefan 	loff_t l;
24635072c59fSSteven Rostedt 
24648fc0c701SSteven Rostedt 	mutex_lock(&ftrace_lock);
246545a4a237SSteven Rostedt 
246645a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
246745a4a237SSteven Rostedt 		return NULL;
246845a4a237SSteven Rostedt 
24690c75a3edSSteven Rostedt 	/*
247098c4fd04SSteven Rostedt 	 * If an lseek was done, then reset and start from beginning.
247198c4fd04SSteven Rostedt 	 */
247298c4fd04SSteven Rostedt 	if (*pos < iter->pos)
247398c4fd04SSteven Rostedt 		reset_iter_read(iter);
247498c4fd04SSteven Rostedt 
247598c4fd04SSteven Rostedt 	/*
24760c75a3edSSteven Rostedt 	 * For set_ftrace_filter reading, if we have the filter
24770c75a3edSSteven Rostedt 	 * off, we can short cut and just print out that all
24780c75a3edSSteven Rostedt 	 * functions are enabled.
24790c75a3edSSteven Rostedt 	 */
248006a51d93SSteven Rostedt 	if (iter->flags & FTRACE_ITER_FILTER &&
248106a51d93SSteven Rostedt 	    ftrace_hash_empty(ops->filter_hash)) {
24820c75a3edSSteven Rostedt 		if (*pos > 0)
24838fc0c701SSteven Rostedt 			return t_hash_start(m, pos);
24840c75a3edSSteven Rostedt 		iter->flags |= FTRACE_ITER_PRINTALL;
2485df091625SChris Wright 		/* reset in case of seek/pread */
2486df091625SChris Wright 		iter->flags &= ~FTRACE_ITER_HASH;
24870c75a3edSSteven Rostedt 		return iter;
24880c75a3edSSteven Rostedt 	}
24890c75a3edSSteven Rostedt 
24908fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
24918fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
24928fc0c701SSteven Rostedt 
249398c4fd04SSteven Rostedt 	/*
249498c4fd04SSteven Rostedt 	 * Unfortunately, we need to restart at ftrace_pages_start
249598c4fd04SSteven Rostedt 	 * every time we let go of the ftrace_mutex. This is because
249698c4fd04SSteven Rostedt 	 * those pointers can change without the lock.
249798c4fd04SSteven Rostedt 	 */
2498694ce0a5SLi Zefan 	iter->pg = ftrace_pages_start;
2499694ce0a5SLi Zefan 	iter->idx = 0;
2500694ce0a5SLi Zefan 	for (l = 0; l <= *pos; ) {
2501694ce0a5SLi Zefan 		p = t_next(m, p, &l);
2502694ce0a5SLi Zefan 		if (!p)
2503694ce0a5SLi Zefan 			break;
250450cdaf08SLiming Wang 	}
25055821e1b7Swalimis 
250669a3083cSSteven Rostedt 	if (!p)
25078fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
25088fc0c701SSteven Rostedt 
25094aeb6967SSteven Rostedt 	return iter;
25105072c59fSSteven Rostedt }
25115072c59fSSteven Rostedt 
25125072c59fSSteven Rostedt static void t_stop(struct seq_file *m, void *p)
25135072c59fSSteven Rostedt {
25148fc0c701SSteven Rostedt 	mutex_unlock(&ftrace_lock);
25155072c59fSSteven Rostedt }
25165072c59fSSteven Rostedt 
25175072c59fSSteven Rostedt static int t_show(struct seq_file *m, void *v)
25185072c59fSSteven Rostedt {
25190c75a3edSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
25204aeb6967SSteven Rostedt 	struct dyn_ftrace *rec;
25215072c59fSSteven Rostedt 
25228fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
25234aeb6967SSteven Rostedt 		return t_hash_show(m, iter);
25248fc0c701SSteven Rostedt 
25250c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL) {
25260c75a3edSSteven Rostedt 		seq_printf(m, "#### all functions enabled ####\n");
25270c75a3edSSteven Rostedt 		return 0;
25280c75a3edSSteven Rostedt 	}
25290c75a3edSSteven Rostedt 
25304aeb6967SSteven Rostedt 	rec = iter->func;
25314aeb6967SSteven Rostedt 
25325072c59fSSteven Rostedt 	if (!rec)
25335072c59fSSteven Rostedt 		return 0;
25345072c59fSSteven Rostedt 
2535647bcd03SSteven Rostedt 	seq_printf(m, "%ps", (void *)rec->ip);
2536647bcd03SSteven Rostedt 	if (iter->flags & FTRACE_ITER_ENABLED)
253708f6fba5SSteven Rostedt 		seq_printf(m, " (%ld)%s",
253808f6fba5SSteven Rostedt 			   rec->flags & ~FTRACE_FL_MASK,
253908f6fba5SSteven Rostedt 			   rec->flags & FTRACE_FL_REGS ? " R" : "");
2540647bcd03SSteven Rostedt 	seq_printf(m, "\n");
25415072c59fSSteven Rostedt 
25425072c59fSSteven Rostedt 	return 0;
25435072c59fSSteven Rostedt }
25445072c59fSSteven Rostedt 
254588e9d34cSJames Morris static const struct seq_operations show_ftrace_seq_ops = {
25465072c59fSSteven Rostedt 	.start = t_start,
25475072c59fSSteven Rostedt 	.next = t_next,
25485072c59fSSteven Rostedt 	.stop = t_stop,
25495072c59fSSteven Rostedt 	.show = t_show,
25505072c59fSSteven Rostedt };
25515072c59fSSteven Rostedt 
2552e309b41dSIngo Molnar static int
25535072c59fSSteven Rostedt ftrace_avail_open(struct inode *inode, struct file *file)
25545072c59fSSteven Rostedt {
25555072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
25565072c59fSSteven Rostedt 
25574eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
25584eebcc81SSteven Rostedt 		return -ENODEV;
25594eebcc81SSteven Rostedt 
256050e18b94SJiri Olsa 	iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
256150e18b94SJiri Olsa 	if (iter) {
25625072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
2563fc13cb0cSSteven Rostedt 		iter->ops = &global_ops;
25644bf39a94SIngo Molnar 	}
25655072c59fSSteven Rostedt 
256650e18b94SJiri Olsa 	return iter ? 0 : -ENOMEM;
25675072c59fSSteven Rostedt }
25685072c59fSSteven Rostedt 
2569647bcd03SSteven Rostedt static int
2570647bcd03SSteven Rostedt ftrace_enabled_open(struct inode *inode, struct file *file)
2571647bcd03SSteven Rostedt {
2572647bcd03SSteven Rostedt 	struct ftrace_iterator *iter;
2573647bcd03SSteven Rostedt 
2574647bcd03SSteven Rostedt 	if (unlikely(ftrace_disabled))
2575647bcd03SSteven Rostedt 		return -ENODEV;
2576647bcd03SSteven Rostedt 
257750e18b94SJiri Olsa 	iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
257850e18b94SJiri Olsa 	if (iter) {
2579647bcd03SSteven Rostedt 		iter->pg = ftrace_pages_start;
2580647bcd03SSteven Rostedt 		iter->flags = FTRACE_ITER_ENABLED;
2581fc13cb0cSSteven Rostedt 		iter->ops = &global_ops;
2582647bcd03SSteven Rostedt 	}
2583647bcd03SSteven Rostedt 
258450e18b94SJiri Olsa 	return iter ? 0 : -ENOMEM;
2585647bcd03SSteven Rostedt }
2586647bcd03SSteven Rostedt 
25871cf41dd7SSteven Rostedt static void ftrace_filter_reset(struct ftrace_hash *hash)
25885072c59fSSteven Rostedt {
258952baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
25901cf41dd7SSteven Rostedt 	ftrace_hash_clear(hash);
259152baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
25925072c59fSSteven Rostedt }
25935072c59fSSteven Rostedt 
2594fc13cb0cSSteven Rostedt /**
2595fc13cb0cSSteven Rostedt  * ftrace_regex_open - initialize function tracer filter files
2596fc13cb0cSSteven Rostedt  * @ops: The ftrace_ops that hold the hash filters
2597fc13cb0cSSteven Rostedt  * @flag: The type of filter to process
2598fc13cb0cSSteven Rostedt  * @inode: The inode, usually passed in to your open routine
2599fc13cb0cSSteven Rostedt  * @file: The file, usually passed in to your open routine
2600fc13cb0cSSteven Rostedt  *
2601fc13cb0cSSteven Rostedt  * ftrace_regex_open() initializes the filter files for the
2602fc13cb0cSSteven Rostedt  * @ops. Depending on @flag it may process the filter hash or
2603fc13cb0cSSteven Rostedt  * the notrace hash of @ops. With this called from the open
2604fc13cb0cSSteven Rostedt  * routine, you can use ftrace_filter_write() for the write
2605fc13cb0cSSteven Rostedt  * routine if @flag has FTRACE_ITER_FILTER set, or
2606fc13cb0cSSteven Rostedt  * ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set.
2607fc13cb0cSSteven Rostedt  * ftrace_regex_lseek() should be used as the lseek routine, and
2608fc13cb0cSSteven Rostedt  * release must call ftrace_regex_release().
2609fc13cb0cSSteven Rostedt  */
2610fc13cb0cSSteven Rostedt int
2611f45948e8SSteven Rostedt ftrace_regex_open(struct ftrace_ops *ops, int flag,
26121cf41dd7SSteven Rostedt 		  struct inode *inode, struct file *file)
26135072c59fSSteven Rostedt {
26145072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
2615f45948e8SSteven Rostedt 	struct ftrace_hash *hash;
26165072c59fSSteven Rostedt 	int ret = 0;
26175072c59fSSteven Rostedt 
26184eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
26194eebcc81SSteven Rostedt 		return -ENODEV;
26204eebcc81SSteven Rostedt 
26215072c59fSSteven Rostedt 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
26225072c59fSSteven Rostedt 	if (!iter)
26235072c59fSSteven Rostedt 		return -ENOMEM;
26245072c59fSSteven Rostedt 
2625689fd8b6S[email protected] 	if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) {
2626689fd8b6S[email protected] 		kfree(iter);
2627689fd8b6S[email protected] 		return -ENOMEM;
2628689fd8b6S[email protected] 	}
2629689fd8b6S[email protected] 
2630f45948e8SSteven Rostedt 	if (flag & FTRACE_ITER_NOTRACE)
2631f45948e8SSteven Rostedt 		hash = ops->notrace_hash;
2632f45948e8SSteven Rostedt 	else
2633f45948e8SSteven Rostedt 		hash = ops->filter_hash;
2634f45948e8SSteven Rostedt 
263533dc9b12SSteven Rostedt 	iter->ops = ops;
263633dc9b12SSteven Rostedt 	iter->flags = flag;
263733dc9b12SSteven Rostedt 
263833dc9b12SSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
263933dc9b12SSteven Rostedt 		mutex_lock(&ftrace_lock);
264033dc9b12SSteven Rostedt 		iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
264133dc9b12SSteven Rostedt 		mutex_unlock(&ftrace_lock);
264233dc9b12SSteven Rostedt 
264333dc9b12SSteven Rostedt 		if (!iter->hash) {
264433dc9b12SSteven Rostedt 			trace_parser_put(&iter->parser);
264533dc9b12SSteven Rostedt 			kfree(iter);
264633dc9b12SSteven Rostedt 			return -ENOMEM;
264733dc9b12SSteven Rostedt 		}
264833dc9b12SSteven Rostedt 	}
26491cf41dd7SSteven Rostedt 
265041c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
265133dc9b12SSteven Rostedt 
26525072c59fSSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
26538650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC))
265433dc9b12SSteven Rostedt 		ftrace_filter_reset(iter->hash);
26555072c59fSSteven Rostedt 
26565072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
26575072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
26585072c59fSSteven Rostedt 
26595072c59fSSteven Rostedt 		ret = seq_open(file, &show_ftrace_seq_ops);
26605072c59fSSteven Rostedt 		if (!ret) {
26615072c59fSSteven Rostedt 			struct seq_file *m = file->private_data;
26625072c59fSSteven Rostedt 			m->private = iter;
266379fe249cSLi Zefan 		} else {
266433dc9b12SSteven Rostedt 			/* Failed */
266533dc9b12SSteven Rostedt 			free_ftrace_hash(iter->hash);
266679fe249cSLi Zefan 			trace_parser_put(&iter->parser);
26675072c59fSSteven Rostedt 			kfree(iter);
266879fe249cSLi Zefan 		}
26695072c59fSSteven Rostedt 	} else
26705072c59fSSteven Rostedt 		file->private_data = iter;
267141c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
26725072c59fSSteven Rostedt 
26735072c59fSSteven Rostedt 	return ret;
26745072c59fSSteven Rostedt }
26755072c59fSSteven Rostedt 
267641c52c0dSSteven Rostedt static int
267741c52c0dSSteven Rostedt ftrace_filter_open(struct inode *inode, struct file *file)
267841c52c0dSSteven Rostedt {
267969a3083cSSteven Rostedt 	return ftrace_regex_open(&global_ops,
268069a3083cSSteven Rostedt 			FTRACE_ITER_FILTER | FTRACE_ITER_DO_HASH,
26811cf41dd7SSteven Rostedt 			inode, file);
268241c52c0dSSteven Rostedt }
268341c52c0dSSteven Rostedt 
268441c52c0dSSteven Rostedt static int
268541c52c0dSSteven Rostedt ftrace_notrace_open(struct inode *inode, struct file *file)
268641c52c0dSSteven Rostedt {
2687f45948e8SSteven Rostedt 	return ftrace_regex_open(&global_ops, FTRACE_ITER_NOTRACE,
26881cf41dd7SSteven Rostedt 				 inode, file);
268941c52c0dSSteven Rostedt }
269041c52c0dSSteven Rostedt 
2691fc13cb0cSSteven Rostedt loff_t
2692965c8e59SAndrew Morton ftrace_regex_lseek(struct file *file, loff_t offset, int whence)
26935072c59fSSteven Rostedt {
26945072c59fSSteven Rostedt 	loff_t ret;
26955072c59fSSteven Rostedt 
26965072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ)
2697965c8e59SAndrew Morton 		ret = seq_lseek(file, offset, whence);
26985072c59fSSteven Rostedt 	else
26995072c59fSSteven Rostedt 		file->f_pos = ret = 1;
27005072c59fSSteven Rostedt 
27015072c59fSSteven Rostedt 	return ret;
27025072c59fSSteven Rostedt }
27035072c59fSSteven Rostedt 
270464e7c440SSteven Rostedt static int ftrace_match(char *str, char *regex, int len, int type)
27059f4801e3SSteven Rostedt {
27069f4801e3SSteven Rostedt 	int matched = 0;
2707751e9983SLi Zefan 	int slen;
27089f4801e3SSteven Rostedt 
27099f4801e3SSteven Rostedt 	switch (type) {
27109f4801e3SSteven Rostedt 	case MATCH_FULL:
27119f4801e3SSteven Rostedt 		if (strcmp(str, regex) == 0)
27129f4801e3SSteven Rostedt 			matched = 1;
27139f4801e3SSteven Rostedt 		break;
27149f4801e3SSteven Rostedt 	case MATCH_FRONT_ONLY:
27159f4801e3SSteven Rostedt 		if (strncmp(str, regex, len) == 0)
27169f4801e3SSteven Rostedt 			matched = 1;
27179f4801e3SSteven Rostedt 		break;
27189f4801e3SSteven Rostedt 	case MATCH_MIDDLE_ONLY:
27199f4801e3SSteven Rostedt 		if (strstr(str, regex))
27209f4801e3SSteven Rostedt 			matched = 1;
27219f4801e3SSteven Rostedt 		break;
27229f4801e3SSteven Rostedt 	case MATCH_END_ONLY:
2723751e9983SLi Zefan 		slen = strlen(str);
2724751e9983SLi Zefan 		if (slen >= len && memcmp(str + slen - len, regex, len) == 0)
27259f4801e3SSteven Rostedt 			matched = 1;
27269f4801e3SSteven Rostedt 		break;
27279f4801e3SSteven Rostedt 	}
27289f4801e3SSteven Rostedt 
27299f4801e3SSteven Rostedt 	return matched;
27309f4801e3SSteven Rostedt }
27319f4801e3SSteven Rostedt 
2732b448c4e3SSteven Rostedt static int
27331cf41dd7SSteven Rostedt enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not)
273464e7c440SSteven Rostedt {
2735b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
2736b448c4e3SSteven Rostedt 	int ret = 0;
2737b448c4e3SSteven Rostedt 
27381cf41dd7SSteven Rostedt 	entry = ftrace_lookup_ip(hash, rec->ip);
2739b448c4e3SSteven Rostedt 	if (not) {
2740b448c4e3SSteven Rostedt 		/* Do nothing if it doesn't exist */
2741b448c4e3SSteven Rostedt 		if (!entry)
2742b448c4e3SSteven Rostedt 			return 0;
2743b448c4e3SSteven Rostedt 
274433dc9b12SSteven Rostedt 		free_hash_entry(hash, entry);
2745b448c4e3SSteven Rostedt 	} else {
2746b448c4e3SSteven Rostedt 		/* Do nothing if it exists */
2747b448c4e3SSteven Rostedt 		if (entry)
2748b448c4e3SSteven Rostedt 			return 0;
2749b448c4e3SSteven Rostedt 
2750b448c4e3SSteven Rostedt 		ret = add_hash_entry(hash, rec->ip);
2751b448c4e3SSteven Rostedt 	}
2752b448c4e3SSteven Rostedt 	return ret;
2753996e87beSSteven Rostedt }
2754996e87beSSteven Rostedt 
275564e7c440SSteven Rostedt static int
2756b9df92d2SSteven Rostedt ftrace_match_record(struct dyn_ftrace *rec, char *mod,
2757b9df92d2SSteven Rostedt 		    char *regex, int len, int type)
275864e7c440SSteven Rostedt {
275964e7c440SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
2760b9df92d2SSteven Rostedt 	char *modname;
276164e7c440SSteven Rostedt 
2762b9df92d2SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
2763b9df92d2SSteven Rostedt 
2764b9df92d2SSteven Rostedt 	if (mod) {
2765b9df92d2SSteven Rostedt 		/* module lookup requires matching the module */
2766b9df92d2SSteven Rostedt 		if (!modname || strcmp(modname, mod))
2767b9df92d2SSteven Rostedt 			return 0;
2768b9df92d2SSteven Rostedt 
2769b9df92d2SSteven Rostedt 		/* blank search means to match all funcs in the mod */
2770b9df92d2SSteven Rostedt 		if (!len)
2771b9df92d2SSteven Rostedt 			return 1;
2772b9df92d2SSteven Rostedt 	}
2773b9df92d2SSteven Rostedt 
277464e7c440SSteven Rostedt 	return ftrace_match(str, regex, len, type);
277564e7c440SSteven Rostedt }
277664e7c440SSteven Rostedt 
27771cf41dd7SSteven Rostedt static int
27781cf41dd7SSteven Rostedt match_records(struct ftrace_hash *hash, char *buff,
27791cf41dd7SSteven Rostedt 	      int len, char *mod, int not)
27809f4801e3SSteven Rostedt {
2781b9df92d2SSteven Rostedt 	unsigned search_len = 0;
27829f4801e3SSteven Rostedt 	struct ftrace_page *pg;
27839f4801e3SSteven Rostedt 	struct dyn_ftrace *rec;
2784b9df92d2SSteven Rostedt 	int type = MATCH_FULL;
2785b9df92d2SSteven Rostedt 	char *search = buff;
2786311d16daSLi Zefan 	int found = 0;
2787b448c4e3SSteven Rostedt 	int ret;
27889f4801e3SSteven Rostedt 
2789b9df92d2SSteven Rostedt 	if (len) {
27903f6fe06dSFrederic Weisbecker 		type = filter_parse_regex(buff, len, &search, &not);
27919f4801e3SSteven Rostedt 		search_len = strlen(search);
2792b9df92d2SSteven Rostedt 	}
2793b9df92d2SSteven Rostedt 
279452baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
2795b9df92d2SSteven Rostedt 
2796b9df92d2SSteven Rostedt 	if (unlikely(ftrace_disabled))
2797b9df92d2SSteven Rostedt 		goto out_unlock;
2798b9df92d2SSteven Rostedt 
2799265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
2800b9df92d2SSteven Rostedt 		if (ftrace_match_record(rec, mod, search, search_len, type)) {
28011cf41dd7SSteven Rostedt 			ret = enter_record(hash, rec, not);
2802b448c4e3SSteven Rostedt 			if (ret < 0) {
2803b448c4e3SSteven Rostedt 				found = ret;
2804b448c4e3SSteven Rostedt 				goto out_unlock;
2805b448c4e3SSteven Rostedt 			}
2806311d16daSLi Zefan 			found = 1;
28075072c59fSSteven Rostedt 		}
2808265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
2809b9df92d2SSteven Rostedt  out_unlock:
281052baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2811311d16daSLi Zefan 
2812311d16daSLi Zefan 	return found;
28135072c59fSSteven Rostedt }
28145072c59fSSteven Rostedt 
281564e7c440SSteven Rostedt static int
28161cf41dd7SSteven Rostedt ftrace_match_records(struct ftrace_hash *hash, char *buff, int len)
281764e7c440SSteven Rostedt {
28181cf41dd7SSteven Rostedt 	return match_records(hash, buff, len, NULL, 0);
281964e7c440SSteven Rostedt }
282064e7c440SSteven Rostedt 
28211cf41dd7SSteven Rostedt static int
28221cf41dd7SSteven Rostedt ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod)
282364e7c440SSteven Rostedt {
282464e7c440SSteven Rostedt 	int not = 0;
28256a24a244SSteven Rostedt 
282664e7c440SSteven Rostedt 	/* blank or '*' mean the same */
282764e7c440SSteven Rostedt 	if (strcmp(buff, "*") == 0)
282864e7c440SSteven Rostedt 		buff[0] = 0;
282964e7c440SSteven Rostedt 
283064e7c440SSteven Rostedt 	/* handle the case of 'dont filter this module' */
283164e7c440SSteven Rostedt 	if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) {
283264e7c440SSteven Rostedt 		buff[0] = 0;
283364e7c440SSteven Rostedt 		not = 1;
283464e7c440SSteven Rostedt 	}
283564e7c440SSteven Rostedt 
28361cf41dd7SSteven Rostedt 	return match_records(hash, buff, strlen(buff), mod, not);
283764e7c440SSteven Rostedt }
283864e7c440SSteven Rostedt 
2839f6180773SSteven Rostedt /*
2840f6180773SSteven Rostedt  * We register the module command as a template to show others how
2841f6180773SSteven Rostedt  * to register the a command as well.
2842f6180773SSteven Rostedt  */
2843f6180773SSteven Rostedt 
2844f6180773SSteven Rostedt static int
284543dd61c9SSteven Rostedt ftrace_mod_callback(struct ftrace_hash *hash,
284643dd61c9SSteven Rostedt 		    char *func, char *cmd, char *param, int enable)
2847f6180773SSteven Rostedt {
2848f6180773SSteven Rostedt 	char *mod;
2849b448c4e3SSteven Rostedt 	int ret = -EINVAL;
2850f6180773SSteven Rostedt 
2851f6180773SSteven Rostedt 	/*
2852f6180773SSteven Rostedt 	 * cmd == 'mod' because we only registered this func
2853f6180773SSteven Rostedt 	 * for the 'mod' ftrace_func_command.
2854f6180773SSteven Rostedt 	 * But if you register one func with multiple commands,
2855f6180773SSteven Rostedt 	 * you can tell which command was used by the cmd
2856f6180773SSteven Rostedt 	 * parameter.
2857f6180773SSteven Rostedt 	 */
2858f6180773SSteven Rostedt 
2859f6180773SSteven Rostedt 	/* we must have a module name */
2860f6180773SSteven Rostedt 	if (!param)
2861b448c4e3SSteven Rostedt 		return ret;
2862f6180773SSteven Rostedt 
2863f6180773SSteven Rostedt 	mod = strsep(&param, ":");
2864f6180773SSteven Rostedt 	if (!strlen(mod))
2865b448c4e3SSteven Rostedt 		return ret;
2866f6180773SSteven Rostedt 
28671cf41dd7SSteven Rostedt 	ret = ftrace_match_module_records(hash, func, mod);
2868b448c4e3SSteven Rostedt 	if (!ret)
2869b448c4e3SSteven Rostedt 		ret = -EINVAL;
2870b448c4e3SSteven Rostedt 	if (ret < 0)
2871b448c4e3SSteven Rostedt 		return ret;
2872b448c4e3SSteven Rostedt 
2873f6180773SSteven Rostedt 	return 0;
2874f6180773SSteven Rostedt }
2875f6180773SSteven Rostedt 
2876f6180773SSteven Rostedt static struct ftrace_func_command ftrace_mod_cmd = {
2877f6180773SSteven Rostedt 	.name			= "mod",
2878f6180773SSteven Rostedt 	.func			= ftrace_mod_callback,
2879f6180773SSteven Rostedt };
2880f6180773SSteven Rostedt 
2881f6180773SSteven Rostedt static int __init ftrace_mod_cmd_init(void)
2882f6180773SSteven Rostedt {
2883f6180773SSteven Rostedt 	return register_ftrace_command(&ftrace_mod_cmd);
2884f6180773SSteven Rostedt }
28856f415672SSteven Rostedt core_initcall(ftrace_mod_cmd_init);
2886f6180773SSteven Rostedt 
28872f5f6ad9SSteven Rostedt static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
2888a1e2e31dSSteven Rostedt 				      struct ftrace_ops *op, struct pt_regs *pt_regs)
288959df055fSSteven Rostedt {
2890b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
289159df055fSSteven Rostedt 	struct hlist_head *hhd;
289259df055fSSteven Rostedt 	struct hlist_node *n;
289359df055fSSteven Rostedt 	unsigned long key;
289459df055fSSteven Rostedt 
289559df055fSSteven Rostedt 	key = hash_long(ip, FTRACE_HASH_BITS);
289659df055fSSteven Rostedt 
289759df055fSSteven Rostedt 	hhd = &ftrace_func_hash[key];
289859df055fSSteven Rostedt 
289959df055fSSteven Rostedt 	if (hlist_empty(hhd))
290059df055fSSteven Rostedt 		return;
290159df055fSSteven Rostedt 
290259df055fSSteven Rostedt 	/*
290359df055fSSteven Rostedt 	 * Disable preemption for these calls to prevent a RCU grace
290459df055fSSteven Rostedt 	 * period. This syncs the hash iteration and freeing of items
290559df055fSSteven Rostedt 	 * on the hash. rcu_read_lock is too dangerous here.
290659df055fSSteven Rostedt 	 */
29075168ae50SSteven Rostedt 	preempt_disable_notrace();
290859df055fSSteven Rostedt 	hlist_for_each_entry_rcu(entry, n, hhd, node) {
290959df055fSSteven Rostedt 		if (entry->ip == ip)
291059df055fSSteven Rostedt 			entry->ops->func(ip, parent_ip, &entry->data);
291159df055fSSteven Rostedt 	}
29125168ae50SSteven Rostedt 	preempt_enable_notrace();
291359df055fSSteven Rostedt }
291459df055fSSteven Rostedt 
2915b6887d79SSteven Rostedt static struct ftrace_ops trace_probe_ops __read_mostly =
291659df055fSSteven Rostedt {
2917b6887d79SSteven Rostedt 	.func		= function_trace_probe_call,
291859df055fSSteven Rostedt };
291959df055fSSteven Rostedt 
2920b6887d79SSteven Rostedt static int ftrace_probe_registered;
292159df055fSSteven Rostedt 
2922b6887d79SSteven Rostedt static void __enable_ftrace_function_probe(void)
292359df055fSSteven Rostedt {
2924b848914cSSteven Rostedt 	int ret;
292559df055fSSteven Rostedt 	int i;
292659df055fSSteven Rostedt 
2927b6887d79SSteven Rostedt 	if (ftrace_probe_registered)
292859df055fSSteven Rostedt 		return;
292959df055fSSteven Rostedt 
293059df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
293159df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
293259df055fSSteven Rostedt 		if (hhd->first)
293359df055fSSteven Rostedt 			break;
293459df055fSSteven Rostedt 	}
293559df055fSSteven Rostedt 	/* Nothing registered? */
293659df055fSSteven Rostedt 	if (i == FTRACE_FUNC_HASHSIZE)
293759df055fSSteven Rostedt 		return;
293859df055fSSteven Rostedt 
2939b848914cSSteven Rostedt 	ret = __register_ftrace_function(&trace_probe_ops);
2940b848914cSSteven Rostedt 	if (!ret)
2941a1cd6173SSteven Rostedt 		ret = ftrace_startup(&trace_probe_ops, 0);
2942b848914cSSteven Rostedt 
2943b6887d79SSteven Rostedt 	ftrace_probe_registered = 1;
294459df055fSSteven Rostedt }
294559df055fSSteven Rostedt 
2946b6887d79SSteven Rostedt static void __disable_ftrace_function_probe(void)
294759df055fSSteven Rostedt {
2948b848914cSSteven Rostedt 	int ret;
294959df055fSSteven Rostedt 	int i;
295059df055fSSteven Rostedt 
2951b6887d79SSteven Rostedt 	if (!ftrace_probe_registered)
295259df055fSSteven Rostedt 		return;
295359df055fSSteven Rostedt 
295459df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
295559df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
295659df055fSSteven Rostedt 		if (hhd->first)
295759df055fSSteven Rostedt 			return;
295859df055fSSteven Rostedt 	}
295959df055fSSteven Rostedt 
296059df055fSSteven Rostedt 	/* no more funcs left */
2961b848914cSSteven Rostedt 	ret = __unregister_ftrace_function(&trace_probe_ops);
2962b848914cSSteven Rostedt 	if (!ret)
2963b848914cSSteven Rostedt 		ftrace_shutdown(&trace_probe_ops, 0);
2964b848914cSSteven Rostedt 
2965b6887d79SSteven Rostedt 	ftrace_probe_registered = 0;
296659df055fSSteven Rostedt }
296759df055fSSteven Rostedt 
296859df055fSSteven Rostedt 
29697818b388SSteven Rostedt (Red Hat) static void ftrace_free_entry(struct ftrace_func_probe *entry)
297059df055fSSteven Rostedt {
297159df055fSSteven Rostedt 	if (entry->ops->free)
2972e67efb93SSteven Rostedt (Red Hat) 		entry->ops->free(entry->ops, entry->ip, &entry->data);
297359df055fSSteven Rostedt 	kfree(entry);
297459df055fSSteven Rostedt }
297559df055fSSteven Rostedt 
297659df055fSSteven Rostedt int
2977b6887d79SSteven Rostedt register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
297859df055fSSteven Rostedt 			      void *data)
297959df055fSSteven Rostedt {
2980b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
2981e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
2982e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
298359df055fSSteven Rostedt 	struct ftrace_page *pg;
298459df055fSSteven Rostedt 	struct dyn_ftrace *rec;
298559df055fSSteven Rostedt 	int type, len, not;
29866a24a244SSteven Rostedt 	unsigned long key;
298759df055fSSteven Rostedt 	int count = 0;
298859df055fSSteven Rostedt 	char *search;
2989e1df4cb6SSteven Rostedt (Red Hat) 	int ret;
299059df055fSSteven Rostedt 
29913f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(glob, strlen(glob), &search, &not);
299259df055fSSteven Rostedt 	len = strlen(search);
299359df055fSSteven Rostedt 
2994b6887d79SSteven Rostedt 	/* we do not support '!' for function probes */
299559df055fSSteven Rostedt 	if (WARN_ON(not))
299659df055fSSteven Rostedt 		return -EINVAL;
299759df055fSSteven Rostedt 
299859df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
299959df055fSSteven Rostedt 
3000e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3001e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash) {
3002e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENOMEM;
300345a4a237SSteven Rostedt 		goto out_unlock;
3004e1df4cb6SSteven Rostedt (Red Hat) 	}
3005e1df4cb6SSteven Rostedt (Red Hat) 
3006e1df4cb6SSteven Rostedt (Red Hat) 	if (unlikely(ftrace_disabled)) {
3007e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENODEV;
3008e1df4cb6SSteven Rostedt (Red Hat) 		goto out_unlock;
3009e1df4cb6SSteven Rostedt (Red Hat) 	}
301045a4a237SSteven Rostedt 
301159df055fSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
301259df055fSSteven Rostedt 
3013b9df92d2SSteven Rostedt 		if (!ftrace_match_record(rec, NULL, search, len, type))
301459df055fSSteven Rostedt 			continue;
301559df055fSSteven Rostedt 
301659df055fSSteven Rostedt 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
301759df055fSSteven Rostedt 		if (!entry) {
3018b6887d79SSteven Rostedt 			/* If we did not process any, then return error */
301959df055fSSteven Rostedt 			if (!count)
302059df055fSSteven Rostedt 				count = -ENOMEM;
302159df055fSSteven Rostedt 			goto out_unlock;
302259df055fSSteven Rostedt 		}
302359df055fSSteven Rostedt 
302459df055fSSteven Rostedt 		count++;
302559df055fSSteven Rostedt 
302659df055fSSteven Rostedt 		entry->data = data;
302759df055fSSteven Rostedt 
302859df055fSSteven Rostedt 		/*
302959df055fSSteven Rostedt 		 * The caller might want to do something special
303059df055fSSteven Rostedt 		 * for each function we find. We call the callback
303159df055fSSteven Rostedt 		 * to give the caller an opportunity to do so.
303259df055fSSteven Rostedt 		 */
3033e67efb93SSteven Rostedt (Red Hat) 		if (ops->init) {
3034e67efb93SSteven Rostedt (Red Hat) 			if (ops->init(ops, rec->ip, &entry->data) < 0) {
303559df055fSSteven Rostedt 				/* caller does not like this func */
303659df055fSSteven Rostedt 				kfree(entry);
303759df055fSSteven Rostedt 				continue;
303859df055fSSteven Rostedt 			}
303959df055fSSteven Rostedt 		}
304059df055fSSteven Rostedt 
3041e1df4cb6SSteven Rostedt (Red Hat) 		ret = enter_record(hash, rec, 0);
3042e1df4cb6SSteven Rostedt (Red Hat) 		if (ret < 0) {
3043e1df4cb6SSteven Rostedt (Red Hat) 			kfree(entry);
3044e1df4cb6SSteven Rostedt (Red Hat) 			count = ret;
3045e1df4cb6SSteven Rostedt (Red Hat) 			goto out_unlock;
3046e1df4cb6SSteven Rostedt (Red Hat) 		}
3047e1df4cb6SSteven Rostedt (Red Hat) 
304859df055fSSteven Rostedt 		entry->ops = ops;
304959df055fSSteven Rostedt 		entry->ip = rec->ip;
305059df055fSSteven Rostedt 
305159df055fSSteven Rostedt 		key = hash_long(entry->ip, FTRACE_HASH_BITS);
305259df055fSSteven Rostedt 		hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]);
305359df055fSSteven Rostedt 
305459df055fSSteven Rostedt 	} while_for_each_ftrace_rec();
3055e1df4cb6SSteven Rostedt (Red Hat) 
3056e1df4cb6SSteven Rostedt (Red Hat) 	ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3057e1df4cb6SSteven Rostedt (Red Hat) 	if (ret < 0)
3058e1df4cb6SSteven Rostedt (Red Hat) 		count = ret;
3059e1df4cb6SSteven Rostedt (Red Hat) 
3060b6887d79SSteven Rostedt 	__enable_ftrace_function_probe();
306159df055fSSteven Rostedt 
306259df055fSSteven Rostedt  out_unlock:
306359df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
3064e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
306559df055fSSteven Rostedt 
306659df055fSSteven Rostedt 	return count;
306759df055fSSteven Rostedt }
306859df055fSSteven Rostedt 
306959df055fSSteven Rostedt enum {
3070b6887d79SSteven Rostedt 	PROBE_TEST_FUNC		= 1,
3071b6887d79SSteven Rostedt 	PROBE_TEST_DATA		= 2
307259df055fSSteven Rostedt };
307359df055fSSteven Rostedt 
307459df055fSSteven Rostedt static void
3075b6887d79SSteven Rostedt __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
307659df055fSSteven Rostedt 				  void *data, int flags)
307759df055fSSteven Rostedt {
3078e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_func_entry *rec_entry;
3079b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
30807818b388SSteven Rostedt (Red Hat) 	struct ftrace_func_probe *p;
3081e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
30827818b388SSteven Rostedt (Red Hat) 	struct list_head free_list;
3083e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
308459df055fSSteven Rostedt 	struct hlist_node *n, *tmp;
308559df055fSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
308659df055fSSteven Rostedt 	int type = MATCH_FULL;
308759df055fSSteven Rostedt 	int i, len = 0;
308859df055fSSteven Rostedt 	char *search;
308959df055fSSteven Rostedt 
3090b36461daSAtsushi Tsuji 	if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
309159df055fSSteven Rostedt 		glob = NULL;
3092b36461daSAtsushi Tsuji 	else if (glob) {
309359df055fSSteven Rostedt 		int not;
309459df055fSSteven Rostedt 
30953f6fe06dSFrederic Weisbecker 		type = filter_parse_regex(glob, strlen(glob), &search, &not);
309659df055fSSteven Rostedt 		len = strlen(search);
309759df055fSSteven Rostedt 
3098b6887d79SSteven Rostedt 		/* we do not support '!' for function probes */
309959df055fSSteven Rostedt 		if (WARN_ON(not))
310059df055fSSteven Rostedt 			return;
310159df055fSSteven Rostedt 	}
310259df055fSSteven Rostedt 
310359df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
3104e1df4cb6SSteven Rostedt (Red Hat) 
3105e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3106e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash)
3107e1df4cb6SSteven Rostedt (Red Hat) 		/* Hmm, should report this somehow */
3108e1df4cb6SSteven Rostedt (Red Hat) 		goto out_unlock;
3109e1df4cb6SSteven Rostedt (Red Hat) 
31107818b388SSteven Rostedt (Red Hat) 	INIT_LIST_HEAD(&free_list);
31117818b388SSteven Rostedt (Red Hat) 
311259df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
311359df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
311459df055fSSteven Rostedt 
311559df055fSSteven Rostedt 		hlist_for_each_entry_safe(entry, n, tmp, hhd, node) {
311659df055fSSteven Rostedt 
311759df055fSSteven Rostedt 			/* break up if statements for readability */
3118b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_FUNC) && entry->ops != ops)
311959df055fSSteven Rostedt 				continue;
312059df055fSSteven Rostedt 
3121b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_DATA) && entry->data != data)
312259df055fSSteven Rostedt 				continue;
312359df055fSSteven Rostedt 
312459df055fSSteven Rostedt 			/* do this last, since it is the most expensive */
312559df055fSSteven Rostedt 			if (glob) {
312659df055fSSteven Rostedt 				kallsyms_lookup(entry->ip, NULL, NULL,
312759df055fSSteven Rostedt 						NULL, str);
312859df055fSSteven Rostedt 				if (!ftrace_match(str, glob, len, type))
312959df055fSSteven Rostedt 					continue;
313059df055fSSteven Rostedt 			}
313159df055fSSteven Rostedt 
3132e1df4cb6SSteven Rostedt (Red Hat) 			rec_entry = ftrace_lookup_ip(hash, entry->ip);
3133e1df4cb6SSteven Rostedt (Red Hat) 			/* It is possible more than one entry had this ip */
3134e1df4cb6SSteven Rostedt (Red Hat) 			if (rec_entry)
3135e1df4cb6SSteven Rostedt (Red Hat) 				free_hash_entry(hash, rec_entry);
3136e1df4cb6SSteven Rostedt (Red Hat) 
3137740466bcSSteven Rostedt (Red Hat) 			hlist_del_rcu(&entry->node);
31387818b388SSteven Rostedt (Red Hat) 			list_add(&entry->free_list, &free_list);
313959df055fSSteven Rostedt 		}
314059df055fSSteven Rostedt 	}
3141b6887d79SSteven Rostedt 	__disable_ftrace_function_probe();
3142e1df4cb6SSteven Rostedt (Red Hat) 	/*
3143e1df4cb6SSteven Rostedt (Red Hat) 	 * Remove after the disable is called. Otherwise, if the last
3144e1df4cb6SSteven Rostedt (Red Hat) 	 * probe is removed, a null hash means *all enabled*.
3145e1df4cb6SSteven Rostedt (Red Hat) 	 */
3146e1df4cb6SSteven Rostedt (Red Hat) 	ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
31477818b388SSteven Rostedt (Red Hat) 	synchronize_sched();
31487818b388SSteven Rostedt (Red Hat) 	list_for_each_entry_safe(entry, p, &free_list, free_list) {
31497818b388SSteven Rostedt (Red Hat) 		list_del(&entry->free_list);
31507818b388SSteven Rostedt (Red Hat) 		ftrace_free_entry(entry);
31517818b388SSteven Rostedt (Red Hat) 	}
31527818b388SSteven Rostedt (Red Hat) 
3153e1df4cb6SSteven Rostedt (Red Hat)  out_unlock:
315459df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
3155e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
315659df055fSSteven Rostedt }
315759df055fSSteven Rostedt 
315859df055fSSteven Rostedt void
3159b6887d79SSteven Rostedt unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
316059df055fSSteven Rostedt 				void *data)
316159df055fSSteven Rostedt {
3162b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, data,
3163b6887d79SSteven Rostedt 					  PROBE_TEST_FUNC | PROBE_TEST_DATA);
316459df055fSSteven Rostedt }
316559df055fSSteven Rostedt 
316659df055fSSteven Rostedt void
3167b6887d79SSteven Rostedt unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops)
316859df055fSSteven Rostedt {
3169b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC);
317059df055fSSteven Rostedt }
317159df055fSSteven Rostedt 
3172b6887d79SSteven Rostedt void unregister_ftrace_function_probe_all(char *glob)
317359df055fSSteven Rostedt {
3174b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, NULL, NULL, 0);
317559df055fSSteven Rostedt }
317659df055fSSteven Rostedt 
3177f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands);
3178f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex);
3179f6180773SSteven Rostedt 
3180f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd)
3181f6180773SSteven Rostedt {
3182f6180773SSteven Rostedt 	struct ftrace_func_command *p;
3183f6180773SSteven Rostedt 	int ret = 0;
3184f6180773SSteven Rostedt 
3185f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3186f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3187f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3188f6180773SSteven Rostedt 			ret = -EBUSY;
3189f6180773SSteven Rostedt 			goto out_unlock;
3190f6180773SSteven Rostedt 		}
3191f6180773SSteven Rostedt 	}
3192f6180773SSteven Rostedt 	list_add(&cmd->list, &ftrace_commands);
3193f6180773SSteven Rostedt  out_unlock:
3194f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3195f6180773SSteven Rostedt 
3196f6180773SSteven Rostedt 	return ret;
3197f6180773SSteven Rostedt }
3198f6180773SSteven Rostedt 
3199f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd)
3200f6180773SSteven Rostedt {
3201f6180773SSteven Rostedt 	struct ftrace_func_command *p, *n;
3202f6180773SSteven Rostedt 	int ret = -ENODEV;
3203f6180773SSteven Rostedt 
3204f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3205f6180773SSteven Rostedt 	list_for_each_entry_safe(p, n, &ftrace_commands, list) {
3206f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3207f6180773SSteven Rostedt 			ret = 0;
3208f6180773SSteven Rostedt 			list_del_init(&p->list);
3209f6180773SSteven Rostedt 			goto out_unlock;
3210f6180773SSteven Rostedt 		}
3211f6180773SSteven Rostedt 	}
3212f6180773SSteven Rostedt  out_unlock:
3213f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3214f6180773SSteven Rostedt 
3215f6180773SSteven Rostedt 	return ret;
3216f6180773SSteven Rostedt }
3217f6180773SSteven Rostedt 
321833dc9b12SSteven Rostedt static int ftrace_process_regex(struct ftrace_hash *hash,
321933dc9b12SSteven Rostedt 				char *buff, int len, int enable)
322064e7c440SSteven Rostedt {
3221f6180773SSteven Rostedt 	char *func, *command, *next = buff;
32226a24a244SSteven Rostedt 	struct ftrace_func_command *p;
32230aff1c0cSGuoWen Li 	int ret = -EINVAL;
322464e7c440SSteven Rostedt 
322564e7c440SSteven Rostedt 	func = strsep(&next, ":");
322664e7c440SSteven Rostedt 
322764e7c440SSteven Rostedt 	if (!next) {
32281cf41dd7SSteven Rostedt 		ret = ftrace_match_records(hash, func, len);
3229b448c4e3SSteven Rostedt 		if (!ret)
3230b448c4e3SSteven Rostedt 			ret = -EINVAL;
3231b448c4e3SSteven Rostedt 		if (ret < 0)
3232311d16daSLi Zefan 			return ret;
3233b448c4e3SSteven Rostedt 		return 0;
323464e7c440SSteven Rostedt 	}
323564e7c440SSteven Rostedt 
3236f6180773SSteven Rostedt 	/* command found */
323764e7c440SSteven Rostedt 
323864e7c440SSteven Rostedt 	command = strsep(&next, ":");
323964e7c440SSteven Rostedt 
3240f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3241f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3242f6180773SSteven Rostedt 		if (strcmp(p->name, command) == 0) {
324343dd61c9SSteven Rostedt 			ret = p->func(hash, func, command, next, enable);
3244f6180773SSteven Rostedt 			goto out_unlock;
324564e7c440SSteven Rostedt 		}
3246f6180773SSteven Rostedt 	}
3247f6180773SSteven Rostedt  out_unlock:
3248f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
324964e7c440SSteven Rostedt 
3250f6180773SSteven Rostedt 	return ret;
325164e7c440SSteven Rostedt }
325264e7c440SSteven Rostedt 
3253e309b41dSIngo Molnar static ssize_t
325441c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf,
325541c52c0dSSteven Rostedt 		   size_t cnt, loff_t *ppos, int enable)
32565072c59fSSteven Rostedt {
32575072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
3258689fd8b6S[email protected] 	struct trace_parser *parser;
3259689fd8b6S[email protected] 	ssize_t ret, read;
32605072c59fSSteven Rostedt 
32614ba7978eSLi Zefan 	if (!cnt)
32625072c59fSSteven Rostedt 		return 0;
32635072c59fSSteven Rostedt 
326441c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
32655072c59fSSteven Rostedt 
326645a4a237SSteven Rostedt 	ret = -ENODEV;
326745a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
326845a4a237SSteven Rostedt 		goto out_unlock;
326945a4a237SSteven Rostedt 
32705072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
32715072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
32725072c59fSSteven Rostedt 		iter = m->private;
32735072c59fSSteven Rostedt 	} else
32745072c59fSSteven Rostedt 		iter = file->private_data;
32755072c59fSSteven Rostedt 
3276689fd8b6S[email protected] 	parser = &iter->parser;
3277689fd8b6S[email protected] 	read = trace_get_user(parser, ubuf, cnt, ppos);
32785072c59fSSteven Rostedt 
32794ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded(parser) &&
3280689fd8b6S[email protected] 	    !trace_parser_cont(parser)) {
328133dc9b12SSteven Rostedt 		ret = ftrace_process_regex(iter->hash, parser->buffer,
3282689fd8b6S[email protected] 					   parser->idx, enable);
3283313254a9SLi Zefan 		trace_parser_clear(parser);
32845072c59fSSteven Rostedt 		if (ret)
3285ed146b25SLi Zefan 			goto out_unlock;
32865072c59fSSteven Rostedt 	}
32875072c59fSSteven Rostedt 
32885072c59fSSteven Rostedt 	ret = read;
3289ed146b25SLi Zefan out_unlock:
329041c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
3291ed146b25SLi Zefan 
32925072c59fSSteven Rostedt 	return ret;
32935072c59fSSteven Rostedt }
32945072c59fSSteven Rostedt 
3295fc13cb0cSSteven Rostedt ssize_t
329641c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf,
329741c52c0dSSteven Rostedt 		    size_t cnt, loff_t *ppos)
329841c52c0dSSteven Rostedt {
329941c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
330041c52c0dSSteven Rostedt }
330141c52c0dSSteven Rostedt 
3302fc13cb0cSSteven Rostedt ssize_t
330341c52c0dSSteven Rostedt ftrace_notrace_write(struct file *file, const char __user *ubuf,
330441c52c0dSSteven Rostedt 		     size_t cnt, loff_t *ppos)
330541c52c0dSSteven Rostedt {
330641c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 0);
330741c52c0dSSteven Rostedt }
330841c52c0dSSteven Rostedt 
330933dc9b12SSteven Rostedt static int
3310647664eaSMasami Hiramatsu ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
3311647664eaSMasami Hiramatsu {
3312647664eaSMasami Hiramatsu 	struct ftrace_func_entry *entry;
3313647664eaSMasami Hiramatsu 
3314647664eaSMasami Hiramatsu 	if (!ftrace_location(ip))
3315647664eaSMasami Hiramatsu 		return -EINVAL;
3316647664eaSMasami Hiramatsu 
3317647664eaSMasami Hiramatsu 	if (remove) {
3318647664eaSMasami Hiramatsu 		entry = ftrace_lookup_ip(hash, ip);
3319647664eaSMasami Hiramatsu 		if (!entry)
3320647664eaSMasami Hiramatsu 			return -ENOENT;
3321647664eaSMasami Hiramatsu 		free_hash_entry(hash, entry);
3322647664eaSMasami Hiramatsu 		return 0;
3323647664eaSMasami Hiramatsu 	}
3324647664eaSMasami Hiramatsu 
3325647664eaSMasami Hiramatsu 	return add_hash_entry(hash, ip);
3326647664eaSMasami Hiramatsu }
3327647664eaSMasami Hiramatsu 
3328647664eaSMasami Hiramatsu static int
3329647664eaSMasami Hiramatsu ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
3330647664eaSMasami Hiramatsu 		unsigned long ip, int remove, int reset, int enable)
333141c52c0dSSteven Rostedt {
333233dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3333f45948e8SSteven Rostedt 	struct ftrace_hash *hash;
333433dc9b12SSteven Rostedt 	int ret;
3335f45948e8SSteven Rostedt 
3336936e074bSSteven Rostedt 	/* All global ops uses the global ops filters */
3337936e074bSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL)
3338936e074bSSteven Rostedt 		ops = &global_ops;
3339936e074bSSteven Rostedt 
334041c52c0dSSteven Rostedt 	if (unlikely(ftrace_disabled))
334133dc9b12SSteven Rostedt 		return -ENODEV;
334241c52c0dSSteven Rostedt 
3343f45948e8SSteven Rostedt 	if (enable)
334433dc9b12SSteven Rostedt 		orig_hash = &ops->filter_hash;
3345f45948e8SSteven Rostedt 	else
334633dc9b12SSteven Rostedt 		orig_hash = &ops->notrace_hash;
334733dc9b12SSteven Rostedt 
334833dc9b12SSteven Rostedt 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
334933dc9b12SSteven Rostedt 	if (!hash)
335033dc9b12SSteven Rostedt 		return -ENOMEM;
3351f45948e8SSteven Rostedt 
335241c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
335341c52c0dSSteven Rostedt 	if (reset)
33541cf41dd7SSteven Rostedt 		ftrace_filter_reset(hash);
3355ac483c44SJiri Olsa 	if (buf && !ftrace_match_records(hash, buf, len)) {
3356ac483c44SJiri Olsa 		ret = -EINVAL;
3357ac483c44SJiri Olsa 		goto out_regex_unlock;
3358ac483c44SJiri Olsa 	}
3359647664eaSMasami Hiramatsu 	if (ip) {
3360647664eaSMasami Hiramatsu 		ret = ftrace_match_addr(hash, ip, remove);
3361647664eaSMasami Hiramatsu 		if (ret < 0)
3362647664eaSMasami Hiramatsu 			goto out_regex_unlock;
3363647664eaSMasami Hiramatsu 	}
336433dc9b12SSteven Rostedt 
336533dc9b12SSteven Rostedt 	mutex_lock(&ftrace_lock);
336641fb61c2SSteven Rostedt 	ret = ftrace_hash_move(ops, enable, orig_hash, hash);
3367072126f4SSteven Rostedt 	if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED
3368072126f4SSteven Rostedt 	    && ftrace_enabled)
336930fb6aa7SJiri Olsa 		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
3370072126f4SSteven Rostedt 
337133dc9b12SSteven Rostedt 	mutex_unlock(&ftrace_lock);
337233dc9b12SSteven Rostedt 
3373ac483c44SJiri Olsa  out_regex_unlock:
337441c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
337533dc9b12SSteven Rostedt 
337633dc9b12SSteven Rostedt 	free_ftrace_hash(hash);
337733dc9b12SSteven Rostedt 	return ret;
337841c52c0dSSteven Rostedt }
337941c52c0dSSteven Rostedt 
3380647664eaSMasami Hiramatsu static int
3381647664eaSMasami Hiramatsu ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
3382647664eaSMasami Hiramatsu 		int reset, int enable)
3383647664eaSMasami Hiramatsu {
3384647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, 0, 0, ip, remove, reset, enable);
3385647664eaSMasami Hiramatsu }
3386647664eaSMasami Hiramatsu 
3387647664eaSMasami Hiramatsu /**
3388647664eaSMasami Hiramatsu  * ftrace_set_filter_ip - set a function to filter on in ftrace by address
3389647664eaSMasami Hiramatsu  * @ops - the ops to set the filter with
3390647664eaSMasami Hiramatsu  * @ip - the address to add to or remove from the filter.
3391647664eaSMasami Hiramatsu  * @remove - non zero to remove the ip from the filter
3392647664eaSMasami Hiramatsu  * @reset - non zero to reset all filters before applying this filter.
3393647664eaSMasami Hiramatsu  *
3394647664eaSMasami Hiramatsu  * Filters denote which functions should be enabled when tracing is enabled
3395647664eaSMasami Hiramatsu  * If @ip is NULL, it failes to update filter.
3396647664eaSMasami Hiramatsu  */
3397647664eaSMasami Hiramatsu int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
3398647664eaSMasami Hiramatsu 			 int remove, int reset)
3399647664eaSMasami Hiramatsu {
3400647664eaSMasami Hiramatsu 	return ftrace_set_addr(ops, ip, remove, reset, 1);
3401647664eaSMasami Hiramatsu }
3402647664eaSMasami Hiramatsu EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
3403647664eaSMasami Hiramatsu 
3404647664eaSMasami Hiramatsu static int
3405647664eaSMasami Hiramatsu ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
3406647664eaSMasami Hiramatsu 		 int reset, int enable)
3407647664eaSMasami Hiramatsu {
3408647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, buf, len, 0, 0, reset, enable);
3409647664eaSMasami Hiramatsu }
3410647664eaSMasami Hiramatsu 
341177a2b37dSSteven Rostedt /**
341277a2b37dSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3413936e074bSSteven Rostedt  * @ops - the ops to set the filter with
341477a2b37dSSteven Rostedt  * @buf - the string that holds the function filter text.
341577a2b37dSSteven Rostedt  * @len - the length of the string.
341677a2b37dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
341777a2b37dSSteven Rostedt  *
341877a2b37dSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
341977a2b37dSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
342077a2b37dSSteven Rostedt  */
3421ac483c44SJiri Olsa int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
3422936e074bSSteven Rostedt 		       int len, int reset)
342377a2b37dSSteven Rostedt {
3424ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 1);
342541c52c0dSSteven Rostedt }
3426936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_filter);
34274eebcc81SSteven Rostedt 
342841c52c0dSSteven Rostedt /**
342941c52c0dSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3430936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
343141c52c0dSSteven Rostedt  * @buf - the string that holds the function notrace text.
343241c52c0dSSteven Rostedt  * @len - the length of the string.
343341c52c0dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
343441c52c0dSSteven Rostedt  *
343541c52c0dSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
343641c52c0dSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
343741c52c0dSSteven Rostedt  * for tracing.
343841c52c0dSSteven Rostedt  */
3439ac483c44SJiri Olsa int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
3440936e074bSSteven Rostedt 			int len, int reset)
3441936e074bSSteven Rostedt {
3442ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 0);
3443936e074bSSteven Rostedt }
3444936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_notrace);
3445936e074bSSteven Rostedt /**
3446936e074bSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3447936e074bSSteven Rostedt  * @ops - the ops to set the filter with
3448936e074bSSteven Rostedt  * @buf - the string that holds the function filter text.
3449936e074bSSteven Rostedt  * @len - the length of the string.
3450936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3451936e074bSSteven Rostedt  *
3452936e074bSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
3453936e074bSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
3454936e074bSSteven Rostedt  */
3455936e074bSSteven Rostedt void ftrace_set_global_filter(unsigned char *buf, int len, int reset)
3456936e074bSSteven Rostedt {
3457936e074bSSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 1);
3458936e074bSSteven Rostedt }
3459936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_filter);
3460936e074bSSteven Rostedt 
3461936e074bSSteven Rostedt /**
3462936e074bSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3463936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
3464936e074bSSteven Rostedt  * @buf - the string that holds the function notrace text.
3465936e074bSSteven Rostedt  * @len - the length of the string.
3466936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3467936e074bSSteven Rostedt  *
3468936e074bSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
3469936e074bSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
3470936e074bSSteven Rostedt  * for tracing.
3471936e074bSSteven Rostedt  */
3472936e074bSSteven Rostedt void ftrace_set_global_notrace(unsigned char *buf, int len, int reset)
347341c52c0dSSteven Rostedt {
3474f45948e8SSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 0);
347577a2b37dSSteven Rostedt }
3476936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_notrace);
347777a2b37dSSteven Rostedt 
34782af15d6aSSteven Rostedt /*
34792af15d6aSSteven Rostedt  * command line interface to allow users to set filters on boot up.
34802af15d6aSSteven Rostedt  */
34812af15d6aSSteven Rostedt #define FTRACE_FILTER_SIZE		COMMAND_LINE_SIZE
34822af15d6aSSteven Rostedt static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
34832af15d6aSSteven Rostedt static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;
34842af15d6aSSteven Rostedt 
34852af15d6aSSteven Rostedt static int __init set_ftrace_notrace(char *str)
34862af15d6aSSteven Rostedt {
34879607a869SChen Gang 	strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
34882af15d6aSSteven Rostedt 	return 1;
34892af15d6aSSteven Rostedt }
34902af15d6aSSteven Rostedt __setup("ftrace_notrace=", set_ftrace_notrace);
34912af15d6aSSteven Rostedt 
34922af15d6aSSteven Rostedt static int __init set_ftrace_filter(char *str)
34932af15d6aSSteven Rostedt {
34949607a869SChen Gang 	strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
34952af15d6aSSteven Rostedt 	return 1;
34962af15d6aSSteven Rostedt }
34972af15d6aSSteven Rostedt __setup("ftrace_filter=", set_ftrace_filter);
34982af15d6aSSteven Rostedt 
3499369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3500f6060f46SLai Jiangshan static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
3501801c29fdSSteven Rostedt static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
3502801c29fdSSteven Rostedt 
3503369bc18fSStefan Assmann static int __init set_graph_function(char *str)
3504369bc18fSStefan Assmann {
350506f43d66SFrederic Weisbecker 	strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
3506369bc18fSStefan Assmann 	return 1;
3507369bc18fSStefan Assmann }
3508369bc18fSStefan Assmann __setup("ftrace_graph_filter=", set_graph_function);
3509369bc18fSStefan Assmann 
3510369bc18fSStefan Assmann static void __init set_ftrace_early_graph(char *buf)
3511369bc18fSStefan Assmann {
3512369bc18fSStefan Assmann 	int ret;
3513369bc18fSStefan Assmann 	char *func;
3514369bc18fSStefan Assmann 
3515369bc18fSStefan Assmann 	while (buf) {
3516369bc18fSStefan Assmann 		func = strsep(&buf, ",");
3517369bc18fSStefan Assmann 		/* we allow only one expression at a time */
3518369bc18fSStefan Assmann 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3519369bc18fSStefan Assmann 				      func);
3520369bc18fSStefan Assmann 		if (ret)
3521369bc18fSStefan Assmann 			printk(KERN_DEBUG "ftrace: function %s not "
3522369bc18fSStefan Assmann 					  "traceable\n", func);
3523369bc18fSStefan Assmann 	}
3524369bc18fSStefan Assmann }
3525369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3526369bc18fSStefan Assmann 
35272a85a37fSSteven Rostedt void __init
35282a85a37fSSteven Rostedt ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable)
35292af15d6aSSteven Rostedt {
35302af15d6aSSteven Rostedt 	char *func;
35312af15d6aSSteven Rostedt 
35322af15d6aSSteven Rostedt 	while (buf) {
35332af15d6aSSteven Rostedt 		func = strsep(&buf, ",");
3534f45948e8SSteven Rostedt 		ftrace_set_regex(ops, func, strlen(func), 0, enable);
35352af15d6aSSteven Rostedt 	}
35362af15d6aSSteven Rostedt }
35372af15d6aSSteven Rostedt 
35382af15d6aSSteven Rostedt static void __init set_ftrace_early_filters(void)
35392af15d6aSSteven Rostedt {
35402af15d6aSSteven Rostedt 	if (ftrace_filter_buf[0])
35412a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_filter_buf, 1);
35422af15d6aSSteven Rostedt 	if (ftrace_notrace_buf[0])
35432a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_notrace_buf, 0);
3544369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3545369bc18fSStefan Assmann 	if (ftrace_graph_buf[0])
3546369bc18fSStefan Assmann 		set_ftrace_early_graph(ftrace_graph_buf);
3547369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
35482af15d6aSSteven Rostedt }
35492af15d6aSSteven Rostedt 
3550fc13cb0cSSteven Rostedt int ftrace_regex_release(struct inode *inode, struct file *file)
35515072c59fSSteven Rostedt {
35525072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
35535072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
355433dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3555689fd8b6S[email protected] 	struct trace_parser *parser;
3556ed926f9bSSteven Rostedt 	int filter_hash;
355733dc9b12SSteven Rostedt 	int ret;
35585072c59fSSteven Rostedt 
355941c52c0dSSteven Rostedt 	mutex_lock(&ftrace_regex_lock);
35605072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
35615072c59fSSteven Rostedt 		iter = m->private;
35625072c59fSSteven Rostedt 
35635072c59fSSteven Rostedt 		seq_release(inode, file);
35645072c59fSSteven Rostedt 	} else
35655072c59fSSteven Rostedt 		iter = file->private_data;
35665072c59fSSteven Rostedt 
3567689fd8b6S[email protected] 	parser = &iter->parser;
3568689fd8b6S[email protected] 	if (trace_parser_loaded(parser)) {
3569689fd8b6S[email protected] 		parser->buffer[parser->idx] = 0;
35701cf41dd7SSteven Rostedt 		ftrace_match_records(iter->hash, parser->buffer, parser->idx);
35715072c59fSSteven Rostedt 	}
35725072c59fSSteven Rostedt 
3573058e297dSSteven Rostedt 	trace_parser_put(parser);
3574058e297dSSteven Rostedt 
3575058e297dSSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
3576ed926f9bSSteven Rostedt 		filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
3577ed926f9bSSteven Rostedt 
3578ed926f9bSSteven Rostedt 		if (filter_hash)
357933dc9b12SSteven Rostedt 			orig_hash = &iter->ops->filter_hash;
3580ed926f9bSSteven Rostedt 		else
3581ed926f9bSSteven Rostedt 			orig_hash = &iter->ops->notrace_hash;
358233dc9b12SSteven Rostedt 
3583e6ea44e9SSteven Rostedt 		mutex_lock(&ftrace_lock);
358441fb61c2SSteven Rostedt 		ret = ftrace_hash_move(iter->ops, filter_hash,
358541fb61c2SSteven Rostedt 				       orig_hash, iter->hash);
358641fb61c2SSteven Rostedt 		if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED)
3587ed926f9bSSteven Rostedt 		    && ftrace_enabled)
358830fb6aa7SJiri Olsa 			ftrace_run_update_code(FTRACE_UPDATE_CALLS);
358941fb61c2SSteven Rostedt 
3590e6ea44e9SSteven Rostedt 		mutex_unlock(&ftrace_lock);
3591058e297dSSteven Rostedt 	}
359233dc9b12SSteven Rostedt 	free_ftrace_hash(iter->hash);
359333dc9b12SSteven Rostedt 	kfree(iter);
3594689fd8b6S[email protected] 
359541c52c0dSSteven Rostedt 	mutex_unlock(&ftrace_regex_lock);
35965072c59fSSteven Rostedt 	return 0;
35975072c59fSSteven Rostedt }
35985072c59fSSteven Rostedt 
35995e2336a0SSteven Rostedt static const struct file_operations ftrace_avail_fops = {
36005072c59fSSteven Rostedt 	.open = ftrace_avail_open,
36015072c59fSSteven Rostedt 	.read = seq_read,
36025072c59fSSteven Rostedt 	.llseek = seq_lseek,
36033be04b47SLi Zefan 	.release = seq_release_private,
36045072c59fSSteven Rostedt };
36055072c59fSSteven Rostedt 
3606647bcd03SSteven Rostedt static const struct file_operations ftrace_enabled_fops = {
3607647bcd03SSteven Rostedt 	.open = ftrace_enabled_open,
3608647bcd03SSteven Rostedt 	.read = seq_read,
3609647bcd03SSteven Rostedt 	.llseek = seq_lseek,
3610647bcd03SSteven Rostedt 	.release = seq_release_private,
3611647bcd03SSteven Rostedt };
3612647bcd03SSteven Rostedt 
36135e2336a0SSteven Rostedt static const struct file_operations ftrace_filter_fops = {
36145072c59fSSteven Rostedt 	.open = ftrace_filter_open,
3615850a80cfSLai Jiangshan 	.read = seq_read,
36165072c59fSSteven Rostedt 	.write = ftrace_filter_write,
361798c4fd04SSteven Rostedt 	.llseek = ftrace_regex_lseek,
36181cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
36195072c59fSSteven Rostedt };
36205072c59fSSteven Rostedt 
36215e2336a0SSteven Rostedt static const struct file_operations ftrace_notrace_fops = {
362241c52c0dSSteven Rostedt 	.open = ftrace_notrace_open,
3623850a80cfSLai Jiangshan 	.read = seq_read,
362441c52c0dSSteven Rostedt 	.write = ftrace_notrace_write,
362541c52c0dSSteven Rostedt 	.llseek = ftrace_regex_lseek,
36261cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
362741c52c0dSSteven Rostedt };
362841c52c0dSSteven Rostedt 
3629ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3630ea4e2bc4SSteven Rostedt 
3631ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock);
3632ea4e2bc4SSteven Rostedt 
3633ea4e2bc4SSteven Rostedt int ftrace_graph_count;
3634c7c6b1feSLi Zefan int ftrace_graph_filter_enabled;
3635ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
3636ea4e2bc4SSteven Rostedt 
3637ea4e2bc4SSteven Rostedt static void *
363885951842SLi Zefan __g_next(struct seq_file *m, loff_t *pos)
3639ea4e2bc4SSteven Rostedt {
364085951842SLi Zefan 	if (*pos >= ftrace_graph_count)
3641ea4e2bc4SSteven Rostedt 		return NULL;
3642a4ec5e0cSLi Zefan 	return &ftrace_graph_funcs[*pos];
364385951842SLi Zefan }
3644ea4e2bc4SSteven Rostedt 
364585951842SLi Zefan static void *
364685951842SLi Zefan g_next(struct seq_file *m, void *v, loff_t *pos)
364785951842SLi Zefan {
364885951842SLi Zefan 	(*pos)++;
364985951842SLi Zefan 	return __g_next(m, pos);
3650ea4e2bc4SSteven Rostedt }
3651ea4e2bc4SSteven Rostedt 
3652ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos)
3653ea4e2bc4SSteven Rostedt {
3654ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3655ea4e2bc4SSteven Rostedt 
3656f9349a8fSFrederic Weisbecker 	/* Nothing, tell g_show to print all functions are enabled */
3657c7c6b1feSLi Zefan 	if (!ftrace_graph_filter_enabled && !*pos)
3658f9349a8fSFrederic Weisbecker 		return (void *)1;
3659f9349a8fSFrederic Weisbecker 
366085951842SLi Zefan 	return __g_next(m, pos);
3661ea4e2bc4SSteven Rostedt }
3662ea4e2bc4SSteven Rostedt 
3663ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p)
3664ea4e2bc4SSteven Rostedt {
3665ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3666ea4e2bc4SSteven Rostedt }
3667ea4e2bc4SSteven Rostedt 
3668ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v)
3669ea4e2bc4SSteven Rostedt {
3670ea4e2bc4SSteven Rostedt 	unsigned long *ptr = v;
3671ea4e2bc4SSteven Rostedt 
3672ea4e2bc4SSteven Rostedt 	if (!ptr)
3673ea4e2bc4SSteven Rostedt 		return 0;
3674ea4e2bc4SSteven Rostedt 
3675f9349a8fSFrederic Weisbecker 	if (ptr == (unsigned long *)1) {
3676f9349a8fSFrederic Weisbecker 		seq_printf(m, "#### all functions enabled ####\n");
3677f9349a8fSFrederic Weisbecker 		return 0;
3678f9349a8fSFrederic Weisbecker 	}
3679f9349a8fSFrederic Weisbecker 
3680b375a11aSSteven Rostedt 	seq_printf(m, "%ps\n", (void *)*ptr);
3681ea4e2bc4SSteven Rostedt 
3682ea4e2bc4SSteven Rostedt 	return 0;
3683ea4e2bc4SSteven Rostedt }
3684ea4e2bc4SSteven Rostedt 
368588e9d34cSJames Morris static const struct seq_operations ftrace_graph_seq_ops = {
3686ea4e2bc4SSteven Rostedt 	.start = g_start,
3687ea4e2bc4SSteven Rostedt 	.next = g_next,
3688ea4e2bc4SSteven Rostedt 	.stop = g_stop,
3689ea4e2bc4SSteven Rostedt 	.show = g_show,
3690ea4e2bc4SSteven Rostedt };
3691ea4e2bc4SSteven Rostedt 
3692ea4e2bc4SSteven Rostedt static int
3693ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file)
3694ea4e2bc4SSteven Rostedt {
3695ea4e2bc4SSteven Rostedt 	int ret = 0;
3696ea4e2bc4SSteven Rostedt 
3697ea4e2bc4SSteven Rostedt 	if (unlikely(ftrace_disabled))
3698ea4e2bc4SSteven Rostedt 		return -ENODEV;
3699ea4e2bc4SSteven Rostedt 
3700ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3701ea4e2bc4SSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
37028650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC)) {
3703c7c6b1feSLi Zefan 		ftrace_graph_filter_enabled = 0;
3704ea4e2bc4SSteven Rostedt 		ftrace_graph_count = 0;
3705ea4e2bc4SSteven Rostedt 		memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
3706ea4e2bc4SSteven Rostedt 	}
3707ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3708ea4e2bc4SSteven Rostedt 
3709a4ec5e0cSLi Zefan 	if (file->f_mode & FMODE_READ)
3710a4ec5e0cSLi Zefan 		ret = seq_open(file, &ftrace_graph_seq_ops);
3711a4ec5e0cSLi Zefan 
3712ea4e2bc4SSteven Rostedt 	return ret;
3713ea4e2bc4SSteven Rostedt }
3714ea4e2bc4SSteven Rostedt 
3715ea4e2bc4SSteven Rostedt static int
371687827111SLi Zefan ftrace_graph_release(struct inode *inode, struct file *file)
371787827111SLi Zefan {
371887827111SLi Zefan 	if (file->f_mode & FMODE_READ)
371987827111SLi Zefan 		seq_release(inode, file);
372087827111SLi Zefan 	return 0;
372187827111SLi Zefan }
372287827111SLi Zefan 
372387827111SLi Zefan static int
3724f9349a8fSFrederic Weisbecker ftrace_set_func(unsigned long *array, int *idx, char *buffer)
3725ea4e2bc4SSteven Rostedt {
3726ea4e2bc4SSteven Rostedt 	struct dyn_ftrace *rec;
3727ea4e2bc4SSteven Rostedt 	struct ftrace_page *pg;
3728f9349a8fSFrederic Weisbecker 	int search_len;
3729c7c6b1feSLi Zefan 	int fail = 1;
3730f9349a8fSFrederic Weisbecker 	int type, not;
3731f9349a8fSFrederic Weisbecker 	char *search;
3732f9349a8fSFrederic Weisbecker 	bool exists;
3733f9349a8fSFrederic Weisbecker 	int i;
3734ea4e2bc4SSteven Rostedt 
3735f9349a8fSFrederic Weisbecker 	/* decode regex */
37363f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
3737c7c6b1feSLi Zefan 	if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS)
3738c7c6b1feSLi Zefan 		return -EBUSY;
3739f9349a8fSFrederic Weisbecker 
3740f9349a8fSFrederic Weisbecker 	search_len = strlen(search);
3741f9349a8fSFrederic Weisbecker 
374252baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
374345a4a237SSteven Rostedt 
374445a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled)) {
374545a4a237SSteven Rostedt 		mutex_unlock(&ftrace_lock);
374645a4a237SSteven Rostedt 		return -ENODEV;
374745a4a237SSteven Rostedt 	}
374845a4a237SSteven Rostedt 
3749265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
3750ea4e2bc4SSteven Rostedt 
3751b9df92d2SSteven Rostedt 		if (ftrace_match_record(rec, NULL, search, search_len, type)) {
3752c7c6b1feSLi Zefan 			/* if it is in the array */
3753f9349a8fSFrederic Weisbecker 			exists = false;
3754c7c6b1feSLi Zefan 			for (i = 0; i < *idx; i++) {
3755f9349a8fSFrederic Weisbecker 				if (array[i] == rec->ip) {
3756f9349a8fSFrederic Weisbecker 					exists = true;
3757faec2ec5SLiming Wang 					break;
3758faec2ec5SLiming Wang 				}
3759c7c6b1feSLi Zefan 			}
3760c7c6b1feSLi Zefan 
3761c7c6b1feSLi Zefan 			if (!not) {
3762c7c6b1feSLi Zefan 				fail = 0;
3763c7c6b1feSLi Zefan 				if (!exists) {
3764f9349a8fSFrederic Weisbecker 					array[(*idx)++] = rec->ip;
3765c7c6b1feSLi Zefan 					if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
3766c7c6b1feSLi Zefan 						goto out;
3767c7c6b1feSLi Zefan 				}
3768c7c6b1feSLi Zefan 			} else {
3769c7c6b1feSLi Zefan 				if (exists) {
3770c7c6b1feSLi Zefan 					array[i] = array[--(*idx)];
3771c7c6b1feSLi Zefan 					array[*idx] = 0;
3772c7c6b1feSLi Zefan 					fail = 0;
3773c7c6b1feSLi Zefan 				}
3774c7c6b1feSLi Zefan 			}
3775f9349a8fSFrederic Weisbecker 		}
3776265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
3777c7c6b1feSLi Zefan out:
377852baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
3779ea4e2bc4SSteven Rostedt 
3780c7c6b1feSLi Zefan 	if (fail)
3781c7c6b1feSLi Zefan 		return -EINVAL;
3782c7c6b1feSLi Zefan 
37839f50afccSNamhyung Kim 	ftrace_graph_filter_enabled = !!(*idx);
37849f50afccSNamhyung Kim 
3785c7c6b1feSLi Zefan 	return 0;
3786ea4e2bc4SSteven Rostedt }
3787ea4e2bc4SSteven Rostedt 
3788ea4e2bc4SSteven Rostedt static ssize_t
3789ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf,
3790ea4e2bc4SSteven Rostedt 		   size_t cnt, loff_t *ppos)
3791ea4e2bc4SSteven Rostedt {
3792689fd8b6S[email protected] 	struct trace_parser parser;
37934ba7978eSLi Zefan 	ssize_t read, ret;
3794ea4e2bc4SSteven Rostedt 
3795c7c6b1feSLi Zefan 	if (!cnt)
3796ea4e2bc4SSteven Rostedt 		return 0;
3797ea4e2bc4SSteven Rostedt 
3798ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3799ea4e2bc4SSteven Rostedt 
3800689fd8b6S[email protected] 	if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
3801689fd8b6S[email protected] 		ret = -ENOMEM;
38021eb90f13SLi Zefan 		goto out_unlock;
3803ea4e2bc4SSteven Rostedt 	}
3804ea4e2bc4SSteven Rostedt 
3805689fd8b6S[email protected] 	read = trace_get_user(&parser, ubuf, cnt, ppos);
3806689fd8b6S[email protected] 
38074ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded((&parser))) {
3808689fd8b6S[email protected] 		parser.buffer[parser.idx] = 0;
3809ea4e2bc4SSteven Rostedt 
3810f9349a8fSFrederic Weisbecker 		/* we allow only one expression at a time */
3811a4ec5e0cSLi Zefan 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3812689fd8b6S[email protected] 					parser.buffer);
3813ea4e2bc4SSteven Rostedt 		if (ret)
38141eb90f13SLi Zefan 			goto out_free;
3815689fd8b6S[email protected] 	}
3816ea4e2bc4SSteven Rostedt 
3817ea4e2bc4SSteven Rostedt 	ret = read;
38181eb90f13SLi Zefan 
38191eb90f13SLi Zefan out_free:
3820689fd8b6S[email protected] 	trace_parser_put(&parser);
38211eb90f13SLi Zefan out_unlock:
3822ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3823ea4e2bc4SSteven Rostedt 
3824ea4e2bc4SSteven Rostedt 	return ret;
3825ea4e2bc4SSteven Rostedt }
3826ea4e2bc4SSteven Rostedt 
3827ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = {
3828ea4e2bc4SSteven Rostedt 	.open		= ftrace_graph_open,
3829850a80cfSLai Jiangshan 	.read		= seq_read,
3830ea4e2bc4SSteven Rostedt 	.write		= ftrace_graph_write,
383187827111SLi Zefan 	.release	= ftrace_graph_release,
38326038f373SArnd Bergmann 	.llseek		= seq_lseek,
3833ea4e2bc4SSteven Rostedt };
3834ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3835ea4e2bc4SSteven Rostedt 
3836df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
38375072c59fSSteven Rostedt {
38385072c59fSSteven Rostedt 
38395452af66SFrederic Weisbecker 	trace_create_file("available_filter_functions", 0444,
38405072c59fSSteven Rostedt 			d_tracer, NULL, &ftrace_avail_fops);
38415072c59fSSteven Rostedt 
3842647bcd03SSteven Rostedt 	trace_create_file("enabled_functions", 0444,
3843647bcd03SSteven Rostedt 			d_tracer, NULL, &ftrace_enabled_fops);
3844647bcd03SSteven Rostedt 
38455452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_filter", 0644, d_tracer,
38465072c59fSSteven Rostedt 			NULL, &ftrace_filter_fops);
384741c52c0dSSteven Rostedt 
38485452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_notrace", 0644, d_tracer,
384941c52c0dSSteven Rostedt 				    NULL, &ftrace_notrace_fops);
3850ad90c0e3SSteven Rostedt 
3851ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
38525452af66SFrederic Weisbecker 	trace_create_file("set_graph_function", 0444, d_tracer,
3853ea4e2bc4SSteven Rostedt 				    NULL,
3854ea4e2bc4SSteven Rostedt 				    &ftrace_graph_fops);
3855ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3856ea4e2bc4SSteven Rostedt 
38575072c59fSSteven Rostedt 	return 0;
38585072c59fSSteven Rostedt }
38595072c59fSSteven Rostedt 
38609fd49328SSteven Rostedt static int ftrace_cmp_ips(const void *a, const void *b)
386168950619SSteven Rostedt {
38629fd49328SSteven Rostedt 	const unsigned long *ipa = a;
38639fd49328SSteven Rostedt 	const unsigned long *ipb = b;
386468950619SSteven Rostedt 
38659fd49328SSteven Rostedt 	if (*ipa > *ipb)
38669fd49328SSteven Rostedt 		return 1;
38679fd49328SSteven Rostedt 	if (*ipa < *ipb)
38689fd49328SSteven Rostedt 		return -1;
38699fd49328SSteven Rostedt 	return 0;
38709fd49328SSteven Rostedt }
38719fd49328SSteven Rostedt 
38729fd49328SSteven Rostedt static void ftrace_swap_ips(void *a, void *b, int size)
38739fd49328SSteven Rostedt {
38749fd49328SSteven Rostedt 	unsigned long *ipa = a;
38759fd49328SSteven Rostedt 	unsigned long *ipb = b;
38769fd49328SSteven Rostedt 	unsigned long t;
38779fd49328SSteven Rostedt 
38789fd49328SSteven Rostedt 	t = *ipa;
38799fd49328SSteven Rostedt 	*ipa = *ipb;
38809fd49328SSteven Rostedt 	*ipb = t;
388168950619SSteven Rostedt }
388268950619SSteven Rostedt 
38835cb084bbSJiri Olsa static int ftrace_process_locs(struct module *mod,
388431e88909SSteven Rostedt 			       unsigned long *start,
388568bf21aaSSteven Rostedt 			       unsigned long *end)
388668bf21aaSSteven Rostedt {
3887706c81f8SSteven Rostedt 	struct ftrace_page *start_pg;
3888a7900875SSteven Rostedt 	struct ftrace_page *pg;
3889706c81f8SSteven Rostedt 	struct dyn_ftrace *rec;
3890a7900875SSteven Rostedt 	unsigned long count;
389168bf21aaSSteven Rostedt 	unsigned long *p;
389268bf21aaSSteven Rostedt 	unsigned long addr;
38934376cac6SSteven Rostedt 	unsigned long flags = 0; /* Shut up gcc */
3894a7900875SSteven Rostedt 	int ret = -ENOMEM;
3895a7900875SSteven Rostedt 
3896a7900875SSteven Rostedt 	count = end - start;
3897a7900875SSteven Rostedt 
3898a7900875SSteven Rostedt 	if (!count)
3899a7900875SSteven Rostedt 		return 0;
3900a7900875SSteven Rostedt 
39019fd49328SSteven Rostedt 	sort(start, count, sizeof(*start),
39029fd49328SSteven Rostedt 	     ftrace_cmp_ips, ftrace_swap_ips);
39039fd49328SSteven Rostedt 
3904706c81f8SSteven Rostedt 	start_pg = ftrace_allocate_pages(count);
3905706c81f8SSteven Rostedt 	if (!start_pg)
3906a7900875SSteven Rostedt 		return -ENOMEM;
390768bf21aaSSteven Rostedt 
3908e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
3909a7900875SSteven Rostedt 
391032082309SSteven Rostedt 	/*
391132082309SSteven Rostedt 	 * Core and each module needs their own pages, as
391232082309SSteven Rostedt 	 * modules will free them when they are removed.
391332082309SSteven Rostedt 	 * Force a new page to be allocated for modules.
391432082309SSteven Rostedt 	 */
3915a7900875SSteven Rostedt 	if (!mod) {
3916a7900875SSteven Rostedt 		WARN_ON(ftrace_pages || ftrace_pages_start);
3917a7900875SSteven Rostedt 		/* First initialization */
3918706c81f8SSteven Rostedt 		ftrace_pages = ftrace_pages_start = start_pg;
3919a7900875SSteven Rostedt 	} else {
392032082309SSteven Rostedt 		if (!ftrace_pages)
3921a7900875SSteven Rostedt 			goto out;
392232082309SSteven Rostedt 
3923a7900875SSteven Rostedt 		if (WARN_ON(ftrace_pages->next)) {
3924a7900875SSteven Rostedt 			/* Hmm, we have free pages? */
3925a7900875SSteven Rostedt 			while (ftrace_pages->next)
392632082309SSteven Rostedt 				ftrace_pages = ftrace_pages->next;
392732082309SSteven Rostedt 		}
3928a7900875SSteven Rostedt 
3929706c81f8SSteven Rostedt 		ftrace_pages->next = start_pg;
393032082309SSteven Rostedt 	}
393132082309SSteven Rostedt 
393268bf21aaSSteven Rostedt 	p = start;
3933706c81f8SSteven Rostedt 	pg = start_pg;
393468bf21aaSSteven Rostedt 	while (p < end) {
393568bf21aaSSteven Rostedt 		addr = ftrace_call_adjust(*p++);
393620e5227eSSteven Rostedt 		/*
393720e5227eSSteven Rostedt 		 * Some architecture linkers will pad between
393820e5227eSSteven Rostedt 		 * the different mcount_loc sections of different
393920e5227eSSteven Rostedt 		 * object files to satisfy alignments.
394020e5227eSSteven Rostedt 		 * Skip any NULL pointers.
394120e5227eSSteven Rostedt 		 */
394220e5227eSSteven Rostedt 		if (!addr)
394320e5227eSSteven Rostedt 			continue;
3944706c81f8SSteven Rostedt 
3945706c81f8SSteven Rostedt 		if (pg->index == pg->size) {
3946706c81f8SSteven Rostedt 			/* We should have allocated enough */
3947706c81f8SSteven Rostedt 			if (WARN_ON(!pg->next))
3948a7900875SSteven Rostedt 				break;
3949706c81f8SSteven Rostedt 			pg = pg->next;
395068bf21aaSSteven Rostedt 		}
395168bf21aaSSteven Rostedt 
3952706c81f8SSteven Rostedt 		rec = &pg->records[pg->index++];
3953706c81f8SSteven Rostedt 		rec->ip = addr;
3954706c81f8SSteven Rostedt 	}
3955706c81f8SSteven Rostedt 
3956706c81f8SSteven Rostedt 	/* We should have used all pages */
3957706c81f8SSteven Rostedt 	WARN_ON(pg->next);
3958706c81f8SSteven Rostedt 
3959706c81f8SSteven Rostedt 	/* Assign the last page to ftrace_pages */
3960706c81f8SSteven Rostedt 	ftrace_pages = pg;
3961706c81f8SSteven Rostedt 
396285ae32aeSSteven Rostedt 	/* These new locations need to be initialized */
3963706c81f8SSteven Rostedt 	ftrace_new_pgs = start_pg;
396485ae32aeSSteven Rostedt 
3965a4f18ed1SSteven Rostedt 	/*
39664376cac6SSteven Rostedt 	 * We only need to disable interrupts on start up
39674376cac6SSteven Rostedt 	 * because we are modifying code that an interrupt
39684376cac6SSteven Rostedt 	 * may execute, and the modification is not atomic.
39694376cac6SSteven Rostedt 	 * But for modules, nothing runs the code we modify
39704376cac6SSteven Rostedt 	 * until we are finished with it, and there's no
39714376cac6SSteven Rostedt 	 * reason to cause large interrupt latencies while we do it.
3972a4f18ed1SSteven Rostedt 	 */
39734376cac6SSteven Rostedt 	if (!mod)
3974a4f18ed1SSteven Rostedt 		local_irq_save(flags);
397531e88909SSteven Rostedt 	ftrace_update_code(mod);
39764376cac6SSteven Rostedt 	if (!mod)
3977a4f18ed1SSteven Rostedt 		local_irq_restore(flags);
3978a7900875SSteven Rostedt 	ret = 0;
3979a7900875SSteven Rostedt  out:
3980e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
398168bf21aaSSteven Rostedt 
3982a7900875SSteven Rostedt 	return ret;
398368bf21aaSSteven Rostedt }
398468bf21aaSSteven Rostedt 
398593eb677dSSteven Rostedt #ifdef CONFIG_MODULES
398632082309SSteven Rostedt 
398732082309SSteven Rostedt #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)
398832082309SSteven Rostedt 
3989e7247a15S[email protected] void ftrace_release_mod(struct module *mod)
399093eb677dSSteven Rostedt {
399193eb677dSSteven Rostedt 	struct dyn_ftrace *rec;
399232082309SSteven Rostedt 	struct ftrace_page **last_pg;
399393eb677dSSteven Rostedt 	struct ftrace_page *pg;
3994a7900875SSteven Rostedt 	int order;
399593eb677dSSteven Rostedt 
399693eb677dSSteven Rostedt 	mutex_lock(&ftrace_lock);
399745a4a237SSteven Rostedt 
399845a4a237SSteven Rostedt 	if (ftrace_disabled)
399945a4a237SSteven Rostedt 		goto out_unlock;
400045a4a237SSteven Rostedt 
400132082309SSteven Rostedt 	/*
400232082309SSteven Rostedt 	 * Each module has its own ftrace_pages, remove
400332082309SSteven Rostedt 	 * them from the list.
400432082309SSteven Rostedt 	 */
400532082309SSteven Rostedt 	last_pg = &ftrace_pages_start;
400632082309SSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = *last_pg) {
400732082309SSteven Rostedt 		rec = &pg->records[0];
4008e7247a15S[email protected] 		if (within_module_core(rec->ip, mod)) {
400993eb677dSSteven Rostedt 			/*
401032082309SSteven Rostedt 			 * As core pages are first, the first
401132082309SSteven Rostedt 			 * page should never be a module page.
401293eb677dSSteven Rostedt 			 */
401332082309SSteven Rostedt 			if (WARN_ON(pg == ftrace_pages_start))
401432082309SSteven Rostedt 				goto out_unlock;
401532082309SSteven Rostedt 
401632082309SSteven Rostedt 			/* Check if we are deleting the last page */
401732082309SSteven Rostedt 			if (pg == ftrace_pages)
401832082309SSteven Rostedt 				ftrace_pages = next_to_ftrace_page(last_pg);
401932082309SSteven Rostedt 
402032082309SSteven Rostedt 			*last_pg = pg->next;
4021a7900875SSteven Rostedt 			order = get_count_order(pg->size / ENTRIES_PER_PAGE);
4022a7900875SSteven Rostedt 			free_pages((unsigned long)pg->records, order);
4023a7900875SSteven Rostedt 			kfree(pg);
402432082309SSteven Rostedt 		} else
402532082309SSteven Rostedt 			last_pg = &pg->next;
402693eb677dSSteven Rostedt 	}
402745a4a237SSteven Rostedt  out_unlock:
402893eb677dSSteven Rostedt 	mutex_unlock(&ftrace_lock);
402993eb677dSSteven Rostedt }
403093eb677dSSteven Rostedt 
403193eb677dSSteven Rostedt static void ftrace_init_module(struct module *mod,
403231e88909SSteven Rostedt 			       unsigned long *start, unsigned long *end)
403390d595feSSteven Rostedt {
403400fd61aeSSteven Rostedt 	if (ftrace_disabled || start == end)
4035fed1939cSSteven Rostedt 		return;
40365cb084bbSJiri Olsa 	ftrace_process_locs(mod, start, end);
403790d595feSSteven Rostedt }
403890d595feSSteven Rostedt 
40398c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
404093eb677dSSteven Rostedt 				      unsigned long val, void *data)
404193eb677dSSteven Rostedt {
404293eb677dSSteven Rostedt 	struct module *mod = data;
404393eb677dSSteven Rostedt 
40448c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_COMING)
404593eb677dSSteven Rostedt 		ftrace_init_module(mod, mod->ftrace_callsites,
404693eb677dSSteven Rostedt 				   mod->ftrace_callsites +
404793eb677dSSteven Rostedt 				   mod->num_ftrace_callsites);
40488c189ea6SSteven Rostedt (Red Hat) 	return 0;
404993eb677dSSteven Rostedt }
405093eb677dSSteven Rostedt 
40518c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
40528c189ea6SSteven Rostedt (Red Hat) 				     unsigned long val, void *data)
40538c189ea6SSteven Rostedt (Red Hat) {
40548c189ea6SSteven Rostedt (Red Hat) 	struct module *mod = data;
40558c189ea6SSteven Rostedt (Red Hat) 
40568c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_GOING)
40578c189ea6SSteven Rostedt (Red Hat) 		ftrace_release_mod(mod);
40588c189ea6SSteven Rostedt (Red Hat) 
405993eb677dSSteven Rostedt 	return 0;
406093eb677dSSteven Rostedt }
406193eb677dSSteven Rostedt #else
40628c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
40638c189ea6SSteven Rostedt (Red Hat) 				      unsigned long val, void *data)
40648c189ea6SSteven Rostedt (Red Hat) {
40658c189ea6SSteven Rostedt (Red Hat) 	return 0;
40668c189ea6SSteven Rostedt (Red Hat) }
40678c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
406893eb677dSSteven Rostedt 				     unsigned long val, void *data)
406993eb677dSSteven Rostedt {
407093eb677dSSteven Rostedt 	return 0;
407193eb677dSSteven Rostedt }
407293eb677dSSteven Rostedt #endif /* CONFIG_MODULES */
407393eb677dSSteven Rostedt 
40748c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_enter_nb = {
40758c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_enter,
4076c1bf08acSSteven Rostedt 	.priority = INT_MAX,	/* Run before anything that can use kprobes */
407793eb677dSSteven Rostedt };
407893eb677dSSteven Rostedt 
40798c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_exit_nb = {
40808c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_exit,
40818c189ea6SSteven Rostedt (Red Hat) 	.priority = INT_MIN,	/* Run after anything that can remove kprobes */
40828c189ea6SSteven Rostedt (Red Hat) };
40838c189ea6SSteven Rostedt (Red Hat) 
408468bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[];
408568bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[];
408668bf21aaSSteven Rostedt 
408768bf21aaSSteven Rostedt void __init ftrace_init(void)
408868bf21aaSSteven Rostedt {
408968bf21aaSSteven Rostedt 	unsigned long count, addr, flags;
409068bf21aaSSteven Rostedt 	int ret;
409168bf21aaSSteven Rostedt 
409268bf21aaSSteven Rostedt 	/* Keep the ftrace pointer to the stub */
409368bf21aaSSteven Rostedt 	addr = (unsigned long)ftrace_stub;
409468bf21aaSSteven Rostedt 
409568bf21aaSSteven Rostedt 	local_irq_save(flags);
409668bf21aaSSteven Rostedt 	ftrace_dyn_arch_init(&addr);
409768bf21aaSSteven Rostedt 	local_irq_restore(flags);
409868bf21aaSSteven Rostedt 
409968bf21aaSSteven Rostedt 	/* ftrace_dyn_arch_init places the return code in addr */
410068bf21aaSSteven Rostedt 	if (addr)
410168bf21aaSSteven Rostedt 		goto failed;
410268bf21aaSSteven Rostedt 
410368bf21aaSSteven Rostedt 	count = __stop_mcount_loc - __start_mcount_loc;
410468bf21aaSSteven Rostedt 
410568bf21aaSSteven Rostedt 	ret = ftrace_dyn_table_alloc(count);
410668bf21aaSSteven Rostedt 	if (ret)
410768bf21aaSSteven Rostedt 		goto failed;
410868bf21aaSSteven Rostedt 
410968bf21aaSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled = 1;
411068bf21aaSSteven Rostedt 
41115cb084bbSJiri Olsa 	ret = ftrace_process_locs(NULL,
411231e88909SSteven Rostedt 				  __start_mcount_loc,
411368bf21aaSSteven Rostedt 				  __stop_mcount_loc);
411468bf21aaSSteven Rostedt 
41158c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_enter_nb);
411624ed0c4bSMing Lei 	if (ret)
41178c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module enter notifier\n");
41188c189ea6SSteven Rostedt (Red Hat) 
41198c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_exit_nb);
41208c189ea6SSteven Rostedt (Red Hat) 	if (ret)
41218c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module exit notifier\n");
412293eb677dSSteven Rostedt 
41232af15d6aSSteven Rostedt 	set_ftrace_early_filters();
41242af15d6aSSteven Rostedt 
412568bf21aaSSteven Rostedt 	return;
412668bf21aaSSteven Rostedt  failed:
412768bf21aaSSteven Rostedt 	ftrace_disabled = 1;
412868bf21aaSSteven Rostedt }
412968bf21aaSSteven Rostedt 
41303d083395SSteven Rostedt #else
41310b6e4d56SFrederic Weisbecker 
41322b499381SSteven Rostedt static struct ftrace_ops global_ops = {
4133bd69c30bSSteven Rostedt 	.func			= ftrace_stub,
41344740974aSSteven Rostedt 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE,
4135bd69c30bSSteven Rostedt };
4136bd69c30bSSteven Rostedt 
41370b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void)
41380b6e4d56SFrederic Weisbecker {
41390b6e4d56SFrederic Weisbecker 	ftrace_enabled = 1;
41400b6e4d56SFrederic Weisbecker 	return 0;
41410b6e4d56SFrederic Weisbecker }
41426f415672SSteven Rostedt core_initcall(ftrace_nodyn_init);
41430b6e4d56SFrederic Weisbecker 
4144df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
4145df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { }
41465a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */
41473b6cfdb1SSteven Rostedt # define ftrace_startup(ops, command)			\
41483b6cfdb1SSteven Rostedt 	({						\
41493b6cfdb1SSteven Rostedt 		(ops)->flags |= FTRACE_OPS_FL_ENABLED;	\
41503b6cfdb1SSteven Rostedt 		0;					\
41513b6cfdb1SSteven Rostedt 	})
4152bd69c30bSSteven Rostedt # define ftrace_shutdown(ops, command)	do { } while (0)
4153b0fc494fSSteven Rostedt # define ftrace_startup_sysctl()	do { } while (0)
4154b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl()	do { } while (0)
4155b848914cSSteven Rostedt 
4156b848914cSSteven Rostedt static inline int
4157b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
4158b848914cSSteven Rostedt {
4159b848914cSSteven Rostedt 	return 1;
4160b848914cSSteven Rostedt }
4161b848914cSSteven Rostedt 
41623d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */
41633d083395SSteven Rostedt 
4164b848914cSSteven Rostedt static void
41652f5f6ad9SSteven Rostedt ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
4166a1e2e31dSSteven Rostedt 			struct ftrace_ops *op, struct pt_regs *regs)
4167e248491aSJiri Olsa {
4168e248491aSJiri Olsa 	if (unlikely(trace_recursion_test(TRACE_CONTROL_BIT)))
4169e248491aSJiri Olsa 		return;
4170e248491aSJiri Olsa 
4171e248491aSJiri Olsa 	/*
4172e248491aSJiri Olsa 	 * Some of the ops may be dynamically allocated,
4173e248491aSJiri Olsa 	 * they must be freed after a synchronize_sched().
4174e248491aSJiri Olsa 	 */
4175e248491aSJiri Olsa 	preempt_disable_notrace();
4176e248491aSJiri Olsa 	trace_recursion_set(TRACE_CONTROL_BIT);
41770a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_control_list) {
4178e248491aSJiri Olsa 		if (!ftrace_function_local_disabled(op) &&
4179e248491aSJiri Olsa 		    ftrace_ops_test(op, ip))
4180a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
41810a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4182e248491aSJiri Olsa 	trace_recursion_clear(TRACE_CONTROL_BIT);
4183e248491aSJiri Olsa 	preempt_enable_notrace();
4184e248491aSJiri Olsa }
4185e248491aSJiri Olsa 
4186e248491aSJiri Olsa static struct ftrace_ops control_ops = {
4187e248491aSJiri Olsa 	.func = ftrace_ops_control_func,
41884740974aSSteven Rostedt 	.flags = FTRACE_OPS_FL_RECURSION_SAFE,
4189e248491aSJiri Olsa };
4190e248491aSJiri Olsa 
41912f5f6ad9SSteven Rostedt static inline void
41922f5f6ad9SSteven Rostedt __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4193a1e2e31dSSteven Rostedt 		       struct ftrace_ops *ignored, struct pt_regs *regs)
4194b848914cSSteven Rostedt {
4195cdbe61bfSSteven Rostedt 	struct ftrace_ops *op;
4196edc15cafSSteven Rostedt 	int bit;
4197b848914cSSteven Rostedt 
4198ccf3672dSSteven Rostedt 	if (function_trace_stop)
4199ccf3672dSSteven Rostedt 		return;
4200ccf3672dSSteven Rostedt 
4201edc15cafSSteven Rostedt 	bit = trace_test_and_set_recursion(TRACE_LIST_START, TRACE_LIST_MAX);
4202edc15cafSSteven Rostedt 	if (bit < 0)
4203b1cff0adSSteven Rostedt 		return;
4204b1cff0adSSteven Rostedt 
4205cdbe61bfSSteven Rostedt 	/*
4206cdbe61bfSSteven Rostedt 	 * Some of the ops may be dynamically allocated,
4207cdbe61bfSSteven Rostedt 	 * they must be freed after a synchronize_sched().
4208cdbe61bfSSteven Rostedt 	 */
4209cdbe61bfSSteven Rostedt 	preempt_disable_notrace();
42100a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_ops_list) {
4211b848914cSSteven Rostedt 		if (ftrace_ops_test(op, ip))
4212a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
42130a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4214cdbe61bfSSteven Rostedt 	preempt_enable_notrace();
4215edc15cafSSteven Rostedt 	trace_clear_recursion(bit);
4216b848914cSSteven Rostedt }
4217b848914cSSteven Rostedt 
42182f5f6ad9SSteven Rostedt /*
42192f5f6ad9SSteven Rostedt  * Some archs only support passing ip and parent_ip. Even though
42202f5f6ad9SSteven Rostedt  * the list function ignores the op parameter, we do not want any
42212f5f6ad9SSteven Rostedt  * C side effects, where a function is called without the caller
42222f5f6ad9SSteven Rostedt  * sending a third parameter.
4223a1e2e31dSSteven Rostedt  * Archs are to support both the regs and ftrace_ops at the same time.
4224a1e2e31dSSteven Rostedt  * If they support ftrace_ops, it is assumed they support regs.
4225a1e2e31dSSteven Rostedt  * If call backs want to use regs, they must either check for regs
422606aeaaeaSMasami Hiramatsu  * being NULL, or CONFIG_DYNAMIC_FTRACE_WITH_REGS.
422706aeaaeaSMasami Hiramatsu  * Note, CONFIG_DYNAMIC_FTRACE_WITH_REGS expects a full regs to be saved.
4228a1e2e31dSSteven Rostedt  * An architecture can pass partial regs with ftrace_ops and still
4229a1e2e31dSSteven Rostedt  * set the ARCH_SUPPORT_FTARCE_OPS.
42302f5f6ad9SSteven Rostedt  */
42312f5f6ad9SSteven Rostedt #if ARCH_SUPPORTS_FTRACE_OPS
42322f5f6ad9SSteven Rostedt static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4233a1e2e31dSSteven Rostedt 				 struct ftrace_ops *op, struct pt_regs *regs)
42342f5f6ad9SSteven Rostedt {
4235a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, regs);
42362f5f6ad9SSteven Rostedt }
42372f5f6ad9SSteven Rostedt #else
42382f5f6ad9SSteven Rostedt static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip)
42392f5f6ad9SSteven Rostedt {
4240a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, NULL);
42412f5f6ad9SSteven Rostedt }
42422f5f6ad9SSteven Rostedt #endif
42432f5f6ad9SSteven Rostedt 
4244e32d8956SSteven Rostedt static void clear_ftrace_swapper(void)
4245e32d8956SSteven Rostedt {
4246e32d8956SSteven Rostedt 	struct task_struct *p;
4247e32d8956SSteven Rostedt 	int cpu;
4248e32d8956SSteven Rostedt 
4249e32d8956SSteven Rostedt 	get_online_cpus();
4250e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4251e32d8956SSteven Rostedt 		p = idle_task(cpu);
4252e32d8956SSteven Rostedt 		clear_tsk_trace_trace(p);
4253e32d8956SSteven Rostedt 	}
4254e32d8956SSteven Rostedt 	put_online_cpus();
4255e32d8956SSteven Rostedt }
4256e32d8956SSteven Rostedt 
4257e32d8956SSteven Rostedt static void set_ftrace_swapper(void)
4258e32d8956SSteven Rostedt {
4259e32d8956SSteven Rostedt 	struct task_struct *p;
4260e32d8956SSteven Rostedt 	int cpu;
4261e32d8956SSteven Rostedt 
4262e32d8956SSteven Rostedt 	get_online_cpus();
4263e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4264e32d8956SSteven Rostedt 		p = idle_task(cpu);
4265e32d8956SSteven Rostedt 		set_tsk_trace_trace(p);
4266e32d8956SSteven Rostedt 	}
4267e32d8956SSteven Rostedt 	put_online_cpus();
4268e32d8956SSteven Rostedt }
4269e32d8956SSteven Rostedt 
4270e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid)
4271978f3a45SSteven Rostedt {
4272978f3a45SSteven Rostedt 	struct task_struct *p;
4273978f3a45SSteven Rostedt 
4274229c4ef8SOleg Nesterov 	rcu_read_lock();
4275e32d8956SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4276978f3a45SSteven Rostedt 		clear_tsk_trace_trace(p);
4277e32d8956SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4278229c4ef8SOleg Nesterov 	rcu_read_unlock();
4279229c4ef8SOleg Nesterov 
4280e32d8956SSteven Rostedt 	put_pid(pid);
4281978f3a45SSteven Rostedt }
4282978f3a45SSteven Rostedt 
4283e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid)
4284978f3a45SSteven Rostedt {
4285978f3a45SSteven Rostedt 	struct task_struct *p;
4286978f3a45SSteven Rostedt 
4287229c4ef8SOleg Nesterov 	rcu_read_lock();
4288978f3a45SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4289978f3a45SSteven Rostedt 		set_tsk_trace_trace(p);
4290978f3a45SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4291229c4ef8SOleg Nesterov 	rcu_read_unlock();
4292978f3a45SSteven Rostedt }
4293978f3a45SSteven Rostedt 
4294756d17eeS[email protected] static void clear_ftrace_pid_task(struct pid *pid)
4295e32d8956SSteven Rostedt {
4296756d17eeS[email protected] 	if (pid == ftrace_swapper_pid)
4297e32d8956SSteven Rostedt 		clear_ftrace_swapper();
4298e32d8956SSteven Rostedt 	else
4299756d17eeS[email protected] 		clear_ftrace_pid(pid);
4300e32d8956SSteven Rostedt }
4301e32d8956SSteven Rostedt 
4302e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid)
4303e32d8956SSteven Rostedt {
4304e32d8956SSteven Rostedt 	if (pid == ftrace_swapper_pid)
4305e32d8956SSteven Rostedt 		set_ftrace_swapper();
4306e32d8956SSteven Rostedt 	else
4307e32d8956SSteven Rostedt 		set_ftrace_pid(pid);
4308e32d8956SSteven Rostedt }
4309e32d8956SSteven Rostedt 
4310756d17eeS[email protected] static int ftrace_pid_add(int p)
4311756d17eeS[email protected] {
4312756d17eeS[email protected] 	struct pid *pid;
4313756d17eeS[email protected] 	struct ftrace_pid *fpid;
4314756d17eeS[email protected] 	int ret = -EINVAL;
4315756d17eeS[email protected] 
4316756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4317756d17eeS[email protected] 
4318756d17eeS[email protected] 	if (!p)
4319756d17eeS[email protected] 		pid = ftrace_swapper_pid;
4320756d17eeS[email protected] 	else
4321756d17eeS[email protected] 		pid = find_get_pid(p);
4322756d17eeS[email protected] 
4323756d17eeS[email protected] 	if (!pid)
4324756d17eeS[email protected] 		goto out;
4325756d17eeS[email protected] 
4326756d17eeS[email protected] 	ret = 0;
4327756d17eeS[email protected] 
4328756d17eeS[email protected] 	list_for_each_entry(fpid, &ftrace_pids, list)
4329756d17eeS[email protected] 		if (fpid->pid == pid)
4330756d17eeS[email protected] 			goto out_put;
4331756d17eeS[email protected] 
4332756d17eeS[email protected] 	ret = -ENOMEM;
4333756d17eeS[email protected] 
4334756d17eeS[email protected] 	fpid = kmalloc(sizeof(*fpid), GFP_KERNEL);
4335756d17eeS[email protected] 	if (!fpid)
4336756d17eeS[email protected] 		goto out_put;
4337756d17eeS[email protected] 
4338756d17eeS[email protected] 	list_add(&fpid->list, &ftrace_pids);
4339756d17eeS[email protected] 	fpid->pid = pid;
4340756d17eeS[email protected] 
4341756d17eeS[email protected] 	set_ftrace_pid_task(pid);
4342756d17eeS[email protected] 
4343756d17eeS[email protected] 	ftrace_update_pid_func();
4344756d17eeS[email protected] 	ftrace_startup_enable(0);
4345756d17eeS[email protected] 
4346756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4347756d17eeS[email protected] 	return 0;
4348756d17eeS[email protected] 
4349756d17eeS[email protected] out_put:
4350756d17eeS[email protected] 	if (pid != ftrace_swapper_pid)
4351756d17eeS[email protected] 		put_pid(pid);
4352756d17eeS[email protected] 
4353756d17eeS[email protected] out:
4354756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4355756d17eeS[email protected] 	return ret;
4356756d17eeS[email protected] }
4357756d17eeS[email protected] 
4358756d17eeS[email protected] static void ftrace_pid_reset(void)
4359756d17eeS[email protected] {
4360756d17eeS[email protected] 	struct ftrace_pid *fpid, *safe;
4361756d17eeS[email protected] 
4362756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4363756d17eeS[email protected] 	list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) {
4364756d17eeS[email protected] 		struct pid *pid = fpid->pid;
4365756d17eeS[email protected] 
4366756d17eeS[email protected] 		clear_ftrace_pid_task(pid);
4367756d17eeS[email protected] 
4368756d17eeS[email protected] 		list_del(&fpid->list);
4369756d17eeS[email protected] 		kfree(fpid);
4370756d17eeS[email protected] 	}
4371756d17eeS[email protected] 
4372756d17eeS[email protected] 	ftrace_update_pid_func();
4373756d17eeS[email protected] 	ftrace_startup_enable(0);
4374756d17eeS[email protected] 
4375756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4376756d17eeS[email protected] }
4377756d17eeS[email protected] 
4378756d17eeS[email protected] static void *fpid_start(struct seq_file *m, loff_t *pos)
4379756d17eeS[email protected] {
4380756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4381756d17eeS[email protected] 
4382756d17eeS[email protected] 	if (list_empty(&ftrace_pids) && (!*pos))
4383756d17eeS[email protected] 		return (void *) 1;
4384756d17eeS[email protected] 
4385756d17eeS[email protected] 	return seq_list_start(&ftrace_pids, *pos);
4386756d17eeS[email protected] }
4387756d17eeS[email protected] 
4388756d17eeS[email protected] static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
4389756d17eeS[email protected] {
4390756d17eeS[email protected] 	if (v == (void *)1)
4391756d17eeS[email protected] 		return NULL;
4392756d17eeS[email protected] 
4393756d17eeS[email protected] 	return seq_list_next(v, &ftrace_pids, pos);
4394756d17eeS[email protected] }
4395756d17eeS[email protected] 
4396756d17eeS[email protected] static void fpid_stop(struct seq_file *m, void *p)
4397756d17eeS[email protected] {
4398756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4399756d17eeS[email protected] }
4400756d17eeS[email protected] 
4401756d17eeS[email protected] static int fpid_show(struct seq_file *m, void *v)
4402756d17eeS[email protected] {
4403756d17eeS[email protected] 	const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list);
4404756d17eeS[email protected] 
4405756d17eeS[email protected] 	if (v == (void *)1) {
4406756d17eeS[email protected] 		seq_printf(m, "no pid\n");
4407756d17eeS[email protected] 		return 0;
4408756d17eeS[email protected] 	}
4409756d17eeS[email protected] 
4410756d17eeS[email protected] 	if (fpid->pid == ftrace_swapper_pid)
4411756d17eeS[email protected] 		seq_printf(m, "swapper tasks\n");
4412756d17eeS[email protected] 	else
4413756d17eeS[email protected] 		seq_printf(m, "%u\n", pid_vnr(fpid->pid));
4414756d17eeS[email protected] 
4415756d17eeS[email protected] 	return 0;
4416756d17eeS[email protected] }
4417756d17eeS[email protected] 
4418756d17eeS[email protected] static const struct seq_operations ftrace_pid_sops = {
4419756d17eeS[email protected] 	.start = fpid_start,
4420756d17eeS[email protected] 	.next = fpid_next,
4421756d17eeS[email protected] 	.stop = fpid_stop,
4422756d17eeS[email protected] 	.show = fpid_show,
4423756d17eeS[email protected] };
4424756d17eeS[email protected] 
4425756d17eeS[email protected] static int
4426756d17eeS[email protected] ftrace_pid_open(struct inode *inode, struct file *file)
4427756d17eeS[email protected] {
4428756d17eeS[email protected] 	int ret = 0;
4429756d17eeS[email protected] 
4430756d17eeS[email protected] 	if ((file->f_mode & FMODE_WRITE) &&
4431756d17eeS[email protected] 	    (file->f_flags & O_TRUNC))
4432756d17eeS[email protected] 		ftrace_pid_reset();
4433756d17eeS[email protected] 
4434756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4435756d17eeS[email protected] 		ret = seq_open(file, &ftrace_pid_sops);
4436756d17eeS[email protected] 
4437756d17eeS[email protected] 	return ret;
4438756d17eeS[email protected] }
4439756d17eeS[email protected] 
4440df4fc315SSteven Rostedt static ssize_t
4441df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf,
4442df4fc315SSteven Rostedt 		   size_t cnt, loff_t *ppos)
4443df4fc315SSteven Rostedt {
4444457dc928SIngo Molnar 	char buf[64], *tmp;
4445df4fc315SSteven Rostedt 	long val;
4446df4fc315SSteven Rostedt 	int ret;
4447df4fc315SSteven Rostedt 
4448df4fc315SSteven Rostedt 	if (cnt >= sizeof(buf))
4449df4fc315SSteven Rostedt 		return -EINVAL;
4450df4fc315SSteven Rostedt 
4451df4fc315SSteven Rostedt 	if (copy_from_user(&buf, ubuf, cnt))
4452df4fc315SSteven Rostedt 		return -EFAULT;
4453df4fc315SSteven Rostedt 
4454df4fc315SSteven Rostedt 	buf[cnt] = 0;
4455df4fc315SSteven Rostedt 
4456756d17eeS[email protected] 	/*
4457756d17eeS[email protected] 	 * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid"
4458756d17eeS[email protected] 	 * to clean the filter quietly.
4459756d17eeS[email protected] 	 */
4460457dc928SIngo Molnar 	tmp = strstrip(buf);
4461457dc928SIngo Molnar 	if (strlen(tmp) == 0)
4462756d17eeS[email protected] 		return 1;
4463756d17eeS[email protected] 
4464bcd83ea6SDaniel Walter 	ret = kstrtol(tmp, 10, &val);
4465df4fc315SSteven Rostedt 	if (ret < 0)
4466df4fc315SSteven Rostedt 		return ret;
4467df4fc315SSteven Rostedt 
4468756d17eeS[email protected] 	ret = ftrace_pid_add(val);
4469978f3a45SSteven Rostedt 
4470756d17eeS[email protected] 	return ret ? ret : cnt;
4471e32d8956SSteven Rostedt }
4472978f3a45SSteven Rostedt 
4473756d17eeS[email protected] static int
4474756d17eeS[email protected] ftrace_pid_release(struct inode *inode, struct file *file)
4475756d17eeS[email protected] {
4476756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4477756d17eeS[email protected] 		seq_release(inode, file);
4478978f3a45SSteven Rostedt 
4479756d17eeS[email protected] 	return 0;
4480df4fc315SSteven Rostedt }
4481df4fc315SSteven Rostedt 
44825e2336a0SSteven Rostedt static const struct file_operations ftrace_pid_fops = {
4483756d17eeS[email protected] 	.open		= ftrace_pid_open,
4484df4fc315SSteven Rostedt 	.write		= ftrace_pid_write,
4485756d17eeS[email protected] 	.read		= seq_read,
4486756d17eeS[email protected] 	.llseek		= seq_lseek,
4487756d17eeS[email protected] 	.release	= ftrace_pid_release,
4488df4fc315SSteven Rostedt };
4489df4fc315SSteven Rostedt 
4490df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void)
4491df4fc315SSteven Rostedt {
4492df4fc315SSteven Rostedt 	struct dentry *d_tracer;
4493df4fc315SSteven Rostedt 
4494df4fc315SSteven Rostedt 	d_tracer = tracing_init_dentry();
4495df4fc315SSteven Rostedt 	if (!d_tracer)
4496df4fc315SSteven Rostedt 		return 0;
4497df4fc315SSteven Rostedt 
4498df4fc315SSteven Rostedt 	ftrace_init_dyn_debugfs(d_tracer);
4499df4fc315SSteven Rostedt 
45005452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_pid", 0644, d_tracer,
4501df4fc315SSteven Rostedt 			    NULL, &ftrace_pid_fops);
4502493762fcSSteven Rostedt 
4503493762fcSSteven Rostedt 	ftrace_profile_debugfs(d_tracer);
4504493762fcSSteven Rostedt 
4505df4fc315SSteven Rostedt 	return 0;
4506df4fc315SSteven Rostedt }
4507df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs);
4508df4fc315SSteven Rostedt 
45093d083395SSteven Rostedt /**
451081adbdc0SSteven Rostedt  * ftrace_kill - kill ftrace
4511a2bb6a3dSSteven Rostedt  *
4512a2bb6a3dSSteven Rostedt  * This function should be used by panic code. It stops ftrace
4513a2bb6a3dSSteven Rostedt  * but in a not so nice way. If you need to simply kill ftrace
4514a2bb6a3dSSteven Rostedt  * from a non-atomic section, use ftrace_kill.
4515a2bb6a3dSSteven Rostedt  */
451681adbdc0SSteven Rostedt void ftrace_kill(void)
4517a2bb6a3dSSteven Rostedt {
4518a2bb6a3dSSteven Rostedt 	ftrace_disabled = 1;
4519a2bb6a3dSSteven Rostedt 	ftrace_enabled = 0;
4520a2bb6a3dSSteven Rostedt 	clear_ftrace_function();
4521a2bb6a3dSSteven Rostedt }
4522a2bb6a3dSSteven Rostedt 
4523a2bb6a3dSSteven Rostedt /**
4524e0a413f6SSteven Rostedt  * Test if ftrace is dead or not.
4525e0a413f6SSteven Rostedt  */
4526e0a413f6SSteven Rostedt int ftrace_is_dead(void)
4527e0a413f6SSteven Rostedt {
4528e0a413f6SSteven Rostedt 	return ftrace_disabled;
4529e0a413f6SSteven Rostedt }
4530e0a413f6SSteven Rostedt 
4531e0a413f6SSteven Rostedt /**
45323d083395SSteven Rostedt  * register_ftrace_function - register a function for profiling
45333d083395SSteven Rostedt  * @ops - ops structure that holds the function for profiling.
45343d083395SSteven Rostedt  *
45353d083395SSteven Rostedt  * Register a function to be called by all functions in the
45363d083395SSteven Rostedt  * kernel.
45373d083395SSteven Rostedt  *
45383d083395SSteven Rostedt  * Note: @ops->func and all the functions it calls must be labeled
45393d083395SSteven Rostedt  *       with "notrace", otherwise it will go into a
45403d083395SSteven Rostedt  *       recursive loop.
45413d083395SSteven Rostedt  */
45423d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops)
45433d083395SSteven Rostedt {
454445a4a237SSteven Rostedt 	int ret = -1;
45454eebcc81SSteven Rostedt 
4546e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4547e7d3737eSFrederic Weisbecker 
4548b0fc494fSSteven Rostedt 	ret = __register_ftrace_function(ops);
4549b848914cSSteven Rostedt 	if (!ret)
4550a1cd6173SSteven Rostedt 		ret = ftrace_startup(ops, 0);
4551b848914cSSteven Rostedt 
4552e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
45538d240dd8SBorislav Petkov 
4554b0fc494fSSteven Rostedt 	return ret;
45553d083395SSteven Rostedt }
4556cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(register_ftrace_function);
45573d083395SSteven Rostedt 
45583d083395SSteven Rostedt /**
455932632920SUwe Kleine-Koenig  * unregister_ftrace_function - unregister a function for profiling.
45603d083395SSteven Rostedt  * @ops - ops structure that holds the function to unregister
45613d083395SSteven Rostedt  *
45623d083395SSteven Rostedt  * Unregister a function that was added to be called by ftrace profiling.
45633d083395SSteven Rostedt  */
45643d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops)
45653d083395SSteven Rostedt {
45663d083395SSteven Rostedt 	int ret;
45673d083395SSteven Rostedt 
4568e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
45693d083395SSteven Rostedt 	ret = __unregister_ftrace_function(ops);
4570b848914cSSteven Rostedt 	if (!ret)
4571b848914cSSteven Rostedt 		ftrace_shutdown(ops, 0);
4572e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4573b0fc494fSSteven Rostedt 
4574b0fc494fSSteven Rostedt 	return ret;
4575b0fc494fSSteven Rostedt }
4576cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(unregister_ftrace_function);
4577b0fc494fSSteven Rostedt 
4578e309b41dSIngo Molnar int
4579b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write,
45808d65af78SAlexey Dobriyan 		     void __user *buffer, size_t *lenp,
4581b0fc494fSSteven Rostedt 		     loff_t *ppos)
4582b0fc494fSSteven Rostedt {
458345a4a237SSteven Rostedt 	int ret = -ENODEV;
45844eebcc81SSteven Rostedt 
4585e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4586b0fc494fSSteven Rostedt 
458745a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
458845a4a237SSteven Rostedt 		goto out;
458945a4a237SSteven Rostedt 
45908d65af78SAlexey Dobriyan 	ret = proc_dointvec(table, write, buffer, lenp, ppos);
4591b0fc494fSSteven Rostedt 
4592a32c7765SLi Zefan 	if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
4593b0fc494fSSteven Rostedt 		goto out;
4594b0fc494fSSteven Rostedt 
4595a32c7765SLi Zefan 	last_ftrace_enabled = !!ftrace_enabled;
4596b0fc494fSSteven Rostedt 
4597b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
4598b0fc494fSSteven Rostedt 
4599b0fc494fSSteven Rostedt 		ftrace_startup_sysctl();
4600b0fc494fSSteven Rostedt 
4601b0fc494fSSteven Rostedt 		/* we are starting ftrace again */
4602b848914cSSteven Rostedt 		if (ftrace_ops_list != &ftrace_list_end) {
4603b848914cSSteven Rostedt 			if (ftrace_ops_list->next == &ftrace_list_end)
4604b848914cSSteven Rostedt 				ftrace_trace_function = ftrace_ops_list->func;
4605b0fc494fSSteven Rostedt 			else
4606b848914cSSteven Rostedt 				ftrace_trace_function = ftrace_ops_list_func;
4607b0fc494fSSteven Rostedt 		}
4608b0fc494fSSteven Rostedt 
4609b0fc494fSSteven Rostedt 	} else {
4610b0fc494fSSteven Rostedt 		/* stopping ftrace calls (just send to ftrace_stub) */
4611b0fc494fSSteven Rostedt 		ftrace_trace_function = ftrace_stub;
4612b0fc494fSSteven Rostedt 
4613b0fc494fSSteven Rostedt 		ftrace_shutdown_sysctl();
4614b0fc494fSSteven Rostedt 	}
4615b0fc494fSSteven Rostedt 
4616b0fc494fSSteven Rostedt  out:
4617e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
46183d083395SSteven Rostedt 	return ret;
461916444a8aSArnaldo Carvalho de Melo }
4620f17845e5SIngo Molnar 
4621fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER
4622e7d3737eSFrederic Weisbecker 
4623597af815SSteven Rostedt static int ftrace_graph_active;
46244a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier;
4625f201ae23SFrederic Weisbecker 
4626e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
4627e49dc19cSSteven Rostedt {
4628e49dc19cSSteven Rostedt 	return 0;
4629e49dc19cSSteven Rostedt }
4630e49dc19cSSteven Rostedt 
4631287b6e68SFrederic Weisbecker /* The callbacks that hook a function */
4632287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return =
4633287b6e68SFrederic Weisbecker 			(trace_func_graph_ret_t)ftrace_stub;
4634e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
4635f201ae23SFrederic Weisbecker 
4636f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
4637f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
4638f201ae23SFrederic Weisbecker {
4639f201ae23SFrederic Weisbecker 	int i;
4640f201ae23SFrederic Weisbecker 	int ret = 0;
4641f201ae23SFrederic Weisbecker 	unsigned long flags;
4642f201ae23SFrederic Weisbecker 	int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE;
4643f201ae23SFrederic Weisbecker 	struct task_struct *g, *t;
4644f201ae23SFrederic Weisbecker 
4645f201ae23SFrederic Weisbecker 	for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
4646f201ae23SFrederic Weisbecker 		ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
4647f201ae23SFrederic Weisbecker 					* sizeof(struct ftrace_ret_stack),
4648f201ae23SFrederic Weisbecker 					GFP_KERNEL);
4649f201ae23SFrederic Weisbecker 		if (!ret_stack_list[i]) {
4650f201ae23SFrederic Weisbecker 			start = 0;
4651f201ae23SFrederic Weisbecker 			end = i;
4652f201ae23SFrederic Weisbecker 			ret = -ENOMEM;
4653f201ae23SFrederic Weisbecker 			goto free;
4654f201ae23SFrederic Weisbecker 		}
4655f201ae23SFrederic Weisbecker 	}
4656f201ae23SFrederic Weisbecker 
4657f201ae23SFrederic Weisbecker 	read_lock_irqsave(&tasklist_lock, flags);
4658f201ae23SFrederic Weisbecker 	do_each_thread(g, t) {
4659f201ae23SFrederic Weisbecker 		if (start == end) {
4660f201ae23SFrederic Weisbecker 			ret = -EAGAIN;
4661f201ae23SFrederic Weisbecker 			goto unlock;
4662f201ae23SFrederic Weisbecker 		}
4663f201ae23SFrederic Weisbecker 
4664f201ae23SFrederic Weisbecker 		if (t->ret_stack == NULL) {
4665380c4b14SFrederic Weisbecker 			atomic_set(&t->tracing_graph_pause, 0);
4666f201ae23SFrederic Weisbecker 			atomic_set(&t->trace_overrun, 0);
466726c01624SSteven Rostedt 			t->curr_ret_stack = -1;
466826c01624SSteven Rostedt 			/* Make sure the tasks see the -1 first: */
466926c01624SSteven Rostedt 			smp_wmb();
467026c01624SSteven Rostedt 			t->ret_stack = ret_stack_list[start++];
4671f201ae23SFrederic Weisbecker 		}
4672f201ae23SFrederic Weisbecker 	} while_each_thread(g, t);
4673f201ae23SFrederic Weisbecker 
4674f201ae23SFrederic Weisbecker unlock:
4675f201ae23SFrederic Weisbecker 	read_unlock_irqrestore(&tasklist_lock, flags);
4676f201ae23SFrederic Weisbecker free:
4677f201ae23SFrederic Weisbecker 	for (i = start; i < end; i++)
4678f201ae23SFrederic Weisbecker 		kfree(ret_stack_list[i]);
4679f201ae23SFrederic Weisbecker 	return ret;
4680f201ae23SFrederic Weisbecker }
4681f201ae23SFrederic Weisbecker 
46828aef2d28SSteven Rostedt static void
468338516ab5SSteven Rostedt ftrace_graph_probe_sched_switch(void *ignore,
468438516ab5SSteven Rostedt 			struct task_struct *prev, struct task_struct *next)
46858aef2d28SSteven Rostedt {
46868aef2d28SSteven Rostedt 	unsigned long long timestamp;
46878aef2d28SSteven Rostedt 	int index;
46888aef2d28SSteven Rostedt 
4689be6f164aSSteven Rostedt 	/*
4690be6f164aSSteven Rostedt 	 * Does the user want to count the time a function was asleep.
4691be6f164aSSteven Rostedt 	 * If so, do not update the time stamps.
4692be6f164aSSteven Rostedt 	 */
4693be6f164aSSteven Rostedt 	if (trace_flags & TRACE_ITER_SLEEP_TIME)
4694be6f164aSSteven Rostedt 		return;
4695be6f164aSSteven Rostedt 
46968aef2d28SSteven Rostedt 	timestamp = trace_clock_local();
46978aef2d28SSteven Rostedt 
46988aef2d28SSteven Rostedt 	prev->ftrace_timestamp = timestamp;
46998aef2d28SSteven Rostedt 
47008aef2d28SSteven Rostedt 	/* only process tasks that we timestamped */
47018aef2d28SSteven Rostedt 	if (!next->ftrace_timestamp)
47028aef2d28SSteven Rostedt 		return;
47038aef2d28SSteven Rostedt 
47048aef2d28SSteven Rostedt 	/*
47058aef2d28SSteven Rostedt 	 * Update all the counters in next to make up for the
47068aef2d28SSteven Rostedt 	 * time next was sleeping.
47078aef2d28SSteven Rostedt 	 */
47088aef2d28SSteven Rostedt 	timestamp -= next->ftrace_timestamp;
47098aef2d28SSteven Rostedt 
47108aef2d28SSteven Rostedt 	for (index = next->curr_ret_stack; index >= 0; index--)
47118aef2d28SSteven Rostedt 		next->ret_stack[index].calltime += timestamp;
47128aef2d28SSteven Rostedt }
47138aef2d28SSteven Rostedt 
4714f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */
4715fb52607aSFrederic Weisbecker static int start_graph_tracing(void)
4716f201ae23SFrederic Weisbecker {
4717f201ae23SFrederic Weisbecker 	struct ftrace_ret_stack **ret_stack_list;
47185b058bcdSFrederic Weisbecker 	int ret, cpu;
4719f201ae23SFrederic Weisbecker 
4720f201ae23SFrederic Weisbecker 	ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
4721f201ae23SFrederic Weisbecker 				sizeof(struct ftrace_ret_stack *),
4722f201ae23SFrederic Weisbecker 				GFP_KERNEL);
4723f201ae23SFrederic Weisbecker 
4724f201ae23SFrederic Weisbecker 	if (!ret_stack_list)
4725f201ae23SFrederic Weisbecker 		return -ENOMEM;
4726f201ae23SFrederic Weisbecker 
47275b058bcdSFrederic Weisbecker 	/* The cpu_boot init_task->ret_stack will never be freed */
4728179c498aSSteven Rostedt 	for_each_online_cpu(cpu) {
4729179c498aSSteven Rostedt 		if (!idle_task(cpu)->ret_stack)
4730868baf07SSteven Rostedt 			ftrace_graph_init_idle_task(idle_task(cpu), cpu);
4731179c498aSSteven Rostedt 	}
47325b058bcdSFrederic Weisbecker 
4733f201ae23SFrederic Weisbecker 	do {
4734f201ae23SFrederic Weisbecker 		ret = alloc_retstack_tasklist(ret_stack_list);
4735f201ae23SFrederic Weisbecker 	} while (ret == -EAGAIN);
4736f201ae23SFrederic Weisbecker 
47378aef2d28SSteven Rostedt 	if (!ret) {
473838516ab5SSteven Rostedt 		ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
47398aef2d28SSteven Rostedt 		if (ret)
47408aef2d28SSteven Rostedt 			pr_info("ftrace_graph: Couldn't activate tracepoint"
47418aef2d28SSteven Rostedt 				" probe to kernel_sched_switch\n");
47428aef2d28SSteven Rostedt 	}
47438aef2d28SSteven Rostedt 
4744f201ae23SFrederic Weisbecker 	kfree(ret_stack_list);
4745f201ae23SFrederic Weisbecker 	return ret;
4746f201ae23SFrederic Weisbecker }
4747f201ae23SFrederic Weisbecker 
47484a2b8ddaSFrederic Weisbecker /*
47494a2b8ddaSFrederic Weisbecker  * Hibernation protection.
47504a2b8ddaSFrederic Weisbecker  * The state of the current task is too much unstable during
47514a2b8ddaSFrederic Weisbecker  * suspend/restore to disk. We want to protect against that.
47524a2b8ddaSFrederic Weisbecker  */
47534a2b8ddaSFrederic Weisbecker static int
47544a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
47554a2b8ddaSFrederic Weisbecker 							void *unused)
47564a2b8ddaSFrederic Weisbecker {
47574a2b8ddaSFrederic Weisbecker 	switch (state) {
47584a2b8ddaSFrederic Weisbecker 	case PM_HIBERNATION_PREPARE:
47594a2b8ddaSFrederic Weisbecker 		pause_graph_tracing();
47604a2b8ddaSFrederic Weisbecker 		break;
47614a2b8ddaSFrederic Weisbecker 
47624a2b8ddaSFrederic Weisbecker 	case PM_POST_HIBERNATION:
47634a2b8ddaSFrederic Weisbecker 		unpause_graph_tracing();
47644a2b8ddaSFrederic Weisbecker 		break;
47654a2b8ddaSFrederic Weisbecker 	}
47664a2b8ddaSFrederic Weisbecker 	return NOTIFY_DONE;
47674a2b8ddaSFrederic Weisbecker }
47684a2b8ddaSFrederic Weisbecker 
4769287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc,
4770287b6e68SFrederic Weisbecker 			trace_func_graph_ent_t entryfunc)
477115e6cb36SFrederic Weisbecker {
4772e7d3737eSFrederic Weisbecker 	int ret = 0;
4773e7d3737eSFrederic Weisbecker 
4774e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4775e7d3737eSFrederic Weisbecker 
477605ce5818SSteven Rostedt 	/* we currently allow only one tracer registered at a time */
4777597af815SSteven Rostedt 	if (ftrace_graph_active) {
477805ce5818SSteven Rostedt 		ret = -EBUSY;
477905ce5818SSteven Rostedt 		goto out;
478005ce5818SSteven Rostedt 	}
478105ce5818SSteven Rostedt 
47824a2b8ddaSFrederic Weisbecker 	ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call;
47834a2b8ddaSFrederic Weisbecker 	register_pm_notifier(&ftrace_suspend_notifier);
47844a2b8ddaSFrederic Weisbecker 
4785597af815SSteven Rostedt 	ftrace_graph_active++;
4786fb52607aSFrederic Weisbecker 	ret = start_graph_tracing();
4787f201ae23SFrederic Weisbecker 	if (ret) {
4788597af815SSteven Rostedt 		ftrace_graph_active--;
4789f201ae23SFrederic Weisbecker 		goto out;
4790f201ae23SFrederic Weisbecker 	}
4791e53a6319SSteven Rostedt 
4792287b6e68SFrederic Weisbecker 	ftrace_graph_return = retfunc;
4793287b6e68SFrederic Weisbecker 	ftrace_graph_entry = entryfunc;
4794e53a6319SSteven Rostedt 
4795a1cd6173SSteven Rostedt 	ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
4796e7d3737eSFrederic Weisbecker 
4797e7d3737eSFrederic Weisbecker out:
4798e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4799e7d3737eSFrederic Weisbecker 	return ret;
480015e6cb36SFrederic Weisbecker }
480115e6cb36SFrederic Weisbecker 
4802fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void)
480315e6cb36SFrederic Weisbecker {
4804e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4805e7d3737eSFrederic Weisbecker 
4806597af815SSteven Rostedt 	if (unlikely(!ftrace_graph_active))
48072aad1b76SSteven Rostedt 		goto out;
48082aad1b76SSteven Rostedt 
4809597af815SSteven Rostedt 	ftrace_graph_active--;
4810287b6e68SFrederic Weisbecker 	ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
4811e49dc19cSSteven Rostedt 	ftrace_graph_entry = ftrace_graph_entry_stub;
4812bd69c30bSSteven Rostedt 	ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
48134a2b8ddaSFrederic Weisbecker 	unregister_pm_notifier(&ftrace_suspend_notifier);
481438516ab5SSteven Rostedt 	unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
4815e7d3737eSFrederic Weisbecker 
48162aad1b76SSteven Rostedt  out:
4817e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
481815e6cb36SFrederic Weisbecker }
4819f201ae23SFrederic Weisbecker 
4820868baf07SSteven Rostedt static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
4821868baf07SSteven Rostedt 
4822868baf07SSteven Rostedt static void
4823868baf07SSteven Rostedt graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
4824868baf07SSteven Rostedt {
4825868baf07SSteven Rostedt 	atomic_set(&t->tracing_graph_pause, 0);
4826868baf07SSteven Rostedt 	atomic_set(&t->trace_overrun, 0);
4827868baf07SSteven Rostedt 	t->ftrace_timestamp = 0;
482825985edcSLucas De Marchi 	/* make curr_ret_stack visible before we add the ret_stack */
4829868baf07SSteven Rostedt 	smp_wmb();
4830868baf07SSteven Rostedt 	t->ret_stack = ret_stack;
4831868baf07SSteven Rostedt }
4832868baf07SSteven Rostedt 
4833868baf07SSteven Rostedt /*
4834868baf07SSteven Rostedt  * Allocate a return stack for the idle task. May be the first
4835868baf07SSteven Rostedt  * time through, or it may be done by CPU hotplug online.
4836868baf07SSteven Rostedt  */
4837868baf07SSteven Rostedt void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
4838868baf07SSteven Rostedt {
4839868baf07SSteven Rostedt 	t->curr_ret_stack = -1;
4840868baf07SSteven Rostedt 	/*
4841868baf07SSteven Rostedt 	 * The idle task has no parent, it either has its own
4842868baf07SSteven Rostedt 	 * stack or no stack at all.
4843868baf07SSteven Rostedt 	 */
4844868baf07SSteven Rostedt 	if (t->ret_stack)
4845868baf07SSteven Rostedt 		WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
4846868baf07SSteven Rostedt 
4847868baf07SSteven Rostedt 	if (ftrace_graph_active) {
4848868baf07SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
4849868baf07SSteven Rostedt 
4850868baf07SSteven Rostedt 		ret_stack = per_cpu(idle_ret_stack, cpu);
4851868baf07SSteven Rostedt 		if (!ret_stack) {
4852868baf07SSteven Rostedt 			ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4853868baf07SSteven Rostedt 					    * sizeof(struct ftrace_ret_stack),
4854868baf07SSteven Rostedt 					    GFP_KERNEL);
4855868baf07SSteven Rostedt 			if (!ret_stack)
4856868baf07SSteven Rostedt 				return;
4857868baf07SSteven Rostedt 			per_cpu(idle_ret_stack, cpu) = ret_stack;
4858868baf07SSteven Rostedt 		}
4859868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
4860868baf07SSteven Rostedt 	}
4861868baf07SSteven Rostedt }
4862868baf07SSteven Rostedt 
4863f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */
4864fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t)
4865f201ae23SFrederic Weisbecker {
486684047e36SSteven Rostedt 	/* Make sure we do not use the parent ret_stack */
486784047e36SSteven Rostedt 	t->ret_stack = NULL;
4868ea14eb71SSteven Rostedt 	t->curr_ret_stack = -1;
486984047e36SSteven Rostedt 
4870597af815SSteven Rostedt 	if (ftrace_graph_active) {
487182310a32SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
487282310a32SSteven Rostedt 
487382310a32SSteven Rostedt 		ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4874f201ae23SFrederic Weisbecker 				* sizeof(struct ftrace_ret_stack),
4875f201ae23SFrederic Weisbecker 				GFP_KERNEL);
487682310a32SSteven Rostedt 		if (!ret_stack)
4877f201ae23SFrederic Weisbecker 			return;
4878868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
487984047e36SSteven Rostedt 	}
4880f201ae23SFrederic Weisbecker }
4881f201ae23SFrederic Weisbecker 
4882fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t)
4883f201ae23SFrederic Weisbecker {
4884eae849caSFrederic Weisbecker 	struct ftrace_ret_stack	*ret_stack = t->ret_stack;
4885eae849caSFrederic Weisbecker 
4886f201ae23SFrederic Weisbecker 	t->ret_stack = NULL;
4887eae849caSFrederic Weisbecker 	/* NULL must become visible to IRQs before we free it: */
4888eae849caSFrederic Weisbecker 	barrier();
4889eae849caSFrederic Weisbecker 
4890eae849caSFrederic Weisbecker 	kfree(ret_stack);
4891f201ae23SFrederic Weisbecker }
489214a866c5SSteven Rostedt 
489314a866c5SSteven Rostedt void ftrace_graph_stop(void)
489414a866c5SSteven Rostedt {
489514a866c5SSteven Rostedt 	ftrace_stop();
489614a866c5SSteven Rostedt }
489715e6cb36SFrederic Weisbecker #endif
4898