xref: /linux-6.15/kernel/trace/ftrace.c (revision 1bb539ca)
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 
67f04f24fbSMasami Hiramatsu #ifdef CONFIG_DYNAMIC_FTRACE
68f04f24fbSMasami Hiramatsu #define INIT_REGEX_LOCK(opsname)	\
69f04f24fbSMasami Hiramatsu 	.regex_lock	= __MUTEX_INITIALIZER(opsname.regex_lock),
70f04f24fbSMasami Hiramatsu #else
71f04f24fbSMasami Hiramatsu #define INIT_REGEX_LOCK(opsname)
72f04f24fbSMasami Hiramatsu #endif
73f04f24fbSMasami Hiramatsu 
742f5f6ad9SSteven Rostedt static struct ftrace_ops ftrace_list_end __read_mostly = {
752f5f6ad9SSteven Rostedt 	.func		= ftrace_stub,
76395b97a3SSteven Rostedt (Red Hat) 	.flags		= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,
772f5f6ad9SSteven Rostedt };
782f5f6ad9SSteven Rostedt 
794eebcc81SSteven Rostedt /* ftrace_enabled is a method to turn ftrace on or off */
804eebcc81SSteven Rostedt int ftrace_enabled __read_mostly;
81d61f82d0SSteven Rostedt static int last_ftrace_enabled;
82b0fc494fSSteven Rostedt 
8360a7ecf4SSteven Rostedt /* Quick disabling of function tracer. */
842f5f6ad9SSteven Rostedt int function_trace_stop __read_mostly;
852f5f6ad9SSteven Rostedt 
862f5f6ad9SSteven Rostedt /* Current function tracing op */
872f5f6ad9SSteven Rostedt struct ftrace_ops *function_trace_op __read_mostly = &ftrace_list_end;
8860a7ecf4SSteven Rostedt 
89756d17eeS[email protected] /* List for set_ftrace_pid's pids. */
90756d17eeS[email protected] LIST_HEAD(ftrace_pids);
91756d17eeS[email protected] struct ftrace_pid {
92756d17eeS[email protected] 	struct list_head list;
93756d17eeS[email protected] 	struct pid *pid;
94756d17eeS[email protected] };
95756d17eeS[email protected] 
964eebcc81SSteven Rostedt /*
974eebcc81SSteven Rostedt  * ftrace_disabled is set when an anomaly is discovered.
984eebcc81SSteven Rostedt  * ftrace_disabled is much stronger than ftrace_enabled.
994eebcc81SSteven Rostedt  */
1004eebcc81SSteven Rostedt static int ftrace_disabled __read_mostly;
1014eebcc81SSteven Rostedt 
10252baf119SSteven Rostedt static DEFINE_MUTEX(ftrace_lock);
103b0fc494fSSteven Rostedt 
104b848914cSSteven Rostedt static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end;
105e248491aSJiri Olsa static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end;
106b848914cSSteven Rostedt static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
10716444a8aSArnaldo Carvalho de Melo ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
108df4fc315SSteven Rostedt ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
1092b499381SSteven Rostedt static struct ftrace_ops global_ops;
110e248491aSJiri Olsa static struct ftrace_ops control_ops;
11116444a8aSArnaldo Carvalho de Melo 
1122f5f6ad9SSteven Rostedt #if ARCH_SUPPORTS_FTRACE_OPS
1132f5f6ad9SSteven Rostedt static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
114a1e2e31dSSteven Rostedt 				 struct ftrace_ops *op, struct pt_regs *regs);
1152f5f6ad9SSteven Rostedt #else
1162f5f6ad9SSteven Rostedt /* See comment below, where ftrace_ops_list_func is defined */
1172f5f6ad9SSteven Rostedt static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);
1182f5f6ad9SSteven Rostedt #define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops)
1192f5f6ad9SSteven Rostedt #endif
120b848914cSSteven Rostedt 
1210a016409SSteven Rostedt /*
1220a016409SSteven Rostedt  * Traverse the ftrace_global_list, invoking all entries.  The reason that we
123*1bb539caSSteven Rostedt  * can use rcu_dereference_raw_notrace() is that elements removed from this list
1240a016409SSteven Rostedt  * are simply leaked, so there is no need to interact with a grace-period
125*1bb539caSSteven Rostedt  * mechanism.  The rcu_dereference_raw_notrace() calls are needed to handle
1260a016409SSteven Rostedt  * concurrent insertions into the ftrace_global_list.
1270a016409SSteven Rostedt  *
1280a016409SSteven Rostedt  * Silly Alpha and silly pointer-speculation compiler optimizations!
1290a016409SSteven Rostedt  */
1300a016409SSteven Rostedt #define do_for_each_ftrace_op(op, list)			\
131*1bb539caSSteven Rostedt 	op = rcu_dereference_raw_notrace(list);			\
1320a016409SSteven Rostedt 	do
1330a016409SSteven Rostedt 
1340a016409SSteven Rostedt /*
1350a016409SSteven Rostedt  * Optimized for just a single item in the list (as that is the normal case).
1360a016409SSteven Rostedt  */
1370a016409SSteven Rostedt #define while_for_each_ftrace_op(op)				\
138*1bb539caSSteven Rostedt 	while (likely(op = rcu_dereference_raw_notrace((op)->next)) &&	\
1390a016409SSteven Rostedt 	       unlikely((op) != &ftrace_list_end))
1400a016409SSteven Rostedt 
141f04f24fbSMasami Hiramatsu static inline void ftrace_ops_init(struct ftrace_ops *ops)
142f04f24fbSMasami Hiramatsu {
143f04f24fbSMasami Hiramatsu #ifdef CONFIG_DYNAMIC_FTRACE
144f04f24fbSMasami Hiramatsu 	if (!(ops->flags & FTRACE_OPS_FL_INITIALIZED)) {
145f04f24fbSMasami Hiramatsu 		mutex_init(&ops->regex_lock);
146f04f24fbSMasami Hiramatsu 		ops->flags |= FTRACE_OPS_FL_INITIALIZED;
147f04f24fbSMasami Hiramatsu 	}
148f04f24fbSMasami Hiramatsu #endif
149f04f24fbSMasami Hiramatsu }
150f04f24fbSMasami Hiramatsu 
151ea701f11SSteven Rostedt /**
152ea701f11SSteven Rostedt  * ftrace_nr_registered_ops - return number of ops registered
153ea701f11SSteven Rostedt  *
154ea701f11SSteven Rostedt  * Returns the number of ftrace_ops registered and tracing functions
155ea701f11SSteven Rostedt  */
156ea701f11SSteven Rostedt int ftrace_nr_registered_ops(void)
157ea701f11SSteven Rostedt {
158ea701f11SSteven Rostedt 	struct ftrace_ops *ops;
159ea701f11SSteven Rostedt 	int cnt = 0;
160ea701f11SSteven Rostedt 
161ea701f11SSteven Rostedt 	mutex_lock(&ftrace_lock);
162ea701f11SSteven Rostedt 
163ea701f11SSteven Rostedt 	for (ops = ftrace_ops_list;
164ea701f11SSteven Rostedt 	     ops != &ftrace_list_end; ops = ops->next)
165ea701f11SSteven Rostedt 		cnt++;
166ea701f11SSteven Rostedt 
167ea701f11SSteven Rostedt 	mutex_unlock(&ftrace_lock);
168ea701f11SSteven Rostedt 
169ea701f11SSteven Rostedt 	return cnt;
170ea701f11SSteven Rostedt }
171ea701f11SSteven Rostedt 
1722f5f6ad9SSteven Rostedt static void
1732f5f6ad9SSteven Rostedt ftrace_global_list_func(unsigned long ip, unsigned long parent_ip,
174a1e2e31dSSteven Rostedt 			struct ftrace_ops *op, struct pt_regs *regs)
17516444a8aSArnaldo Carvalho de Melo {
176c29f122cSSteven Rostedt 	int bit;
177c29f122cSSteven Rostedt 
178edc15cafSSteven Rostedt 	bit = trace_test_and_set_recursion(TRACE_GLOBAL_START, TRACE_GLOBAL_MAX);
179edc15cafSSteven Rostedt 	if (bit < 0)
180b1cff0adSSteven Rostedt 		return;
181b1cff0adSSteven Rostedt 
1820a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_global_list) {
183a1e2e31dSSteven Rostedt 		op->func(ip, parent_ip, op, regs);
1840a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
185edc15cafSSteven Rostedt 
186edc15cafSSteven Rostedt 	trace_clear_recursion(bit);
18716444a8aSArnaldo Carvalho de Melo }
18816444a8aSArnaldo Carvalho de Melo 
1892f5f6ad9SSteven Rostedt static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip,
190a1e2e31dSSteven Rostedt 			    struct ftrace_ops *op, struct pt_regs *regs)
191df4fc315SSteven Rostedt {
1920ef8cde5SSteven Rostedt 	if (!test_tsk_trace_trace(current))
193df4fc315SSteven Rostedt 		return;
194df4fc315SSteven Rostedt 
195a1e2e31dSSteven Rostedt 	ftrace_pid_function(ip, parent_ip, op, regs);
196df4fc315SSteven Rostedt }
197df4fc315SSteven Rostedt 
198df4fc315SSteven Rostedt static void set_ftrace_pid_function(ftrace_func_t func)
199df4fc315SSteven Rostedt {
200df4fc315SSteven Rostedt 	/* do not set ftrace_pid_function to itself! */
201df4fc315SSteven Rostedt 	if (func != ftrace_pid_func)
202df4fc315SSteven Rostedt 		ftrace_pid_function = func;
203df4fc315SSteven Rostedt }
204df4fc315SSteven Rostedt 
20516444a8aSArnaldo Carvalho de Melo /**
2063d083395SSteven Rostedt  * clear_ftrace_function - reset the ftrace function
20716444a8aSArnaldo Carvalho de Melo  *
2083d083395SSteven Rostedt  * This NULLs the ftrace function and in essence stops
2093d083395SSteven Rostedt  * tracing.  There may be lag
21016444a8aSArnaldo Carvalho de Melo  */
2113d083395SSteven Rostedt void clear_ftrace_function(void)
21216444a8aSArnaldo Carvalho de Melo {
2133d083395SSteven Rostedt 	ftrace_trace_function = ftrace_stub;
214df4fc315SSteven Rostedt 	ftrace_pid_function = ftrace_stub;
2153d083395SSteven Rostedt }
21616444a8aSArnaldo Carvalho de Melo 
217e248491aSJiri Olsa static void control_ops_disable_all(struct ftrace_ops *ops)
218e248491aSJiri Olsa {
219e248491aSJiri Olsa 	int cpu;
220e248491aSJiri Olsa 
221e248491aSJiri Olsa 	for_each_possible_cpu(cpu)
222e248491aSJiri Olsa 		*per_cpu_ptr(ops->disabled, cpu) = 1;
223e248491aSJiri Olsa }
224e248491aSJiri Olsa 
225e248491aSJiri Olsa static int control_ops_alloc(struct ftrace_ops *ops)
226e248491aSJiri Olsa {
227e248491aSJiri Olsa 	int __percpu *disabled;
228e248491aSJiri Olsa 
229e248491aSJiri Olsa 	disabled = alloc_percpu(int);
230e248491aSJiri Olsa 	if (!disabled)
231e248491aSJiri Olsa 		return -ENOMEM;
232e248491aSJiri Olsa 
233e248491aSJiri Olsa 	ops->disabled = disabled;
234e248491aSJiri Olsa 	control_ops_disable_all(ops);
235e248491aSJiri Olsa 	return 0;
236e248491aSJiri Olsa }
237e248491aSJiri Olsa 
238e248491aSJiri Olsa static void control_ops_free(struct ftrace_ops *ops)
239e248491aSJiri Olsa {
240e248491aSJiri Olsa 	free_percpu(ops->disabled);
241e248491aSJiri Olsa }
242e248491aSJiri Olsa 
2432b499381SSteven Rostedt static void update_global_ops(void)
244491d0dcfSSteven Rostedt {
245491d0dcfSSteven Rostedt 	ftrace_func_t func;
246491d0dcfSSteven Rostedt 
247491d0dcfSSteven Rostedt 	/*
248491d0dcfSSteven Rostedt 	 * If there's only one function registered, then call that
249491d0dcfSSteven Rostedt 	 * function directly. Otherwise, we need to iterate over the
250491d0dcfSSteven Rostedt 	 * registered callers.
251491d0dcfSSteven Rostedt 	 */
252b848914cSSteven Rostedt 	if (ftrace_global_list == &ftrace_list_end ||
25363503794SSteven Rostedt 	    ftrace_global_list->next == &ftrace_list_end) {
254b848914cSSteven Rostedt 		func = ftrace_global_list->func;
25563503794SSteven Rostedt 		/*
25663503794SSteven Rostedt 		 * As we are calling the function directly.
25763503794SSteven Rostedt 		 * If it does not have recursion protection,
25863503794SSteven Rostedt 		 * the function_trace_op needs to be updated
25963503794SSteven Rostedt 		 * accordingly.
26063503794SSteven Rostedt 		 */
26163503794SSteven Rostedt 		if (ftrace_global_list->flags & FTRACE_OPS_FL_RECURSION_SAFE)
26263503794SSteven Rostedt 			global_ops.flags |= FTRACE_OPS_FL_RECURSION_SAFE;
263491d0dcfSSteven Rostedt 		else
26463503794SSteven Rostedt 			global_ops.flags &= ~FTRACE_OPS_FL_RECURSION_SAFE;
26563503794SSteven Rostedt 	} else {
266b848914cSSteven Rostedt 		func = ftrace_global_list_func;
26763503794SSteven Rostedt 		/* The list has its own recursion protection. */
26863503794SSteven Rostedt 		global_ops.flags |= FTRACE_OPS_FL_RECURSION_SAFE;
26963503794SSteven Rostedt 	}
27063503794SSteven Rostedt 
271491d0dcfSSteven Rostedt 
272491d0dcfSSteven Rostedt 	/* If we filter on pids, update to use the pid function */
273491d0dcfSSteven Rostedt 	if (!list_empty(&ftrace_pids)) {
274491d0dcfSSteven Rostedt 		set_ftrace_pid_function(func);
275491d0dcfSSteven Rostedt 		func = ftrace_pid_func;
276491d0dcfSSteven Rostedt 	}
2772b499381SSteven Rostedt 
2782b499381SSteven Rostedt 	global_ops.func = func;
2792b499381SSteven Rostedt }
2802b499381SSteven Rostedt 
2812b499381SSteven Rostedt static void update_ftrace_function(void)
2822b499381SSteven Rostedt {
2832b499381SSteven Rostedt 	ftrace_func_t func;
2842b499381SSteven Rostedt 
2852b499381SSteven Rostedt 	update_global_ops();
2862b499381SSteven Rostedt 
287cdbe61bfSSteven Rostedt 	/*
288cdbe61bfSSteven Rostedt 	 * If we are at the end of the list and this ops is
2894740974aSSteven Rostedt 	 * recursion safe and not dynamic and the arch supports passing ops,
2904740974aSSteven Rostedt 	 * then have the mcount trampoline call the function directly.
291cdbe61bfSSteven Rostedt 	 */
292b848914cSSteven Rostedt 	if (ftrace_ops_list == &ftrace_list_end ||
293cdbe61bfSSteven Rostedt 	    (ftrace_ops_list->next == &ftrace_list_end &&
2942f5f6ad9SSteven Rostedt 	     !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC) &&
2954740974aSSteven Rostedt 	     (ftrace_ops_list->flags & FTRACE_OPS_FL_RECURSION_SAFE) &&
296ccf3672dSSteven Rostedt 	     !FTRACE_FORCE_LIST_FUNC)) {
2972f5f6ad9SSteven Rostedt 		/* Set the ftrace_ops that the arch callback uses */
2982f5f6ad9SSteven Rostedt 		if (ftrace_ops_list == &global_ops)
2992f5f6ad9SSteven Rostedt 			function_trace_op = ftrace_global_list;
300b848914cSSteven Rostedt 		else
3012f5f6ad9SSteven Rostedt 			function_trace_op = ftrace_ops_list;
3022f5f6ad9SSteven Rostedt 		func = ftrace_ops_list->func;
3032f5f6ad9SSteven Rostedt 	} else {
3042f5f6ad9SSteven Rostedt 		/* Just use the default ftrace_ops */
3052f5f6ad9SSteven Rostedt 		function_trace_op = &ftrace_list_end;
306b848914cSSteven Rostedt 		func = ftrace_ops_list_func;
3072f5f6ad9SSteven Rostedt 	}
3082b499381SSteven Rostedt 
309491d0dcfSSteven Rostedt 	ftrace_trace_function = func;
310491d0dcfSSteven Rostedt }
311491d0dcfSSteven Rostedt 
3122b499381SSteven Rostedt static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
3133d083395SSteven Rostedt {
3142b499381SSteven Rostedt 	ops->next = *list;
31516444a8aSArnaldo Carvalho de Melo 	/*
316b848914cSSteven Rostedt 	 * We are entering ops into the list but another
31716444a8aSArnaldo Carvalho de Melo 	 * CPU might be walking that list. We need to make sure
31816444a8aSArnaldo Carvalho de Melo 	 * the ops->next pointer is valid before another CPU sees
319b848914cSSteven Rostedt 	 * the ops pointer included into the list.
32016444a8aSArnaldo Carvalho de Melo 	 */
3212b499381SSteven Rostedt 	rcu_assign_pointer(*list, ops);
3222b499381SSteven Rostedt }
3233d083395SSteven Rostedt 
3242b499381SSteven Rostedt static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
3252b499381SSteven Rostedt {
3262b499381SSteven Rostedt 	struct ftrace_ops **p;
3272b499381SSteven Rostedt 
3282b499381SSteven Rostedt 	/*
3292b499381SSteven Rostedt 	 * If we are removing the last function, then simply point
3302b499381SSteven Rostedt 	 * to the ftrace_stub.
3312b499381SSteven Rostedt 	 */
3322b499381SSteven Rostedt 	if (*list == ops && ops->next == &ftrace_list_end) {
3332b499381SSteven Rostedt 		*list = &ftrace_list_end;
3342b499381SSteven Rostedt 		return 0;
3352b499381SSteven Rostedt 	}
3362b499381SSteven Rostedt 
3372b499381SSteven Rostedt 	for (p = list; *p != &ftrace_list_end; p = &(*p)->next)
3382b499381SSteven Rostedt 		if (*p == ops)
3392b499381SSteven Rostedt 			break;
3402b499381SSteven Rostedt 
3412b499381SSteven Rostedt 	if (*p != ops)
3422b499381SSteven Rostedt 		return -1;
3432b499381SSteven Rostedt 
3442b499381SSteven Rostedt 	*p = (*p)->next;
3452b499381SSteven Rostedt 	return 0;
3462b499381SSteven Rostedt }
3472b499381SSteven Rostedt 
348e248491aSJiri Olsa static void add_ftrace_list_ops(struct ftrace_ops **list,
349e248491aSJiri Olsa 				struct ftrace_ops *main_ops,
350e248491aSJiri Olsa 				struct ftrace_ops *ops)
351e248491aSJiri Olsa {
352e248491aSJiri Olsa 	int first = *list == &ftrace_list_end;
353e248491aSJiri Olsa 	add_ftrace_ops(list, ops);
354e248491aSJiri Olsa 	if (first)
355e248491aSJiri Olsa 		add_ftrace_ops(&ftrace_ops_list, main_ops);
356e248491aSJiri Olsa }
357e248491aSJiri Olsa 
358e248491aSJiri Olsa static int remove_ftrace_list_ops(struct ftrace_ops **list,
359e248491aSJiri Olsa 				  struct ftrace_ops *main_ops,
360e248491aSJiri Olsa 				  struct ftrace_ops *ops)
361e248491aSJiri Olsa {
362e248491aSJiri Olsa 	int ret = remove_ftrace_ops(list, ops);
363e248491aSJiri Olsa 	if (!ret && *list == &ftrace_list_end)
364e248491aSJiri Olsa 		ret = remove_ftrace_ops(&ftrace_ops_list, main_ops);
365e248491aSJiri Olsa 	return ret;
366e248491aSJiri Olsa }
367e248491aSJiri Olsa 
3682b499381SSteven Rostedt static int __register_ftrace_function(struct ftrace_ops *ops)
3692b499381SSteven Rostedt {
3708d240dd8SBorislav Petkov 	if (unlikely(ftrace_disabled))
3712b499381SSteven Rostedt 		return -ENODEV;
3722b499381SSteven Rostedt 
3732b499381SSteven Rostedt 	if (FTRACE_WARN_ON(ops == &global_ops))
3742b499381SSteven Rostedt 		return -EINVAL;
3752b499381SSteven Rostedt 
376b848914cSSteven Rostedt 	if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED))
377b848914cSSteven Rostedt 		return -EBUSY;
378b848914cSSteven Rostedt 
379e248491aSJiri Olsa 	/* We don't support both control and global flags set. */
380e248491aSJiri Olsa 	if ((ops->flags & FL_GLOBAL_CONTROL_MASK) == FL_GLOBAL_CONTROL_MASK)
381e248491aSJiri Olsa 		return -EINVAL;
382e248491aSJiri Olsa 
38306aeaaeaSMasami Hiramatsu #ifndef CONFIG_DYNAMIC_FTRACE_WITH_REGS
38408f6fba5SSteven Rostedt 	/*
38508f6fba5SSteven Rostedt 	 * If the ftrace_ops specifies SAVE_REGS, then it only can be used
38608f6fba5SSteven Rostedt 	 * if the arch supports it, or SAVE_REGS_IF_SUPPORTED is also set.
38708f6fba5SSteven Rostedt 	 * Setting SAVE_REGS_IF_SUPPORTED makes SAVE_REGS irrelevant.
38808f6fba5SSteven Rostedt 	 */
38908f6fba5SSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_SAVE_REGS &&
39008f6fba5SSteven Rostedt 	    !(ops->flags & FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED))
39108f6fba5SSteven Rostedt 		return -EINVAL;
39208f6fba5SSteven Rostedt 
39308f6fba5SSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED)
39408f6fba5SSteven Rostedt 		ops->flags |= FTRACE_OPS_FL_SAVE_REGS;
39508f6fba5SSteven Rostedt #endif
39608f6fba5SSteven Rostedt 
397cdbe61bfSSteven Rostedt 	if (!core_kernel_data((unsigned long)ops))
398cdbe61bfSSteven Rostedt 		ops->flags |= FTRACE_OPS_FL_DYNAMIC;
399cdbe61bfSSteven Rostedt 
400b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
401e248491aSJiri Olsa 		add_ftrace_list_ops(&ftrace_global_list, &global_ops, ops);
402b848914cSSteven Rostedt 		ops->flags |= FTRACE_OPS_FL_ENABLED;
403e248491aSJiri Olsa 	} else if (ops->flags & FTRACE_OPS_FL_CONTROL) {
404e248491aSJiri Olsa 		if (control_ops_alloc(ops))
405e248491aSJiri Olsa 			return -ENOMEM;
406e248491aSJiri Olsa 		add_ftrace_list_ops(&ftrace_control_list, &control_ops, ops);
407b848914cSSteven Rostedt 	} else
408b848914cSSteven Rostedt 		add_ftrace_ops(&ftrace_ops_list, ops);
409b848914cSSteven Rostedt 
410491d0dcfSSteven Rostedt 	if (ftrace_enabled)
411491d0dcfSSteven Rostedt 		update_ftrace_function();
4123d083395SSteven Rostedt 
41316444a8aSArnaldo Carvalho de Melo 	return 0;
41416444a8aSArnaldo Carvalho de Melo }
41516444a8aSArnaldo Carvalho de Melo 
416e309b41dSIngo Molnar static int __unregister_ftrace_function(struct ftrace_ops *ops)
41716444a8aSArnaldo Carvalho de Melo {
4182b499381SSteven Rostedt 	int ret;
41916444a8aSArnaldo Carvalho de Melo 
4202b499381SSteven Rostedt 	if (ftrace_disabled)
4212b499381SSteven Rostedt 		return -ENODEV;
42216444a8aSArnaldo Carvalho de Melo 
423b848914cSSteven Rostedt 	if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
424b848914cSSteven Rostedt 		return -EBUSY;
425b848914cSSteven Rostedt 
4262b499381SSteven Rostedt 	if (FTRACE_WARN_ON(ops == &global_ops))
4272b499381SSteven Rostedt 		return -EINVAL;
42816444a8aSArnaldo Carvalho de Melo 
429b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
430e248491aSJiri Olsa 		ret = remove_ftrace_list_ops(&ftrace_global_list,
431e248491aSJiri Olsa 					     &global_ops, ops);
432b848914cSSteven Rostedt 		if (!ret)
433b848914cSSteven Rostedt 			ops->flags &= ~FTRACE_OPS_FL_ENABLED;
434e248491aSJiri Olsa 	} else if (ops->flags & FTRACE_OPS_FL_CONTROL) {
435e248491aSJiri Olsa 		ret = remove_ftrace_list_ops(&ftrace_control_list,
436e248491aSJiri Olsa 					     &control_ops, ops);
437e248491aSJiri Olsa 		if (!ret) {
438e248491aSJiri Olsa 			/*
439e248491aSJiri Olsa 			 * The ftrace_ops is now removed from the list,
440e248491aSJiri Olsa 			 * so there'll be no new users. We must ensure
441e248491aSJiri Olsa 			 * all current users are done before we free
442e248491aSJiri Olsa 			 * the control data.
443e248491aSJiri Olsa 			 */
444e248491aSJiri Olsa 			synchronize_sched();
445e248491aSJiri Olsa 			control_ops_free(ops);
446e248491aSJiri Olsa 		}
447b848914cSSteven Rostedt 	} else
448b848914cSSteven Rostedt 		ret = remove_ftrace_ops(&ftrace_ops_list, ops);
449b848914cSSteven Rostedt 
4502b499381SSteven Rostedt 	if (ret < 0)
4512b499381SSteven Rostedt 		return ret;
452b848914cSSteven Rostedt 
453491d0dcfSSteven Rostedt 	if (ftrace_enabled)
454491d0dcfSSteven Rostedt 		update_ftrace_function();
45516444a8aSArnaldo Carvalho de Melo 
456cdbe61bfSSteven Rostedt 	/*
457cdbe61bfSSteven Rostedt 	 * Dynamic ops may be freed, we must make sure that all
458cdbe61bfSSteven Rostedt 	 * callers are done before leaving this function.
459cdbe61bfSSteven Rostedt 	 */
460cdbe61bfSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
461cdbe61bfSSteven Rostedt 		synchronize_sched();
462cdbe61bfSSteven Rostedt 
463e6ea44e9SSteven Rostedt 	return 0;
4643d083395SSteven Rostedt }
4653d083395SSteven Rostedt 
466df4fc315SSteven Rostedt static void ftrace_update_pid_func(void)
467df4fc315SSteven Rostedt {
468491d0dcfSSteven Rostedt 	/* Only do something if we are tracing something */
469df4fc315SSteven Rostedt 	if (ftrace_trace_function == ftrace_stub)
47010dd3ebeSKOSAKI Motohiro 		return;
471df4fc315SSteven Rostedt 
472491d0dcfSSteven Rostedt 	update_ftrace_function();
473df4fc315SSteven Rostedt }
474df4fc315SSteven Rostedt 
475493762fcSSteven Rostedt #ifdef CONFIG_FUNCTION_PROFILER
476493762fcSSteven Rostedt struct ftrace_profile {
477493762fcSSteven Rostedt 	struct hlist_node		node;
478493762fcSSteven Rostedt 	unsigned long			ip;
479493762fcSSteven Rostedt 	unsigned long			counter;
4800706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
4810706f1c4SSteven Rostedt 	unsigned long long		time;
482e330b3bcSChase Douglas 	unsigned long long		time_squared;
4830706f1c4SSteven Rostedt #endif
484493762fcSSteven Rostedt };
485493762fcSSteven Rostedt 
486493762fcSSteven Rostedt struct ftrace_profile_page {
487493762fcSSteven Rostedt 	struct ftrace_profile_page	*next;
488493762fcSSteven Rostedt 	unsigned long			index;
489493762fcSSteven Rostedt 	struct ftrace_profile		records[];
490493762fcSSteven Rostedt };
491493762fcSSteven Rostedt 
492cafb168aSSteven Rostedt struct ftrace_profile_stat {
493cafb168aSSteven Rostedt 	atomic_t			disabled;
494cafb168aSSteven Rostedt 	struct hlist_head		*hash;
495cafb168aSSteven Rostedt 	struct ftrace_profile_page	*pages;
496cafb168aSSteven Rostedt 	struct ftrace_profile_page	*start;
497cafb168aSSteven Rostedt 	struct tracer_stat		stat;
498cafb168aSSteven Rostedt };
499cafb168aSSteven Rostedt 
500493762fcSSteven Rostedt #define PROFILE_RECORDS_SIZE						\
501493762fcSSteven Rostedt 	(PAGE_SIZE - offsetof(struct ftrace_profile_page, records))
502493762fcSSteven Rostedt 
503493762fcSSteven Rostedt #define PROFILES_PER_PAGE					\
504493762fcSSteven Rostedt 	(PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile))
505493762fcSSteven Rostedt 
506fb9fb015SSteven Rostedt static int ftrace_profile_enabled __read_mostly;
507fb9fb015SSteven Rostedt 
508fb9fb015SSteven Rostedt /* ftrace_profile_lock - synchronize the enable and disable of the profiler */
509493762fcSSteven Rostedt static DEFINE_MUTEX(ftrace_profile_lock);
510493762fcSSteven Rostedt 
511cafb168aSSteven Rostedt static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats);
512493762fcSSteven Rostedt 
51320079ebeSNamhyung Kim #define FTRACE_PROFILE_HASH_BITS 10
51420079ebeSNamhyung Kim #define FTRACE_PROFILE_HASH_SIZE (1 << FTRACE_PROFILE_HASH_BITS)
515493762fcSSteven Rostedt 
516493762fcSSteven Rostedt static void *
517493762fcSSteven Rostedt function_stat_next(void *v, int idx)
518493762fcSSteven Rostedt {
519493762fcSSteven Rostedt 	struct ftrace_profile *rec = v;
520493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
521493762fcSSteven Rostedt 
522493762fcSSteven Rostedt 	pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK);
523493762fcSSteven Rostedt 
524493762fcSSteven Rostedt  again:
5250296e425SLi Zefan 	if (idx != 0)
526493762fcSSteven Rostedt 		rec++;
5270296e425SLi Zefan 
528493762fcSSteven Rostedt 	if ((void *)rec >= (void *)&pg->records[pg->index]) {
529493762fcSSteven Rostedt 		pg = pg->next;
530493762fcSSteven Rostedt 		if (!pg)
531493762fcSSteven Rostedt 			return NULL;
532493762fcSSteven Rostedt 		rec = &pg->records[0];
533493762fcSSteven Rostedt 		if (!rec->counter)
534493762fcSSteven Rostedt 			goto again;
535493762fcSSteven Rostedt 	}
536493762fcSSteven Rostedt 
537493762fcSSteven Rostedt 	return rec;
538493762fcSSteven Rostedt }
539493762fcSSteven Rostedt 
540493762fcSSteven Rostedt static void *function_stat_start(struct tracer_stat *trace)
541493762fcSSteven Rostedt {
542cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat =
543cafb168aSSteven Rostedt 		container_of(trace, struct ftrace_profile_stat, stat);
544cafb168aSSteven Rostedt 
545cafb168aSSteven Rostedt 	if (!stat || !stat->start)
546cafb168aSSteven Rostedt 		return NULL;
547cafb168aSSteven Rostedt 
548cafb168aSSteven Rostedt 	return function_stat_next(&stat->start->records[0], 0);
549493762fcSSteven Rostedt }
550493762fcSSteven Rostedt 
5510706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
5520706f1c4SSteven Rostedt /* function graph compares on total time */
5530706f1c4SSteven Rostedt static int function_stat_cmp(void *p1, void *p2)
5540706f1c4SSteven Rostedt {
5550706f1c4SSteven Rostedt 	struct ftrace_profile *a = p1;
5560706f1c4SSteven Rostedt 	struct ftrace_profile *b = p2;
5570706f1c4SSteven Rostedt 
5580706f1c4SSteven Rostedt 	if (a->time < b->time)
5590706f1c4SSteven Rostedt 		return -1;
5600706f1c4SSteven Rostedt 	if (a->time > b->time)
5610706f1c4SSteven Rostedt 		return 1;
5620706f1c4SSteven Rostedt 	else
5630706f1c4SSteven Rostedt 		return 0;
5640706f1c4SSteven Rostedt }
5650706f1c4SSteven Rostedt #else
5660706f1c4SSteven Rostedt /* not function graph compares against hits */
567493762fcSSteven Rostedt static int function_stat_cmp(void *p1, void *p2)
568493762fcSSteven Rostedt {
569493762fcSSteven Rostedt 	struct ftrace_profile *a = p1;
570493762fcSSteven Rostedt 	struct ftrace_profile *b = p2;
571493762fcSSteven Rostedt 
572493762fcSSteven Rostedt 	if (a->counter < b->counter)
573493762fcSSteven Rostedt 		return -1;
574493762fcSSteven Rostedt 	if (a->counter > b->counter)
575493762fcSSteven Rostedt 		return 1;
576493762fcSSteven Rostedt 	else
577493762fcSSteven Rostedt 		return 0;
578493762fcSSteven Rostedt }
5790706f1c4SSteven Rostedt #endif
580493762fcSSteven Rostedt 
581493762fcSSteven Rostedt static int function_stat_headers(struct seq_file *m)
582493762fcSSteven Rostedt {
5830706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
58434886c8bSSteven Rostedt 	seq_printf(m, "  Function                               "
585e330b3bcSChase Douglas 		   "Hit    Time            Avg             s^2\n"
58634886c8bSSteven Rostedt 		      "  --------                               "
587e330b3bcSChase Douglas 		   "---    ----            ---             ---\n");
5880706f1c4SSteven Rostedt #else
589493762fcSSteven Rostedt 	seq_printf(m, "  Function                               Hit\n"
590493762fcSSteven Rostedt 		      "  --------                               ---\n");
5910706f1c4SSteven Rostedt #endif
592493762fcSSteven Rostedt 	return 0;
593493762fcSSteven Rostedt }
594493762fcSSteven Rostedt 
595493762fcSSteven Rostedt static int function_stat_show(struct seq_file *m, void *v)
596493762fcSSteven Rostedt {
597493762fcSSteven Rostedt 	struct ftrace_profile *rec = v;
598493762fcSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
5993aaba20fSLi Zefan 	int ret = 0;
6000706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
60134886c8bSSteven Rostedt 	static struct trace_seq s;
60234886c8bSSteven Rostedt 	unsigned long long avg;
603e330b3bcSChase Douglas 	unsigned long long stddev;
6040706f1c4SSteven Rostedt #endif
6053aaba20fSLi Zefan 	mutex_lock(&ftrace_profile_lock);
6063aaba20fSLi Zefan 
6073aaba20fSLi Zefan 	/* we raced with function_profile_reset() */
6083aaba20fSLi Zefan 	if (unlikely(rec->counter == 0)) {
6093aaba20fSLi Zefan 		ret = -EBUSY;
6103aaba20fSLi Zefan 		goto out;
6113aaba20fSLi Zefan 	}
612493762fcSSteven Rostedt 
613493762fcSSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
6140706f1c4SSteven Rostedt 	seq_printf(m, "  %-30.30s  %10lu", str, rec->counter);
615493762fcSSteven Rostedt 
6160706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
6170706f1c4SSteven Rostedt 	seq_printf(m, "    ");
61834886c8bSSteven Rostedt 	avg = rec->time;
61934886c8bSSteven Rostedt 	do_div(avg, rec->counter);
62034886c8bSSteven Rostedt 
621e330b3bcSChase Douglas 	/* Sample standard deviation (s^2) */
622e330b3bcSChase Douglas 	if (rec->counter <= 1)
623e330b3bcSChase Douglas 		stddev = 0;
624e330b3bcSChase Douglas 	else {
625e330b3bcSChase Douglas 		stddev = rec->time_squared - rec->counter * avg * avg;
626e330b3bcSChase Douglas 		/*
627e330b3bcSChase Douglas 		 * Divide only 1000 for ns^2 -> us^2 conversion.
628e330b3bcSChase Douglas 		 * trace_print_graph_duration will divide 1000 again.
629e330b3bcSChase Douglas 		 */
630e330b3bcSChase Douglas 		do_div(stddev, (rec->counter - 1) * 1000);
631e330b3bcSChase Douglas 	}
632e330b3bcSChase Douglas 
63334886c8bSSteven Rostedt 	trace_seq_init(&s);
63434886c8bSSteven Rostedt 	trace_print_graph_duration(rec->time, &s);
63534886c8bSSteven Rostedt 	trace_seq_puts(&s, "    ");
63634886c8bSSteven Rostedt 	trace_print_graph_duration(avg, &s);
637e330b3bcSChase Douglas 	trace_seq_puts(&s, "    ");
638e330b3bcSChase Douglas 	trace_print_graph_duration(stddev, &s);
6390706f1c4SSteven Rostedt 	trace_print_seq(m, &s);
6400706f1c4SSteven Rostedt #endif
6410706f1c4SSteven Rostedt 	seq_putc(m, '\n');
6423aaba20fSLi Zefan out:
6433aaba20fSLi Zefan 	mutex_unlock(&ftrace_profile_lock);
6440706f1c4SSteven Rostedt 
6453aaba20fSLi Zefan 	return ret;
646493762fcSSteven Rostedt }
647493762fcSSteven Rostedt 
648cafb168aSSteven Rostedt static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
649493762fcSSteven Rostedt {
650493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
651493762fcSSteven Rostedt 
652cafb168aSSteven Rostedt 	pg = stat->pages = stat->start;
653493762fcSSteven Rostedt 
654493762fcSSteven Rostedt 	while (pg) {
655493762fcSSteven Rostedt 		memset(pg->records, 0, PROFILE_RECORDS_SIZE);
656493762fcSSteven Rostedt 		pg->index = 0;
657493762fcSSteven Rostedt 		pg = pg->next;
658493762fcSSteven Rostedt 	}
659493762fcSSteven Rostedt 
660cafb168aSSteven Rostedt 	memset(stat->hash, 0,
661493762fcSSteven Rostedt 	       FTRACE_PROFILE_HASH_SIZE * sizeof(struct hlist_head));
662493762fcSSteven Rostedt }
663493762fcSSteven Rostedt 
664cafb168aSSteven Rostedt int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)
665493762fcSSteven Rostedt {
666493762fcSSteven Rostedt 	struct ftrace_profile_page *pg;
667318e0a73SSteven Rostedt 	int functions;
668318e0a73SSteven Rostedt 	int pages;
669493762fcSSteven Rostedt 	int i;
670493762fcSSteven Rostedt 
671493762fcSSteven Rostedt 	/* If we already allocated, do nothing */
672cafb168aSSteven Rostedt 	if (stat->pages)
673493762fcSSteven Rostedt 		return 0;
674493762fcSSteven Rostedt 
675cafb168aSSteven Rostedt 	stat->pages = (void *)get_zeroed_page(GFP_KERNEL);
676cafb168aSSteven Rostedt 	if (!stat->pages)
677493762fcSSteven Rostedt 		return -ENOMEM;
678493762fcSSteven Rostedt 
679318e0a73SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE
680318e0a73SSteven Rostedt 	functions = ftrace_update_tot_cnt;
681318e0a73SSteven Rostedt #else
682318e0a73SSteven Rostedt 	/*
683318e0a73SSteven Rostedt 	 * We do not know the number of functions that exist because
684318e0a73SSteven Rostedt 	 * dynamic tracing is what counts them. With past experience
685318e0a73SSteven Rostedt 	 * we have around 20K functions. That should be more than enough.
686318e0a73SSteven Rostedt 	 * It is highly unlikely we will execute every function in
687318e0a73SSteven Rostedt 	 * the kernel.
688318e0a73SSteven Rostedt 	 */
689318e0a73SSteven Rostedt 	functions = 20000;
690318e0a73SSteven Rostedt #endif
691318e0a73SSteven Rostedt 
692cafb168aSSteven Rostedt 	pg = stat->start = stat->pages;
693493762fcSSteven Rostedt 
694318e0a73SSteven Rostedt 	pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE);
695318e0a73SSteven Rostedt 
69639e30cd1SNamhyung Kim 	for (i = 1; i < pages; i++) {
697493762fcSSteven Rostedt 		pg->next = (void *)get_zeroed_page(GFP_KERNEL);
698493762fcSSteven Rostedt 		if (!pg->next)
699318e0a73SSteven Rostedt 			goto out_free;
700493762fcSSteven Rostedt 		pg = pg->next;
701493762fcSSteven Rostedt 	}
702493762fcSSteven Rostedt 
703493762fcSSteven Rostedt 	return 0;
704318e0a73SSteven Rostedt 
705318e0a73SSteven Rostedt  out_free:
706318e0a73SSteven Rostedt 	pg = stat->start;
707318e0a73SSteven Rostedt 	while (pg) {
708318e0a73SSteven Rostedt 		unsigned long tmp = (unsigned long)pg;
709318e0a73SSteven Rostedt 
710318e0a73SSteven Rostedt 		pg = pg->next;
711318e0a73SSteven Rostedt 		free_page(tmp);
712318e0a73SSteven Rostedt 	}
713318e0a73SSteven Rostedt 
714318e0a73SSteven Rostedt 	stat->pages = NULL;
715318e0a73SSteven Rostedt 	stat->start = NULL;
716318e0a73SSteven Rostedt 
717318e0a73SSteven Rostedt 	return -ENOMEM;
718493762fcSSteven Rostedt }
719493762fcSSteven Rostedt 
720cafb168aSSteven Rostedt static int ftrace_profile_init_cpu(int cpu)
721493762fcSSteven Rostedt {
722cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
723493762fcSSteven Rostedt 	int size;
724493762fcSSteven Rostedt 
725cafb168aSSteven Rostedt 	stat = &per_cpu(ftrace_profile_stats, cpu);
726cafb168aSSteven Rostedt 
727cafb168aSSteven Rostedt 	if (stat->hash) {
728493762fcSSteven Rostedt 		/* If the profile is already created, simply reset it */
729cafb168aSSteven Rostedt 		ftrace_profile_reset(stat);
730493762fcSSteven Rostedt 		return 0;
731493762fcSSteven Rostedt 	}
732493762fcSSteven Rostedt 
733493762fcSSteven Rostedt 	/*
734493762fcSSteven Rostedt 	 * We are profiling all functions, but usually only a few thousand
735493762fcSSteven Rostedt 	 * functions are hit. We'll make a hash of 1024 items.
736493762fcSSteven Rostedt 	 */
737493762fcSSteven Rostedt 	size = FTRACE_PROFILE_HASH_SIZE;
738493762fcSSteven Rostedt 
739cafb168aSSteven Rostedt 	stat->hash = kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL);
740493762fcSSteven Rostedt 
741cafb168aSSteven Rostedt 	if (!stat->hash)
742493762fcSSteven Rostedt 		return -ENOMEM;
743493762fcSSteven Rostedt 
744318e0a73SSteven Rostedt 	/* Preallocate the function profiling pages */
745cafb168aSSteven Rostedt 	if (ftrace_profile_pages_init(stat) < 0) {
746cafb168aSSteven Rostedt 		kfree(stat->hash);
747cafb168aSSteven Rostedt 		stat->hash = NULL;
748493762fcSSteven Rostedt 		return -ENOMEM;
749493762fcSSteven Rostedt 	}
750493762fcSSteven Rostedt 
751493762fcSSteven Rostedt 	return 0;
752493762fcSSteven Rostedt }
753493762fcSSteven Rostedt 
754cafb168aSSteven Rostedt static int ftrace_profile_init(void)
755cafb168aSSteven Rostedt {
756cafb168aSSteven Rostedt 	int cpu;
757cafb168aSSteven Rostedt 	int ret = 0;
758cafb168aSSteven Rostedt 
759cafb168aSSteven Rostedt 	for_each_online_cpu(cpu) {
760cafb168aSSteven Rostedt 		ret = ftrace_profile_init_cpu(cpu);
761cafb168aSSteven Rostedt 		if (ret)
762cafb168aSSteven Rostedt 			break;
763cafb168aSSteven Rostedt 	}
764cafb168aSSteven Rostedt 
765cafb168aSSteven Rostedt 	return ret;
766cafb168aSSteven Rostedt }
767cafb168aSSteven Rostedt 
768493762fcSSteven Rostedt /* interrupts must be disabled */
769cafb168aSSteven Rostedt static struct ftrace_profile *
770cafb168aSSteven Rostedt ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)
771493762fcSSteven Rostedt {
772493762fcSSteven Rostedt 	struct ftrace_profile *rec;
773493762fcSSteven Rostedt 	struct hlist_head *hhd;
774493762fcSSteven Rostedt 	unsigned long key;
775493762fcSSteven Rostedt 
77620079ebeSNamhyung Kim 	key = hash_long(ip, FTRACE_PROFILE_HASH_BITS);
777cafb168aSSteven Rostedt 	hhd = &stat->hash[key];
778493762fcSSteven Rostedt 
779493762fcSSteven Rostedt 	if (hlist_empty(hhd))
780493762fcSSteven Rostedt 		return NULL;
781493762fcSSteven Rostedt 
782*1bb539caSSteven Rostedt 	hlist_for_each_entry_rcu_notrace(rec, hhd, node) {
783493762fcSSteven Rostedt 		if (rec->ip == ip)
784493762fcSSteven Rostedt 			return rec;
785493762fcSSteven Rostedt 	}
786493762fcSSteven Rostedt 
787493762fcSSteven Rostedt 	return NULL;
788493762fcSSteven Rostedt }
789493762fcSSteven Rostedt 
790cafb168aSSteven Rostedt static void ftrace_add_profile(struct ftrace_profile_stat *stat,
791cafb168aSSteven Rostedt 			       struct ftrace_profile *rec)
792493762fcSSteven Rostedt {
793493762fcSSteven Rostedt 	unsigned long key;
794493762fcSSteven Rostedt 
79520079ebeSNamhyung Kim 	key = hash_long(rec->ip, FTRACE_PROFILE_HASH_BITS);
796cafb168aSSteven Rostedt 	hlist_add_head_rcu(&rec->node, &stat->hash[key]);
797493762fcSSteven Rostedt }
798493762fcSSteven Rostedt 
799318e0a73SSteven Rostedt /*
800318e0a73SSteven Rostedt  * The memory is already allocated, this simply finds a new record to use.
801318e0a73SSteven Rostedt  */
802493762fcSSteven Rostedt static struct ftrace_profile *
803318e0a73SSteven Rostedt ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)
804493762fcSSteven Rostedt {
805493762fcSSteven Rostedt 	struct ftrace_profile *rec = NULL;
806493762fcSSteven Rostedt 
807318e0a73SSteven Rostedt 	/* prevent recursion (from NMIs) */
808cafb168aSSteven Rostedt 	if (atomic_inc_return(&stat->disabled) != 1)
809493762fcSSteven Rostedt 		goto out;
810493762fcSSteven Rostedt 
811493762fcSSteven Rostedt 	/*
812318e0a73SSteven Rostedt 	 * Try to find the function again since an NMI
813318e0a73SSteven Rostedt 	 * could have added it
814493762fcSSteven Rostedt 	 */
815cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, ip);
816493762fcSSteven Rostedt 	if (rec)
817cafb168aSSteven Rostedt 		goto out;
818493762fcSSteven Rostedt 
819cafb168aSSteven Rostedt 	if (stat->pages->index == PROFILES_PER_PAGE) {
820cafb168aSSteven Rostedt 		if (!stat->pages->next)
821cafb168aSSteven Rostedt 			goto out;
822cafb168aSSteven Rostedt 		stat->pages = stat->pages->next;
823493762fcSSteven Rostedt 	}
824493762fcSSteven Rostedt 
825cafb168aSSteven Rostedt 	rec = &stat->pages->records[stat->pages->index++];
826493762fcSSteven Rostedt 	rec->ip = ip;
827cafb168aSSteven Rostedt 	ftrace_add_profile(stat, rec);
828493762fcSSteven Rostedt 
829493762fcSSteven Rostedt  out:
830cafb168aSSteven Rostedt 	atomic_dec(&stat->disabled);
831493762fcSSteven Rostedt 
832493762fcSSteven Rostedt 	return rec;
833493762fcSSteven Rostedt }
834493762fcSSteven Rostedt 
835493762fcSSteven Rostedt static void
8362f5f6ad9SSteven Rostedt function_profile_call(unsigned long ip, unsigned long parent_ip,
837a1e2e31dSSteven Rostedt 		      struct ftrace_ops *ops, struct pt_regs *regs)
838493762fcSSteven Rostedt {
839cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
840493762fcSSteven Rostedt 	struct ftrace_profile *rec;
841493762fcSSteven Rostedt 	unsigned long flags;
842493762fcSSteven Rostedt 
843493762fcSSteven Rostedt 	if (!ftrace_profile_enabled)
844493762fcSSteven Rostedt 		return;
845493762fcSSteven Rostedt 
846493762fcSSteven Rostedt 	local_irq_save(flags);
847cafb168aSSteven Rostedt 
848cafb168aSSteven Rostedt 	stat = &__get_cpu_var(ftrace_profile_stats);
8490f6ce3deSSteven Rostedt 	if (!stat->hash || !ftrace_profile_enabled)
850cafb168aSSteven Rostedt 		goto out;
851cafb168aSSteven Rostedt 
852cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, ip);
853493762fcSSteven Rostedt 	if (!rec) {
854318e0a73SSteven Rostedt 		rec = ftrace_profile_alloc(stat, ip);
855493762fcSSteven Rostedt 		if (!rec)
856493762fcSSteven Rostedt 			goto out;
857493762fcSSteven Rostedt 	}
858493762fcSSteven Rostedt 
859493762fcSSteven Rostedt 	rec->counter++;
860493762fcSSteven Rostedt  out:
861493762fcSSteven Rostedt 	local_irq_restore(flags);
862493762fcSSteven Rostedt }
863493762fcSSteven Rostedt 
8640706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
8650706f1c4SSteven Rostedt static int profile_graph_entry(struct ftrace_graph_ent *trace)
8660706f1c4SSteven Rostedt {
867a1e2e31dSSteven Rostedt 	function_profile_call(trace->func, 0, NULL, NULL);
8680706f1c4SSteven Rostedt 	return 1;
8690706f1c4SSteven Rostedt }
8700706f1c4SSteven Rostedt 
8710706f1c4SSteven Rostedt static void profile_graph_return(struct ftrace_graph_ret *trace)
8720706f1c4SSteven Rostedt {
873cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
874a2a16d6aSSteven Rostedt 	unsigned long long calltime;
8750706f1c4SSteven Rostedt 	struct ftrace_profile *rec;
876cafb168aSSteven Rostedt 	unsigned long flags;
8770706f1c4SSteven Rostedt 
8780706f1c4SSteven Rostedt 	local_irq_save(flags);
879cafb168aSSteven Rostedt 	stat = &__get_cpu_var(ftrace_profile_stats);
8800f6ce3deSSteven Rostedt 	if (!stat->hash || !ftrace_profile_enabled)
881cafb168aSSteven Rostedt 		goto out;
882cafb168aSSteven Rostedt 
88337e44bc5SSteven Rostedt 	/* If the calltime was zero'd ignore it */
88437e44bc5SSteven Rostedt 	if (!trace->calltime)
88537e44bc5SSteven Rostedt 		goto out;
88637e44bc5SSteven Rostedt 
887a2a16d6aSSteven Rostedt 	calltime = trace->rettime - trace->calltime;
888a2a16d6aSSteven Rostedt 
889a2a16d6aSSteven Rostedt 	if (!(trace_flags & TRACE_ITER_GRAPH_TIME)) {
890a2a16d6aSSteven Rostedt 		int index;
891a2a16d6aSSteven Rostedt 
892a2a16d6aSSteven Rostedt 		index = trace->depth;
893a2a16d6aSSteven Rostedt 
894a2a16d6aSSteven Rostedt 		/* Append this call time to the parent time to subtract */
895a2a16d6aSSteven Rostedt 		if (index)
896a2a16d6aSSteven Rostedt 			current->ret_stack[index - 1].subtime += calltime;
897a2a16d6aSSteven Rostedt 
898a2a16d6aSSteven Rostedt 		if (current->ret_stack[index].subtime < calltime)
899a2a16d6aSSteven Rostedt 			calltime -= current->ret_stack[index].subtime;
900a2a16d6aSSteven Rostedt 		else
901a2a16d6aSSteven Rostedt 			calltime = 0;
902a2a16d6aSSteven Rostedt 	}
903a2a16d6aSSteven Rostedt 
904cafb168aSSteven Rostedt 	rec = ftrace_find_profiled_func(stat, trace->func);
905e330b3bcSChase Douglas 	if (rec) {
906a2a16d6aSSteven Rostedt 		rec->time += calltime;
907e330b3bcSChase Douglas 		rec->time_squared += calltime * calltime;
908e330b3bcSChase Douglas 	}
909a2a16d6aSSteven Rostedt 
910cafb168aSSteven Rostedt  out:
9110706f1c4SSteven Rostedt 	local_irq_restore(flags);
9120706f1c4SSteven Rostedt }
9130706f1c4SSteven Rostedt 
9140706f1c4SSteven Rostedt static int register_ftrace_profiler(void)
9150706f1c4SSteven Rostedt {
9160706f1c4SSteven Rostedt 	return register_ftrace_graph(&profile_graph_return,
9170706f1c4SSteven Rostedt 				     &profile_graph_entry);
9180706f1c4SSteven Rostedt }
9190706f1c4SSteven Rostedt 
9200706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void)
9210706f1c4SSteven Rostedt {
9220706f1c4SSteven Rostedt 	unregister_ftrace_graph();
9230706f1c4SSteven Rostedt }
9240706f1c4SSteven Rostedt #else
925bd38c0e6SPaul McQuade static struct ftrace_ops ftrace_profile_ops __read_mostly = {
926493762fcSSteven Rostedt 	.func		= function_profile_call,
927f04f24fbSMasami Hiramatsu 	.flags		= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
928f04f24fbSMasami Hiramatsu 	INIT_REGEX_LOCK(ftrace_profile_ops)
929493762fcSSteven Rostedt };
930493762fcSSteven Rostedt 
9310706f1c4SSteven Rostedt static int register_ftrace_profiler(void)
9320706f1c4SSteven Rostedt {
9330706f1c4SSteven Rostedt 	return register_ftrace_function(&ftrace_profile_ops);
9340706f1c4SSteven Rostedt }
9350706f1c4SSteven Rostedt 
9360706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void)
9370706f1c4SSteven Rostedt {
9380706f1c4SSteven Rostedt 	unregister_ftrace_function(&ftrace_profile_ops);
9390706f1c4SSteven Rostedt }
9400706f1c4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
9410706f1c4SSteven Rostedt 
942493762fcSSteven Rostedt static ssize_t
943493762fcSSteven Rostedt ftrace_profile_write(struct file *filp, const char __user *ubuf,
944493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
945493762fcSSteven Rostedt {
946493762fcSSteven Rostedt 	unsigned long val;
947493762fcSSteven Rostedt 	int ret;
948493762fcSSteven Rostedt 
94922fe9b54SPeter Huewe 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
95022fe9b54SPeter Huewe 	if (ret)
951493762fcSSteven Rostedt 		return ret;
952493762fcSSteven Rostedt 
953493762fcSSteven Rostedt 	val = !!val;
954493762fcSSteven Rostedt 
955493762fcSSteven Rostedt 	mutex_lock(&ftrace_profile_lock);
956493762fcSSteven Rostedt 	if (ftrace_profile_enabled ^ val) {
957493762fcSSteven Rostedt 		if (val) {
958493762fcSSteven Rostedt 			ret = ftrace_profile_init();
959493762fcSSteven Rostedt 			if (ret < 0) {
960493762fcSSteven Rostedt 				cnt = ret;
961493762fcSSteven Rostedt 				goto out;
962493762fcSSteven Rostedt 			}
963493762fcSSteven Rostedt 
9640706f1c4SSteven Rostedt 			ret = register_ftrace_profiler();
9650706f1c4SSteven Rostedt 			if (ret < 0) {
9660706f1c4SSteven Rostedt 				cnt = ret;
9670706f1c4SSteven Rostedt 				goto out;
9680706f1c4SSteven Rostedt 			}
969493762fcSSteven Rostedt 			ftrace_profile_enabled = 1;
970493762fcSSteven Rostedt 		} else {
971493762fcSSteven Rostedt 			ftrace_profile_enabled = 0;
9720f6ce3deSSteven Rostedt 			/*
9730f6ce3deSSteven Rostedt 			 * unregister_ftrace_profiler calls stop_machine
9740f6ce3deSSteven Rostedt 			 * so this acts like an synchronize_sched.
9750f6ce3deSSteven Rostedt 			 */
9760706f1c4SSteven Rostedt 			unregister_ftrace_profiler();
977493762fcSSteven Rostedt 		}
978493762fcSSteven Rostedt 	}
979493762fcSSteven Rostedt  out:
980493762fcSSteven Rostedt 	mutex_unlock(&ftrace_profile_lock);
981493762fcSSteven Rostedt 
982cf8517cfSJiri Olsa 	*ppos += cnt;
983493762fcSSteven Rostedt 
984493762fcSSteven Rostedt 	return cnt;
985493762fcSSteven Rostedt }
986493762fcSSteven Rostedt 
987493762fcSSteven Rostedt static ssize_t
988493762fcSSteven Rostedt ftrace_profile_read(struct file *filp, char __user *ubuf,
989493762fcSSteven Rostedt 		     size_t cnt, loff_t *ppos)
990493762fcSSteven Rostedt {
991fb9fb015SSteven Rostedt 	char buf[64];		/* big enough to hold a number */
992493762fcSSteven Rostedt 	int r;
993493762fcSSteven Rostedt 
994493762fcSSteven Rostedt 	r = sprintf(buf, "%u\n", ftrace_profile_enabled);
995493762fcSSteven Rostedt 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
996493762fcSSteven Rostedt }
997493762fcSSteven Rostedt 
998493762fcSSteven Rostedt static const struct file_operations ftrace_profile_fops = {
999493762fcSSteven Rostedt 	.open		= tracing_open_generic,
1000493762fcSSteven Rostedt 	.read		= ftrace_profile_read,
1001493762fcSSteven Rostedt 	.write		= ftrace_profile_write,
10026038f373SArnd Bergmann 	.llseek		= default_llseek,
1003493762fcSSteven Rostedt };
1004493762fcSSteven Rostedt 
1005cafb168aSSteven Rostedt /* used to initialize the real stat files */
1006cafb168aSSteven Rostedt static struct tracer_stat function_stats __initdata = {
1007cafb168aSSteven Rostedt 	.name		= "functions",
1008cafb168aSSteven Rostedt 	.stat_start	= function_stat_start,
1009cafb168aSSteven Rostedt 	.stat_next	= function_stat_next,
1010cafb168aSSteven Rostedt 	.stat_cmp	= function_stat_cmp,
1011cafb168aSSteven Rostedt 	.stat_headers	= function_stat_headers,
1012cafb168aSSteven Rostedt 	.stat_show	= function_stat_show
1013cafb168aSSteven Rostedt };
1014cafb168aSSteven Rostedt 
10156ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
1016493762fcSSteven Rostedt {
1017cafb168aSSteven Rostedt 	struct ftrace_profile_stat *stat;
1018493762fcSSteven Rostedt 	struct dentry *entry;
1019cafb168aSSteven Rostedt 	char *name;
1020493762fcSSteven Rostedt 	int ret;
1021cafb168aSSteven Rostedt 	int cpu;
1022493762fcSSteven Rostedt 
1023cafb168aSSteven Rostedt 	for_each_possible_cpu(cpu) {
1024cafb168aSSteven Rostedt 		stat = &per_cpu(ftrace_profile_stats, cpu);
1025cafb168aSSteven Rostedt 
1026cafb168aSSteven Rostedt 		/* allocate enough for function name + cpu number */
1027cafb168aSSteven Rostedt 		name = kmalloc(32, GFP_KERNEL);
1028cafb168aSSteven Rostedt 		if (!name) {
1029cafb168aSSteven Rostedt 			/*
1030cafb168aSSteven Rostedt 			 * The files created are permanent, if something happens
1031cafb168aSSteven Rostedt 			 * we still do not free memory.
1032cafb168aSSteven Rostedt 			 */
1033cafb168aSSteven Rostedt 			WARN(1,
1034cafb168aSSteven Rostedt 			     "Could not allocate stat file for cpu %d\n",
1035cafb168aSSteven Rostedt 			     cpu);
1036493762fcSSteven Rostedt 			return;
1037493762fcSSteven Rostedt 		}
1038cafb168aSSteven Rostedt 		stat->stat = function_stats;
1039cafb168aSSteven Rostedt 		snprintf(name, 32, "function%d", cpu);
1040cafb168aSSteven Rostedt 		stat->stat.name = name;
1041cafb168aSSteven Rostedt 		ret = register_stat_tracer(&stat->stat);
1042cafb168aSSteven Rostedt 		if (ret) {
1043cafb168aSSteven Rostedt 			WARN(1,
1044cafb168aSSteven Rostedt 			     "Could not register function stat for cpu %d\n",
1045cafb168aSSteven Rostedt 			     cpu);
1046cafb168aSSteven Rostedt 			kfree(name);
1047cafb168aSSteven Rostedt 			return;
1048cafb168aSSteven Rostedt 		}
1049cafb168aSSteven Rostedt 	}
1050493762fcSSteven Rostedt 
1051493762fcSSteven Rostedt 	entry = debugfs_create_file("function_profile_enabled", 0644,
1052493762fcSSteven Rostedt 				    d_tracer, NULL, &ftrace_profile_fops);
1053493762fcSSteven Rostedt 	if (!entry)
1054493762fcSSteven Rostedt 		pr_warning("Could not create debugfs "
1055493762fcSSteven Rostedt 			   "'function_profile_enabled' entry\n");
1056493762fcSSteven Rostedt }
1057493762fcSSteven Rostedt 
1058493762fcSSteven Rostedt #else /* CONFIG_FUNCTION_PROFILER */
10596ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
1060493762fcSSteven Rostedt {
1061493762fcSSteven Rostedt }
1062493762fcSSteven Rostedt #endif /* CONFIG_FUNCTION_PROFILER */
1063493762fcSSteven Rostedt 
106473d3fd96SIngo Molnar static struct pid * const ftrace_swapper_pid = &init_struct_pid;
106573d3fd96SIngo Molnar 
10667f49ef69SSteven Rostedt (Red Hat) loff_t
10677f49ef69SSteven Rostedt (Red Hat) ftrace_filter_lseek(struct file *file, loff_t offset, int whence)
10687f49ef69SSteven Rostedt (Red Hat) {
10697f49ef69SSteven Rostedt (Red Hat) 	loff_t ret;
10707f49ef69SSteven Rostedt (Red Hat) 
10717f49ef69SSteven Rostedt (Red Hat) 	if (file->f_mode & FMODE_READ)
10727f49ef69SSteven Rostedt (Red Hat) 		ret = seq_lseek(file, offset, whence);
10737f49ef69SSteven Rostedt (Red Hat) 	else
10747f49ef69SSteven Rostedt (Red Hat) 		file->f_pos = ret = 1;
10757f49ef69SSteven Rostedt (Red Hat) 
10767f49ef69SSteven Rostedt (Red Hat) 	return ret;
10777f49ef69SSteven Rostedt (Red Hat) }
10787f49ef69SSteven Rostedt (Red Hat) 
10793d083395SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE
108073d3fd96SIngo Molnar 
108199ecdc43SSteven Rostedt #ifndef CONFIG_FTRACE_MCOUNT_RECORD
1082cb7be3b2SSteven Rostedt # error Dynamic ftrace depends on MCOUNT_RECORD
108399ecdc43SSteven Rostedt #endif
108499ecdc43SSteven Rostedt 
10858fc0c701SSteven Rostedt static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly;
10868fc0c701SSteven Rostedt 
1087b6887d79SSteven Rostedt struct ftrace_func_probe {
10888fc0c701SSteven Rostedt 	struct hlist_node	node;
1089b6887d79SSteven Rostedt 	struct ftrace_probe_ops	*ops;
10908fc0c701SSteven Rostedt 	unsigned long		flags;
10918fc0c701SSteven Rostedt 	unsigned long		ip;
10928fc0c701SSteven Rostedt 	void			*data;
10937818b388SSteven Rostedt (Red Hat) 	struct list_head	free_list;
10948fc0c701SSteven Rostedt };
10958fc0c701SSteven Rostedt 
1096b448c4e3SSteven Rostedt struct ftrace_func_entry {
1097b448c4e3SSteven Rostedt 	struct hlist_node hlist;
1098b448c4e3SSteven Rostedt 	unsigned long ip;
1099b448c4e3SSteven Rostedt };
1100b448c4e3SSteven Rostedt 
1101b448c4e3SSteven Rostedt struct ftrace_hash {
1102b448c4e3SSteven Rostedt 	unsigned long		size_bits;
1103b448c4e3SSteven Rostedt 	struct hlist_head	*buckets;
1104b448c4e3SSteven Rostedt 	unsigned long		count;
110507fd5515SSteven Rostedt 	struct rcu_head		rcu;
1106b448c4e3SSteven Rostedt };
1107b448c4e3SSteven Rostedt 
110833dc9b12SSteven Rostedt /*
110933dc9b12SSteven Rostedt  * We make these constant because no one should touch them,
111033dc9b12SSteven Rostedt  * but they are used as the default "empty hash", to avoid allocating
111133dc9b12SSteven Rostedt  * it all the time. These are in a read only section such that if
111233dc9b12SSteven Rostedt  * anyone does try to modify it, it will cause an exception.
111333dc9b12SSteven Rostedt  */
111433dc9b12SSteven Rostedt static const struct hlist_head empty_buckets[1];
111533dc9b12SSteven Rostedt static const struct ftrace_hash empty_hash = {
111633dc9b12SSteven Rostedt 	.buckets = (struct hlist_head *)empty_buckets,
1117b448c4e3SSteven Rostedt };
111833dc9b12SSteven Rostedt #define EMPTY_HASH	((struct ftrace_hash *)&empty_hash)
11195072c59fSSteven Rostedt 
11202b499381SSteven Rostedt static struct ftrace_ops global_ops = {
1121f45948e8SSteven Rostedt 	.func			= ftrace_stub,
112233dc9b12SSteven Rostedt 	.notrace_hash		= EMPTY_HASH,
112333dc9b12SSteven Rostedt 	.filter_hash		= EMPTY_HASH,
1124f04f24fbSMasami Hiramatsu 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
1125f04f24fbSMasami Hiramatsu 	INIT_REGEX_LOCK(global_ops)
1126f45948e8SSteven Rostedt };
1127f45948e8SSteven Rostedt 
11283c1720f0SSteven Rostedt struct ftrace_page {
11293c1720f0SSteven Rostedt 	struct ftrace_page	*next;
1130a7900875SSteven Rostedt 	struct dyn_ftrace	*records;
1131431aa3fbSSteven Rostedt 	int			index;
1132a7900875SSteven Rostedt 	int			size;
1133aa5e5ceaSDavid Miller };
11343c1720f0SSteven Rostedt 
113585ae32aeSSteven Rostedt static struct ftrace_page *ftrace_new_pgs;
113685ae32aeSSteven Rostedt 
1137a7900875SSteven Rostedt #define ENTRY_SIZE sizeof(struct dyn_ftrace)
1138a7900875SSteven Rostedt #define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
11393c1720f0SSteven Rostedt 
11403c1720f0SSteven Rostedt /* estimate from running different kernels */
11413c1720f0SSteven Rostedt #define NR_TO_INIT		10000
11423c1720f0SSteven Rostedt 
11433c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages_start;
11443c1720f0SSteven Rostedt static struct ftrace_page	*ftrace_pages;
11453c1720f0SSteven Rostedt 
114606a51d93SSteven Rostedt static bool ftrace_hash_empty(struct ftrace_hash *hash)
114706a51d93SSteven Rostedt {
114806a51d93SSteven Rostedt 	return !hash || !hash->count;
114906a51d93SSteven Rostedt }
115006a51d93SSteven Rostedt 
1151b448c4e3SSteven Rostedt static struct ftrace_func_entry *
1152b448c4e3SSteven Rostedt ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
1153b448c4e3SSteven Rostedt {
1154b448c4e3SSteven Rostedt 	unsigned long key;
1155b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1156b448c4e3SSteven Rostedt 	struct hlist_head *hhd;
1157b448c4e3SSteven Rostedt 
115806a51d93SSteven Rostedt 	if (ftrace_hash_empty(hash))
1159b448c4e3SSteven Rostedt 		return NULL;
1160b448c4e3SSteven Rostedt 
1161b448c4e3SSteven Rostedt 	if (hash->size_bits > 0)
1162b448c4e3SSteven Rostedt 		key = hash_long(ip, hash->size_bits);
1163b448c4e3SSteven Rostedt 	else
1164b448c4e3SSteven Rostedt 		key = 0;
1165b448c4e3SSteven Rostedt 
1166b448c4e3SSteven Rostedt 	hhd = &hash->buckets[key];
1167b448c4e3SSteven Rostedt 
1168*1bb539caSSteven Rostedt 	hlist_for_each_entry_rcu_notrace(entry, hhd, hlist) {
1169b448c4e3SSteven Rostedt 		if (entry->ip == ip)
1170b448c4e3SSteven Rostedt 			return entry;
1171b448c4e3SSteven Rostedt 	}
1172b448c4e3SSteven Rostedt 	return NULL;
1173b448c4e3SSteven Rostedt }
1174b448c4e3SSteven Rostedt 
117533dc9b12SSteven Rostedt static void __add_hash_entry(struct ftrace_hash *hash,
117633dc9b12SSteven Rostedt 			     struct ftrace_func_entry *entry)
117733dc9b12SSteven Rostedt {
117833dc9b12SSteven Rostedt 	struct hlist_head *hhd;
117933dc9b12SSteven Rostedt 	unsigned long key;
118033dc9b12SSteven Rostedt 
118133dc9b12SSteven Rostedt 	if (hash->size_bits)
118233dc9b12SSteven Rostedt 		key = hash_long(entry->ip, hash->size_bits);
118333dc9b12SSteven Rostedt 	else
118433dc9b12SSteven Rostedt 		key = 0;
118533dc9b12SSteven Rostedt 
118633dc9b12SSteven Rostedt 	hhd = &hash->buckets[key];
118733dc9b12SSteven Rostedt 	hlist_add_head(&entry->hlist, hhd);
118833dc9b12SSteven Rostedt 	hash->count++;
118933dc9b12SSteven Rostedt }
119033dc9b12SSteven Rostedt 
1191b448c4e3SSteven Rostedt static int add_hash_entry(struct ftrace_hash *hash, unsigned long ip)
1192b448c4e3SSteven Rostedt {
1193b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1194b448c4e3SSteven Rostedt 
1195b448c4e3SSteven Rostedt 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
1196b448c4e3SSteven Rostedt 	if (!entry)
1197b448c4e3SSteven Rostedt 		return -ENOMEM;
1198b448c4e3SSteven Rostedt 
1199b448c4e3SSteven Rostedt 	entry->ip = ip;
120033dc9b12SSteven Rostedt 	__add_hash_entry(hash, entry);
1201b448c4e3SSteven Rostedt 
1202b448c4e3SSteven Rostedt 	return 0;
1203b448c4e3SSteven Rostedt }
1204b448c4e3SSteven Rostedt 
1205b448c4e3SSteven Rostedt static void
120633dc9b12SSteven Rostedt free_hash_entry(struct ftrace_hash *hash,
120733dc9b12SSteven Rostedt 		  struct ftrace_func_entry *entry)
120833dc9b12SSteven Rostedt {
120933dc9b12SSteven Rostedt 	hlist_del(&entry->hlist);
121033dc9b12SSteven Rostedt 	kfree(entry);
121133dc9b12SSteven Rostedt 	hash->count--;
121233dc9b12SSteven Rostedt }
121333dc9b12SSteven Rostedt 
121433dc9b12SSteven Rostedt static void
1215b448c4e3SSteven Rostedt remove_hash_entry(struct ftrace_hash *hash,
1216b448c4e3SSteven Rostedt 		  struct ftrace_func_entry *entry)
1217b448c4e3SSteven Rostedt {
1218b448c4e3SSteven Rostedt 	hlist_del(&entry->hlist);
1219b448c4e3SSteven Rostedt 	hash->count--;
1220b448c4e3SSteven Rostedt }
1221b448c4e3SSteven Rostedt 
1222b448c4e3SSteven Rostedt static void ftrace_hash_clear(struct ftrace_hash *hash)
1223b448c4e3SSteven Rostedt {
1224b448c4e3SSteven Rostedt 	struct hlist_head *hhd;
1225b67bfe0dSSasha Levin 	struct hlist_node *tn;
1226b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
1227b448c4e3SSteven Rostedt 	int size = 1 << hash->size_bits;
1228b448c4e3SSteven Rostedt 	int i;
1229b448c4e3SSteven Rostedt 
123033dc9b12SSteven Rostedt 	if (!hash->count)
123133dc9b12SSteven Rostedt 		return;
123233dc9b12SSteven Rostedt 
1233b448c4e3SSteven Rostedt 	for (i = 0; i < size; i++) {
1234b448c4e3SSteven Rostedt 		hhd = &hash->buckets[i];
1235b67bfe0dSSasha Levin 		hlist_for_each_entry_safe(entry, tn, hhd, hlist)
123633dc9b12SSteven Rostedt 			free_hash_entry(hash, entry);
1237b448c4e3SSteven Rostedt 	}
1238b448c4e3SSteven Rostedt 	FTRACE_WARN_ON(hash->count);
1239b448c4e3SSteven Rostedt }
1240b448c4e3SSteven Rostedt 
124133dc9b12SSteven Rostedt static void free_ftrace_hash(struct ftrace_hash *hash)
124233dc9b12SSteven Rostedt {
124333dc9b12SSteven Rostedt 	if (!hash || hash == EMPTY_HASH)
124433dc9b12SSteven Rostedt 		return;
124533dc9b12SSteven Rostedt 	ftrace_hash_clear(hash);
124633dc9b12SSteven Rostedt 	kfree(hash->buckets);
124733dc9b12SSteven Rostedt 	kfree(hash);
124833dc9b12SSteven Rostedt }
124933dc9b12SSteven Rostedt 
125007fd5515SSteven Rostedt static void __free_ftrace_hash_rcu(struct rcu_head *rcu)
125107fd5515SSteven Rostedt {
125207fd5515SSteven Rostedt 	struct ftrace_hash *hash;
125307fd5515SSteven Rostedt 
125407fd5515SSteven Rostedt 	hash = container_of(rcu, struct ftrace_hash, rcu);
125507fd5515SSteven Rostedt 	free_ftrace_hash(hash);
125607fd5515SSteven Rostedt }
125707fd5515SSteven Rostedt 
125807fd5515SSteven Rostedt static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
125907fd5515SSteven Rostedt {
126007fd5515SSteven Rostedt 	if (!hash || hash == EMPTY_HASH)
126107fd5515SSteven Rostedt 		return;
126207fd5515SSteven Rostedt 	call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu);
126307fd5515SSteven Rostedt }
126407fd5515SSteven Rostedt 
12655500fa51SJiri Olsa void ftrace_free_filter(struct ftrace_ops *ops)
12665500fa51SJiri Olsa {
1267f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
12685500fa51SJiri Olsa 	free_ftrace_hash(ops->filter_hash);
12695500fa51SJiri Olsa 	free_ftrace_hash(ops->notrace_hash);
12705500fa51SJiri Olsa }
12715500fa51SJiri Olsa 
127233dc9b12SSteven Rostedt static struct ftrace_hash *alloc_ftrace_hash(int size_bits)
127333dc9b12SSteven Rostedt {
127433dc9b12SSteven Rostedt 	struct ftrace_hash *hash;
127533dc9b12SSteven Rostedt 	int size;
127633dc9b12SSteven Rostedt 
127733dc9b12SSteven Rostedt 	hash = kzalloc(sizeof(*hash), GFP_KERNEL);
127833dc9b12SSteven Rostedt 	if (!hash)
127933dc9b12SSteven Rostedt 		return NULL;
128033dc9b12SSteven Rostedt 
128133dc9b12SSteven Rostedt 	size = 1 << size_bits;
128247b0edcbSThomas Meyer 	hash->buckets = kcalloc(size, sizeof(*hash->buckets), GFP_KERNEL);
128333dc9b12SSteven Rostedt 
128433dc9b12SSteven Rostedt 	if (!hash->buckets) {
128533dc9b12SSteven Rostedt 		kfree(hash);
128633dc9b12SSteven Rostedt 		return NULL;
128733dc9b12SSteven Rostedt 	}
128833dc9b12SSteven Rostedt 
128933dc9b12SSteven Rostedt 	hash->size_bits = size_bits;
129033dc9b12SSteven Rostedt 
129133dc9b12SSteven Rostedt 	return hash;
129233dc9b12SSteven Rostedt }
129333dc9b12SSteven Rostedt 
129433dc9b12SSteven Rostedt static struct ftrace_hash *
129533dc9b12SSteven Rostedt alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
129633dc9b12SSteven Rostedt {
129733dc9b12SSteven Rostedt 	struct ftrace_func_entry *entry;
129833dc9b12SSteven Rostedt 	struct ftrace_hash *new_hash;
129933dc9b12SSteven Rostedt 	int size;
130033dc9b12SSteven Rostedt 	int ret;
130133dc9b12SSteven Rostedt 	int i;
130233dc9b12SSteven Rostedt 
130333dc9b12SSteven Rostedt 	new_hash = alloc_ftrace_hash(size_bits);
130433dc9b12SSteven Rostedt 	if (!new_hash)
130533dc9b12SSteven Rostedt 		return NULL;
130633dc9b12SSteven Rostedt 
130733dc9b12SSteven Rostedt 	/* Empty hash? */
130806a51d93SSteven Rostedt 	if (ftrace_hash_empty(hash))
130933dc9b12SSteven Rostedt 		return new_hash;
131033dc9b12SSteven Rostedt 
131133dc9b12SSteven Rostedt 	size = 1 << hash->size_bits;
131233dc9b12SSteven Rostedt 	for (i = 0; i < size; i++) {
1313b67bfe0dSSasha Levin 		hlist_for_each_entry(entry, &hash->buckets[i], hlist) {
131433dc9b12SSteven Rostedt 			ret = add_hash_entry(new_hash, entry->ip);
131533dc9b12SSteven Rostedt 			if (ret < 0)
131633dc9b12SSteven Rostedt 				goto free_hash;
131733dc9b12SSteven Rostedt 		}
131833dc9b12SSteven Rostedt 	}
131933dc9b12SSteven Rostedt 
132033dc9b12SSteven Rostedt 	FTRACE_WARN_ON(new_hash->count != hash->count);
132133dc9b12SSteven Rostedt 
132233dc9b12SSteven Rostedt 	return new_hash;
132333dc9b12SSteven Rostedt 
132433dc9b12SSteven Rostedt  free_hash:
132533dc9b12SSteven Rostedt 	free_ftrace_hash(new_hash);
132633dc9b12SSteven Rostedt 	return NULL;
132733dc9b12SSteven Rostedt }
132833dc9b12SSteven Rostedt 
132941fb61c2SSteven Rostedt static void
133041fb61c2SSteven Rostedt ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash);
133141fb61c2SSteven Rostedt static void
133241fb61c2SSteven Rostedt ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash);
133341fb61c2SSteven Rostedt 
133433dc9b12SSteven Rostedt static int
133541fb61c2SSteven Rostedt ftrace_hash_move(struct ftrace_ops *ops, int enable,
133641fb61c2SSteven Rostedt 		 struct ftrace_hash **dst, struct ftrace_hash *src)
133733dc9b12SSteven Rostedt {
133833dc9b12SSteven Rostedt 	struct ftrace_func_entry *entry;
1339b67bfe0dSSasha Levin 	struct hlist_node *tn;
134033dc9b12SSteven Rostedt 	struct hlist_head *hhd;
134107fd5515SSteven Rostedt 	struct ftrace_hash *old_hash;
134207fd5515SSteven Rostedt 	struct ftrace_hash *new_hash;
134333dc9b12SSteven Rostedt 	int size = src->count;
134433dc9b12SSteven Rostedt 	int bits = 0;
134541fb61c2SSteven Rostedt 	int ret;
134633dc9b12SSteven Rostedt 	int i;
134733dc9b12SSteven Rostedt 
134833dc9b12SSteven Rostedt 	/*
134941fb61c2SSteven Rostedt 	 * Remove the current set, update the hash and add
135041fb61c2SSteven Rostedt 	 * them back.
135141fb61c2SSteven Rostedt 	 */
135241fb61c2SSteven Rostedt 	ftrace_hash_rec_disable(ops, enable);
135341fb61c2SSteven Rostedt 
135441fb61c2SSteven Rostedt 	/*
135533dc9b12SSteven Rostedt 	 * If the new source is empty, just free dst and assign it
135633dc9b12SSteven Rostedt 	 * the empty_hash.
135733dc9b12SSteven Rostedt 	 */
135833dc9b12SSteven Rostedt 	if (!src->count) {
135907fd5515SSteven Rostedt 		free_ftrace_hash_rcu(*dst);
136007fd5515SSteven Rostedt 		rcu_assign_pointer(*dst, EMPTY_HASH);
1361d4d34b98SSteven Rostedt 		/* still need to update the function records */
1362d4d34b98SSteven Rostedt 		ret = 0;
1363d4d34b98SSteven Rostedt 		goto out;
136433dc9b12SSteven Rostedt 	}
136533dc9b12SSteven Rostedt 
136633dc9b12SSteven Rostedt 	/*
136733dc9b12SSteven Rostedt 	 * Make the hash size about 1/2 the # found
136833dc9b12SSteven Rostedt 	 */
136933dc9b12SSteven Rostedt 	for (size /= 2; size; size >>= 1)
137033dc9b12SSteven Rostedt 		bits++;
137133dc9b12SSteven Rostedt 
137233dc9b12SSteven Rostedt 	/* Don't allocate too much */
137333dc9b12SSteven Rostedt 	if (bits > FTRACE_HASH_MAX_BITS)
137433dc9b12SSteven Rostedt 		bits = FTRACE_HASH_MAX_BITS;
137533dc9b12SSteven Rostedt 
137641fb61c2SSteven Rostedt 	ret = -ENOMEM;
137707fd5515SSteven Rostedt 	new_hash = alloc_ftrace_hash(bits);
137807fd5515SSteven Rostedt 	if (!new_hash)
137941fb61c2SSteven Rostedt 		goto out;
138033dc9b12SSteven Rostedt 
138133dc9b12SSteven Rostedt 	size = 1 << src->size_bits;
138233dc9b12SSteven Rostedt 	for (i = 0; i < size; i++) {
138333dc9b12SSteven Rostedt 		hhd = &src->buckets[i];
1384b67bfe0dSSasha Levin 		hlist_for_each_entry_safe(entry, tn, hhd, hlist) {
138533dc9b12SSteven Rostedt 			remove_hash_entry(src, entry);
138607fd5515SSteven Rostedt 			__add_hash_entry(new_hash, entry);
138733dc9b12SSteven Rostedt 		}
138833dc9b12SSteven Rostedt 	}
138933dc9b12SSteven Rostedt 
139007fd5515SSteven Rostedt 	old_hash = *dst;
139107fd5515SSteven Rostedt 	rcu_assign_pointer(*dst, new_hash);
139207fd5515SSteven Rostedt 	free_ftrace_hash_rcu(old_hash);
139307fd5515SSteven Rostedt 
139441fb61c2SSteven Rostedt 	ret = 0;
139541fb61c2SSteven Rostedt  out:
139641fb61c2SSteven Rostedt 	/*
139741fb61c2SSteven Rostedt 	 * Enable regardless of ret:
139841fb61c2SSteven Rostedt 	 *  On success, we enable the new hash.
139941fb61c2SSteven Rostedt 	 *  On failure, we re-enable the original hash.
140041fb61c2SSteven Rostedt 	 */
140141fb61c2SSteven Rostedt 	ftrace_hash_rec_enable(ops, enable);
140241fb61c2SSteven Rostedt 
140341fb61c2SSteven Rostedt 	return ret;
140433dc9b12SSteven Rostedt }
140533dc9b12SSteven Rostedt 
1406265c831cSSteven Rostedt /*
1407b848914cSSteven Rostedt  * Test the hashes for this ops to see if we want to call
1408b848914cSSteven Rostedt  * the ops->func or not.
1409b848914cSSteven Rostedt  *
1410b848914cSSteven Rostedt  * It's a match if the ip is in the ops->filter_hash or
1411b848914cSSteven Rostedt  * the filter_hash does not exist or is empty,
1412b848914cSSteven Rostedt  *  AND
1413b848914cSSteven Rostedt  * the ip is not in the ops->notrace_hash.
1414cdbe61bfSSteven Rostedt  *
1415cdbe61bfSSteven Rostedt  * This needs to be called with preemption disabled as
1416cdbe61bfSSteven Rostedt  * the hashes are freed with call_rcu_sched().
1417b848914cSSteven Rostedt  */
1418b848914cSSteven Rostedt static int
1419b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
1420b848914cSSteven Rostedt {
1421b848914cSSteven Rostedt 	struct ftrace_hash *filter_hash;
1422b848914cSSteven Rostedt 	struct ftrace_hash *notrace_hash;
1423b848914cSSteven Rostedt 	int ret;
1424b848914cSSteven Rostedt 
1425*1bb539caSSteven Rostedt 	filter_hash = rcu_dereference_raw_notrace(ops->filter_hash);
1426*1bb539caSSteven Rostedt 	notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash);
1427b848914cSSteven Rostedt 
142806a51d93SSteven Rostedt 	if ((ftrace_hash_empty(filter_hash) ||
1429b848914cSSteven Rostedt 	     ftrace_lookup_ip(filter_hash, ip)) &&
143006a51d93SSteven Rostedt 	    (ftrace_hash_empty(notrace_hash) ||
1431b848914cSSteven Rostedt 	     !ftrace_lookup_ip(notrace_hash, ip)))
1432b848914cSSteven Rostedt 		ret = 1;
1433b848914cSSteven Rostedt 	else
1434b848914cSSteven Rostedt 		ret = 0;
1435b848914cSSteven Rostedt 
1436b848914cSSteven Rostedt 	return ret;
1437b848914cSSteven Rostedt }
1438b848914cSSteven Rostedt 
1439b848914cSSteven Rostedt /*
1440265c831cSSteven Rostedt  * This is a double for. Do not use 'break' to break out of the loop,
1441265c831cSSteven Rostedt  * you must use a goto.
1442265c831cSSteven Rostedt  */
1443265c831cSSteven Rostedt #define do_for_each_ftrace_rec(pg, rec)					\
1444265c831cSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {		\
1445265c831cSSteven Rostedt 		int _____i;						\
1446265c831cSSteven Rostedt 		for (_____i = 0; _____i < pg->index; _____i++) {	\
1447265c831cSSteven Rostedt 			rec = &pg->records[_____i];
1448265c831cSSteven Rostedt 
1449265c831cSSteven Rostedt #define while_for_each_ftrace_rec()		\
1450265c831cSSteven Rostedt 		}				\
1451265c831cSSteven Rostedt 	}
1452ecea656dSAbhishek Sagar 
14535855feadSSteven Rostedt 
14545855feadSSteven Rostedt static int ftrace_cmp_recs(const void *a, const void *b)
14555855feadSSteven Rostedt {
1456a650e02aSSteven Rostedt 	const struct dyn_ftrace *key = a;
1457a650e02aSSteven Rostedt 	const struct dyn_ftrace *rec = b;
14585855feadSSteven Rostedt 
1459a650e02aSSteven Rostedt 	if (key->flags < rec->ip)
14605855feadSSteven Rostedt 		return -1;
1461a650e02aSSteven Rostedt 	if (key->ip >= rec->ip + MCOUNT_INSN_SIZE)
1462a650e02aSSteven Rostedt 		return 1;
1463a650e02aSSteven Rostedt 	return 0;
1464a650e02aSSteven Rostedt }
1465a650e02aSSteven Rostedt 
1466f0cf973aSSteven Rostedt static unsigned long ftrace_location_range(unsigned long start, unsigned long end)
1467a650e02aSSteven Rostedt {
1468a650e02aSSteven Rostedt 	struct ftrace_page *pg;
1469a650e02aSSteven Rostedt 	struct dyn_ftrace *rec;
1470a650e02aSSteven Rostedt 	struct dyn_ftrace key;
1471a650e02aSSteven Rostedt 
1472a650e02aSSteven Rostedt 	key.ip = start;
1473a650e02aSSteven Rostedt 	key.flags = end;	/* overload flags, as it is unsigned long */
1474a650e02aSSteven Rostedt 
1475a650e02aSSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = pg->next) {
1476a650e02aSSteven Rostedt 		if (end < pg->records[0].ip ||
1477a650e02aSSteven Rostedt 		    start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
1478a650e02aSSteven Rostedt 			continue;
1479a650e02aSSteven Rostedt 		rec = bsearch(&key, pg->records, pg->index,
1480a650e02aSSteven Rostedt 			      sizeof(struct dyn_ftrace),
1481a650e02aSSteven Rostedt 			      ftrace_cmp_recs);
1482a650e02aSSteven Rostedt 		if (rec)
1483f0cf973aSSteven Rostedt 			return rec->ip;
1484a650e02aSSteven Rostedt 	}
1485a650e02aSSteven Rostedt 
14865855feadSSteven Rostedt 	return 0;
14875855feadSSteven Rostedt }
14885855feadSSteven Rostedt 
1489c88fd863SSteven Rostedt /**
1490c88fd863SSteven Rostedt  * ftrace_location - return true if the ip giving is a traced location
1491c88fd863SSteven Rostedt  * @ip: the instruction pointer to check
1492c88fd863SSteven Rostedt  *
1493f0cf973aSSteven Rostedt  * Returns rec->ip if @ip given is a pointer to a ftrace location.
1494c88fd863SSteven Rostedt  * That is, the instruction that is either a NOP or call to
1495c88fd863SSteven Rostedt  * the function tracer. It checks the ftrace internal tables to
1496c88fd863SSteven Rostedt  * determine if the address belongs or not.
1497c88fd863SSteven Rostedt  */
1498f0cf973aSSteven Rostedt unsigned long ftrace_location(unsigned long ip)
1499c88fd863SSteven Rostedt {
1500a650e02aSSteven Rostedt 	return ftrace_location_range(ip, ip);
15015855feadSSteven Rostedt }
1502c88fd863SSteven Rostedt 
1503a650e02aSSteven Rostedt /**
1504a650e02aSSteven Rostedt  * ftrace_text_reserved - return true if range contains an ftrace location
1505a650e02aSSteven Rostedt  * @start: start of range to search
1506a650e02aSSteven Rostedt  * @end: end of range to search (inclusive). @end points to the last byte to check.
1507a650e02aSSteven Rostedt  *
1508a650e02aSSteven Rostedt  * Returns 1 if @start and @end contains a ftrace location.
1509a650e02aSSteven Rostedt  * That is, the instruction that is either a NOP or call to
1510a650e02aSSteven Rostedt  * the function tracer. It checks the ftrace internal tables to
1511a650e02aSSteven Rostedt  * determine if the address belongs or not.
1512a650e02aSSteven Rostedt  */
1513a650e02aSSteven Rostedt int ftrace_text_reserved(void *start, void *end)
1514a650e02aSSteven Rostedt {
1515f0cf973aSSteven Rostedt 	unsigned long ret;
1516f0cf973aSSteven Rostedt 
1517f0cf973aSSteven Rostedt 	ret = ftrace_location_range((unsigned long)start,
1518a650e02aSSteven Rostedt 				    (unsigned long)end);
1519f0cf973aSSteven Rostedt 
1520f0cf973aSSteven Rostedt 	return (int)!!ret;
1521c88fd863SSteven Rostedt }
1522c88fd863SSteven Rostedt 
1523ed926f9bSSteven Rostedt static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1524ed926f9bSSteven Rostedt 				     int filter_hash,
1525ed926f9bSSteven Rostedt 				     bool inc)
1526ed926f9bSSteven Rostedt {
1527ed926f9bSSteven Rostedt 	struct ftrace_hash *hash;
1528ed926f9bSSteven Rostedt 	struct ftrace_hash *other_hash;
1529ed926f9bSSteven Rostedt 	struct ftrace_page *pg;
1530ed926f9bSSteven Rostedt 	struct dyn_ftrace *rec;
1531ed926f9bSSteven Rostedt 	int count = 0;
1532ed926f9bSSteven Rostedt 	int all = 0;
1533ed926f9bSSteven Rostedt 
1534ed926f9bSSteven Rostedt 	/* Only update if the ops has been registered */
1535ed926f9bSSteven Rostedt 	if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
1536ed926f9bSSteven Rostedt 		return;
1537ed926f9bSSteven Rostedt 
1538ed926f9bSSteven Rostedt 	/*
1539ed926f9bSSteven Rostedt 	 * In the filter_hash case:
1540ed926f9bSSteven Rostedt 	 *   If the count is zero, we update all records.
1541ed926f9bSSteven Rostedt 	 *   Otherwise we just update the items in the hash.
1542ed926f9bSSteven Rostedt 	 *
1543ed926f9bSSteven Rostedt 	 * In the notrace_hash case:
1544ed926f9bSSteven Rostedt 	 *   We enable the update in the hash.
1545ed926f9bSSteven Rostedt 	 *   As disabling notrace means enabling the tracing,
1546ed926f9bSSteven Rostedt 	 *   and enabling notrace means disabling, the inc variable
1547ed926f9bSSteven Rostedt 	 *   gets inversed.
1548ed926f9bSSteven Rostedt 	 */
1549ed926f9bSSteven Rostedt 	if (filter_hash) {
1550ed926f9bSSteven Rostedt 		hash = ops->filter_hash;
1551ed926f9bSSteven Rostedt 		other_hash = ops->notrace_hash;
155206a51d93SSteven Rostedt 		if (ftrace_hash_empty(hash))
1553ed926f9bSSteven Rostedt 			all = 1;
1554ed926f9bSSteven Rostedt 	} else {
1555ed926f9bSSteven Rostedt 		inc = !inc;
1556ed926f9bSSteven Rostedt 		hash = ops->notrace_hash;
1557ed926f9bSSteven Rostedt 		other_hash = ops->filter_hash;
1558ed926f9bSSteven Rostedt 		/*
1559ed926f9bSSteven Rostedt 		 * If the notrace hash has no items,
1560ed926f9bSSteven Rostedt 		 * then there's nothing to do.
1561ed926f9bSSteven Rostedt 		 */
156206a51d93SSteven Rostedt 		if (ftrace_hash_empty(hash))
1563ed926f9bSSteven Rostedt 			return;
1564ed926f9bSSteven Rostedt 	}
1565ed926f9bSSteven Rostedt 
1566ed926f9bSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
1567ed926f9bSSteven Rostedt 		int in_other_hash = 0;
1568ed926f9bSSteven Rostedt 		int in_hash = 0;
1569ed926f9bSSteven Rostedt 		int match = 0;
1570ed926f9bSSteven Rostedt 
1571ed926f9bSSteven Rostedt 		if (all) {
1572ed926f9bSSteven Rostedt 			/*
1573ed926f9bSSteven Rostedt 			 * Only the filter_hash affects all records.
1574ed926f9bSSteven Rostedt 			 * Update if the record is not in the notrace hash.
1575ed926f9bSSteven Rostedt 			 */
1576b848914cSSteven Rostedt 			if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip))
1577ed926f9bSSteven Rostedt 				match = 1;
1578ed926f9bSSteven Rostedt 		} else {
157906a51d93SSteven Rostedt 			in_hash = !!ftrace_lookup_ip(hash, rec->ip);
158006a51d93SSteven Rostedt 			in_other_hash = !!ftrace_lookup_ip(other_hash, rec->ip);
1581ed926f9bSSteven Rostedt 
1582ed926f9bSSteven Rostedt 			/*
1583ed926f9bSSteven Rostedt 			 *
1584ed926f9bSSteven Rostedt 			 */
1585ed926f9bSSteven Rostedt 			if (filter_hash && in_hash && !in_other_hash)
1586ed926f9bSSteven Rostedt 				match = 1;
1587ed926f9bSSteven Rostedt 			else if (!filter_hash && in_hash &&
158806a51d93SSteven Rostedt 				 (in_other_hash || ftrace_hash_empty(other_hash)))
1589ed926f9bSSteven Rostedt 				match = 1;
1590ed926f9bSSteven Rostedt 		}
1591ed926f9bSSteven Rostedt 		if (!match)
1592ed926f9bSSteven Rostedt 			continue;
1593ed926f9bSSteven Rostedt 
1594ed926f9bSSteven Rostedt 		if (inc) {
1595ed926f9bSSteven Rostedt 			rec->flags++;
1596ed926f9bSSteven Rostedt 			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX))
1597ed926f9bSSteven Rostedt 				return;
159808f6fba5SSteven Rostedt 			/*
159908f6fba5SSteven Rostedt 			 * If any ops wants regs saved for this function
160008f6fba5SSteven Rostedt 			 * then all ops will get saved regs.
160108f6fba5SSteven Rostedt 			 */
160208f6fba5SSteven Rostedt 			if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
160308f6fba5SSteven Rostedt 				rec->flags |= FTRACE_FL_REGS;
1604ed926f9bSSteven Rostedt 		} else {
1605ed926f9bSSteven Rostedt 			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0))
1606ed926f9bSSteven Rostedt 				return;
1607ed926f9bSSteven Rostedt 			rec->flags--;
1608ed926f9bSSteven Rostedt 		}
1609ed926f9bSSteven Rostedt 		count++;
1610ed926f9bSSteven Rostedt 		/* Shortcut, if we handled all records, we are done. */
1611ed926f9bSSteven Rostedt 		if (!all && count == hash->count)
1612ed926f9bSSteven Rostedt 			return;
1613ed926f9bSSteven Rostedt 	} while_for_each_ftrace_rec();
1614ed926f9bSSteven Rostedt }
1615ed926f9bSSteven Rostedt 
1616ed926f9bSSteven Rostedt static void ftrace_hash_rec_disable(struct ftrace_ops *ops,
1617ed926f9bSSteven Rostedt 				    int filter_hash)
1618ed926f9bSSteven Rostedt {
1619ed926f9bSSteven Rostedt 	__ftrace_hash_rec_update(ops, filter_hash, 0);
1620ed926f9bSSteven Rostedt }
1621ed926f9bSSteven Rostedt 
1622ed926f9bSSteven Rostedt static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
1623ed926f9bSSteven Rostedt 				   int filter_hash)
1624ed926f9bSSteven Rostedt {
1625ed926f9bSSteven Rostedt 	__ftrace_hash_rec_update(ops, filter_hash, 1);
1626ed926f9bSSteven Rostedt }
1627ed926f9bSSteven Rostedt 
162805736a42SSteven Rostedt static void print_ip_ins(const char *fmt, unsigned char *p)
162905736a42SSteven Rostedt {
163005736a42SSteven Rostedt 	int i;
163105736a42SSteven Rostedt 
163205736a42SSteven Rostedt 	printk(KERN_CONT "%s", fmt);
163305736a42SSteven Rostedt 
163405736a42SSteven Rostedt 	for (i = 0; i < MCOUNT_INSN_SIZE; i++)
163505736a42SSteven Rostedt 		printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
163605736a42SSteven Rostedt }
163705736a42SSteven Rostedt 
1638c88fd863SSteven Rostedt /**
1639c88fd863SSteven Rostedt  * ftrace_bug - report and shutdown function tracer
1640c88fd863SSteven Rostedt  * @failed: The failed type (EFAULT, EINVAL, EPERM)
1641c88fd863SSteven Rostedt  * @ip: The address that failed
1642c88fd863SSteven Rostedt  *
1643c88fd863SSteven Rostedt  * The arch code that enables or disables the function tracing
1644c88fd863SSteven Rostedt  * can call ftrace_bug() when it has detected a problem in
1645c88fd863SSteven Rostedt  * modifying the code. @failed should be one of either:
1646c88fd863SSteven Rostedt  * EFAULT - if the problem happens on reading the @ip address
1647c88fd863SSteven Rostedt  * EINVAL - if what is read at @ip is not what was expected
1648c88fd863SSteven Rostedt  * EPERM - if the problem happens on writting to the @ip address
1649c88fd863SSteven Rostedt  */
1650c88fd863SSteven Rostedt void ftrace_bug(int failed, unsigned long ip)
16513c1720f0SSteven Rostedt {
1652b17e8a37SSteven Rostedt 	switch (failed) {
1653593eb8a2SSteven Rostedt 	case -EFAULT:
16546912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
165505736a42SSteven Rostedt 		pr_info("ftrace faulted on modifying ");
165605736a42SSteven Rostedt 		print_ip_sym(ip);
165705736a42SSteven Rostedt 		break;
1658593eb8a2SSteven Rostedt 	case -EINVAL:
16596912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
166005736a42SSteven Rostedt 		pr_info("ftrace failed to modify ");
166105736a42SSteven Rostedt 		print_ip_sym(ip);
166205736a42SSteven Rostedt 		print_ip_ins(" actual: ", (unsigned char *)ip);
166305736a42SSteven Rostedt 		printk(KERN_CONT "\n");
166405736a42SSteven Rostedt 		break;
1665593eb8a2SSteven Rostedt 	case -EPERM:
16666912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
1667593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on writing ");
1668593eb8a2SSteven Rostedt 		print_ip_sym(ip);
1669593eb8a2SSteven Rostedt 		break;
1670593eb8a2SSteven Rostedt 	default:
16716912896eSSteven Rostedt 		FTRACE_WARN_ON_ONCE(1);
1672593eb8a2SSteven Rostedt 		pr_info("ftrace faulted on unknown error ");
1673593eb8a2SSteven Rostedt 		print_ip_sym(ip);
167405736a42SSteven Rostedt 	}
1675b17e8a37SSteven Rostedt }
167605736a42SSteven Rostedt 
1677c88fd863SSteven Rostedt static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
16783d083395SSteven Rostedt {
167964fbcd16SXiao Guangrong 	unsigned long flag = 0UL;
1680e7d3737eSFrederic Weisbecker 
16813d083395SSteven Rostedt 	/*
168230fb6aa7SJiri Olsa 	 * If we are updating calls:
16833d083395SSteven Rostedt 	 *
1684ed926f9bSSteven Rostedt 	 *   If the record has a ref count, then we need to enable it
1685ed926f9bSSteven Rostedt 	 *   because someone is using it.
16863d083395SSteven Rostedt 	 *
1687ed926f9bSSteven Rostedt 	 *   Otherwise we make sure its disabled.
1688ed926f9bSSteven Rostedt 	 *
168930fb6aa7SJiri Olsa 	 * If we are disabling calls, then disable all records that
1690ed926f9bSSteven Rostedt 	 * are enabled.
16913d083395SSteven Rostedt 	 */
1692c88fd863SSteven Rostedt 	if (enable && (rec->flags & ~FTRACE_FL_MASK))
169364fbcd16SXiao Guangrong 		flag = FTRACE_FL_ENABLED;
16943d083395SSteven Rostedt 
169508f6fba5SSteven Rostedt 	/*
169608f6fba5SSteven Rostedt 	 * If enabling and the REGS flag does not match the REGS_EN, then
169708f6fba5SSteven Rostedt 	 * do not ignore this record. Set flags to fail the compare against
169808f6fba5SSteven Rostedt 	 * ENABLED.
169908f6fba5SSteven Rostedt 	 */
170008f6fba5SSteven Rostedt 	if (flag &&
170108f6fba5SSteven Rostedt 	    (!(rec->flags & FTRACE_FL_REGS) != !(rec->flags & FTRACE_FL_REGS_EN)))
170208f6fba5SSteven Rostedt 		flag |= FTRACE_FL_REGS;
170308f6fba5SSteven Rostedt 
170464fbcd16SXiao Guangrong 	/* If the state of this record hasn't changed, then do nothing */
170564fbcd16SXiao Guangrong 	if ((rec->flags & FTRACE_FL_ENABLED) == flag)
1706c88fd863SSteven Rostedt 		return FTRACE_UPDATE_IGNORE;
170764fbcd16SXiao Guangrong 
170864fbcd16SXiao Guangrong 	if (flag) {
170908f6fba5SSteven Rostedt 		/* Save off if rec is being enabled (for return value) */
171008f6fba5SSteven Rostedt 		flag ^= rec->flags & FTRACE_FL_ENABLED;
171108f6fba5SSteven Rostedt 
171208f6fba5SSteven Rostedt 		if (update) {
171364fbcd16SXiao Guangrong 			rec->flags |= FTRACE_FL_ENABLED;
171408f6fba5SSteven Rostedt 			if (flag & FTRACE_FL_REGS) {
171508f6fba5SSteven Rostedt 				if (rec->flags & FTRACE_FL_REGS)
171608f6fba5SSteven Rostedt 					rec->flags |= FTRACE_FL_REGS_EN;
171708f6fba5SSteven Rostedt 				else
171808f6fba5SSteven Rostedt 					rec->flags &= ~FTRACE_FL_REGS_EN;
171908f6fba5SSteven Rostedt 			}
172064fbcd16SXiao Guangrong 		}
172164fbcd16SXiao Guangrong 
172208f6fba5SSteven Rostedt 		/*
172308f6fba5SSteven Rostedt 		 * If this record is being updated from a nop, then
172408f6fba5SSteven Rostedt 		 *   return UPDATE_MAKE_CALL.
172508f6fba5SSteven Rostedt 		 * Otherwise, if the EN flag is set, then return
172608f6fba5SSteven Rostedt 		 *   UPDATE_MODIFY_CALL_REGS to tell the caller to convert
172708f6fba5SSteven Rostedt 		 *   from the non-save regs, to a save regs function.
172808f6fba5SSteven Rostedt 		 * Otherwise,
172908f6fba5SSteven Rostedt 		 *   return UPDATE_MODIFY_CALL to tell the caller to convert
173008f6fba5SSteven Rostedt 		 *   from the save regs, to a non-save regs function.
173108f6fba5SSteven Rostedt 		 */
173208f6fba5SSteven Rostedt 		if (flag & FTRACE_FL_ENABLED)
173308f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MAKE_CALL;
173408f6fba5SSteven Rostedt 		else if (rec->flags & FTRACE_FL_REGS_EN)
173508f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MODIFY_CALL_REGS;
173608f6fba5SSteven Rostedt 		else
173708f6fba5SSteven Rostedt 			return FTRACE_UPDATE_MODIFY_CALL;
173808f6fba5SSteven Rostedt 	}
173908f6fba5SSteven Rostedt 
174008f6fba5SSteven Rostedt 	if (update) {
174108f6fba5SSteven Rostedt 		/* If there's no more users, clear all flags */
174208f6fba5SSteven Rostedt 		if (!(rec->flags & ~FTRACE_FL_MASK))
174308f6fba5SSteven Rostedt 			rec->flags = 0;
174408f6fba5SSteven Rostedt 		else
174508f6fba5SSteven Rostedt 			/* Just disable the record (keep REGS state) */
174664fbcd16SXiao Guangrong 			rec->flags &= ~FTRACE_FL_ENABLED;
174708f6fba5SSteven Rostedt 	}
1748c88fd863SSteven Rostedt 
1749c88fd863SSteven Rostedt 	return FTRACE_UPDATE_MAKE_NOP;
1750c88fd863SSteven Rostedt }
1751c88fd863SSteven Rostedt 
1752c88fd863SSteven Rostedt /**
1753c88fd863SSteven Rostedt  * ftrace_update_record, set a record that now is tracing or not
1754c88fd863SSteven Rostedt  * @rec: the record to update
1755c88fd863SSteven Rostedt  * @enable: set to 1 if the record is tracing, zero to force disable
1756c88fd863SSteven Rostedt  *
1757c88fd863SSteven Rostedt  * The records that represent all functions that can be traced need
1758c88fd863SSteven Rostedt  * to be updated when tracing has been enabled.
1759c88fd863SSteven Rostedt  */
1760c88fd863SSteven Rostedt int ftrace_update_record(struct dyn_ftrace *rec, int enable)
1761c88fd863SSteven Rostedt {
1762c88fd863SSteven Rostedt 	return ftrace_check_record(rec, enable, 1);
1763c88fd863SSteven Rostedt }
1764c88fd863SSteven Rostedt 
1765c88fd863SSteven Rostedt /**
1766c88fd863SSteven Rostedt  * ftrace_test_record, check if the record has been enabled or not
1767c88fd863SSteven Rostedt  * @rec: the record to test
1768c88fd863SSteven Rostedt  * @enable: set to 1 to check if enabled, 0 if it is disabled
1769c88fd863SSteven Rostedt  *
1770c88fd863SSteven Rostedt  * The arch code may need to test if a record is already set to
1771c88fd863SSteven Rostedt  * tracing to determine how to modify the function code that it
1772c88fd863SSteven Rostedt  * represents.
1773c88fd863SSteven Rostedt  */
1774c88fd863SSteven Rostedt int ftrace_test_record(struct dyn_ftrace *rec, int enable)
1775c88fd863SSteven Rostedt {
1776c88fd863SSteven Rostedt 	return ftrace_check_record(rec, enable, 0);
1777c88fd863SSteven Rostedt }
1778c88fd863SSteven Rostedt 
1779c88fd863SSteven Rostedt static int
1780c88fd863SSteven Rostedt __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
1781c88fd863SSteven Rostedt {
178208f6fba5SSteven Rostedt 	unsigned long ftrace_old_addr;
1783c88fd863SSteven Rostedt 	unsigned long ftrace_addr;
1784c88fd863SSteven Rostedt 	int ret;
1785c88fd863SSteven Rostedt 
1786c88fd863SSteven Rostedt 	ret = ftrace_update_record(rec, enable);
1787c88fd863SSteven Rostedt 
178808f6fba5SSteven Rostedt 	if (rec->flags & FTRACE_FL_REGS)
178908f6fba5SSteven Rostedt 		ftrace_addr = (unsigned long)FTRACE_REGS_ADDR;
179008f6fba5SSteven Rostedt 	else
179108f6fba5SSteven Rostedt 		ftrace_addr = (unsigned long)FTRACE_ADDR;
179208f6fba5SSteven Rostedt 
1793c88fd863SSteven Rostedt 	switch (ret) {
1794c88fd863SSteven Rostedt 	case FTRACE_UPDATE_IGNORE:
1795c88fd863SSteven Rostedt 		return 0;
1796c88fd863SSteven Rostedt 
1797c88fd863SSteven Rostedt 	case FTRACE_UPDATE_MAKE_CALL:
1798c88fd863SSteven Rostedt 		return ftrace_make_call(rec, ftrace_addr);
1799c88fd863SSteven Rostedt 
1800c88fd863SSteven Rostedt 	case FTRACE_UPDATE_MAKE_NOP:
1801e7d3737eSFrederic Weisbecker 		return ftrace_make_nop(NULL, rec, ftrace_addr);
180208f6fba5SSteven Rostedt 
180308f6fba5SSteven Rostedt 	case FTRACE_UPDATE_MODIFY_CALL_REGS:
180408f6fba5SSteven Rostedt 	case FTRACE_UPDATE_MODIFY_CALL:
180508f6fba5SSteven Rostedt 		if (rec->flags & FTRACE_FL_REGS)
180608f6fba5SSteven Rostedt 			ftrace_old_addr = (unsigned long)FTRACE_ADDR;
180708f6fba5SSteven Rostedt 		else
180808f6fba5SSteven Rostedt 			ftrace_old_addr = (unsigned long)FTRACE_REGS_ADDR;
180908f6fba5SSteven Rostedt 
181008f6fba5SSteven Rostedt 		return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr);
18113d083395SSteven Rostedt 	}
18123d083395SSteven Rostedt 
1813c88fd863SSteven Rostedt 	return -1; /* unknow ftrace bug */
1814c88fd863SSteven Rostedt }
1815c88fd863SSteven Rostedt 
1816e4f5d544SSteven Rostedt void __weak ftrace_replace_code(int enable)
18173d083395SSteven Rostedt {
18183d083395SSteven Rostedt 	struct dyn_ftrace *rec;
18193d083395SSteven Rostedt 	struct ftrace_page *pg;
18206a24a244SSteven Rostedt 	int failed;
18213d083395SSteven Rostedt 
182245a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
182345a4a237SSteven Rostedt 		return;
182445a4a237SSteven Rostedt 
1825265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
1826e4f5d544SSteven Rostedt 		failed = __ftrace_replace_code(rec, enable);
1827fa9d13cfSZhaolei 		if (failed) {
182831e88909SSteven Rostedt 			ftrace_bug(failed, rec->ip);
18294377245aSSteven Rostedt 			/* Stop processing */
18304377245aSSteven Rostedt 			return;
18314377245aSSteven Rostedt 		}
1832265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
18333d083395SSteven Rostedt }
18343c1720f0SSteven Rostedt 
1835c88fd863SSteven Rostedt struct ftrace_rec_iter {
1836c88fd863SSteven Rostedt 	struct ftrace_page	*pg;
1837c88fd863SSteven Rostedt 	int			index;
1838c88fd863SSteven Rostedt };
1839c88fd863SSteven Rostedt 
1840c88fd863SSteven Rostedt /**
1841c88fd863SSteven Rostedt  * ftrace_rec_iter_start, start up iterating over traced functions
1842c88fd863SSteven Rostedt  *
1843c88fd863SSteven Rostedt  * Returns an iterator handle that is used to iterate over all
1844c88fd863SSteven Rostedt  * the records that represent address locations where functions
1845c88fd863SSteven Rostedt  * are traced.
1846c88fd863SSteven Rostedt  *
1847c88fd863SSteven Rostedt  * May return NULL if no records are available.
1848c88fd863SSteven Rostedt  */
1849c88fd863SSteven Rostedt struct ftrace_rec_iter *ftrace_rec_iter_start(void)
1850c88fd863SSteven Rostedt {
1851c88fd863SSteven Rostedt 	/*
1852c88fd863SSteven Rostedt 	 * We only use a single iterator.
1853c88fd863SSteven Rostedt 	 * Protected by the ftrace_lock mutex.
1854c88fd863SSteven Rostedt 	 */
1855c88fd863SSteven Rostedt 	static struct ftrace_rec_iter ftrace_rec_iter;
1856c88fd863SSteven Rostedt 	struct ftrace_rec_iter *iter = &ftrace_rec_iter;
1857c88fd863SSteven Rostedt 
1858c88fd863SSteven Rostedt 	iter->pg = ftrace_pages_start;
1859c88fd863SSteven Rostedt 	iter->index = 0;
1860c88fd863SSteven Rostedt 
1861c88fd863SSteven Rostedt 	/* Could have empty pages */
1862c88fd863SSteven Rostedt 	while (iter->pg && !iter->pg->index)
1863c88fd863SSteven Rostedt 		iter->pg = iter->pg->next;
1864c88fd863SSteven Rostedt 
1865c88fd863SSteven Rostedt 	if (!iter->pg)
1866c88fd863SSteven Rostedt 		return NULL;
1867c88fd863SSteven Rostedt 
1868c88fd863SSteven Rostedt 	return iter;
1869c88fd863SSteven Rostedt }
1870c88fd863SSteven Rostedt 
1871c88fd863SSteven Rostedt /**
1872c88fd863SSteven Rostedt  * ftrace_rec_iter_next, get the next record to process.
1873c88fd863SSteven Rostedt  * @iter: The handle to the iterator.
1874c88fd863SSteven Rostedt  *
1875c88fd863SSteven Rostedt  * Returns the next iterator after the given iterator @iter.
1876c88fd863SSteven Rostedt  */
1877c88fd863SSteven Rostedt struct ftrace_rec_iter *ftrace_rec_iter_next(struct ftrace_rec_iter *iter)
1878c88fd863SSteven Rostedt {
1879c88fd863SSteven Rostedt 	iter->index++;
1880c88fd863SSteven Rostedt 
1881c88fd863SSteven Rostedt 	if (iter->index >= iter->pg->index) {
1882c88fd863SSteven Rostedt 		iter->pg = iter->pg->next;
1883c88fd863SSteven Rostedt 		iter->index = 0;
1884c88fd863SSteven Rostedt 
1885c88fd863SSteven Rostedt 		/* Could have empty pages */
1886c88fd863SSteven Rostedt 		while (iter->pg && !iter->pg->index)
1887c88fd863SSteven Rostedt 			iter->pg = iter->pg->next;
1888c88fd863SSteven Rostedt 	}
1889c88fd863SSteven Rostedt 
1890c88fd863SSteven Rostedt 	if (!iter->pg)
1891c88fd863SSteven Rostedt 		return NULL;
1892c88fd863SSteven Rostedt 
1893c88fd863SSteven Rostedt 	return iter;
1894c88fd863SSteven Rostedt }
1895c88fd863SSteven Rostedt 
1896c88fd863SSteven Rostedt /**
1897c88fd863SSteven Rostedt  * ftrace_rec_iter_record, get the record at the iterator location
1898c88fd863SSteven Rostedt  * @iter: The current iterator location
1899c88fd863SSteven Rostedt  *
1900c88fd863SSteven Rostedt  * Returns the record that the current @iter is at.
1901c88fd863SSteven Rostedt  */
1902c88fd863SSteven Rostedt struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter)
1903c88fd863SSteven Rostedt {
1904c88fd863SSteven Rostedt 	return &iter->pg->records[iter->index];
1905c88fd863SSteven Rostedt }
1906c88fd863SSteven Rostedt 
19073b47bfc1SSteven Rostedt static int
190831e88909SSteven Rostedt ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
19093c1720f0SSteven Rostedt {
191037ad5084SSteven Rostedt 	unsigned long ip;
1911492a7ea5SAbhishek Sagar 	int ret;
191237ad5084SSteven Rostedt 
1913492a7ea5SAbhishek Sagar 	ip = rec->ip;
19143c1720f0SSteven Rostedt 
191545a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
191645a4a237SSteven Rostedt 		return 0;
191745a4a237SSteven Rostedt 
191825aac9dcSShaohua Li 	ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
19193d083395SSteven Rostedt 	if (ret) {
192031e88909SSteven Rostedt 		ftrace_bug(ret, ip);
19213d083395SSteven Rostedt 		return 0;
1922d61f82d0SSteven Rostedt 	}
1923d61f82d0SSteven Rostedt 	return 1;
19243d083395SSteven Rostedt }
19253d083395SSteven Rostedt 
1926000ab691SSteven Rostedt /*
1927000ab691SSteven Rostedt  * archs can override this function if they must do something
1928000ab691SSteven Rostedt  * before the modifying code is performed.
1929000ab691SSteven Rostedt  */
1930000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_prepare(void)
1931000ab691SSteven Rostedt {
1932000ab691SSteven Rostedt 	return 0;
1933000ab691SSteven Rostedt }
1934000ab691SSteven Rostedt 
1935000ab691SSteven Rostedt /*
1936000ab691SSteven Rostedt  * archs can override this function if they must do something
1937000ab691SSteven Rostedt  * after the modifying code is performed.
1938000ab691SSteven Rostedt  */
1939000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_post_process(void)
1940000ab691SSteven Rostedt {
1941000ab691SSteven Rostedt 	return 0;
1942000ab691SSteven Rostedt }
1943000ab691SSteven Rostedt 
19448ed3e2cfSSteven Rostedt void ftrace_modify_all_code(int command)
19458ed3e2cfSSteven Rostedt {
19468ed3e2cfSSteven Rostedt 	if (command & FTRACE_UPDATE_CALLS)
19478ed3e2cfSSteven Rostedt 		ftrace_replace_code(1);
19488ed3e2cfSSteven Rostedt 	else if (command & FTRACE_DISABLE_CALLS)
19498ed3e2cfSSteven Rostedt 		ftrace_replace_code(0);
19508ed3e2cfSSteven Rostedt 
19518ed3e2cfSSteven Rostedt 	if (command & FTRACE_UPDATE_TRACE_FUNC)
19528ed3e2cfSSteven Rostedt 		ftrace_update_ftrace_func(ftrace_trace_function);
19538ed3e2cfSSteven Rostedt 
19548ed3e2cfSSteven Rostedt 	if (command & FTRACE_START_FUNC_RET)
19558ed3e2cfSSteven Rostedt 		ftrace_enable_ftrace_graph_caller();
19568ed3e2cfSSteven Rostedt 	else if (command & FTRACE_STOP_FUNC_RET)
19578ed3e2cfSSteven Rostedt 		ftrace_disable_ftrace_graph_caller();
19588ed3e2cfSSteven Rostedt }
19598ed3e2cfSSteven Rostedt 
19603d083395SSteven Rostedt static int __ftrace_modify_code(void *data)
19613d083395SSteven Rostedt {
19623d083395SSteven Rostedt 	int *command = data;
19633d083395SSteven Rostedt 
19648ed3e2cfSSteven Rostedt 	ftrace_modify_all_code(*command);
19655a45cfe1SSteven Rostedt 
1966c88fd863SSteven Rostedt 	return 0;
1967c88fd863SSteven Rostedt }
1968c88fd863SSteven Rostedt 
1969c88fd863SSteven Rostedt /**
1970c88fd863SSteven Rostedt  * ftrace_run_stop_machine, go back to the stop machine method
1971c88fd863SSteven Rostedt  * @command: The command to tell ftrace what to do
1972c88fd863SSteven Rostedt  *
1973c88fd863SSteven Rostedt  * If an arch needs to fall back to the stop machine method, the
1974c88fd863SSteven Rostedt  * it can call this function.
1975c88fd863SSteven Rostedt  */
1976c88fd863SSteven Rostedt void ftrace_run_stop_machine(int command)
1977c88fd863SSteven Rostedt {
1978c88fd863SSteven Rostedt 	stop_machine(__ftrace_modify_code, &command, NULL);
1979c88fd863SSteven Rostedt }
1980c88fd863SSteven Rostedt 
1981c88fd863SSteven Rostedt /**
1982c88fd863SSteven Rostedt  * arch_ftrace_update_code, modify the code to trace or not trace
1983c88fd863SSteven Rostedt  * @command: The command that needs to be done
1984c88fd863SSteven Rostedt  *
1985c88fd863SSteven Rostedt  * Archs can override this function if it does not need to
1986c88fd863SSteven Rostedt  * run stop_machine() to modify code.
1987c88fd863SSteven Rostedt  */
1988c88fd863SSteven Rostedt void __weak arch_ftrace_update_code(int command)
1989c88fd863SSteven Rostedt {
1990c88fd863SSteven Rostedt 	ftrace_run_stop_machine(command);
1991c88fd863SSteven Rostedt }
1992c88fd863SSteven Rostedt 
1993c88fd863SSteven Rostedt static void ftrace_run_update_code(int command)
1994c88fd863SSteven Rostedt {
1995c88fd863SSteven Rostedt 	int ret;
1996c88fd863SSteven Rostedt 
1997c88fd863SSteven Rostedt 	ret = ftrace_arch_code_modify_prepare();
1998c88fd863SSteven Rostedt 	FTRACE_WARN_ON(ret);
1999c88fd863SSteven Rostedt 	if (ret)
2000c88fd863SSteven Rostedt 		return;
2001c88fd863SSteven Rostedt 	/*
2002c88fd863SSteven Rostedt 	 * Do not call function tracer while we update the code.
2003c88fd863SSteven Rostedt 	 * We are in stop machine.
2004c88fd863SSteven Rostedt 	 */
2005c88fd863SSteven Rostedt 	function_trace_stop++;
2006c88fd863SSteven Rostedt 
2007c88fd863SSteven Rostedt 	/*
2008c88fd863SSteven Rostedt 	 * By default we use stop_machine() to modify the code.
2009c88fd863SSteven Rostedt 	 * But archs can do what ever they want as long as it
2010c88fd863SSteven Rostedt 	 * is safe. The stop_machine() is the safest, but also
2011c88fd863SSteven Rostedt 	 * produces the most overhead.
2012c88fd863SSteven Rostedt 	 */
2013c88fd863SSteven Rostedt 	arch_ftrace_update_code(command);
2014c88fd863SSteven Rostedt 
20156331c28cSSteven Rostedt 	function_trace_stop--;
20166331c28cSSteven Rostedt 
2017000ab691SSteven Rostedt 	ret = ftrace_arch_code_modify_post_process();
2018000ab691SSteven Rostedt 	FTRACE_WARN_ON(ret);
20193d083395SSteven Rostedt }
20203d083395SSteven Rostedt 
20213d083395SSteven Rostedt static ftrace_func_t saved_ftrace_func;
202260a7ecf4SSteven Rostedt static int ftrace_start_up;
2023b848914cSSteven Rostedt static int global_start_up;
2024df4fc315SSteven Rostedt 
2025df4fc315SSteven Rostedt static void ftrace_startup_enable(int command)
2026df4fc315SSteven Rostedt {
2027df4fc315SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
2028df4fc315SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
2029df4fc315SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
2030df4fc315SSteven Rostedt 	}
2031df4fc315SSteven Rostedt 
2032df4fc315SSteven Rostedt 	if (!command || !ftrace_enabled)
2033df4fc315SSteven Rostedt 		return;
2034df4fc315SSteven Rostedt 
2035df4fc315SSteven Rostedt 	ftrace_run_update_code(command);
2036df4fc315SSteven Rostedt }
20373d083395SSteven Rostedt 
2038a1cd6173SSteven Rostedt static int ftrace_startup(struct ftrace_ops *ops, int command)
20393d083395SSteven Rostedt {
2040b848914cSSteven Rostedt 	bool hash_enable = true;
2041b848914cSSteven Rostedt 
20424eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
2043a1cd6173SSteven Rostedt 		return -ENODEV;
20444eebcc81SSteven Rostedt 
204560a7ecf4SSteven Rostedt 	ftrace_start_up++;
204630fb6aa7SJiri Olsa 	command |= FTRACE_UPDATE_CALLS;
20473d083395SSteven Rostedt 
2048b848914cSSteven Rostedt 	/* ops marked global share the filter hashes */
2049b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
2050b848914cSSteven Rostedt 		ops = &global_ops;
2051b848914cSSteven Rostedt 		/* Don't update hash if global is already set */
2052b848914cSSteven Rostedt 		if (global_start_up)
2053b848914cSSteven Rostedt 			hash_enable = false;
2054b848914cSSteven Rostedt 		global_start_up++;
2055b848914cSSteven Rostedt 	}
2056b848914cSSteven Rostedt 
2057ed926f9bSSteven Rostedt 	ops->flags |= FTRACE_OPS_FL_ENABLED;
2058b848914cSSteven Rostedt 	if (hash_enable)
2059ed926f9bSSteven Rostedt 		ftrace_hash_rec_enable(ops, 1);
2060ed926f9bSSteven Rostedt 
2061df4fc315SSteven Rostedt 	ftrace_startup_enable(command);
2062a1cd6173SSteven Rostedt 
2063a1cd6173SSteven Rostedt 	return 0;
20643d083395SSteven Rostedt }
20653d083395SSteven Rostedt 
2066bd69c30bSSteven Rostedt static void ftrace_shutdown(struct ftrace_ops *ops, int command)
20673d083395SSteven Rostedt {
2068b848914cSSteven Rostedt 	bool hash_disable = true;
2069b848914cSSteven Rostedt 
20704eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
20714eebcc81SSteven Rostedt 		return;
20724eebcc81SSteven Rostedt 
207360a7ecf4SSteven Rostedt 	ftrace_start_up--;
20749ea1a153SFrederic Weisbecker 	/*
20759ea1a153SFrederic Weisbecker 	 * Just warn in case of unbalance, no need to kill ftrace, it's not
20769ea1a153SFrederic Weisbecker 	 * critical but the ftrace_call callers may be never nopped again after
20779ea1a153SFrederic Weisbecker 	 * further ftrace uses.
20789ea1a153SFrederic Weisbecker 	 */
20799ea1a153SFrederic Weisbecker 	WARN_ON_ONCE(ftrace_start_up < 0);
20809ea1a153SFrederic Weisbecker 
2081b848914cSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
2082b848914cSSteven Rostedt 		ops = &global_ops;
2083b848914cSSteven Rostedt 		global_start_up--;
2084b848914cSSteven Rostedt 		WARN_ON_ONCE(global_start_up < 0);
2085b848914cSSteven Rostedt 		/* Don't update hash if global still has users */
2086b848914cSSteven Rostedt 		if (global_start_up) {
2087b848914cSSteven Rostedt 			WARN_ON_ONCE(!ftrace_start_up);
2088b848914cSSteven Rostedt 			hash_disable = false;
2089b848914cSSteven Rostedt 		}
2090b848914cSSteven Rostedt 	}
2091b848914cSSteven Rostedt 
2092b848914cSSteven Rostedt 	if (hash_disable)
2093ed926f9bSSteven Rostedt 		ftrace_hash_rec_disable(ops, 1);
2094ed926f9bSSteven Rostedt 
2095b848914cSSteven Rostedt 	if (ops != &global_ops || !global_start_up)
2096ed926f9bSSteven Rostedt 		ops->flags &= ~FTRACE_OPS_FL_ENABLED;
2097b848914cSSteven Rostedt 
209830fb6aa7SJiri Olsa 	command |= FTRACE_UPDATE_CALLS;
2099d61f82d0SSteven Rostedt 
2100d61f82d0SSteven Rostedt 	if (saved_ftrace_func != ftrace_trace_function) {
2101d61f82d0SSteven Rostedt 		saved_ftrace_func = ftrace_trace_function;
2102d61f82d0SSteven Rostedt 		command |= FTRACE_UPDATE_TRACE_FUNC;
2103d61f82d0SSteven Rostedt 	}
2104d61f82d0SSteven Rostedt 
2105d61f82d0SSteven Rostedt 	if (!command || !ftrace_enabled)
2106e6ea44e9SSteven Rostedt 		return;
21073d083395SSteven Rostedt 
2108d61f82d0SSteven Rostedt 	ftrace_run_update_code(command);
21093d083395SSteven Rostedt }
21103d083395SSteven Rostedt 
2111e309b41dSIngo Molnar static void ftrace_startup_sysctl(void)
2112b0fc494fSSteven Rostedt {
21134eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
21144eebcc81SSteven Rostedt 		return;
21154eebcc81SSteven Rostedt 
2116d61f82d0SSteven Rostedt 	/* Force update next time */
2117d61f82d0SSteven Rostedt 	saved_ftrace_func = NULL;
211860a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if we want ftrace running */
211960a7ecf4SSteven Rostedt 	if (ftrace_start_up)
212030fb6aa7SJiri Olsa 		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
2121b0fc494fSSteven Rostedt }
2122b0fc494fSSteven Rostedt 
2123e309b41dSIngo Molnar static void ftrace_shutdown_sysctl(void)
2124b0fc494fSSteven Rostedt {
21254eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
21264eebcc81SSteven Rostedt 		return;
21274eebcc81SSteven Rostedt 
212860a7ecf4SSteven Rostedt 	/* ftrace_start_up is true if ftrace is running */
212960a7ecf4SSteven Rostedt 	if (ftrace_start_up)
213079e406d7SSteven Rostedt 		ftrace_run_update_code(FTRACE_DISABLE_CALLS);
2131b0fc494fSSteven Rostedt }
2132b0fc494fSSteven Rostedt 
21333d083395SSteven Rostedt static cycle_t		ftrace_update_time;
21343d083395SSteven Rostedt static unsigned long	ftrace_update_cnt;
21353d083395SSteven Rostedt unsigned long		ftrace_update_tot_cnt;
21363d083395SSteven Rostedt 
2137f7bc8b61SSteven Rostedt static int ops_traces_mod(struct ftrace_ops *ops)
2138f7bc8b61SSteven Rostedt {
2139f7bc8b61SSteven Rostedt 	struct ftrace_hash *hash;
2140f7bc8b61SSteven Rostedt 
2141f7bc8b61SSteven Rostedt 	hash = ops->filter_hash;
214206a51d93SSteven Rostedt 	return ftrace_hash_empty(hash);
2143f7bc8b61SSteven Rostedt }
2144f7bc8b61SSteven Rostedt 
214531e88909SSteven Rostedt static int ftrace_update_code(struct module *mod)
21463d083395SSteven Rostedt {
214785ae32aeSSteven Rostedt 	struct ftrace_page *pg;
2148e94142a6SLai Jiangshan 	struct dyn_ftrace *p;
2149f22f9a89SAbhishek Sagar 	cycle_t start, stop;
2150f7bc8b61SSteven Rostedt 	unsigned long ref = 0;
215185ae32aeSSteven Rostedt 	int i;
2152f7bc8b61SSteven Rostedt 
2153f7bc8b61SSteven Rostedt 	/*
2154f7bc8b61SSteven Rostedt 	 * When adding a module, we need to check if tracers are
2155f7bc8b61SSteven Rostedt 	 * currently enabled and if they are set to trace all functions.
2156f7bc8b61SSteven Rostedt 	 * If they are, we need to enable the module functions as well
2157f7bc8b61SSteven Rostedt 	 * as update the reference counts for those function records.
2158f7bc8b61SSteven Rostedt 	 */
2159f7bc8b61SSteven Rostedt 	if (mod) {
2160f7bc8b61SSteven Rostedt 		struct ftrace_ops *ops;
2161f7bc8b61SSteven Rostedt 
2162f7bc8b61SSteven Rostedt 		for (ops = ftrace_ops_list;
2163f7bc8b61SSteven Rostedt 		     ops != &ftrace_list_end; ops = ops->next) {
2164f7bc8b61SSteven Rostedt 			if (ops->flags & FTRACE_OPS_FL_ENABLED &&
2165f7bc8b61SSteven Rostedt 			    ops_traces_mod(ops))
2166f7bc8b61SSteven Rostedt 				ref++;
2167f7bc8b61SSteven Rostedt 		}
2168f7bc8b61SSteven Rostedt 	}
21693d083395SSteven Rostedt 
2170750ed1a4SIngo Molnar 	start = ftrace_now(raw_smp_processor_id());
21713d083395SSteven Rostedt 	ftrace_update_cnt = 0;
21723d083395SSteven Rostedt 
217385ae32aeSSteven Rostedt 	for (pg = ftrace_new_pgs; pg; pg = pg->next) {
2174f22f9a89SAbhishek Sagar 
217585ae32aeSSteven Rostedt 		for (i = 0; i < pg->index; i++) {
217608f5ac90SSteven Rostedt 			/* If something went wrong, bail without enabling anything */
217708f5ac90SSteven Rostedt 			if (unlikely(ftrace_disabled))
217808f5ac90SSteven Rostedt 				return -1;
21793d083395SSteven Rostedt 
218085ae32aeSSteven Rostedt 			p = &pg->records[i];
2181f7bc8b61SSteven Rostedt 			p->flags = ref;
2182f22f9a89SAbhishek Sagar 
21835cb084bbSJiri Olsa 			/*
218425985edcSLucas De Marchi 			 * Do the initial record conversion from mcount jump
21855cb084bbSJiri Olsa 			 * to the NOP instructions.
21865cb084bbSJiri Olsa 			 */
218732082309SSteven Rostedt 			if (!ftrace_code_disable(mod, p))
2188d2c8c3eaSSteven Rostedt 				break;
21895cb084bbSJiri Olsa 
21903d083395SSteven Rostedt 			ftrace_update_cnt++;
21915cb084bbSJiri Olsa 
21925cb084bbSJiri Olsa 			/*
21935cb084bbSJiri Olsa 			 * If the tracing is enabled, go ahead and enable the record.
21945cb084bbSJiri Olsa 			 *
21955cb084bbSJiri Olsa 			 * The reason not to enable the record immediatelly is the
21965cb084bbSJiri Olsa 			 * inherent check of ftrace_make_nop/ftrace_make_call for
21975cb084bbSJiri Olsa 			 * correct previous instructions.  Making first the NOP
21985cb084bbSJiri Olsa 			 * conversion puts the module to the correct state, thus
21995cb084bbSJiri Olsa 			 * passing the ftrace_make_call check.
22005cb084bbSJiri Olsa 			 */
2201f7bc8b61SSteven Rostedt 			if (ftrace_start_up && ref) {
22025cb084bbSJiri Olsa 				int failed = __ftrace_replace_code(p, 1);
220332082309SSteven Rostedt 				if (failed)
22045cb084bbSJiri Olsa 					ftrace_bug(failed, p->ip);
22055cb084bbSJiri Olsa 			}
22065cb084bbSJiri Olsa 		}
220785ae32aeSSteven Rostedt 	}
220885ae32aeSSteven Rostedt 
220985ae32aeSSteven Rostedt 	ftrace_new_pgs = NULL;
22103d083395SSteven Rostedt 
2211750ed1a4SIngo Molnar 	stop = ftrace_now(raw_smp_processor_id());
22123d083395SSteven Rostedt 	ftrace_update_time = stop - start;
22133d083395SSteven Rostedt 	ftrace_update_tot_cnt += ftrace_update_cnt;
22143d083395SSteven Rostedt 
221516444a8aSArnaldo Carvalho de Melo 	return 0;
221616444a8aSArnaldo Carvalho de Melo }
221716444a8aSArnaldo Carvalho de Melo 
2218a7900875SSteven Rostedt static int ftrace_allocate_records(struct ftrace_page *pg, int count)
22193c1720f0SSteven Rostedt {
2220a7900875SSteven Rostedt 	int order;
22213c1720f0SSteven Rostedt 	int cnt;
22223c1720f0SSteven Rostedt 
2223a7900875SSteven Rostedt 	if (WARN_ON(!count))
2224a7900875SSteven Rostedt 		return -EINVAL;
2225a7900875SSteven Rostedt 
2226a7900875SSteven Rostedt 	order = get_count_order(DIV_ROUND_UP(count, ENTRIES_PER_PAGE));
22273c1720f0SSteven Rostedt 
22283c1720f0SSteven Rostedt 	/*
2229a7900875SSteven Rostedt 	 * We want to fill as much as possible. No more than a page
2230a7900875SSteven Rostedt 	 * may be empty.
22313c1720f0SSteven Rostedt 	 */
2232a7900875SSteven Rostedt 	while ((PAGE_SIZE << order) / ENTRY_SIZE >= count + ENTRIES_PER_PAGE)
2233a7900875SSteven Rostedt 		order--;
22343c1720f0SSteven Rostedt 
2235a7900875SSteven Rostedt  again:
2236a7900875SSteven Rostedt 	pg->records = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
2237a7900875SSteven Rostedt 
2238a7900875SSteven Rostedt 	if (!pg->records) {
2239a7900875SSteven Rostedt 		/* if we can't allocate this size, try something smaller */
2240a7900875SSteven Rostedt 		if (!order)
2241a7900875SSteven Rostedt 			return -ENOMEM;
2242a7900875SSteven Rostedt 		order >>= 1;
2243a7900875SSteven Rostedt 		goto again;
2244a7900875SSteven Rostedt 	}
2245a7900875SSteven Rostedt 
2246a7900875SSteven Rostedt 	cnt = (PAGE_SIZE << order) / ENTRY_SIZE;
2247a7900875SSteven Rostedt 	pg->size = cnt;
2248a7900875SSteven Rostedt 
2249a7900875SSteven Rostedt 	if (cnt > count)
2250a7900875SSteven Rostedt 		cnt = count;
2251a7900875SSteven Rostedt 
2252a7900875SSteven Rostedt 	return cnt;
2253a7900875SSteven Rostedt }
2254a7900875SSteven Rostedt 
2255a7900875SSteven Rostedt static struct ftrace_page *
2256a7900875SSteven Rostedt ftrace_allocate_pages(unsigned long num_to_init)
2257a7900875SSteven Rostedt {
2258a7900875SSteven Rostedt 	struct ftrace_page *start_pg;
2259a7900875SSteven Rostedt 	struct ftrace_page *pg;
2260a7900875SSteven Rostedt 	int order;
2261a7900875SSteven Rostedt 	int cnt;
2262a7900875SSteven Rostedt 
2263a7900875SSteven Rostedt 	if (!num_to_init)
2264a7900875SSteven Rostedt 		return 0;
2265a7900875SSteven Rostedt 
2266a7900875SSteven Rostedt 	start_pg = pg = kzalloc(sizeof(*pg), GFP_KERNEL);
2267a7900875SSteven Rostedt 	if (!pg)
2268a7900875SSteven Rostedt 		return NULL;
2269a7900875SSteven Rostedt 
2270a7900875SSteven Rostedt 	/*
2271a7900875SSteven Rostedt 	 * Try to allocate as much as possible in one continues
2272a7900875SSteven Rostedt 	 * location that fills in all of the space. We want to
2273a7900875SSteven Rostedt 	 * waste as little space as possible.
2274a7900875SSteven Rostedt 	 */
2275a7900875SSteven Rostedt 	for (;;) {
2276a7900875SSteven Rostedt 		cnt = ftrace_allocate_records(pg, num_to_init);
2277a7900875SSteven Rostedt 		if (cnt < 0)
2278a7900875SSteven Rostedt 			goto free_pages;
2279a7900875SSteven Rostedt 
2280a7900875SSteven Rostedt 		num_to_init -= cnt;
2281a7900875SSteven Rostedt 		if (!num_to_init)
2282a7900875SSteven Rostedt 			break;
2283a7900875SSteven Rostedt 
2284a7900875SSteven Rostedt 		pg->next = kzalloc(sizeof(*pg), GFP_KERNEL);
2285a7900875SSteven Rostedt 		if (!pg->next)
2286a7900875SSteven Rostedt 			goto free_pages;
2287a7900875SSteven Rostedt 
2288a7900875SSteven Rostedt 		pg = pg->next;
2289a7900875SSteven Rostedt 	}
2290a7900875SSteven Rostedt 
2291a7900875SSteven Rostedt 	return start_pg;
2292a7900875SSteven Rostedt 
2293a7900875SSteven Rostedt  free_pages:
2294a7900875SSteven Rostedt 	while (start_pg) {
2295a7900875SSteven Rostedt 		order = get_count_order(pg->size / ENTRIES_PER_PAGE);
2296a7900875SSteven Rostedt 		free_pages((unsigned long)pg->records, order);
2297a7900875SSteven Rostedt 		start_pg = pg->next;
2298a7900875SSteven Rostedt 		kfree(pg);
2299a7900875SSteven Rostedt 		pg = start_pg;
2300a7900875SSteven Rostedt 	}
2301a7900875SSteven Rostedt 	pr_info("ftrace: FAILED to allocate memory for functions\n");
2302a7900875SSteven Rostedt 	return NULL;
2303a7900875SSteven Rostedt }
2304a7900875SSteven Rostedt 
2305a7900875SSteven Rostedt static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
2306a7900875SSteven Rostedt {
2307a7900875SSteven Rostedt 	int cnt;
2308a7900875SSteven Rostedt 
2309a7900875SSteven Rostedt 	if (!num_to_init) {
2310a7900875SSteven Rostedt 		pr_info("ftrace: No functions to be traced?\n");
2311a7900875SSteven Rostedt 		return -1;
2312a7900875SSteven Rostedt 	}
23133c1720f0SSteven Rostedt 
231468bf21aaSSteven Rostedt 	cnt = num_to_init / ENTRIES_PER_PAGE;
231508f5ac90SSteven Rostedt 	pr_info("ftrace: allocating %ld entries in %d pages\n",
23165821e1b7Swalimis 		num_to_init, cnt + 1);
23173c1720f0SSteven Rostedt 
23183c1720f0SSteven Rostedt 	return 0;
23193c1720f0SSteven Rostedt }
23203c1720f0SSteven Rostedt 
23215072c59fSSteven Rostedt #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
23225072c59fSSteven Rostedt 
23235072c59fSSteven Rostedt struct ftrace_iterator {
232498c4fd04SSteven Rostedt 	loff_t				pos;
23252bccfffdSSteven Rostedt 	loff_t				func_pos;
23265072c59fSSteven Rostedt 	struct ftrace_page		*pg;
23274aeb6967SSteven Rostedt 	struct dyn_ftrace		*func;
23284aeb6967SSteven Rostedt 	struct ftrace_func_probe	*probe;
23294aeb6967SSteven Rostedt 	struct trace_parser		parser;
23301cf41dd7SSteven Rostedt 	struct ftrace_hash		*hash;
233133dc9b12SSteven Rostedt 	struct ftrace_ops		*ops;
23328fc0c701SSteven Rostedt 	int				hidx;
2333431aa3fbSSteven Rostedt 	int				idx;
23345072c59fSSteven Rostedt 	unsigned			flags;
23355072c59fSSteven Rostedt };
23365072c59fSSteven Rostedt 
2337e309b41dSIngo Molnar static void *
23384aeb6967SSteven Rostedt t_hash_next(struct seq_file *m, loff_t *pos)
23398fc0c701SSteven Rostedt {
23408fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
23414aeb6967SSteven Rostedt 	struct hlist_node *hnd = NULL;
23428fc0c701SSteven Rostedt 	struct hlist_head *hhd;
23438fc0c701SSteven Rostedt 
23448fc0c701SSteven Rostedt 	(*pos)++;
234598c4fd04SSteven Rostedt 	iter->pos = *pos;
23468fc0c701SSteven Rostedt 
23474aeb6967SSteven Rostedt 	if (iter->probe)
23484aeb6967SSteven Rostedt 		hnd = &iter->probe->node;
23498fc0c701SSteven Rostedt  retry:
23508fc0c701SSteven Rostedt 	if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
23518fc0c701SSteven Rostedt 		return NULL;
23528fc0c701SSteven Rostedt 
23538fc0c701SSteven Rostedt 	hhd = &ftrace_func_hash[iter->hidx];
23548fc0c701SSteven Rostedt 
23558fc0c701SSteven Rostedt 	if (hlist_empty(hhd)) {
23568fc0c701SSteven Rostedt 		iter->hidx++;
23578fc0c701SSteven Rostedt 		hnd = NULL;
23588fc0c701SSteven Rostedt 		goto retry;
23598fc0c701SSteven Rostedt 	}
23608fc0c701SSteven Rostedt 
23618fc0c701SSteven Rostedt 	if (!hnd)
23628fc0c701SSteven Rostedt 		hnd = hhd->first;
23638fc0c701SSteven Rostedt 	else {
23648fc0c701SSteven Rostedt 		hnd = hnd->next;
23658fc0c701SSteven Rostedt 		if (!hnd) {
23668fc0c701SSteven Rostedt 			iter->hidx++;
23678fc0c701SSteven Rostedt 			goto retry;
23688fc0c701SSteven Rostedt 		}
23698fc0c701SSteven Rostedt 	}
23708fc0c701SSteven Rostedt 
23714aeb6967SSteven Rostedt 	if (WARN_ON_ONCE(!hnd))
23724aeb6967SSteven Rostedt 		return NULL;
23734aeb6967SSteven Rostedt 
23744aeb6967SSteven Rostedt 	iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node);
23754aeb6967SSteven Rostedt 
23764aeb6967SSteven Rostedt 	return iter;
23778fc0c701SSteven Rostedt }
23788fc0c701SSteven Rostedt 
23798fc0c701SSteven Rostedt static void *t_hash_start(struct seq_file *m, loff_t *pos)
23808fc0c701SSteven Rostedt {
23818fc0c701SSteven Rostedt 	struct ftrace_iterator *iter = m->private;
23828fc0c701SSteven Rostedt 	void *p = NULL;
2383d82d6244SLi Zefan 	loff_t l;
2384d82d6244SLi Zefan 
238569a3083cSSteven Rostedt 	if (!(iter->flags & FTRACE_ITER_DO_HASH))
238669a3083cSSteven Rostedt 		return NULL;
238769a3083cSSteven Rostedt 
23882bccfffdSSteven Rostedt 	if (iter->func_pos > *pos)
23892bccfffdSSteven Rostedt 		return NULL;
23908fc0c701SSteven Rostedt 
2391d82d6244SLi Zefan 	iter->hidx = 0;
23922bccfffdSSteven Rostedt 	for (l = 0; l <= (*pos - iter->func_pos); ) {
23934aeb6967SSteven Rostedt 		p = t_hash_next(m, &l);
2394d82d6244SLi Zefan 		if (!p)
2395d82d6244SLi Zefan 			break;
2396d82d6244SLi Zefan 	}
23974aeb6967SSteven Rostedt 	if (!p)
23984aeb6967SSteven Rostedt 		return NULL;
23994aeb6967SSteven Rostedt 
240098c4fd04SSteven Rostedt 	/* Only set this if we have an item */
240198c4fd04SSteven Rostedt 	iter->flags |= FTRACE_ITER_HASH;
240298c4fd04SSteven Rostedt 
24034aeb6967SSteven Rostedt 	return iter;
24048fc0c701SSteven Rostedt }
24058fc0c701SSteven Rostedt 
24064aeb6967SSteven Rostedt static int
24074aeb6967SSteven Rostedt t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
24088fc0c701SSteven Rostedt {
2409b6887d79SSteven Rostedt 	struct ftrace_func_probe *rec;
24108fc0c701SSteven Rostedt 
24114aeb6967SSteven Rostedt 	rec = iter->probe;
24124aeb6967SSteven Rostedt 	if (WARN_ON_ONCE(!rec))
24134aeb6967SSteven Rostedt 		return -EIO;
24148fc0c701SSteven Rostedt 
2415809dcf29SSteven Rostedt 	if (rec->ops->print)
2416809dcf29SSteven Rostedt 		return rec->ops->print(m, rec->ip, rec->ops, rec->data);
2417809dcf29SSteven Rostedt 
2418b375a11aSSteven Rostedt 	seq_printf(m, "%ps:%ps", (void *)rec->ip, (void *)rec->ops->func);
24198fc0c701SSteven Rostedt 
24208fc0c701SSteven Rostedt 	if (rec->data)
24218fc0c701SSteven Rostedt 		seq_printf(m, ":%p", rec->data);
24228fc0c701SSteven Rostedt 	seq_putc(m, '\n');
24238fc0c701SSteven Rostedt 
24248fc0c701SSteven Rostedt 	return 0;
24258fc0c701SSteven Rostedt }
24268fc0c701SSteven Rostedt 
24278fc0c701SSteven Rostedt static void *
24285072c59fSSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos)
24295072c59fSSteven Rostedt {
24305072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
2431fc13cb0cSSteven Rostedt 	struct ftrace_ops *ops = iter->ops;
24325072c59fSSteven Rostedt 	struct dyn_ftrace *rec = NULL;
24335072c59fSSteven Rostedt 
243445a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
243545a4a237SSteven Rostedt 		return NULL;
243645a4a237SSteven Rostedt 
24378fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
24384aeb6967SSteven Rostedt 		return t_hash_next(m, pos);
24398fc0c701SSteven Rostedt 
24405072c59fSSteven Rostedt 	(*pos)++;
24411106b699SJiri Olsa 	iter->pos = iter->func_pos = *pos;
24425072c59fSSteven Rostedt 
24430c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL)
244457c072c7SSteven Rostedt 		return t_hash_start(m, pos);
24450c75a3edSSteven Rostedt 
24465072c59fSSteven Rostedt  retry:
24475072c59fSSteven Rostedt 	if (iter->idx >= iter->pg->index) {
24485072c59fSSteven Rostedt 		if (iter->pg->next) {
24495072c59fSSteven Rostedt 			iter->pg = iter->pg->next;
24505072c59fSSteven Rostedt 			iter->idx = 0;
24515072c59fSSteven Rostedt 			goto retry;
24525072c59fSSteven Rostedt 		}
24535072c59fSSteven Rostedt 	} else {
24545072c59fSSteven Rostedt 		rec = &iter->pg->records[iter->idx++];
245532082309SSteven Rostedt 		if (((iter->flags & FTRACE_ITER_FILTER) &&
2456f45948e8SSteven Rostedt 		     !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) ||
24570183fb1cSSteven Rostedt 
245841c52c0dSSteven Rostedt 		    ((iter->flags & FTRACE_ITER_NOTRACE) &&
2459647bcd03SSteven Rostedt 		     !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) ||
2460647bcd03SSteven Rostedt 
2461647bcd03SSteven Rostedt 		    ((iter->flags & FTRACE_ITER_ENABLED) &&
246223ea9c4dSSteven Rostedt (Red Hat) 		     !(rec->flags & FTRACE_FL_ENABLED))) {
2463647bcd03SSteven Rostedt 
24645072c59fSSteven Rostedt 			rec = NULL;
24655072c59fSSteven Rostedt 			goto retry;
24665072c59fSSteven Rostedt 		}
24675072c59fSSteven Rostedt 	}
24685072c59fSSteven Rostedt 
24694aeb6967SSteven Rostedt 	if (!rec)
247057c072c7SSteven Rostedt 		return t_hash_start(m, pos);
24714aeb6967SSteven Rostedt 
24724aeb6967SSteven Rostedt 	iter->func = rec;
24734aeb6967SSteven Rostedt 
24744aeb6967SSteven Rostedt 	return iter;
24755072c59fSSteven Rostedt }
24765072c59fSSteven Rostedt 
247798c4fd04SSteven Rostedt static void reset_iter_read(struct ftrace_iterator *iter)
247898c4fd04SSteven Rostedt {
247998c4fd04SSteven Rostedt 	iter->pos = 0;
248098c4fd04SSteven Rostedt 	iter->func_pos = 0;
248170f77b3fSDan Carpenter 	iter->flags &= ~(FTRACE_ITER_PRINTALL | FTRACE_ITER_HASH);
24825072c59fSSteven Rostedt }
24835072c59fSSteven Rostedt 
24845072c59fSSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos)
24855072c59fSSteven Rostedt {
24865072c59fSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
2487fc13cb0cSSteven Rostedt 	struct ftrace_ops *ops = iter->ops;
24885072c59fSSteven Rostedt 	void *p = NULL;
2489694ce0a5SLi Zefan 	loff_t l;
24905072c59fSSteven Rostedt 
24918fc0c701SSteven Rostedt 	mutex_lock(&ftrace_lock);
249245a4a237SSteven Rostedt 
249345a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
249445a4a237SSteven Rostedt 		return NULL;
249545a4a237SSteven Rostedt 
24960c75a3edSSteven Rostedt 	/*
249798c4fd04SSteven Rostedt 	 * If an lseek was done, then reset and start from beginning.
249898c4fd04SSteven Rostedt 	 */
249998c4fd04SSteven Rostedt 	if (*pos < iter->pos)
250098c4fd04SSteven Rostedt 		reset_iter_read(iter);
250198c4fd04SSteven Rostedt 
250298c4fd04SSteven Rostedt 	/*
25030c75a3edSSteven Rostedt 	 * For set_ftrace_filter reading, if we have the filter
25040c75a3edSSteven Rostedt 	 * off, we can short cut and just print out that all
25050c75a3edSSteven Rostedt 	 * functions are enabled.
25060c75a3edSSteven Rostedt 	 */
250706a51d93SSteven Rostedt 	if (iter->flags & FTRACE_ITER_FILTER &&
250806a51d93SSteven Rostedt 	    ftrace_hash_empty(ops->filter_hash)) {
25090c75a3edSSteven Rostedt 		if (*pos > 0)
25108fc0c701SSteven Rostedt 			return t_hash_start(m, pos);
25110c75a3edSSteven Rostedt 		iter->flags |= FTRACE_ITER_PRINTALL;
2512df091625SChris Wright 		/* reset in case of seek/pread */
2513df091625SChris Wright 		iter->flags &= ~FTRACE_ITER_HASH;
25140c75a3edSSteven Rostedt 		return iter;
25150c75a3edSSteven Rostedt 	}
25160c75a3edSSteven Rostedt 
25178fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
25188fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
25198fc0c701SSteven Rostedt 
252098c4fd04SSteven Rostedt 	/*
252198c4fd04SSteven Rostedt 	 * Unfortunately, we need to restart at ftrace_pages_start
252298c4fd04SSteven Rostedt 	 * every time we let go of the ftrace_mutex. This is because
252398c4fd04SSteven Rostedt 	 * those pointers can change without the lock.
252498c4fd04SSteven Rostedt 	 */
2525694ce0a5SLi Zefan 	iter->pg = ftrace_pages_start;
2526694ce0a5SLi Zefan 	iter->idx = 0;
2527694ce0a5SLi Zefan 	for (l = 0; l <= *pos; ) {
2528694ce0a5SLi Zefan 		p = t_next(m, p, &l);
2529694ce0a5SLi Zefan 		if (!p)
2530694ce0a5SLi Zefan 			break;
253150cdaf08SLiming Wang 	}
25325821e1b7Swalimis 
253369a3083cSSteven Rostedt 	if (!p)
25348fc0c701SSteven Rostedt 		return t_hash_start(m, pos);
25358fc0c701SSteven Rostedt 
25364aeb6967SSteven Rostedt 	return iter;
25375072c59fSSteven Rostedt }
25385072c59fSSteven Rostedt 
25395072c59fSSteven Rostedt static void t_stop(struct seq_file *m, void *p)
25405072c59fSSteven Rostedt {
25418fc0c701SSteven Rostedt 	mutex_unlock(&ftrace_lock);
25425072c59fSSteven Rostedt }
25435072c59fSSteven Rostedt 
25445072c59fSSteven Rostedt static int t_show(struct seq_file *m, void *v)
25455072c59fSSteven Rostedt {
25460c75a3edSSteven Rostedt 	struct ftrace_iterator *iter = m->private;
25474aeb6967SSteven Rostedt 	struct dyn_ftrace *rec;
25485072c59fSSteven Rostedt 
25498fc0c701SSteven Rostedt 	if (iter->flags & FTRACE_ITER_HASH)
25504aeb6967SSteven Rostedt 		return t_hash_show(m, iter);
25518fc0c701SSteven Rostedt 
25520c75a3edSSteven Rostedt 	if (iter->flags & FTRACE_ITER_PRINTALL) {
25530c75a3edSSteven Rostedt 		seq_printf(m, "#### all functions enabled ####\n");
25540c75a3edSSteven Rostedt 		return 0;
25550c75a3edSSteven Rostedt 	}
25560c75a3edSSteven Rostedt 
25574aeb6967SSteven Rostedt 	rec = iter->func;
25584aeb6967SSteven Rostedt 
25595072c59fSSteven Rostedt 	if (!rec)
25605072c59fSSteven Rostedt 		return 0;
25615072c59fSSteven Rostedt 
2562647bcd03SSteven Rostedt 	seq_printf(m, "%ps", (void *)rec->ip);
2563647bcd03SSteven Rostedt 	if (iter->flags & FTRACE_ITER_ENABLED)
256408f6fba5SSteven Rostedt 		seq_printf(m, " (%ld)%s",
256508f6fba5SSteven Rostedt 			   rec->flags & ~FTRACE_FL_MASK,
256608f6fba5SSteven Rostedt 			   rec->flags & FTRACE_FL_REGS ? " R" : "");
2567647bcd03SSteven Rostedt 	seq_printf(m, "\n");
25685072c59fSSteven Rostedt 
25695072c59fSSteven Rostedt 	return 0;
25705072c59fSSteven Rostedt }
25715072c59fSSteven Rostedt 
257288e9d34cSJames Morris static const struct seq_operations show_ftrace_seq_ops = {
25735072c59fSSteven Rostedt 	.start = t_start,
25745072c59fSSteven Rostedt 	.next = t_next,
25755072c59fSSteven Rostedt 	.stop = t_stop,
25765072c59fSSteven Rostedt 	.show = t_show,
25775072c59fSSteven Rostedt };
25785072c59fSSteven Rostedt 
2579e309b41dSIngo Molnar static int
25805072c59fSSteven Rostedt ftrace_avail_open(struct inode *inode, struct file *file)
25815072c59fSSteven Rostedt {
25825072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
25835072c59fSSteven Rostedt 
25844eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
25854eebcc81SSteven Rostedt 		return -ENODEV;
25864eebcc81SSteven Rostedt 
258750e18b94SJiri Olsa 	iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
258850e18b94SJiri Olsa 	if (iter) {
25895072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
2590fc13cb0cSSteven Rostedt 		iter->ops = &global_ops;
25914bf39a94SIngo Molnar 	}
25925072c59fSSteven Rostedt 
259350e18b94SJiri Olsa 	return iter ? 0 : -ENOMEM;
25945072c59fSSteven Rostedt }
25955072c59fSSteven Rostedt 
2596647bcd03SSteven Rostedt static int
2597647bcd03SSteven Rostedt ftrace_enabled_open(struct inode *inode, struct file *file)
2598647bcd03SSteven Rostedt {
2599647bcd03SSteven Rostedt 	struct ftrace_iterator *iter;
2600647bcd03SSteven Rostedt 
2601647bcd03SSteven Rostedt 	if (unlikely(ftrace_disabled))
2602647bcd03SSteven Rostedt 		return -ENODEV;
2603647bcd03SSteven Rostedt 
260450e18b94SJiri Olsa 	iter = __seq_open_private(file, &show_ftrace_seq_ops, sizeof(*iter));
260550e18b94SJiri Olsa 	if (iter) {
2606647bcd03SSteven Rostedt 		iter->pg = ftrace_pages_start;
2607647bcd03SSteven Rostedt 		iter->flags = FTRACE_ITER_ENABLED;
2608fc13cb0cSSteven Rostedt 		iter->ops = &global_ops;
2609647bcd03SSteven Rostedt 	}
2610647bcd03SSteven Rostedt 
261150e18b94SJiri Olsa 	return iter ? 0 : -ENOMEM;
2612647bcd03SSteven Rostedt }
2613647bcd03SSteven Rostedt 
26141cf41dd7SSteven Rostedt static void ftrace_filter_reset(struct ftrace_hash *hash)
26155072c59fSSteven Rostedt {
261652baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
26171cf41dd7SSteven Rostedt 	ftrace_hash_clear(hash);
261852baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
26195072c59fSSteven Rostedt }
26205072c59fSSteven Rostedt 
2621fc13cb0cSSteven Rostedt /**
2622fc13cb0cSSteven Rostedt  * ftrace_regex_open - initialize function tracer filter files
2623fc13cb0cSSteven Rostedt  * @ops: The ftrace_ops that hold the hash filters
2624fc13cb0cSSteven Rostedt  * @flag: The type of filter to process
2625fc13cb0cSSteven Rostedt  * @inode: The inode, usually passed in to your open routine
2626fc13cb0cSSteven Rostedt  * @file: The file, usually passed in to your open routine
2627fc13cb0cSSteven Rostedt  *
2628fc13cb0cSSteven Rostedt  * ftrace_regex_open() initializes the filter files for the
2629fc13cb0cSSteven Rostedt  * @ops. Depending on @flag it may process the filter hash or
2630fc13cb0cSSteven Rostedt  * the notrace hash of @ops. With this called from the open
2631fc13cb0cSSteven Rostedt  * routine, you can use ftrace_filter_write() for the write
2632fc13cb0cSSteven Rostedt  * routine if @flag has FTRACE_ITER_FILTER set, or
2633fc13cb0cSSteven Rostedt  * ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set.
26347f49ef69SSteven Rostedt (Red Hat)  * ftrace_filter_lseek() should be used as the lseek routine, and
2635fc13cb0cSSteven Rostedt  * release must call ftrace_regex_release().
2636fc13cb0cSSteven Rostedt  */
2637fc13cb0cSSteven Rostedt int
2638f45948e8SSteven Rostedt ftrace_regex_open(struct ftrace_ops *ops, int flag,
26391cf41dd7SSteven Rostedt 		  struct inode *inode, struct file *file)
26405072c59fSSteven Rostedt {
26415072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
2642f45948e8SSteven Rostedt 	struct ftrace_hash *hash;
26435072c59fSSteven Rostedt 	int ret = 0;
26445072c59fSSteven Rostedt 
2645f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
2646f04f24fbSMasami Hiramatsu 
26474eebcc81SSteven Rostedt 	if (unlikely(ftrace_disabled))
26484eebcc81SSteven Rostedt 		return -ENODEV;
26494eebcc81SSteven Rostedt 
26505072c59fSSteven Rostedt 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
26515072c59fSSteven Rostedt 	if (!iter)
26525072c59fSSteven Rostedt 		return -ENOMEM;
26535072c59fSSteven Rostedt 
2654689fd8b6S[email protected] 	if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) {
2655689fd8b6S[email protected] 		kfree(iter);
2656689fd8b6S[email protected] 		return -ENOMEM;
2657689fd8b6S[email protected] 	}
2658689fd8b6S[email protected] 
26593f2367baSMasami Hiramatsu 	iter->ops = ops;
26603f2367baSMasami Hiramatsu 	iter->flags = flag;
26613f2367baSMasami Hiramatsu 
26623f2367baSMasami Hiramatsu 	mutex_lock(&ops->regex_lock);
26633f2367baSMasami Hiramatsu 
2664f45948e8SSteven Rostedt 	if (flag & FTRACE_ITER_NOTRACE)
2665f45948e8SSteven Rostedt 		hash = ops->notrace_hash;
2666f45948e8SSteven Rostedt 	else
2667f45948e8SSteven Rostedt 		hash = ops->filter_hash;
2668f45948e8SSteven Rostedt 
266933dc9b12SSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
267033dc9b12SSteven Rostedt 		iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
267133dc9b12SSteven Rostedt 		if (!iter->hash) {
267233dc9b12SSteven Rostedt 			trace_parser_put(&iter->parser);
267333dc9b12SSteven Rostedt 			kfree(iter);
26743f2367baSMasami Hiramatsu 			ret = -ENOMEM;
26753f2367baSMasami Hiramatsu 			goto out_unlock;
267633dc9b12SSteven Rostedt 		}
267733dc9b12SSteven Rostedt 	}
26781cf41dd7SSteven Rostedt 
26795072c59fSSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
26808650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC))
268133dc9b12SSteven Rostedt 		ftrace_filter_reset(iter->hash);
26825072c59fSSteven Rostedt 
26835072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
26845072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
26855072c59fSSteven Rostedt 
26865072c59fSSteven Rostedt 		ret = seq_open(file, &show_ftrace_seq_ops);
26875072c59fSSteven Rostedt 		if (!ret) {
26885072c59fSSteven Rostedt 			struct seq_file *m = file->private_data;
26895072c59fSSteven Rostedt 			m->private = iter;
269079fe249cSLi Zefan 		} else {
269133dc9b12SSteven Rostedt 			/* Failed */
269233dc9b12SSteven Rostedt 			free_ftrace_hash(iter->hash);
269379fe249cSLi Zefan 			trace_parser_put(&iter->parser);
26945072c59fSSteven Rostedt 			kfree(iter);
269579fe249cSLi Zefan 		}
26965072c59fSSteven Rostedt 	} else
26975072c59fSSteven Rostedt 		file->private_data = iter;
26983f2367baSMasami Hiramatsu 
26993f2367baSMasami Hiramatsu  out_unlock:
2700f04f24fbSMasami Hiramatsu 	mutex_unlock(&ops->regex_lock);
27015072c59fSSteven Rostedt 
27025072c59fSSteven Rostedt 	return ret;
27035072c59fSSteven Rostedt }
27045072c59fSSteven Rostedt 
270541c52c0dSSteven Rostedt static int
270641c52c0dSSteven Rostedt ftrace_filter_open(struct inode *inode, struct file *file)
270741c52c0dSSteven Rostedt {
270869a3083cSSteven Rostedt 	return ftrace_regex_open(&global_ops,
270969a3083cSSteven Rostedt 			FTRACE_ITER_FILTER | FTRACE_ITER_DO_HASH,
27101cf41dd7SSteven Rostedt 			inode, file);
271141c52c0dSSteven Rostedt }
271241c52c0dSSteven Rostedt 
271341c52c0dSSteven Rostedt static int
271441c52c0dSSteven Rostedt ftrace_notrace_open(struct inode *inode, struct file *file)
271541c52c0dSSteven Rostedt {
2716f45948e8SSteven Rostedt 	return ftrace_regex_open(&global_ops, FTRACE_ITER_NOTRACE,
27171cf41dd7SSteven Rostedt 				 inode, file);
271841c52c0dSSteven Rostedt }
271941c52c0dSSteven Rostedt 
272064e7c440SSteven Rostedt static int ftrace_match(char *str, char *regex, int len, int type)
27219f4801e3SSteven Rostedt {
27229f4801e3SSteven Rostedt 	int matched = 0;
2723751e9983SLi Zefan 	int slen;
27249f4801e3SSteven Rostedt 
27259f4801e3SSteven Rostedt 	switch (type) {
27269f4801e3SSteven Rostedt 	case MATCH_FULL:
27279f4801e3SSteven Rostedt 		if (strcmp(str, regex) == 0)
27289f4801e3SSteven Rostedt 			matched = 1;
27299f4801e3SSteven Rostedt 		break;
27309f4801e3SSteven Rostedt 	case MATCH_FRONT_ONLY:
27319f4801e3SSteven Rostedt 		if (strncmp(str, regex, len) == 0)
27329f4801e3SSteven Rostedt 			matched = 1;
27339f4801e3SSteven Rostedt 		break;
27349f4801e3SSteven Rostedt 	case MATCH_MIDDLE_ONLY:
27359f4801e3SSteven Rostedt 		if (strstr(str, regex))
27369f4801e3SSteven Rostedt 			matched = 1;
27379f4801e3SSteven Rostedt 		break;
27389f4801e3SSteven Rostedt 	case MATCH_END_ONLY:
2739751e9983SLi Zefan 		slen = strlen(str);
2740751e9983SLi Zefan 		if (slen >= len && memcmp(str + slen - len, regex, len) == 0)
27419f4801e3SSteven Rostedt 			matched = 1;
27429f4801e3SSteven Rostedt 		break;
27439f4801e3SSteven Rostedt 	}
27449f4801e3SSteven Rostedt 
27459f4801e3SSteven Rostedt 	return matched;
27469f4801e3SSteven Rostedt }
27479f4801e3SSteven Rostedt 
2748b448c4e3SSteven Rostedt static int
27491cf41dd7SSteven Rostedt enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not)
275064e7c440SSteven Rostedt {
2751b448c4e3SSteven Rostedt 	struct ftrace_func_entry *entry;
2752b448c4e3SSteven Rostedt 	int ret = 0;
2753b448c4e3SSteven Rostedt 
27541cf41dd7SSteven Rostedt 	entry = ftrace_lookup_ip(hash, rec->ip);
2755b448c4e3SSteven Rostedt 	if (not) {
2756b448c4e3SSteven Rostedt 		/* Do nothing if it doesn't exist */
2757b448c4e3SSteven Rostedt 		if (!entry)
2758b448c4e3SSteven Rostedt 			return 0;
2759b448c4e3SSteven Rostedt 
276033dc9b12SSteven Rostedt 		free_hash_entry(hash, entry);
2761b448c4e3SSteven Rostedt 	} else {
2762b448c4e3SSteven Rostedt 		/* Do nothing if it exists */
2763b448c4e3SSteven Rostedt 		if (entry)
2764b448c4e3SSteven Rostedt 			return 0;
2765b448c4e3SSteven Rostedt 
2766b448c4e3SSteven Rostedt 		ret = add_hash_entry(hash, rec->ip);
2767b448c4e3SSteven Rostedt 	}
2768b448c4e3SSteven Rostedt 	return ret;
2769996e87beSSteven Rostedt }
2770996e87beSSteven Rostedt 
277164e7c440SSteven Rostedt static int
2772b9df92d2SSteven Rostedt ftrace_match_record(struct dyn_ftrace *rec, char *mod,
2773b9df92d2SSteven Rostedt 		    char *regex, int len, int type)
277464e7c440SSteven Rostedt {
277564e7c440SSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
2776b9df92d2SSteven Rostedt 	char *modname;
277764e7c440SSteven Rostedt 
2778b9df92d2SSteven Rostedt 	kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
2779b9df92d2SSteven Rostedt 
2780b9df92d2SSteven Rostedt 	if (mod) {
2781b9df92d2SSteven Rostedt 		/* module lookup requires matching the module */
2782b9df92d2SSteven Rostedt 		if (!modname || strcmp(modname, mod))
2783b9df92d2SSteven Rostedt 			return 0;
2784b9df92d2SSteven Rostedt 
2785b9df92d2SSteven Rostedt 		/* blank search means to match all funcs in the mod */
2786b9df92d2SSteven Rostedt 		if (!len)
2787b9df92d2SSteven Rostedt 			return 1;
2788b9df92d2SSteven Rostedt 	}
2789b9df92d2SSteven Rostedt 
279064e7c440SSteven Rostedt 	return ftrace_match(str, regex, len, type);
279164e7c440SSteven Rostedt }
279264e7c440SSteven Rostedt 
27931cf41dd7SSteven Rostedt static int
27941cf41dd7SSteven Rostedt match_records(struct ftrace_hash *hash, char *buff,
27951cf41dd7SSteven Rostedt 	      int len, char *mod, int not)
27969f4801e3SSteven Rostedt {
2797b9df92d2SSteven Rostedt 	unsigned search_len = 0;
27989f4801e3SSteven Rostedt 	struct ftrace_page *pg;
27999f4801e3SSteven Rostedt 	struct dyn_ftrace *rec;
2800b9df92d2SSteven Rostedt 	int type = MATCH_FULL;
2801b9df92d2SSteven Rostedt 	char *search = buff;
2802311d16daSLi Zefan 	int found = 0;
2803b448c4e3SSteven Rostedt 	int ret;
28049f4801e3SSteven Rostedt 
2805b9df92d2SSteven Rostedt 	if (len) {
28063f6fe06dSFrederic Weisbecker 		type = filter_parse_regex(buff, len, &search, &not);
28079f4801e3SSteven Rostedt 		search_len = strlen(search);
2808b9df92d2SSteven Rostedt 	}
2809b9df92d2SSteven Rostedt 
281052baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
2811b9df92d2SSteven Rostedt 
2812b9df92d2SSteven Rostedt 	if (unlikely(ftrace_disabled))
2813b9df92d2SSteven Rostedt 		goto out_unlock;
2814b9df92d2SSteven Rostedt 
2815265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
2816b9df92d2SSteven Rostedt 		if (ftrace_match_record(rec, mod, search, search_len, type)) {
28171cf41dd7SSteven Rostedt 			ret = enter_record(hash, rec, not);
2818b448c4e3SSteven Rostedt 			if (ret < 0) {
2819b448c4e3SSteven Rostedt 				found = ret;
2820b448c4e3SSteven Rostedt 				goto out_unlock;
2821b448c4e3SSteven Rostedt 			}
2822311d16daSLi Zefan 			found = 1;
28235072c59fSSteven Rostedt 		}
2824265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
2825b9df92d2SSteven Rostedt  out_unlock:
282652baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
2827311d16daSLi Zefan 
2828311d16daSLi Zefan 	return found;
28295072c59fSSteven Rostedt }
28305072c59fSSteven Rostedt 
283164e7c440SSteven Rostedt static int
28321cf41dd7SSteven Rostedt ftrace_match_records(struct ftrace_hash *hash, char *buff, int len)
283364e7c440SSteven Rostedt {
28341cf41dd7SSteven Rostedt 	return match_records(hash, buff, len, NULL, 0);
283564e7c440SSteven Rostedt }
283664e7c440SSteven Rostedt 
28371cf41dd7SSteven Rostedt static int
28381cf41dd7SSteven Rostedt ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod)
283964e7c440SSteven Rostedt {
284064e7c440SSteven Rostedt 	int not = 0;
28416a24a244SSteven Rostedt 
284264e7c440SSteven Rostedt 	/* blank or '*' mean the same */
284364e7c440SSteven Rostedt 	if (strcmp(buff, "*") == 0)
284464e7c440SSteven Rostedt 		buff[0] = 0;
284564e7c440SSteven Rostedt 
284664e7c440SSteven Rostedt 	/* handle the case of 'dont filter this module' */
284764e7c440SSteven Rostedt 	if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) {
284864e7c440SSteven Rostedt 		buff[0] = 0;
284964e7c440SSteven Rostedt 		not = 1;
285064e7c440SSteven Rostedt 	}
285164e7c440SSteven Rostedt 
28521cf41dd7SSteven Rostedt 	return match_records(hash, buff, strlen(buff), mod, not);
285364e7c440SSteven Rostedt }
285464e7c440SSteven Rostedt 
2855f6180773SSteven Rostedt /*
2856f6180773SSteven Rostedt  * We register the module command as a template to show others how
2857f6180773SSteven Rostedt  * to register the a command as well.
2858f6180773SSteven Rostedt  */
2859f6180773SSteven Rostedt 
2860f6180773SSteven Rostedt static int
286143dd61c9SSteven Rostedt ftrace_mod_callback(struct ftrace_hash *hash,
286243dd61c9SSteven Rostedt 		    char *func, char *cmd, char *param, int enable)
2863f6180773SSteven Rostedt {
2864f6180773SSteven Rostedt 	char *mod;
2865b448c4e3SSteven Rostedt 	int ret = -EINVAL;
2866f6180773SSteven Rostedt 
2867f6180773SSteven Rostedt 	/*
2868f6180773SSteven Rostedt 	 * cmd == 'mod' because we only registered this func
2869f6180773SSteven Rostedt 	 * for the 'mod' ftrace_func_command.
2870f6180773SSteven Rostedt 	 * But if you register one func with multiple commands,
2871f6180773SSteven Rostedt 	 * you can tell which command was used by the cmd
2872f6180773SSteven Rostedt 	 * parameter.
2873f6180773SSteven Rostedt 	 */
2874f6180773SSteven Rostedt 
2875f6180773SSteven Rostedt 	/* we must have a module name */
2876f6180773SSteven Rostedt 	if (!param)
2877b448c4e3SSteven Rostedt 		return ret;
2878f6180773SSteven Rostedt 
2879f6180773SSteven Rostedt 	mod = strsep(&param, ":");
2880f6180773SSteven Rostedt 	if (!strlen(mod))
2881b448c4e3SSteven Rostedt 		return ret;
2882f6180773SSteven Rostedt 
28831cf41dd7SSteven Rostedt 	ret = ftrace_match_module_records(hash, func, mod);
2884b448c4e3SSteven Rostedt 	if (!ret)
2885b448c4e3SSteven Rostedt 		ret = -EINVAL;
2886b448c4e3SSteven Rostedt 	if (ret < 0)
2887b448c4e3SSteven Rostedt 		return ret;
2888b448c4e3SSteven Rostedt 
2889f6180773SSteven Rostedt 	return 0;
2890f6180773SSteven Rostedt }
2891f6180773SSteven Rostedt 
2892f6180773SSteven Rostedt static struct ftrace_func_command ftrace_mod_cmd = {
2893f6180773SSteven Rostedt 	.name			= "mod",
2894f6180773SSteven Rostedt 	.func			= ftrace_mod_callback,
2895f6180773SSteven Rostedt };
2896f6180773SSteven Rostedt 
2897f6180773SSteven Rostedt static int __init ftrace_mod_cmd_init(void)
2898f6180773SSteven Rostedt {
2899f6180773SSteven Rostedt 	return register_ftrace_command(&ftrace_mod_cmd);
2900f6180773SSteven Rostedt }
29016f415672SSteven Rostedt core_initcall(ftrace_mod_cmd_init);
2902f6180773SSteven Rostedt 
29032f5f6ad9SSteven Rostedt static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
2904a1e2e31dSSteven Rostedt 				      struct ftrace_ops *op, struct pt_regs *pt_regs)
290559df055fSSteven Rostedt {
2906b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
290759df055fSSteven Rostedt 	struct hlist_head *hhd;
290859df055fSSteven Rostedt 	unsigned long key;
290959df055fSSteven Rostedt 
291059df055fSSteven Rostedt 	key = hash_long(ip, FTRACE_HASH_BITS);
291159df055fSSteven Rostedt 
291259df055fSSteven Rostedt 	hhd = &ftrace_func_hash[key];
291359df055fSSteven Rostedt 
291459df055fSSteven Rostedt 	if (hlist_empty(hhd))
291559df055fSSteven Rostedt 		return;
291659df055fSSteven Rostedt 
291759df055fSSteven Rostedt 	/*
291859df055fSSteven Rostedt 	 * Disable preemption for these calls to prevent a RCU grace
291959df055fSSteven Rostedt 	 * period. This syncs the hash iteration and freeing of items
292059df055fSSteven Rostedt 	 * on the hash. rcu_read_lock is too dangerous here.
292159df055fSSteven Rostedt 	 */
29225168ae50SSteven Rostedt 	preempt_disable_notrace();
2923*1bb539caSSteven Rostedt 	hlist_for_each_entry_rcu_notrace(entry, hhd, node) {
292459df055fSSteven Rostedt 		if (entry->ip == ip)
292559df055fSSteven Rostedt 			entry->ops->func(ip, parent_ip, &entry->data);
292659df055fSSteven Rostedt 	}
29275168ae50SSteven Rostedt 	preempt_enable_notrace();
292859df055fSSteven Rostedt }
292959df055fSSteven Rostedt 
2930b6887d79SSteven Rostedt static struct ftrace_ops trace_probe_ops __read_mostly =
293159df055fSSteven Rostedt {
2932b6887d79SSteven Rostedt 	.func		= function_trace_probe_call,
2933f04f24fbSMasami Hiramatsu 	.flags		= FTRACE_OPS_FL_INITIALIZED,
2934f04f24fbSMasami Hiramatsu 	INIT_REGEX_LOCK(trace_probe_ops)
293559df055fSSteven Rostedt };
293659df055fSSteven Rostedt 
2937b6887d79SSteven Rostedt static int ftrace_probe_registered;
293859df055fSSteven Rostedt 
2939b6887d79SSteven Rostedt static void __enable_ftrace_function_probe(void)
294059df055fSSteven Rostedt {
2941b848914cSSteven Rostedt 	int ret;
294259df055fSSteven Rostedt 	int i;
294359df055fSSteven Rostedt 
294419dd603eSSteven Rostedt (Red Hat) 	if (ftrace_probe_registered) {
294519dd603eSSteven Rostedt (Red Hat) 		/* still need to update the function call sites */
294619dd603eSSteven Rostedt (Red Hat) 		if (ftrace_enabled)
294719dd603eSSteven Rostedt (Red Hat) 			ftrace_run_update_code(FTRACE_UPDATE_CALLS);
294859df055fSSteven Rostedt 		return;
294919dd603eSSteven Rostedt (Red Hat) 	}
295059df055fSSteven Rostedt 
295159df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
295259df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
295359df055fSSteven Rostedt 		if (hhd->first)
295459df055fSSteven Rostedt 			break;
295559df055fSSteven Rostedt 	}
295659df055fSSteven Rostedt 	/* Nothing registered? */
295759df055fSSteven Rostedt 	if (i == FTRACE_FUNC_HASHSIZE)
295859df055fSSteven Rostedt 		return;
295959df055fSSteven Rostedt 
2960b848914cSSteven Rostedt 	ret = __register_ftrace_function(&trace_probe_ops);
2961b848914cSSteven Rostedt 	if (!ret)
2962a1cd6173SSteven Rostedt 		ret = ftrace_startup(&trace_probe_ops, 0);
2963b848914cSSteven Rostedt 
2964b6887d79SSteven Rostedt 	ftrace_probe_registered = 1;
296559df055fSSteven Rostedt }
296659df055fSSteven Rostedt 
2967b6887d79SSteven Rostedt static void __disable_ftrace_function_probe(void)
296859df055fSSteven Rostedt {
2969b848914cSSteven Rostedt 	int ret;
297059df055fSSteven Rostedt 	int i;
297159df055fSSteven Rostedt 
2972b6887d79SSteven Rostedt 	if (!ftrace_probe_registered)
297359df055fSSteven Rostedt 		return;
297459df055fSSteven Rostedt 
297559df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
297659df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
297759df055fSSteven Rostedt 		if (hhd->first)
297859df055fSSteven Rostedt 			return;
297959df055fSSteven Rostedt 	}
298059df055fSSteven Rostedt 
298159df055fSSteven Rostedt 	/* no more funcs left */
2982b848914cSSteven Rostedt 	ret = __unregister_ftrace_function(&trace_probe_ops);
2983b848914cSSteven Rostedt 	if (!ret)
2984b848914cSSteven Rostedt 		ftrace_shutdown(&trace_probe_ops, 0);
2985b848914cSSteven Rostedt 
2986b6887d79SSteven Rostedt 	ftrace_probe_registered = 0;
298759df055fSSteven Rostedt }
298859df055fSSteven Rostedt 
298959df055fSSteven Rostedt 
29907818b388SSteven Rostedt (Red Hat) static void ftrace_free_entry(struct ftrace_func_probe *entry)
299159df055fSSteven Rostedt {
299259df055fSSteven Rostedt 	if (entry->ops->free)
2993e67efb93SSteven Rostedt (Red Hat) 		entry->ops->free(entry->ops, entry->ip, &entry->data);
299459df055fSSteven Rostedt 	kfree(entry);
299559df055fSSteven Rostedt }
299659df055fSSteven Rostedt 
299759df055fSSteven Rostedt int
2998b6887d79SSteven Rostedt register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
299959df055fSSteven Rostedt 			      void *data)
300059df055fSSteven Rostedt {
3001b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
3002e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
3003e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
300459df055fSSteven Rostedt 	struct ftrace_page *pg;
300559df055fSSteven Rostedt 	struct dyn_ftrace *rec;
300659df055fSSteven Rostedt 	int type, len, not;
30076a24a244SSteven Rostedt 	unsigned long key;
300859df055fSSteven Rostedt 	int count = 0;
300959df055fSSteven Rostedt 	char *search;
3010e1df4cb6SSteven Rostedt (Red Hat) 	int ret;
301159df055fSSteven Rostedt 
30123f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(glob, strlen(glob), &search, &not);
301359df055fSSteven Rostedt 	len = strlen(search);
301459df055fSSteven Rostedt 
3015b6887d79SSteven Rostedt 	/* we do not support '!' for function probes */
301659df055fSSteven Rostedt 	if (WARN_ON(not))
301759df055fSSteven Rostedt 		return -EINVAL;
301859df055fSSteven Rostedt 
30193f2367baSMasami Hiramatsu 	mutex_lock(&trace_probe_ops.regex_lock);
302059df055fSSteven Rostedt 
3021e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3022e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash) {
3023e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENOMEM;
30245ae0bf59SSteven Rostedt (Red Hat) 		goto out;
3025e1df4cb6SSteven Rostedt (Red Hat) 	}
3026e1df4cb6SSteven Rostedt (Red Hat) 
3027e1df4cb6SSteven Rostedt (Red Hat) 	if (unlikely(ftrace_disabled)) {
3028e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENODEV;
30295ae0bf59SSteven Rostedt (Red Hat) 		goto out;
3030e1df4cb6SSteven Rostedt (Red Hat) 	}
303145a4a237SSteven Rostedt 
30325ae0bf59SSteven Rostedt (Red Hat) 	mutex_lock(&ftrace_lock);
30335ae0bf59SSteven Rostedt (Red Hat) 
303459df055fSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
303559df055fSSteven Rostedt 
3036b9df92d2SSteven Rostedt 		if (!ftrace_match_record(rec, NULL, search, len, type))
303759df055fSSteven Rostedt 			continue;
303859df055fSSteven Rostedt 
303959df055fSSteven Rostedt 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
304059df055fSSteven Rostedt 		if (!entry) {
3041b6887d79SSteven Rostedt 			/* If we did not process any, then return error */
304259df055fSSteven Rostedt 			if (!count)
304359df055fSSteven Rostedt 				count = -ENOMEM;
304459df055fSSteven Rostedt 			goto out_unlock;
304559df055fSSteven Rostedt 		}
304659df055fSSteven Rostedt 
304759df055fSSteven Rostedt 		count++;
304859df055fSSteven Rostedt 
304959df055fSSteven Rostedt 		entry->data = data;
305059df055fSSteven Rostedt 
305159df055fSSteven Rostedt 		/*
305259df055fSSteven Rostedt 		 * The caller might want to do something special
305359df055fSSteven Rostedt 		 * for each function we find. We call the callback
305459df055fSSteven Rostedt 		 * to give the caller an opportunity to do so.
305559df055fSSteven Rostedt 		 */
3056e67efb93SSteven Rostedt (Red Hat) 		if (ops->init) {
3057e67efb93SSteven Rostedt (Red Hat) 			if (ops->init(ops, rec->ip, &entry->data) < 0) {
305859df055fSSteven Rostedt 				/* caller does not like this func */
305959df055fSSteven Rostedt 				kfree(entry);
306059df055fSSteven Rostedt 				continue;
306159df055fSSteven Rostedt 			}
306259df055fSSteven Rostedt 		}
306359df055fSSteven Rostedt 
3064e1df4cb6SSteven Rostedt (Red Hat) 		ret = enter_record(hash, rec, 0);
3065e1df4cb6SSteven Rostedt (Red Hat) 		if (ret < 0) {
3066e1df4cb6SSteven Rostedt (Red Hat) 			kfree(entry);
3067e1df4cb6SSteven Rostedt (Red Hat) 			count = ret;
3068e1df4cb6SSteven Rostedt (Red Hat) 			goto out_unlock;
3069e1df4cb6SSteven Rostedt (Red Hat) 		}
3070e1df4cb6SSteven Rostedt (Red Hat) 
307159df055fSSteven Rostedt 		entry->ops = ops;
307259df055fSSteven Rostedt 		entry->ip = rec->ip;
307359df055fSSteven Rostedt 
307459df055fSSteven Rostedt 		key = hash_long(entry->ip, FTRACE_HASH_BITS);
307559df055fSSteven Rostedt 		hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]);
307659df055fSSteven Rostedt 
307759df055fSSteven Rostedt 	} while_for_each_ftrace_rec();
3078e1df4cb6SSteven Rostedt (Red Hat) 
3079e1df4cb6SSteven Rostedt (Red Hat) 	ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3080e1df4cb6SSteven Rostedt (Red Hat) 	if (ret < 0)
3081e1df4cb6SSteven Rostedt (Red Hat) 		count = ret;
3082e1df4cb6SSteven Rostedt (Red Hat) 
3083b6887d79SSteven Rostedt 	__enable_ftrace_function_probe();
308459df055fSSteven Rostedt 
308559df055fSSteven Rostedt  out_unlock:
30865ae0bf59SSteven Rostedt (Red Hat) 	mutex_unlock(&ftrace_lock);
30875ae0bf59SSteven Rostedt (Red Hat)  out:
30883f2367baSMasami Hiramatsu 	mutex_unlock(&trace_probe_ops.regex_lock);
3089e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
309059df055fSSteven Rostedt 
309159df055fSSteven Rostedt 	return count;
309259df055fSSteven Rostedt }
309359df055fSSteven Rostedt 
309459df055fSSteven Rostedt enum {
3095b6887d79SSteven Rostedt 	PROBE_TEST_FUNC		= 1,
3096b6887d79SSteven Rostedt 	PROBE_TEST_DATA		= 2
309759df055fSSteven Rostedt };
309859df055fSSteven Rostedt 
309959df055fSSteven Rostedt static void
3100b6887d79SSteven Rostedt __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
310159df055fSSteven Rostedt 				  void *data, int flags)
310259df055fSSteven Rostedt {
3103e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_func_entry *rec_entry;
3104b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
31057818b388SSteven Rostedt (Red Hat) 	struct ftrace_func_probe *p;
3106e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
31077818b388SSteven Rostedt (Red Hat) 	struct list_head free_list;
3108e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
3109b67bfe0dSSasha Levin 	struct hlist_node *tmp;
311059df055fSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
311159df055fSSteven Rostedt 	int type = MATCH_FULL;
311259df055fSSteven Rostedt 	int i, len = 0;
311359df055fSSteven Rostedt 	char *search;
311459df055fSSteven Rostedt 
3115b36461daSAtsushi Tsuji 	if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
311659df055fSSteven Rostedt 		glob = NULL;
3117b36461daSAtsushi Tsuji 	else if (glob) {
311859df055fSSteven Rostedt 		int not;
311959df055fSSteven Rostedt 
31203f6fe06dSFrederic Weisbecker 		type = filter_parse_regex(glob, strlen(glob), &search, &not);
312159df055fSSteven Rostedt 		len = strlen(search);
312259df055fSSteven Rostedt 
3123b6887d79SSteven Rostedt 		/* we do not support '!' for function probes */
312459df055fSSteven Rostedt 		if (WARN_ON(not))
312559df055fSSteven Rostedt 			return;
312659df055fSSteven Rostedt 	}
312759df055fSSteven Rostedt 
31283f2367baSMasami Hiramatsu 	mutex_lock(&trace_probe_ops.regex_lock);
3129e1df4cb6SSteven Rostedt (Red Hat) 
3130e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3131e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash)
3132e1df4cb6SSteven Rostedt (Red Hat) 		/* Hmm, should report this somehow */
3133e1df4cb6SSteven Rostedt (Red Hat) 		goto out_unlock;
3134e1df4cb6SSteven Rostedt (Red Hat) 
31357818b388SSteven Rostedt (Red Hat) 	INIT_LIST_HEAD(&free_list);
31367818b388SSteven Rostedt (Red Hat) 
313759df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
313859df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
313959df055fSSteven Rostedt 
3140b67bfe0dSSasha Levin 		hlist_for_each_entry_safe(entry, tmp, hhd, node) {
314159df055fSSteven Rostedt 
314259df055fSSteven Rostedt 			/* break up if statements for readability */
3143b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_FUNC) && entry->ops != ops)
314459df055fSSteven Rostedt 				continue;
314559df055fSSteven Rostedt 
3146b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_DATA) && entry->data != data)
314759df055fSSteven Rostedt 				continue;
314859df055fSSteven Rostedt 
314959df055fSSteven Rostedt 			/* do this last, since it is the most expensive */
315059df055fSSteven Rostedt 			if (glob) {
315159df055fSSteven Rostedt 				kallsyms_lookup(entry->ip, NULL, NULL,
315259df055fSSteven Rostedt 						NULL, str);
315359df055fSSteven Rostedt 				if (!ftrace_match(str, glob, len, type))
315459df055fSSteven Rostedt 					continue;
315559df055fSSteven Rostedt 			}
315659df055fSSteven Rostedt 
3157e1df4cb6SSteven Rostedt (Red Hat) 			rec_entry = ftrace_lookup_ip(hash, entry->ip);
3158e1df4cb6SSteven Rostedt (Red Hat) 			/* It is possible more than one entry had this ip */
3159e1df4cb6SSteven Rostedt (Red Hat) 			if (rec_entry)
3160e1df4cb6SSteven Rostedt (Red Hat) 				free_hash_entry(hash, rec_entry);
3161e1df4cb6SSteven Rostedt (Red Hat) 
3162740466bcSSteven Rostedt (Red Hat) 			hlist_del_rcu(&entry->node);
31637818b388SSteven Rostedt (Red Hat) 			list_add(&entry->free_list, &free_list);
316459df055fSSteven Rostedt 		}
316559df055fSSteven Rostedt 	}
31663f2367baSMasami Hiramatsu 	mutex_lock(&ftrace_lock);
3167b6887d79SSteven Rostedt 	__disable_ftrace_function_probe();
3168e1df4cb6SSteven Rostedt (Red Hat) 	/*
3169e1df4cb6SSteven Rostedt (Red Hat) 	 * Remove after the disable is called. Otherwise, if the last
3170e1df4cb6SSteven Rostedt (Red Hat) 	 * probe is removed, a null hash means *all enabled*.
3171e1df4cb6SSteven Rostedt (Red Hat) 	 */
3172e1df4cb6SSteven Rostedt (Red Hat) 	ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
31737818b388SSteven Rostedt (Red Hat) 	synchronize_sched();
31747818b388SSteven Rostedt (Red Hat) 	list_for_each_entry_safe(entry, p, &free_list, free_list) {
31757818b388SSteven Rostedt (Red Hat) 		list_del(&entry->free_list);
31767818b388SSteven Rostedt (Red Hat) 		ftrace_free_entry(entry);
31777818b388SSteven Rostedt (Red Hat) 	}
31783f2367baSMasami Hiramatsu 	mutex_unlock(&ftrace_lock);
31797818b388SSteven Rostedt (Red Hat) 
3180e1df4cb6SSteven Rostedt (Red Hat)  out_unlock:
31813f2367baSMasami Hiramatsu 	mutex_unlock(&trace_probe_ops.regex_lock);
3182e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
318359df055fSSteven Rostedt }
318459df055fSSteven Rostedt 
318559df055fSSteven Rostedt void
3186b6887d79SSteven Rostedt unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
318759df055fSSteven Rostedt 				void *data)
318859df055fSSteven Rostedt {
3189b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, data,
3190b6887d79SSteven Rostedt 					  PROBE_TEST_FUNC | PROBE_TEST_DATA);
319159df055fSSteven Rostedt }
319259df055fSSteven Rostedt 
319359df055fSSteven Rostedt void
3194b6887d79SSteven Rostedt unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops)
319559df055fSSteven Rostedt {
3196b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC);
319759df055fSSteven Rostedt }
319859df055fSSteven Rostedt 
3199b6887d79SSteven Rostedt void unregister_ftrace_function_probe_all(char *glob)
320059df055fSSteven Rostedt {
3201b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, NULL, NULL, 0);
320259df055fSSteven Rostedt }
320359df055fSSteven Rostedt 
3204f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands);
3205f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex);
3206f6180773SSteven Rostedt 
3207f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd)
3208f6180773SSteven Rostedt {
3209f6180773SSteven Rostedt 	struct ftrace_func_command *p;
3210f6180773SSteven Rostedt 	int ret = 0;
3211f6180773SSteven Rostedt 
3212f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3213f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3214f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3215f6180773SSteven Rostedt 			ret = -EBUSY;
3216f6180773SSteven Rostedt 			goto out_unlock;
3217f6180773SSteven Rostedt 		}
3218f6180773SSteven Rostedt 	}
3219f6180773SSteven Rostedt 	list_add(&cmd->list, &ftrace_commands);
3220f6180773SSteven Rostedt  out_unlock:
3221f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3222f6180773SSteven Rostedt 
3223f6180773SSteven Rostedt 	return ret;
3224f6180773SSteven Rostedt }
3225f6180773SSteven Rostedt 
3226f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd)
3227f6180773SSteven Rostedt {
3228f6180773SSteven Rostedt 	struct ftrace_func_command *p, *n;
3229f6180773SSteven Rostedt 	int ret = -ENODEV;
3230f6180773SSteven Rostedt 
3231f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3232f6180773SSteven Rostedt 	list_for_each_entry_safe(p, n, &ftrace_commands, list) {
3233f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3234f6180773SSteven Rostedt 			ret = 0;
3235f6180773SSteven Rostedt 			list_del_init(&p->list);
3236f6180773SSteven Rostedt 			goto out_unlock;
3237f6180773SSteven Rostedt 		}
3238f6180773SSteven Rostedt 	}
3239f6180773SSteven Rostedt  out_unlock:
3240f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3241f6180773SSteven Rostedt 
3242f6180773SSteven Rostedt 	return ret;
3243f6180773SSteven Rostedt }
3244f6180773SSteven Rostedt 
324533dc9b12SSteven Rostedt static int ftrace_process_regex(struct ftrace_hash *hash,
324633dc9b12SSteven Rostedt 				char *buff, int len, int enable)
324764e7c440SSteven Rostedt {
3248f6180773SSteven Rostedt 	char *func, *command, *next = buff;
32496a24a244SSteven Rostedt 	struct ftrace_func_command *p;
32500aff1c0cSGuoWen Li 	int ret = -EINVAL;
325164e7c440SSteven Rostedt 
325264e7c440SSteven Rostedt 	func = strsep(&next, ":");
325364e7c440SSteven Rostedt 
325464e7c440SSteven Rostedt 	if (!next) {
32551cf41dd7SSteven Rostedt 		ret = ftrace_match_records(hash, func, len);
3256b448c4e3SSteven Rostedt 		if (!ret)
3257b448c4e3SSteven Rostedt 			ret = -EINVAL;
3258b448c4e3SSteven Rostedt 		if (ret < 0)
3259311d16daSLi Zefan 			return ret;
3260b448c4e3SSteven Rostedt 		return 0;
326164e7c440SSteven Rostedt 	}
326264e7c440SSteven Rostedt 
3263f6180773SSteven Rostedt 	/* command found */
326464e7c440SSteven Rostedt 
326564e7c440SSteven Rostedt 	command = strsep(&next, ":");
326664e7c440SSteven Rostedt 
3267f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3268f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3269f6180773SSteven Rostedt 		if (strcmp(p->name, command) == 0) {
327043dd61c9SSteven Rostedt 			ret = p->func(hash, func, command, next, enable);
3271f6180773SSteven Rostedt 			goto out_unlock;
327264e7c440SSteven Rostedt 		}
3273f6180773SSteven Rostedt 	}
3274f6180773SSteven Rostedt  out_unlock:
3275f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
327664e7c440SSteven Rostedt 
3277f6180773SSteven Rostedt 	return ret;
327864e7c440SSteven Rostedt }
327964e7c440SSteven Rostedt 
3280e309b41dSIngo Molnar static ssize_t
328141c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf,
328241c52c0dSSteven Rostedt 		   size_t cnt, loff_t *ppos, int enable)
32835072c59fSSteven Rostedt {
32845072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
3285689fd8b6S[email protected] 	struct trace_parser *parser;
3286689fd8b6S[email protected] 	ssize_t ret, read;
32875072c59fSSteven Rostedt 
32884ba7978eSLi Zefan 	if (!cnt)
32895072c59fSSteven Rostedt 		return 0;
32905072c59fSSteven Rostedt 
32915072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
32925072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
32935072c59fSSteven Rostedt 		iter = m->private;
32945072c59fSSteven Rostedt 	} else
32955072c59fSSteven Rostedt 		iter = file->private_data;
32965072c59fSSteven Rostedt 
3297f04f24fbSMasami Hiramatsu 	if (unlikely(ftrace_disabled))
32983f2367baSMasami Hiramatsu 		return -ENODEV;
32993f2367baSMasami Hiramatsu 
33003f2367baSMasami Hiramatsu 	/* iter->hash is a local copy, so we don't need regex_lock */
3301f04f24fbSMasami Hiramatsu 
3302689fd8b6S[email protected] 	parser = &iter->parser;
3303689fd8b6S[email protected] 	read = trace_get_user(parser, ubuf, cnt, ppos);
33045072c59fSSteven Rostedt 
33054ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded(parser) &&
3306689fd8b6S[email protected] 	    !trace_parser_cont(parser)) {
330733dc9b12SSteven Rostedt 		ret = ftrace_process_regex(iter->hash, parser->buffer,
3308689fd8b6S[email protected] 					   parser->idx, enable);
3309313254a9SLi Zefan 		trace_parser_clear(parser);
33107c088b51SSteven Rostedt (Red Hat) 		if (ret < 0)
33113f2367baSMasami Hiramatsu 			goto out;
33125072c59fSSteven Rostedt 	}
33135072c59fSSteven Rostedt 
33145072c59fSSteven Rostedt 	ret = read;
33153f2367baSMasami Hiramatsu  out:
33165072c59fSSteven Rostedt 	return ret;
33175072c59fSSteven Rostedt }
33185072c59fSSteven Rostedt 
3319fc13cb0cSSteven Rostedt ssize_t
332041c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf,
332141c52c0dSSteven Rostedt 		    size_t cnt, loff_t *ppos)
332241c52c0dSSteven Rostedt {
332341c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
332441c52c0dSSteven Rostedt }
332541c52c0dSSteven Rostedt 
3326fc13cb0cSSteven Rostedt ssize_t
332741c52c0dSSteven Rostedt ftrace_notrace_write(struct file *file, const char __user *ubuf,
332841c52c0dSSteven Rostedt 		     size_t cnt, loff_t *ppos)
332941c52c0dSSteven Rostedt {
333041c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 0);
333141c52c0dSSteven Rostedt }
333241c52c0dSSteven Rostedt 
333333dc9b12SSteven Rostedt static int
3334647664eaSMasami Hiramatsu ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
3335647664eaSMasami Hiramatsu {
3336647664eaSMasami Hiramatsu 	struct ftrace_func_entry *entry;
3337647664eaSMasami Hiramatsu 
3338647664eaSMasami Hiramatsu 	if (!ftrace_location(ip))
3339647664eaSMasami Hiramatsu 		return -EINVAL;
3340647664eaSMasami Hiramatsu 
3341647664eaSMasami Hiramatsu 	if (remove) {
3342647664eaSMasami Hiramatsu 		entry = ftrace_lookup_ip(hash, ip);
3343647664eaSMasami Hiramatsu 		if (!entry)
3344647664eaSMasami Hiramatsu 			return -ENOENT;
3345647664eaSMasami Hiramatsu 		free_hash_entry(hash, entry);
3346647664eaSMasami Hiramatsu 		return 0;
3347647664eaSMasami Hiramatsu 	}
3348647664eaSMasami Hiramatsu 
3349647664eaSMasami Hiramatsu 	return add_hash_entry(hash, ip);
3350647664eaSMasami Hiramatsu }
3351647664eaSMasami Hiramatsu 
3352647664eaSMasami Hiramatsu static int
3353647664eaSMasami Hiramatsu ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
3354647664eaSMasami Hiramatsu 		unsigned long ip, int remove, int reset, int enable)
335541c52c0dSSteven Rostedt {
335633dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3357f45948e8SSteven Rostedt 	struct ftrace_hash *hash;
335833dc9b12SSteven Rostedt 	int ret;
3359f45948e8SSteven Rostedt 
3360936e074bSSteven Rostedt 	/* All global ops uses the global ops filters */
3361936e074bSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL)
3362936e074bSSteven Rostedt 		ops = &global_ops;
3363936e074bSSteven Rostedt 
336441c52c0dSSteven Rostedt 	if (unlikely(ftrace_disabled))
336533dc9b12SSteven Rostedt 		return -ENODEV;
336641c52c0dSSteven Rostedt 
33673f2367baSMasami Hiramatsu 	mutex_lock(&ops->regex_lock);
33683f2367baSMasami Hiramatsu 
3369f45948e8SSteven Rostedt 	if (enable)
337033dc9b12SSteven Rostedt 		orig_hash = &ops->filter_hash;
3371f45948e8SSteven Rostedt 	else
337233dc9b12SSteven Rostedt 		orig_hash = &ops->notrace_hash;
337333dc9b12SSteven Rostedt 
337433dc9b12SSteven Rostedt 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
33753f2367baSMasami Hiramatsu 	if (!hash) {
33763f2367baSMasami Hiramatsu 		ret = -ENOMEM;
33773f2367baSMasami Hiramatsu 		goto out_regex_unlock;
33783f2367baSMasami Hiramatsu 	}
3379f45948e8SSteven Rostedt 
338041c52c0dSSteven Rostedt 	if (reset)
33811cf41dd7SSteven Rostedt 		ftrace_filter_reset(hash);
3382ac483c44SJiri Olsa 	if (buf && !ftrace_match_records(hash, buf, len)) {
3383ac483c44SJiri Olsa 		ret = -EINVAL;
3384ac483c44SJiri Olsa 		goto out_regex_unlock;
3385ac483c44SJiri Olsa 	}
3386647664eaSMasami Hiramatsu 	if (ip) {
3387647664eaSMasami Hiramatsu 		ret = ftrace_match_addr(hash, ip, remove);
3388647664eaSMasami Hiramatsu 		if (ret < 0)
3389647664eaSMasami Hiramatsu 			goto out_regex_unlock;
3390647664eaSMasami Hiramatsu 	}
339133dc9b12SSteven Rostedt 
339233dc9b12SSteven Rostedt 	mutex_lock(&ftrace_lock);
339341fb61c2SSteven Rostedt 	ret = ftrace_hash_move(ops, enable, orig_hash, hash);
3394072126f4SSteven Rostedt 	if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED
3395072126f4SSteven Rostedt 	    && ftrace_enabled)
339630fb6aa7SJiri Olsa 		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
3397072126f4SSteven Rostedt 
339833dc9b12SSteven Rostedt 	mutex_unlock(&ftrace_lock);
339933dc9b12SSteven Rostedt 
3400ac483c44SJiri Olsa  out_regex_unlock:
3401f04f24fbSMasami Hiramatsu 	mutex_unlock(&ops->regex_lock);
340233dc9b12SSteven Rostedt 
340333dc9b12SSteven Rostedt 	free_ftrace_hash(hash);
340433dc9b12SSteven Rostedt 	return ret;
340541c52c0dSSteven Rostedt }
340641c52c0dSSteven Rostedt 
3407647664eaSMasami Hiramatsu static int
3408647664eaSMasami Hiramatsu ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
3409647664eaSMasami Hiramatsu 		int reset, int enable)
3410647664eaSMasami Hiramatsu {
3411647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, 0, 0, ip, remove, reset, enable);
3412647664eaSMasami Hiramatsu }
3413647664eaSMasami Hiramatsu 
3414647664eaSMasami Hiramatsu /**
3415647664eaSMasami Hiramatsu  * ftrace_set_filter_ip - set a function to filter on in ftrace by address
3416647664eaSMasami Hiramatsu  * @ops - the ops to set the filter with
3417647664eaSMasami Hiramatsu  * @ip - the address to add to or remove from the filter.
3418647664eaSMasami Hiramatsu  * @remove - non zero to remove the ip from the filter
3419647664eaSMasami Hiramatsu  * @reset - non zero to reset all filters before applying this filter.
3420647664eaSMasami Hiramatsu  *
3421647664eaSMasami Hiramatsu  * Filters denote which functions should be enabled when tracing is enabled
3422647664eaSMasami Hiramatsu  * If @ip is NULL, it failes to update filter.
3423647664eaSMasami Hiramatsu  */
3424647664eaSMasami Hiramatsu int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
3425647664eaSMasami Hiramatsu 			 int remove, int reset)
3426647664eaSMasami Hiramatsu {
3427f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3428647664eaSMasami Hiramatsu 	return ftrace_set_addr(ops, ip, remove, reset, 1);
3429647664eaSMasami Hiramatsu }
3430647664eaSMasami Hiramatsu EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
3431647664eaSMasami Hiramatsu 
3432647664eaSMasami Hiramatsu static int
3433647664eaSMasami Hiramatsu ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
3434647664eaSMasami Hiramatsu 		 int reset, int enable)
3435647664eaSMasami Hiramatsu {
3436647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, buf, len, 0, 0, reset, enable);
3437647664eaSMasami Hiramatsu }
3438647664eaSMasami Hiramatsu 
343977a2b37dSSteven Rostedt /**
344077a2b37dSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3441936e074bSSteven Rostedt  * @ops - the ops to set the filter with
344277a2b37dSSteven Rostedt  * @buf - the string that holds the function filter text.
344377a2b37dSSteven Rostedt  * @len - the length of the string.
344477a2b37dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
344577a2b37dSSteven Rostedt  *
344677a2b37dSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
344777a2b37dSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
344877a2b37dSSteven Rostedt  */
3449ac483c44SJiri Olsa int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
3450936e074bSSteven Rostedt 		       int len, int reset)
345177a2b37dSSteven Rostedt {
3452f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3453ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 1);
345441c52c0dSSteven Rostedt }
3455936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_filter);
34564eebcc81SSteven Rostedt 
345741c52c0dSSteven Rostedt /**
345841c52c0dSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3459936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
346041c52c0dSSteven Rostedt  * @buf - the string that holds the function notrace text.
346141c52c0dSSteven Rostedt  * @len - the length of the string.
346241c52c0dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
346341c52c0dSSteven Rostedt  *
346441c52c0dSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
346541c52c0dSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
346641c52c0dSSteven Rostedt  * for tracing.
346741c52c0dSSteven Rostedt  */
3468ac483c44SJiri Olsa int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
3469936e074bSSteven Rostedt 			int len, int reset)
3470936e074bSSteven Rostedt {
3471f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3472ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 0);
3473936e074bSSteven Rostedt }
3474936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_notrace);
3475936e074bSSteven Rostedt /**
3476936e074bSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3477936e074bSSteven Rostedt  * @ops - the ops to set the filter with
3478936e074bSSteven Rostedt  * @buf - the string that holds the function filter text.
3479936e074bSSteven Rostedt  * @len - the length of the string.
3480936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3481936e074bSSteven Rostedt  *
3482936e074bSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
3483936e074bSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
3484936e074bSSteven Rostedt  */
3485936e074bSSteven Rostedt void ftrace_set_global_filter(unsigned char *buf, int len, int reset)
3486936e074bSSteven Rostedt {
3487936e074bSSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 1);
3488936e074bSSteven Rostedt }
3489936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_filter);
3490936e074bSSteven Rostedt 
3491936e074bSSteven Rostedt /**
3492936e074bSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3493936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
3494936e074bSSteven Rostedt  * @buf - the string that holds the function notrace text.
3495936e074bSSteven Rostedt  * @len - the length of the string.
3496936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3497936e074bSSteven Rostedt  *
3498936e074bSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
3499936e074bSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
3500936e074bSSteven Rostedt  * for tracing.
3501936e074bSSteven Rostedt  */
3502936e074bSSteven Rostedt void ftrace_set_global_notrace(unsigned char *buf, int len, int reset)
350341c52c0dSSteven Rostedt {
3504f45948e8SSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 0);
350577a2b37dSSteven Rostedt }
3506936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_notrace);
350777a2b37dSSteven Rostedt 
35082af15d6aSSteven Rostedt /*
35092af15d6aSSteven Rostedt  * command line interface to allow users to set filters on boot up.
35102af15d6aSSteven Rostedt  */
35112af15d6aSSteven Rostedt #define FTRACE_FILTER_SIZE		COMMAND_LINE_SIZE
35122af15d6aSSteven Rostedt static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
35132af15d6aSSteven Rostedt static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;
35142af15d6aSSteven Rostedt 
35152af15d6aSSteven Rostedt static int __init set_ftrace_notrace(char *str)
35162af15d6aSSteven Rostedt {
351775761cc1SChen Gang 	strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
35182af15d6aSSteven Rostedt 	return 1;
35192af15d6aSSteven Rostedt }
35202af15d6aSSteven Rostedt __setup("ftrace_notrace=", set_ftrace_notrace);
35212af15d6aSSteven Rostedt 
35222af15d6aSSteven Rostedt static int __init set_ftrace_filter(char *str)
35232af15d6aSSteven Rostedt {
352475761cc1SChen Gang 	strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
35252af15d6aSSteven Rostedt 	return 1;
35262af15d6aSSteven Rostedt }
35272af15d6aSSteven Rostedt __setup("ftrace_filter=", set_ftrace_filter);
35282af15d6aSSteven Rostedt 
3529369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3530f6060f46SLai Jiangshan static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
3531801c29fdSSteven Rostedt static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
3532801c29fdSSteven Rostedt 
3533369bc18fSStefan Assmann static int __init set_graph_function(char *str)
3534369bc18fSStefan Assmann {
353506f43d66SFrederic Weisbecker 	strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
3536369bc18fSStefan Assmann 	return 1;
3537369bc18fSStefan Assmann }
3538369bc18fSStefan Assmann __setup("ftrace_graph_filter=", set_graph_function);
3539369bc18fSStefan Assmann 
3540369bc18fSStefan Assmann static void __init set_ftrace_early_graph(char *buf)
3541369bc18fSStefan Assmann {
3542369bc18fSStefan Assmann 	int ret;
3543369bc18fSStefan Assmann 	char *func;
3544369bc18fSStefan Assmann 
3545369bc18fSStefan Assmann 	while (buf) {
3546369bc18fSStefan Assmann 		func = strsep(&buf, ",");
3547369bc18fSStefan Assmann 		/* we allow only one expression at a time */
3548369bc18fSStefan Assmann 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3549369bc18fSStefan Assmann 				      func);
3550369bc18fSStefan Assmann 		if (ret)
3551369bc18fSStefan Assmann 			printk(KERN_DEBUG "ftrace: function %s not "
3552369bc18fSStefan Assmann 					  "traceable\n", func);
3553369bc18fSStefan Assmann 	}
3554369bc18fSStefan Assmann }
3555369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3556369bc18fSStefan Assmann 
35572a85a37fSSteven Rostedt void __init
35582a85a37fSSteven Rostedt ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable)
35592af15d6aSSteven Rostedt {
35602af15d6aSSteven Rostedt 	char *func;
35612af15d6aSSteven Rostedt 
3562f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3563f04f24fbSMasami Hiramatsu 
35642af15d6aSSteven Rostedt 	while (buf) {
35652af15d6aSSteven Rostedt 		func = strsep(&buf, ",");
3566f45948e8SSteven Rostedt 		ftrace_set_regex(ops, func, strlen(func), 0, enable);
35672af15d6aSSteven Rostedt 	}
35682af15d6aSSteven Rostedt }
35692af15d6aSSteven Rostedt 
35702af15d6aSSteven Rostedt static void __init set_ftrace_early_filters(void)
35712af15d6aSSteven Rostedt {
35722af15d6aSSteven Rostedt 	if (ftrace_filter_buf[0])
35732a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_filter_buf, 1);
35742af15d6aSSteven Rostedt 	if (ftrace_notrace_buf[0])
35752a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_notrace_buf, 0);
3576369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3577369bc18fSStefan Assmann 	if (ftrace_graph_buf[0])
3578369bc18fSStefan Assmann 		set_ftrace_early_graph(ftrace_graph_buf);
3579369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
35802af15d6aSSteven Rostedt }
35812af15d6aSSteven Rostedt 
3582fc13cb0cSSteven Rostedt int ftrace_regex_release(struct inode *inode, struct file *file)
35835072c59fSSteven Rostedt {
35845072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
35855072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
358633dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3587689fd8b6S[email protected] 	struct trace_parser *parser;
3588ed926f9bSSteven Rostedt 	int filter_hash;
358933dc9b12SSteven Rostedt 	int ret;
35905072c59fSSteven Rostedt 
35915072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
35925072c59fSSteven Rostedt 		iter = m->private;
35935072c59fSSteven Rostedt 		seq_release(inode, file);
35945072c59fSSteven Rostedt 	} else
35955072c59fSSteven Rostedt 		iter = file->private_data;
35965072c59fSSteven Rostedt 
3597689fd8b6S[email protected] 	parser = &iter->parser;
3598689fd8b6S[email protected] 	if (trace_parser_loaded(parser)) {
3599689fd8b6S[email protected] 		parser->buffer[parser->idx] = 0;
36001cf41dd7SSteven Rostedt 		ftrace_match_records(iter->hash, parser->buffer, parser->idx);
36015072c59fSSteven Rostedt 	}
36025072c59fSSteven Rostedt 
3603058e297dSSteven Rostedt 	trace_parser_put(parser);
3604058e297dSSteven Rostedt 
36053f2367baSMasami Hiramatsu 	mutex_lock(&iter->ops->regex_lock);
36063f2367baSMasami Hiramatsu 
3607058e297dSSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
3608ed926f9bSSteven Rostedt 		filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
3609ed926f9bSSteven Rostedt 
3610ed926f9bSSteven Rostedt 		if (filter_hash)
361133dc9b12SSteven Rostedt 			orig_hash = &iter->ops->filter_hash;
3612ed926f9bSSteven Rostedt 		else
3613ed926f9bSSteven Rostedt 			orig_hash = &iter->ops->notrace_hash;
361433dc9b12SSteven Rostedt 
3615e6ea44e9SSteven Rostedt 		mutex_lock(&ftrace_lock);
361641fb61c2SSteven Rostedt 		ret = ftrace_hash_move(iter->ops, filter_hash,
361741fb61c2SSteven Rostedt 				       orig_hash, iter->hash);
361841fb61c2SSteven Rostedt 		if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED)
3619ed926f9bSSteven Rostedt 		    && ftrace_enabled)
362030fb6aa7SJiri Olsa 			ftrace_run_update_code(FTRACE_UPDATE_CALLS);
362141fb61c2SSteven Rostedt 
3622e6ea44e9SSteven Rostedt 		mutex_unlock(&ftrace_lock);
3623058e297dSSteven Rostedt 	}
36243f2367baSMasami Hiramatsu 
36253f2367baSMasami Hiramatsu 	mutex_unlock(&iter->ops->regex_lock);
362633dc9b12SSteven Rostedt 	free_ftrace_hash(iter->hash);
362733dc9b12SSteven Rostedt 	kfree(iter);
3628689fd8b6S[email protected] 
36295072c59fSSteven Rostedt 	return 0;
36305072c59fSSteven Rostedt }
36315072c59fSSteven Rostedt 
36325e2336a0SSteven Rostedt static const struct file_operations ftrace_avail_fops = {
36335072c59fSSteven Rostedt 	.open = ftrace_avail_open,
36345072c59fSSteven Rostedt 	.read = seq_read,
36355072c59fSSteven Rostedt 	.llseek = seq_lseek,
36363be04b47SLi Zefan 	.release = seq_release_private,
36375072c59fSSteven Rostedt };
36385072c59fSSteven Rostedt 
3639647bcd03SSteven Rostedt static const struct file_operations ftrace_enabled_fops = {
3640647bcd03SSteven Rostedt 	.open = ftrace_enabled_open,
3641647bcd03SSteven Rostedt 	.read = seq_read,
3642647bcd03SSteven Rostedt 	.llseek = seq_lseek,
3643647bcd03SSteven Rostedt 	.release = seq_release_private,
3644647bcd03SSteven Rostedt };
3645647bcd03SSteven Rostedt 
36465e2336a0SSteven Rostedt static const struct file_operations ftrace_filter_fops = {
36475072c59fSSteven Rostedt 	.open = ftrace_filter_open,
3648850a80cfSLai Jiangshan 	.read = seq_read,
36495072c59fSSteven Rostedt 	.write = ftrace_filter_write,
36506a76f8c0SNamhyung Kim 	.llseek = ftrace_filter_lseek,
36511cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
36525072c59fSSteven Rostedt };
36535072c59fSSteven Rostedt 
36545e2336a0SSteven Rostedt static const struct file_operations ftrace_notrace_fops = {
365541c52c0dSSteven Rostedt 	.open = ftrace_notrace_open,
3656850a80cfSLai Jiangshan 	.read = seq_read,
365741c52c0dSSteven Rostedt 	.write = ftrace_notrace_write,
36586a76f8c0SNamhyung Kim 	.llseek = ftrace_filter_lseek,
36591cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
366041c52c0dSSteven Rostedt };
366141c52c0dSSteven Rostedt 
3662ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3663ea4e2bc4SSteven Rostedt 
3664ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock);
3665ea4e2bc4SSteven Rostedt 
3666ea4e2bc4SSteven Rostedt int ftrace_graph_count;
3667c7c6b1feSLi Zefan int ftrace_graph_filter_enabled;
3668ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
3669ea4e2bc4SSteven Rostedt 
3670ea4e2bc4SSteven Rostedt static void *
367185951842SLi Zefan __g_next(struct seq_file *m, loff_t *pos)
3672ea4e2bc4SSteven Rostedt {
367385951842SLi Zefan 	if (*pos >= ftrace_graph_count)
3674ea4e2bc4SSteven Rostedt 		return NULL;
3675a4ec5e0cSLi Zefan 	return &ftrace_graph_funcs[*pos];
367685951842SLi Zefan }
3677ea4e2bc4SSteven Rostedt 
367885951842SLi Zefan static void *
367985951842SLi Zefan g_next(struct seq_file *m, void *v, loff_t *pos)
368085951842SLi Zefan {
368185951842SLi Zefan 	(*pos)++;
368285951842SLi Zefan 	return __g_next(m, pos);
3683ea4e2bc4SSteven Rostedt }
3684ea4e2bc4SSteven Rostedt 
3685ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos)
3686ea4e2bc4SSteven Rostedt {
3687ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3688ea4e2bc4SSteven Rostedt 
3689f9349a8fSFrederic Weisbecker 	/* Nothing, tell g_show to print all functions are enabled */
3690c7c6b1feSLi Zefan 	if (!ftrace_graph_filter_enabled && !*pos)
3691f9349a8fSFrederic Weisbecker 		return (void *)1;
3692f9349a8fSFrederic Weisbecker 
369385951842SLi Zefan 	return __g_next(m, pos);
3694ea4e2bc4SSteven Rostedt }
3695ea4e2bc4SSteven Rostedt 
3696ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p)
3697ea4e2bc4SSteven Rostedt {
3698ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3699ea4e2bc4SSteven Rostedt }
3700ea4e2bc4SSteven Rostedt 
3701ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v)
3702ea4e2bc4SSteven Rostedt {
3703ea4e2bc4SSteven Rostedt 	unsigned long *ptr = v;
3704ea4e2bc4SSteven Rostedt 
3705ea4e2bc4SSteven Rostedt 	if (!ptr)
3706ea4e2bc4SSteven Rostedt 		return 0;
3707ea4e2bc4SSteven Rostedt 
3708f9349a8fSFrederic Weisbecker 	if (ptr == (unsigned long *)1) {
3709f9349a8fSFrederic Weisbecker 		seq_printf(m, "#### all functions enabled ####\n");
3710f9349a8fSFrederic Weisbecker 		return 0;
3711f9349a8fSFrederic Weisbecker 	}
3712f9349a8fSFrederic Weisbecker 
3713b375a11aSSteven Rostedt 	seq_printf(m, "%ps\n", (void *)*ptr);
3714ea4e2bc4SSteven Rostedt 
3715ea4e2bc4SSteven Rostedt 	return 0;
3716ea4e2bc4SSteven Rostedt }
3717ea4e2bc4SSteven Rostedt 
371888e9d34cSJames Morris static const struct seq_operations ftrace_graph_seq_ops = {
3719ea4e2bc4SSteven Rostedt 	.start = g_start,
3720ea4e2bc4SSteven Rostedt 	.next = g_next,
3721ea4e2bc4SSteven Rostedt 	.stop = g_stop,
3722ea4e2bc4SSteven Rostedt 	.show = g_show,
3723ea4e2bc4SSteven Rostedt };
3724ea4e2bc4SSteven Rostedt 
3725ea4e2bc4SSteven Rostedt static int
3726ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file)
3727ea4e2bc4SSteven Rostedt {
3728ea4e2bc4SSteven Rostedt 	int ret = 0;
3729ea4e2bc4SSteven Rostedt 
3730ea4e2bc4SSteven Rostedt 	if (unlikely(ftrace_disabled))
3731ea4e2bc4SSteven Rostedt 		return -ENODEV;
3732ea4e2bc4SSteven Rostedt 
3733ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3734ea4e2bc4SSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
37358650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC)) {
3736c7c6b1feSLi Zefan 		ftrace_graph_filter_enabled = 0;
3737ea4e2bc4SSteven Rostedt 		ftrace_graph_count = 0;
3738ea4e2bc4SSteven Rostedt 		memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
3739ea4e2bc4SSteven Rostedt 	}
3740ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3741ea4e2bc4SSteven Rostedt 
3742a4ec5e0cSLi Zefan 	if (file->f_mode & FMODE_READ)
3743a4ec5e0cSLi Zefan 		ret = seq_open(file, &ftrace_graph_seq_ops);
3744a4ec5e0cSLi Zefan 
3745ea4e2bc4SSteven Rostedt 	return ret;
3746ea4e2bc4SSteven Rostedt }
3747ea4e2bc4SSteven Rostedt 
3748ea4e2bc4SSteven Rostedt static int
374987827111SLi Zefan ftrace_graph_release(struct inode *inode, struct file *file)
375087827111SLi Zefan {
375187827111SLi Zefan 	if (file->f_mode & FMODE_READ)
375287827111SLi Zefan 		seq_release(inode, file);
375387827111SLi Zefan 	return 0;
375487827111SLi Zefan }
375587827111SLi Zefan 
375687827111SLi Zefan static int
3757f9349a8fSFrederic Weisbecker ftrace_set_func(unsigned long *array, int *idx, char *buffer)
3758ea4e2bc4SSteven Rostedt {
3759ea4e2bc4SSteven Rostedt 	struct dyn_ftrace *rec;
3760ea4e2bc4SSteven Rostedt 	struct ftrace_page *pg;
3761f9349a8fSFrederic Weisbecker 	int search_len;
3762c7c6b1feSLi Zefan 	int fail = 1;
3763f9349a8fSFrederic Weisbecker 	int type, not;
3764f9349a8fSFrederic Weisbecker 	char *search;
3765f9349a8fSFrederic Weisbecker 	bool exists;
3766f9349a8fSFrederic Weisbecker 	int i;
3767ea4e2bc4SSteven Rostedt 
3768f9349a8fSFrederic Weisbecker 	/* decode regex */
37693f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
3770c7c6b1feSLi Zefan 	if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS)
3771c7c6b1feSLi Zefan 		return -EBUSY;
3772f9349a8fSFrederic Weisbecker 
3773f9349a8fSFrederic Weisbecker 	search_len = strlen(search);
3774f9349a8fSFrederic Weisbecker 
377552baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
377645a4a237SSteven Rostedt 
377745a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled)) {
377845a4a237SSteven Rostedt 		mutex_unlock(&ftrace_lock);
377945a4a237SSteven Rostedt 		return -ENODEV;
378045a4a237SSteven Rostedt 	}
378145a4a237SSteven Rostedt 
3782265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
3783ea4e2bc4SSteven Rostedt 
3784b9df92d2SSteven Rostedt 		if (ftrace_match_record(rec, NULL, search, search_len, type)) {
3785c7c6b1feSLi Zefan 			/* if it is in the array */
3786f9349a8fSFrederic Weisbecker 			exists = false;
3787c7c6b1feSLi Zefan 			for (i = 0; i < *idx; i++) {
3788f9349a8fSFrederic Weisbecker 				if (array[i] == rec->ip) {
3789f9349a8fSFrederic Weisbecker 					exists = true;
3790faec2ec5SLiming Wang 					break;
3791faec2ec5SLiming Wang 				}
3792c7c6b1feSLi Zefan 			}
3793c7c6b1feSLi Zefan 
3794c7c6b1feSLi Zefan 			if (!not) {
3795c7c6b1feSLi Zefan 				fail = 0;
3796c7c6b1feSLi Zefan 				if (!exists) {
3797f9349a8fSFrederic Weisbecker 					array[(*idx)++] = rec->ip;
3798c7c6b1feSLi Zefan 					if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
3799c7c6b1feSLi Zefan 						goto out;
3800c7c6b1feSLi Zefan 				}
3801c7c6b1feSLi Zefan 			} else {
3802c7c6b1feSLi Zefan 				if (exists) {
3803c7c6b1feSLi Zefan 					array[i] = array[--(*idx)];
3804c7c6b1feSLi Zefan 					array[*idx] = 0;
3805c7c6b1feSLi Zefan 					fail = 0;
3806c7c6b1feSLi Zefan 				}
3807c7c6b1feSLi Zefan 			}
3808f9349a8fSFrederic Weisbecker 		}
3809265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
3810c7c6b1feSLi Zefan out:
381152baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
3812ea4e2bc4SSteven Rostedt 
3813c7c6b1feSLi Zefan 	if (fail)
3814c7c6b1feSLi Zefan 		return -EINVAL;
3815c7c6b1feSLi Zefan 
38169f50afccSNamhyung Kim 	ftrace_graph_filter_enabled = !!(*idx);
38179f50afccSNamhyung Kim 
3818c7c6b1feSLi Zefan 	return 0;
3819ea4e2bc4SSteven Rostedt }
3820ea4e2bc4SSteven Rostedt 
3821ea4e2bc4SSteven Rostedt static ssize_t
3822ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf,
3823ea4e2bc4SSteven Rostedt 		   size_t cnt, loff_t *ppos)
3824ea4e2bc4SSteven Rostedt {
3825689fd8b6S[email protected] 	struct trace_parser parser;
38264ba7978eSLi Zefan 	ssize_t read, ret;
3827ea4e2bc4SSteven Rostedt 
3828c7c6b1feSLi Zefan 	if (!cnt)
3829ea4e2bc4SSteven Rostedt 		return 0;
3830ea4e2bc4SSteven Rostedt 
3831ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3832ea4e2bc4SSteven Rostedt 
3833689fd8b6S[email protected] 	if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
3834689fd8b6S[email protected] 		ret = -ENOMEM;
38351eb90f13SLi Zefan 		goto out_unlock;
3836ea4e2bc4SSteven Rostedt 	}
3837ea4e2bc4SSteven Rostedt 
3838689fd8b6S[email protected] 	read = trace_get_user(&parser, ubuf, cnt, ppos);
3839689fd8b6S[email protected] 
38404ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded((&parser))) {
3841689fd8b6S[email protected] 		parser.buffer[parser.idx] = 0;
3842ea4e2bc4SSteven Rostedt 
3843f9349a8fSFrederic Weisbecker 		/* we allow only one expression at a time */
3844a4ec5e0cSLi Zefan 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3845689fd8b6S[email protected] 					parser.buffer);
3846ea4e2bc4SSteven Rostedt 		if (ret)
38471eb90f13SLi Zefan 			goto out_free;
3848689fd8b6S[email protected] 	}
3849ea4e2bc4SSteven Rostedt 
3850ea4e2bc4SSteven Rostedt 	ret = read;
38511eb90f13SLi Zefan 
38521eb90f13SLi Zefan out_free:
3853689fd8b6S[email protected] 	trace_parser_put(&parser);
38541eb90f13SLi Zefan out_unlock:
3855ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3856ea4e2bc4SSteven Rostedt 
3857ea4e2bc4SSteven Rostedt 	return ret;
3858ea4e2bc4SSteven Rostedt }
3859ea4e2bc4SSteven Rostedt 
3860ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = {
3861ea4e2bc4SSteven Rostedt 	.open		= ftrace_graph_open,
3862850a80cfSLai Jiangshan 	.read		= seq_read,
3863ea4e2bc4SSteven Rostedt 	.write		= ftrace_graph_write,
38646a76f8c0SNamhyung Kim 	.llseek		= ftrace_filter_lseek,
386587827111SLi Zefan 	.release	= ftrace_graph_release,
3866ea4e2bc4SSteven Rostedt };
3867ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3868ea4e2bc4SSteven Rostedt 
3869df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
38705072c59fSSteven Rostedt {
38715072c59fSSteven Rostedt 
38725452af66SFrederic Weisbecker 	trace_create_file("available_filter_functions", 0444,
38735072c59fSSteven Rostedt 			d_tracer, NULL, &ftrace_avail_fops);
38745072c59fSSteven Rostedt 
3875647bcd03SSteven Rostedt 	trace_create_file("enabled_functions", 0444,
3876647bcd03SSteven Rostedt 			d_tracer, NULL, &ftrace_enabled_fops);
3877647bcd03SSteven Rostedt 
38785452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_filter", 0644, d_tracer,
38795072c59fSSteven Rostedt 			NULL, &ftrace_filter_fops);
388041c52c0dSSteven Rostedt 
38815452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_notrace", 0644, d_tracer,
388241c52c0dSSteven Rostedt 				    NULL, &ftrace_notrace_fops);
3883ad90c0e3SSteven Rostedt 
3884ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
38855452af66SFrederic Weisbecker 	trace_create_file("set_graph_function", 0444, d_tracer,
3886ea4e2bc4SSteven Rostedt 				    NULL,
3887ea4e2bc4SSteven Rostedt 				    &ftrace_graph_fops);
3888ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3889ea4e2bc4SSteven Rostedt 
38905072c59fSSteven Rostedt 	return 0;
38915072c59fSSteven Rostedt }
38925072c59fSSteven Rostedt 
38939fd49328SSteven Rostedt static int ftrace_cmp_ips(const void *a, const void *b)
389468950619SSteven Rostedt {
38959fd49328SSteven Rostedt 	const unsigned long *ipa = a;
38969fd49328SSteven Rostedt 	const unsigned long *ipb = b;
389768950619SSteven Rostedt 
38989fd49328SSteven Rostedt 	if (*ipa > *ipb)
38999fd49328SSteven Rostedt 		return 1;
39009fd49328SSteven Rostedt 	if (*ipa < *ipb)
39019fd49328SSteven Rostedt 		return -1;
39029fd49328SSteven Rostedt 	return 0;
39039fd49328SSteven Rostedt }
39049fd49328SSteven Rostedt 
39059fd49328SSteven Rostedt static void ftrace_swap_ips(void *a, void *b, int size)
39069fd49328SSteven Rostedt {
39079fd49328SSteven Rostedt 	unsigned long *ipa = a;
39089fd49328SSteven Rostedt 	unsigned long *ipb = b;
39099fd49328SSteven Rostedt 	unsigned long t;
39109fd49328SSteven Rostedt 
39119fd49328SSteven Rostedt 	t = *ipa;
39129fd49328SSteven Rostedt 	*ipa = *ipb;
39139fd49328SSteven Rostedt 	*ipb = t;
391468950619SSteven Rostedt }
391568950619SSteven Rostedt 
39165cb084bbSJiri Olsa static int ftrace_process_locs(struct module *mod,
391731e88909SSteven Rostedt 			       unsigned long *start,
391868bf21aaSSteven Rostedt 			       unsigned long *end)
391968bf21aaSSteven Rostedt {
3920706c81f8SSteven Rostedt 	struct ftrace_page *start_pg;
3921a7900875SSteven Rostedt 	struct ftrace_page *pg;
3922706c81f8SSteven Rostedt 	struct dyn_ftrace *rec;
3923a7900875SSteven Rostedt 	unsigned long count;
392468bf21aaSSteven Rostedt 	unsigned long *p;
392568bf21aaSSteven Rostedt 	unsigned long addr;
39264376cac6SSteven Rostedt 	unsigned long flags = 0; /* Shut up gcc */
3927a7900875SSteven Rostedt 	int ret = -ENOMEM;
3928a7900875SSteven Rostedt 
3929a7900875SSteven Rostedt 	count = end - start;
3930a7900875SSteven Rostedt 
3931a7900875SSteven Rostedt 	if (!count)
3932a7900875SSteven Rostedt 		return 0;
3933a7900875SSteven Rostedt 
39349fd49328SSteven Rostedt 	sort(start, count, sizeof(*start),
39359fd49328SSteven Rostedt 	     ftrace_cmp_ips, ftrace_swap_ips);
39369fd49328SSteven Rostedt 
3937706c81f8SSteven Rostedt 	start_pg = ftrace_allocate_pages(count);
3938706c81f8SSteven Rostedt 	if (!start_pg)
3939a7900875SSteven Rostedt 		return -ENOMEM;
394068bf21aaSSteven Rostedt 
3941e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
3942a7900875SSteven Rostedt 
394332082309SSteven Rostedt 	/*
394432082309SSteven Rostedt 	 * Core and each module needs their own pages, as
394532082309SSteven Rostedt 	 * modules will free them when they are removed.
394632082309SSteven Rostedt 	 * Force a new page to be allocated for modules.
394732082309SSteven Rostedt 	 */
3948a7900875SSteven Rostedt 	if (!mod) {
3949a7900875SSteven Rostedt 		WARN_ON(ftrace_pages || ftrace_pages_start);
3950a7900875SSteven Rostedt 		/* First initialization */
3951706c81f8SSteven Rostedt 		ftrace_pages = ftrace_pages_start = start_pg;
3952a7900875SSteven Rostedt 	} else {
395332082309SSteven Rostedt 		if (!ftrace_pages)
3954a7900875SSteven Rostedt 			goto out;
395532082309SSteven Rostedt 
3956a7900875SSteven Rostedt 		if (WARN_ON(ftrace_pages->next)) {
3957a7900875SSteven Rostedt 			/* Hmm, we have free pages? */
3958a7900875SSteven Rostedt 			while (ftrace_pages->next)
395932082309SSteven Rostedt 				ftrace_pages = ftrace_pages->next;
396032082309SSteven Rostedt 		}
3961a7900875SSteven Rostedt 
3962706c81f8SSteven Rostedt 		ftrace_pages->next = start_pg;
396332082309SSteven Rostedt 	}
396432082309SSteven Rostedt 
396568bf21aaSSteven Rostedt 	p = start;
3966706c81f8SSteven Rostedt 	pg = start_pg;
396768bf21aaSSteven Rostedt 	while (p < end) {
396868bf21aaSSteven Rostedt 		addr = ftrace_call_adjust(*p++);
396920e5227eSSteven Rostedt 		/*
397020e5227eSSteven Rostedt 		 * Some architecture linkers will pad between
397120e5227eSSteven Rostedt 		 * the different mcount_loc sections of different
397220e5227eSSteven Rostedt 		 * object files to satisfy alignments.
397320e5227eSSteven Rostedt 		 * Skip any NULL pointers.
397420e5227eSSteven Rostedt 		 */
397520e5227eSSteven Rostedt 		if (!addr)
397620e5227eSSteven Rostedt 			continue;
3977706c81f8SSteven Rostedt 
3978706c81f8SSteven Rostedt 		if (pg->index == pg->size) {
3979706c81f8SSteven Rostedt 			/* We should have allocated enough */
3980706c81f8SSteven Rostedt 			if (WARN_ON(!pg->next))
3981a7900875SSteven Rostedt 				break;
3982706c81f8SSteven Rostedt 			pg = pg->next;
398368bf21aaSSteven Rostedt 		}
398468bf21aaSSteven Rostedt 
3985706c81f8SSteven Rostedt 		rec = &pg->records[pg->index++];
3986706c81f8SSteven Rostedt 		rec->ip = addr;
3987706c81f8SSteven Rostedt 	}
3988706c81f8SSteven Rostedt 
3989706c81f8SSteven Rostedt 	/* We should have used all pages */
3990706c81f8SSteven Rostedt 	WARN_ON(pg->next);
3991706c81f8SSteven Rostedt 
3992706c81f8SSteven Rostedt 	/* Assign the last page to ftrace_pages */
3993706c81f8SSteven Rostedt 	ftrace_pages = pg;
3994706c81f8SSteven Rostedt 
399585ae32aeSSteven Rostedt 	/* These new locations need to be initialized */
3996706c81f8SSteven Rostedt 	ftrace_new_pgs = start_pg;
399785ae32aeSSteven Rostedt 
3998a4f18ed1SSteven Rostedt 	/*
39994376cac6SSteven Rostedt 	 * We only need to disable interrupts on start up
40004376cac6SSteven Rostedt 	 * because we are modifying code that an interrupt
40014376cac6SSteven Rostedt 	 * may execute, and the modification is not atomic.
40024376cac6SSteven Rostedt 	 * But for modules, nothing runs the code we modify
40034376cac6SSteven Rostedt 	 * until we are finished with it, and there's no
40044376cac6SSteven Rostedt 	 * reason to cause large interrupt latencies while we do it.
4005a4f18ed1SSteven Rostedt 	 */
40064376cac6SSteven Rostedt 	if (!mod)
4007a4f18ed1SSteven Rostedt 		local_irq_save(flags);
400831e88909SSteven Rostedt 	ftrace_update_code(mod);
40094376cac6SSteven Rostedt 	if (!mod)
4010a4f18ed1SSteven Rostedt 		local_irq_restore(flags);
4011a7900875SSteven Rostedt 	ret = 0;
4012a7900875SSteven Rostedt  out:
4013e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
401468bf21aaSSteven Rostedt 
4015a7900875SSteven Rostedt 	return ret;
401668bf21aaSSteven Rostedt }
401768bf21aaSSteven Rostedt 
401893eb677dSSteven Rostedt #ifdef CONFIG_MODULES
401932082309SSteven Rostedt 
402032082309SSteven Rostedt #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)
402132082309SSteven Rostedt 
4022e7247a15S[email protected] void ftrace_release_mod(struct module *mod)
402393eb677dSSteven Rostedt {
402493eb677dSSteven Rostedt 	struct dyn_ftrace *rec;
402532082309SSteven Rostedt 	struct ftrace_page **last_pg;
402693eb677dSSteven Rostedt 	struct ftrace_page *pg;
4027a7900875SSteven Rostedt 	int order;
402893eb677dSSteven Rostedt 
402993eb677dSSteven Rostedt 	mutex_lock(&ftrace_lock);
403045a4a237SSteven Rostedt 
403145a4a237SSteven Rostedt 	if (ftrace_disabled)
403245a4a237SSteven Rostedt 		goto out_unlock;
403345a4a237SSteven Rostedt 
403432082309SSteven Rostedt 	/*
403532082309SSteven Rostedt 	 * Each module has its own ftrace_pages, remove
403632082309SSteven Rostedt 	 * them from the list.
403732082309SSteven Rostedt 	 */
403832082309SSteven Rostedt 	last_pg = &ftrace_pages_start;
403932082309SSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = *last_pg) {
404032082309SSteven Rostedt 		rec = &pg->records[0];
4041e7247a15S[email protected] 		if (within_module_core(rec->ip, mod)) {
404293eb677dSSteven Rostedt 			/*
404332082309SSteven Rostedt 			 * As core pages are first, the first
404432082309SSteven Rostedt 			 * page should never be a module page.
404593eb677dSSteven Rostedt 			 */
404632082309SSteven Rostedt 			if (WARN_ON(pg == ftrace_pages_start))
404732082309SSteven Rostedt 				goto out_unlock;
404832082309SSteven Rostedt 
404932082309SSteven Rostedt 			/* Check if we are deleting the last page */
405032082309SSteven Rostedt 			if (pg == ftrace_pages)
405132082309SSteven Rostedt 				ftrace_pages = next_to_ftrace_page(last_pg);
405232082309SSteven Rostedt 
405332082309SSteven Rostedt 			*last_pg = pg->next;
4054a7900875SSteven Rostedt 			order = get_count_order(pg->size / ENTRIES_PER_PAGE);
4055a7900875SSteven Rostedt 			free_pages((unsigned long)pg->records, order);
4056a7900875SSteven Rostedt 			kfree(pg);
405732082309SSteven Rostedt 		} else
405832082309SSteven Rostedt 			last_pg = &pg->next;
405993eb677dSSteven Rostedt 	}
406045a4a237SSteven Rostedt  out_unlock:
406193eb677dSSteven Rostedt 	mutex_unlock(&ftrace_lock);
406293eb677dSSteven Rostedt }
406393eb677dSSteven Rostedt 
406493eb677dSSteven Rostedt static void ftrace_init_module(struct module *mod,
406531e88909SSteven Rostedt 			       unsigned long *start, unsigned long *end)
406690d595feSSteven Rostedt {
406700fd61aeSSteven Rostedt 	if (ftrace_disabled || start == end)
4068fed1939cSSteven Rostedt 		return;
40695cb084bbSJiri Olsa 	ftrace_process_locs(mod, start, end);
407090d595feSSteven Rostedt }
407190d595feSSteven Rostedt 
40728c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
407393eb677dSSteven Rostedt 				      unsigned long val, void *data)
407493eb677dSSteven Rostedt {
407593eb677dSSteven Rostedt 	struct module *mod = data;
407693eb677dSSteven Rostedt 
40778c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_COMING)
407893eb677dSSteven Rostedt 		ftrace_init_module(mod, mod->ftrace_callsites,
407993eb677dSSteven Rostedt 				   mod->ftrace_callsites +
408093eb677dSSteven Rostedt 				   mod->num_ftrace_callsites);
40818c189ea6SSteven Rostedt (Red Hat) 	return 0;
408293eb677dSSteven Rostedt }
408393eb677dSSteven Rostedt 
40848c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
40858c189ea6SSteven Rostedt (Red Hat) 				     unsigned long val, void *data)
40868c189ea6SSteven Rostedt (Red Hat) {
40878c189ea6SSteven Rostedt (Red Hat) 	struct module *mod = data;
40888c189ea6SSteven Rostedt (Red Hat) 
40898c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_GOING)
40908c189ea6SSteven Rostedt (Red Hat) 		ftrace_release_mod(mod);
40918c189ea6SSteven Rostedt (Red Hat) 
409293eb677dSSteven Rostedt 	return 0;
409393eb677dSSteven Rostedt }
409493eb677dSSteven Rostedt #else
40958c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
40968c189ea6SSteven Rostedt (Red Hat) 				      unsigned long val, void *data)
40978c189ea6SSteven Rostedt (Red Hat) {
40988c189ea6SSteven Rostedt (Red Hat) 	return 0;
40998c189ea6SSteven Rostedt (Red Hat) }
41008c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
410193eb677dSSteven Rostedt 				     unsigned long val, void *data)
410293eb677dSSteven Rostedt {
410393eb677dSSteven Rostedt 	return 0;
410493eb677dSSteven Rostedt }
410593eb677dSSteven Rostedt #endif /* CONFIG_MODULES */
410693eb677dSSteven Rostedt 
41078c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_enter_nb = {
41088c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_enter,
4109c1bf08acSSteven Rostedt 	.priority = INT_MAX,	/* Run before anything that can use kprobes */
411093eb677dSSteven Rostedt };
411193eb677dSSteven Rostedt 
41128c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_exit_nb = {
41138c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_exit,
41148c189ea6SSteven Rostedt (Red Hat) 	.priority = INT_MIN,	/* Run after anything that can remove kprobes */
41158c189ea6SSteven Rostedt (Red Hat) };
41168c189ea6SSteven Rostedt (Red Hat) 
411768bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[];
411868bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[];
411968bf21aaSSteven Rostedt 
412068bf21aaSSteven Rostedt void __init ftrace_init(void)
412168bf21aaSSteven Rostedt {
412268bf21aaSSteven Rostedt 	unsigned long count, addr, flags;
412368bf21aaSSteven Rostedt 	int ret;
412468bf21aaSSteven Rostedt 
412568bf21aaSSteven Rostedt 	/* Keep the ftrace pointer to the stub */
412668bf21aaSSteven Rostedt 	addr = (unsigned long)ftrace_stub;
412768bf21aaSSteven Rostedt 
412868bf21aaSSteven Rostedt 	local_irq_save(flags);
412968bf21aaSSteven Rostedt 	ftrace_dyn_arch_init(&addr);
413068bf21aaSSteven Rostedt 	local_irq_restore(flags);
413168bf21aaSSteven Rostedt 
413268bf21aaSSteven Rostedt 	/* ftrace_dyn_arch_init places the return code in addr */
413368bf21aaSSteven Rostedt 	if (addr)
413468bf21aaSSteven Rostedt 		goto failed;
413568bf21aaSSteven Rostedt 
413668bf21aaSSteven Rostedt 	count = __stop_mcount_loc - __start_mcount_loc;
413768bf21aaSSteven Rostedt 
413868bf21aaSSteven Rostedt 	ret = ftrace_dyn_table_alloc(count);
413968bf21aaSSteven Rostedt 	if (ret)
414068bf21aaSSteven Rostedt 		goto failed;
414168bf21aaSSteven Rostedt 
414268bf21aaSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled = 1;
414368bf21aaSSteven Rostedt 
41445cb084bbSJiri Olsa 	ret = ftrace_process_locs(NULL,
414531e88909SSteven Rostedt 				  __start_mcount_loc,
414668bf21aaSSteven Rostedt 				  __stop_mcount_loc);
414768bf21aaSSteven Rostedt 
41488c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_enter_nb);
414924ed0c4bSMing Lei 	if (ret)
41508c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module enter notifier\n");
41518c189ea6SSteven Rostedt (Red Hat) 
41528c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_exit_nb);
41538c189ea6SSteven Rostedt (Red Hat) 	if (ret)
41548c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module exit notifier\n");
415593eb677dSSteven Rostedt 
41562af15d6aSSteven Rostedt 	set_ftrace_early_filters();
41572af15d6aSSteven Rostedt 
415868bf21aaSSteven Rostedt 	return;
415968bf21aaSSteven Rostedt  failed:
416068bf21aaSSteven Rostedt 	ftrace_disabled = 1;
416168bf21aaSSteven Rostedt }
416268bf21aaSSteven Rostedt 
41633d083395SSteven Rostedt #else
41640b6e4d56SFrederic Weisbecker 
41652b499381SSteven Rostedt static struct ftrace_ops global_ops = {
4166bd69c30bSSteven Rostedt 	.func			= ftrace_stub,
4167f04f24fbSMasami Hiramatsu 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
4168f04f24fbSMasami Hiramatsu 	INIT_REGEX_LOCK(global_ops)
4169bd69c30bSSteven Rostedt };
4170bd69c30bSSteven Rostedt 
41710b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void)
41720b6e4d56SFrederic Weisbecker {
41730b6e4d56SFrederic Weisbecker 	ftrace_enabled = 1;
41740b6e4d56SFrederic Weisbecker 	return 0;
41750b6e4d56SFrederic Weisbecker }
41766f415672SSteven Rostedt core_initcall(ftrace_nodyn_init);
41770b6e4d56SFrederic Weisbecker 
4178df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
4179df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { }
41805a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */
41813b6cfdb1SSteven Rostedt # define ftrace_startup(ops, command)			\
41823b6cfdb1SSteven Rostedt 	({						\
41833b6cfdb1SSteven Rostedt 		(ops)->flags |= FTRACE_OPS_FL_ENABLED;	\
41843b6cfdb1SSteven Rostedt 		0;					\
41853b6cfdb1SSteven Rostedt 	})
4186bd69c30bSSteven Rostedt # define ftrace_shutdown(ops, command)	do { } while (0)
4187b0fc494fSSteven Rostedt # define ftrace_startup_sysctl()	do { } while (0)
4188b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl()	do { } while (0)
4189b848914cSSteven Rostedt 
4190b848914cSSteven Rostedt static inline int
4191b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
4192b848914cSSteven Rostedt {
4193b848914cSSteven Rostedt 	return 1;
4194b848914cSSteven Rostedt }
4195b848914cSSteven Rostedt 
41963d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */
41973d083395SSteven Rostedt 
4198b848914cSSteven Rostedt static void
41992f5f6ad9SSteven Rostedt ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
4200a1e2e31dSSteven Rostedt 			struct ftrace_ops *op, struct pt_regs *regs)
4201e248491aSJiri Olsa {
4202e248491aSJiri Olsa 	if (unlikely(trace_recursion_test(TRACE_CONTROL_BIT)))
4203e248491aSJiri Olsa 		return;
4204e248491aSJiri Olsa 
4205e248491aSJiri Olsa 	/*
4206e248491aSJiri Olsa 	 * Some of the ops may be dynamically allocated,
4207e248491aSJiri Olsa 	 * they must be freed after a synchronize_sched().
4208e248491aSJiri Olsa 	 */
4209e248491aSJiri Olsa 	preempt_disable_notrace();
4210e248491aSJiri Olsa 	trace_recursion_set(TRACE_CONTROL_BIT);
42110a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_control_list) {
4212395b97a3SSteven Rostedt (Red Hat) 		if (!(op->flags & FTRACE_OPS_FL_STUB) &&
4213395b97a3SSteven Rostedt (Red Hat) 		    !ftrace_function_local_disabled(op) &&
4214e248491aSJiri Olsa 		    ftrace_ops_test(op, ip))
4215a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
42160a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4217e248491aSJiri Olsa 	trace_recursion_clear(TRACE_CONTROL_BIT);
4218e248491aSJiri Olsa 	preempt_enable_notrace();
4219e248491aSJiri Olsa }
4220e248491aSJiri Olsa 
4221e248491aSJiri Olsa static struct ftrace_ops control_ops = {
4222e248491aSJiri Olsa 	.func	= ftrace_ops_control_func,
4223f04f24fbSMasami Hiramatsu 	.flags	= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
4224f04f24fbSMasami Hiramatsu 	INIT_REGEX_LOCK(control_ops)
4225e248491aSJiri Olsa };
4226e248491aSJiri Olsa 
42272f5f6ad9SSteven Rostedt static inline void
42282f5f6ad9SSteven Rostedt __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4229a1e2e31dSSteven Rostedt 		       struct ftrace_ops *ignored, struct pt_regs *regs)
4230b848914cSSteven Rostedt {
4231cdbe61bfSSteven Rostedt 	struct ftrace_ops *op;
4232edc15cafSSteven Rostedt 	int bit;
4233b848914cSSteven Rostedt 
4234ccf3672dSSteven Rostedt 	if (function_trace_stop)
4235ccf3672dSSteven Rostedt 		return;
4236ccf3672dSSteven Rostedt 
4237edc15cafSSteven Rostedt 	bit = trace_test_and_set_recursion(TRACE_LIST_START, TRACE_LIST_MAX);
4238edc15cafSSteven Rostedt 	if (bit < 0)
4239b1cff0adSSteven Rostedt 		return;
4240b1cff0adSSteven Rostedt 
4241cdbe61bfSSteven Rostedt 	/*
4242cdbe61bfSSteven Rostedt 	 * Some of the ops may be dynamically allocated,
4243cdbe61bfSSteven Rostedt 	 * they must be freed after a synchronize_sched().
4244cdbe61bfSSteven Rostedt 	 */
4245cdbe61bfSSteven Rostedt 	preempt_disable_notrace();
42460a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_ops_list) {
4247b848914cSSteven Rostedt 		if (ftrace_ops_test(op, ip))
4248a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
42490a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4250cdbe61bfSSteven Rostedt 	preempt_enable_notrace();
4251edc15cafSSteven Rostedt 	trace_clear_recursion(bit);
4252b848914cSSteven Rostedt }
4253b848914cSSteven Rostedt 
42542f5f6ad9SSteven Rostedt /*
42552f5f6ad9SSteven Rostedt  * Some archs only support passing ip and parent_ip. Even though
42562f5f6ad9SSteven Rostedt  * the list function ignores the op parameter, we do not want any
42572f5f6ad9SSteven Rostedt  * C side effects, where a function is called without the caller
42582f5f6ad9SSteven Rostedt  * sending a third parameter.
4259a1e2e31dSSteven Rostedt  * Archs are to support both the regs and ftrace_ops at the same time.
4260a1e2e31dSSteven Rostedt  * If they support ftrace_ops, it is assumed they support regs.
4261a1e2e31dSSteven Rostedt  * If call backs want to use regs, they must either check for regs
426206aeaaeaSMasami Hiramatsu  * being NULL, or CONFIG_DYNAMIC_FTRACE_WITH_REGS.
426306aeaaeaSMasami Hiramatsu  * Note, CONFIG_DYNAMIC_FTRACE_WITH_REGS expects a full regs to be saved.
4264a1e2e31dSSteven Rostedt  * An architecture can pass partial regs with ftrace_ops and still
4265a1e2e31dSSteven Rostedt  * set the ARCH_SUPPORT_FTARCE_OPS.
42662f5f6ad9SSteven Rostedt  */
42672f5f6ad9SSteven Rostedt #if ARCH_SUPPORTS_FTRACE_OPS
42682f5f6ad9SSteven Rostedt static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4269a1e2e31dSSteven Rostedt 				 struct ftrace_ops *op, struct pt_regs *regs)
42702f5f6ad9SSteven Rostedt {
4271a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, regs);
42722f5f6ad9SSteven Rostedt }
42732f5f6ad9SSteven Rostedt #else
42742f5f6ad9SSteven Rostedt static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip)
42752f5f6ad9SSteven Rostedt {
4276a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, NULL);
42772f5f6ad9SSteven Rostedt }
42782f5f6ad9SSteven Rostedt #endif
42792f5f6ad9SSteven Rostedt 
4280e32d8956SSteven Rostedt static void clear_ftrace_swapper(void)
4281e32d8956SSteven Rostedt {
4282e32d8956SSteven Rostedt 	struct task_struct *p;
4283e32d8956SSteven Rostedt 	int cpu;
4284e32d8956SSteven Rostedt 
4285e32d8956SSteven Rostedt 	get_online_cpus();
4286e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4287e32d8956SSteven Rostedt 		p = idle_task(cpu);
4288e32d8956SSteven Rostedt 		clear_tsk_trace_trace(p);
4289e32d8956SSteven Rostedt 	}
4290e32d8956SSteven Rostedt 	put_online_cpus();
4291e32d8956SSteven Rostedt }
4292e32d8956SSteven Rostedt 
4293e32d8956SSteven Rostedt static void set_ftrace_swapper(void)
4294e32d8956SSteven Rostedt {
4295e32d8956SSteven Rostedt 	struct task_struct *p;
4296e32d8956SSteven Rostedt 	int cpu;
4297e32d8956SSteven Rostedt 
4298e32d8956SSteven Rostedt 	get_online_cpus();
4299e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4300e32d8956SSteven Rostedt 		p = idle_task(cpu);
4301e32d8956SSteven Rostedt 		set_tsk_trace_trace(p);
4302e32d8956SSteven Rostedt 	}
4303e32d8956SSteven Rostedt 	put_online_cpus();
4304e32d8956SSteven Rostedt }
4305e32d8956SSteven Rostedt 
4306e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid)
4307978f3a45SSteven Rostedt {
4308978f3a45SSteven Rostedt 	struct task_struct *p;
4309978f3a45SSteven Rostedt 
4310229c4ef8SOleg Nesterov 	rcu_read_lock();
4311e32d8956SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4312978f3a45SSteven Rostedt 		clear_tsk_trace_trace(p);
4313e32d8956SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4314229c4ef8SOleg Nesterov 	rcu_read_unlock();
4315229c4ef8SOleg Nesterov 
4316e32d8956SSteven Rostedt 	put_pid(pid);
4317978f3a45SSteven Rostedt }
4318978f3a45SSteven Rostedt 
4319e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid)
4320978f3a45SSteven Rostedt {
4321978f3a45SSteven Rostedt 	struct task_struct *p;
4322978f3a45SSteven Rostedt 
4323229c4ef8SOleg Nesterov 	rcu_read_lock();
4324978f3a45SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4325978f3a45SSteven Rostedt 		set_tsk_trace_trace(p);
4326978f3a45SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4327229c4ef8SOleg Nesterov 	rcu_read_unlock();
4328978f3a45SSteven Rostedt }
4329978f3a45SSteven Rostedt 
4330756d17eeS[email protected] static void clear_ftrace_pid_task(struct pid *pid)
4331e32d8956SSteven Rostedt {
4332756d17eeS[email protected] 	if (pid == ftrace_swapper_pid)
4333e32d8956SSteven Rostedt 		clear_ftrace_swapper();
4334e32d8956SSteven Rostedt 	else
4335756d17eeS[email protected] 		clear_ftrace_pid(pid);
4336e32d8956SSteven Rostedt }
4337e32d8956SSteven Rostedt 
4338e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid)
4339e32d8956SSteven Rostedt {
4340e32d8956SSteven Rostedt 	if (pid == ftrace_swapper_pid)
4341e32d8956SSteven Rostedt 		set_ftrace_swapper();
4342e32d8956SSteven Rostedt 	else
4343e32d8956SSteven Rostedt 		set_ftrace_pid(pid);
4344e32d8956SSteven Rostedt }
4345e32d8956SSteven Rostedt 
4346756d17eeS[email protected] static int ftrace_pid_add(int p)
4347756d17eeS[email protected] {
4348756d17eeS[email protected] 	struct pid *pid;
4349756d17eeS[email protected] 	struct ftrace_pid *fpid;
4350756d17eeS[email protected] 	int ret = -EINVAL;
4351756d17eeS[email protected] 
4352756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4353756d17eeS[email protected] 
4354756d17eeS[email protected] 	if (!p)
4355756d17eeS[email protected] 		pid = ftrace_swapper_pid;
4356756d17eeS[email protected] 	else
4357756d17eeS[email protected] 		pid = find_get_pid(p);
4358756d17eeS[email protected] 
4359756d17eeS[email protected] 	if (!pid)
4360756d17eeS[email protected] 		goto out;
4361756d17eeS[email protected] 
4362756d17eeS[email protected] 	ret = 0;
4363756d17eeS[email protected] 
4364756d17eeS[email protected] 	list_for_each_entry(fpid, &ftrace_pids, list)
4365756d17eeS[email protected] 		if (fpid->pid == pid)
4366756d17eeS[email protected] 			goto out_put;
4367756d17eeS[email protected] 
4368756d17eeS[email protected] 	ret = -ENOMEM;
4369756d17eeS[email protected] 
4370756d17eeS[email protected] 	fpid = kmalloc(sizeof(*fpid), GFP_KERNEL);
4371756d17eeS[email protected] 	if (!fpid)
4372756d17eeS[email protected] 		goto out_put;
4373756d17eeS[email protected] 
4374756d17eeS[email protected] 	list_add(&fpid->list, &ftrace_pids);
4375756d17eeS[email protected] 	fpid->pid = pid;
4376756d17eeS[email protected] 
4377756d17eeS[email protected] 	set_ftrace_pid_task(pid);
4378756d17eeS[email protected] 
4379756d17eeS[email protected] 	ftrace_update_pid_func();
4380756d17eeS[email protected] 	ftrace_startup_enable(0);
4381756d17eeS[email protected] 
4382756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4383756d17eeS[email protected] 	return 0;
4384756d17eeS[email protected] 
4385756d17eeS[email protected] out_put:
4386756d17eeS[email protected] 	if (pid != ftrace_swapper_pid)
4387756d17eeS[email protected] 		put_pid(pid);
4388756d17eeS[email protected] 
4389756d17eeS[email protected] out:
4390756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4391756d17eeS[email protected] 	return ret;
4392756d17eeS[email protected] }
4393756d17eeS[email protected] 
4394756d17eeS[email protected] static void ftrace_pid_reset(void)
4395756d17eeS[email protected] {
4396756d17eeS[email protected] 	struct ftrace_pid *fpid, *safe;
4397756d17eeS[email protected] 
4398756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4399756d17eeS[email protected] 	list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) {
4400756d17eeS[email protected] 		struct pid *pid = fpid->pid;
4401756d17eeS[email protected] 
4402756d17eeS[email protected] 		clear_ftrace_pid_task(pid);
4403756d17eeS[email protected] 
4404756d17eeS[email protected] 		list_del(&fpid->list);
4405756d17eeS[email protected] 		kfree(fpid);
4406756d17eeS[email protected] 	}
4407756d17eeS[email protected] 
4408756d17eeS[email protected] 	ftrace_update_pid_func();
4409756d17eeS[email protected] 	ftrace_startup_enable(0);
4410756d17eeS[email protected] 
4411756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4412756d17eeS[email protected] }
4413756d17eeS[email protected] 
4414756d17eeS[email protected] static void *fpid_start(struct seq_file *m, loff_t *pos)
4415756d17eeS[email protected] {
4416756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4417756d17eeS[email protected] 
4418756d17eeS[email protected] 	if (list_empty(&ftrace_pids) && (!*pos))
4419756d17eeS[email protected] 		return (void *) 1;
4420756d17eeS[email protected] 
4421756d17eeS[email protected] 	return seq_list_start(&ftrace_pids, *pos);
4422756d17eeS[email protected] }
4423756d17eeS[email protected] 
4424756d17eeS[email protected] static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
4425756d17eeS[email protected] {
4426756d17eeS[email protected] 	if (v == (void *)1)
4427756d17eeS[email protected] 		return NULL;
4428756d17eeS[email protected] 
4429756d17eeS[email protected] 	return seq_list_next(v, &ftrace_pids, pos);
4430756d17eeS[email protected] }
4431756d17eeS[email protected] 
4432756d17eeS[email protected] static void fpid_stop(struct seq_file *m, void *p)
4433756d17eeS[email protected] {
4434756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4435756d17eeS[email protected] }
4436756d17eeS[email protected] 
4437756d17eeS[email protected] static int fpid_show(struct seq_file *m, void *v)
4438756d17eeS[email protected] {
4439756d17eeS[email protected] 	const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list);
4440756d17eeS[email protected] 
4441756d17eeS[email protected] 	if (v == (void *)1) {
4442756d17eeS[email protected] 		seq_printf(m, "no pid\n");
4443756d17eeS[email protected] 		return 0;
4444756d17eeS[email protected] 	}
4445756d17eeS[email protected] 
4446756d17eeS[email protected] 	if (fpid->pid == ftrace_swapper_pid)
4447756d17eeS[email protected] 		seq_printf(m, "swapper tasks\n");
4448756d17eeS[email protected] 	else
4449756d17eeS[email protected] 		seq_printf(m, "%u\n", pid_vnr(fpid->pid));
4450756d17eeS[email protected] 
4451756d17eeS[email protected] 	return 0;
4452756d17eeS[email protected] }
4453756d17eeS[email protected] 
4454756d17eeS[email protected] static const struct seq_operations ftrace_pid_sops = {
4455756d17eeS[email protected] 	.start = fpid_start,
4456756d17eeS[email protected] 	.next = fpid_next,
4457756d17eeS[email protected] 	.stop = fpid_stop,
4458756d17eeS[email protected] 	.show = fpid_show,
4459756d17eeS[email protected] };
4460756d17eeS[email protected] 
4461756d17eeS[email protected] static int
4462756d17eeS[email protected] ftrace_pid_open(struct inode *inode, struct file *file)
4463756d17eeS[email protected] {
4464756d17eeS[email protected] 	int ret = 0;
4465756d17eeS[email protected] 
4466756d17eeS[email protected] 	if ((file->f_mode & FMODE_WRITE) &&
4467756d17eeS[email protected] 	    (file->f_flags & O_TRUNC))
4468756d17eeS[email protected] 		ftrace_pid_reset();
4469756d17eeS[email protected] 
4470756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4471756d17eeS[email protected] 		ret = seq_open(file, &ftrace_pid_sops);
4472756d17eeS[email protected] 
4473756d17eeS[email protected] 	return ret;
4474756d17eeS[email protected] }
4475756d17eeS[email protected] 
4476df4fc315SSteven Rostedt static ssize_t
4477df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf,
4478df4fc315SSteven Rostedt 		   size_t cnt, loff_t *ppos)
4479df4fc315SSteven Rostedt {
4480457dc928SIngo Molnar 	char buf[64], *tmp;
4481df4fc315SSteven Rostedt 	long val;
4482df4fc315SSteven Rostedt 	int ret;
4483df4fc315SSteven Rostedt 
4484df4fc315SSteven Rostedt 	if (cnt >= sizeof(buf))
4485df4fc315SSteven Rostedt 		return -EINVAL;
4486df4fc315SSteven Rostedt 
4487df4fc315SSteven Rostedt 	if (copy_from_user(&buf, ubuf, cnt))
4488df4fc315SSteven Rostedt 		return -EFAULT;
4489df4fc315SSteven Rostedt 
4490df4fc315SSteven Rostedt 	buf[cnt] = 0;
4491df4fc315SSteven Rostedt 
4492756d17eeS[email protected] 	/*
4493756d17eeS[email protected] 	 * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid"
4494756d17eeS[email protected] 	 * to clean the filter quietly.
4495756d17eeS[email protected] 	 */
4496457dc928SIngo Molnar 	tmp = strstrip(buf);
4497457dc928SIngo Molnar 	if (strlen(tmp) == 0)
4498756d17eeS[email protected] 		return 1;
4499756d17eeS[email protected] 
4500bcd83ea6SDaniel Walter 	ret = kstrtol(tmp, 10, &val);
4501df4fc315SSteven Rostedt 	if (ret < 0)
4502df4fc315SSteven Rostedt 		return ret;
4503df4fc315SSteven Rostedt 
4504756d17eeS[email protected] 	ret = ftrace_pid_add(val);
4505978f3a45SSteven Rostedt 
4506756d17eeS[email protected] 	return ret ? ret : cnt;
4507e32d8956SSteven Rostedt }
4508978f3a45SSteven Rostedt 
4509756d17eeS[email protected] static int
4510756d17eeS[email protected] ftrace_pid_release(struct inode *inode, struct file *file)
4511756d17eeS[email protected] {
4512756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4513756d17eeS[email protected] 		seq_release(inode, file);
4514978f3a45SSteven Rostedt 
4515756d17eeS[email protected] 	return 0;
4516df4fc315SSteven Rostedt }
4517df4fc315SSteven Rostedt 
45185e2336a0SSteven Rostedt static const struct file_operations ftrace_pid_fops = {
4519756d17eeS[email protected] 	.open		= ftrace_pid_open,
4520df4fc315SSteven Rostedt 	.write		= ftrace_pid_write,
4521756d17eeS[email protected] 	.read		= seq_read,
45226a76f8c0SNamhyung Kim 	.llseek		= ftrace_filter_lseek,
4523756d17eeS[email protected] 	.release	= ftrace_pid_release,
4524df4fc315SSteven Rostedt };
4525df4fc315SSteven Rostedt 
4526df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void)
4527df4fc315SSteven Rostedt {
4528df4fc315SSteven Rostedt 	struct dentry *d_tracer;
4529df4fc315SSteven Rostedt 
4530df4fc315SSteven Rostedt 	d_tracer = tracing_init_dentry();
4531df4fc315SSteven Rostedt 	if (!d_tracer)
4532df4fc315SSteven Rostedt 		return 0;
4533df4fc315SSteven Rostedt 
4534df4fc315SSteven Rostedt 	ftrace_init_dyn_debugfs(d_tracer);
4535df4fc315SSteven Rostedt 
45365452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_pid", 0644, d_tracer,
4537df4fc315SSteven Rostedt 			    NULL, &ftrace_pid_fops);
4538493762fcSSteven Rostedt 
4539493762fcSSteven Rostedt 	ftrace_profile_debugfs(d_tracer);
4540493762fcSSteven Rostedt 
4541df4fc315SSteven Rostedt 	return 0;
4542df4fc315SSteven Rostedt }
4543df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs);
4544df4fc315SSteven Rostedt 
45453d083395SSteven Rostedt /**
454681adbdc0SSteven Rostedt  * ftrace_kill - kill ftrace
4547a2bb6a3dSSteven Rostedt  *
4548a2bb6a3dSSteven Rostedt  * This function should be used by panic code. It stops ftrace
4549a2bb6a3dSSteven Rostedt  * but in a not so nice way. If you need to simply kill ftrace
4550a2bb6a3dSSteven Rostedt  * from a non-atomic section, use ftrace_kill.
4551a2bb6a3dSSteven Rostedt  */
455281adbdc0SSteven Rostedt void ftrace_kill(void)
4553a2bb6a3dSSteven Rostedt {
4554a2bb6a3dSSteven Rostedt 	ftrace_disabled = 1;
4555a2bb6a3dSSteven Rostedt 	ftrace_enabled = 0;
4556a2bb6a3dSSteven Rostedt 	clear_ftrace_function();
4557a2bb6a3dSSteven Rostedt }
4558a2bb6a3dSSteven Rostedt 
4559a2bb6a3dSSteven Rostedt /**
4560e0a413f6SSteven Rostedt  * Test if ftrace is dead or not.
4561e0a413f6SSteven Rostedt  */
4562e0a413f6SSteven Rostedt int ftrace_is_dead(void)
4563e0a413f6SSteven Rostedt {
4564e0a413f6SSteven Rostedt 	return ftrace_disabled;
4565e0a413f6SSteven Rostedt }
4566e0a413f6SSteven Rostedt 
4567e0a413f6SSteven Rostedt /**
45683d083395SSteven Rostedt  * register_ftrace_function - register a function for profiling
45693d083395SSteven Rostedt  * @ops - ops structure that holds the function for profiling.
45703d083395SSteven Rostedt  *
45713d083395SSteven Rostedt  * Register a function to be called by all functions in the
45723d083395SSteven Rostedt  * kernel.
45733d083395SSteven Rostedt  *
45743d083395SSteven Rostedt  * Note: @ops->func and all the functions it calls must be labeled
45753d083395SSteven Rostedt  *       with "notrace", otherwise it will go into a
45763d083395SSteven Rostedt  *       recursive loop.
45773d083395SSteven Rostedt  */
45783d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops)
45793d083395SSteven Rostedt {
458045a4a237SSteven Rostedt 	int ret = -1;
45814eebcc81SSteven Rostedt 
4582f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
4583f04f24fbSMasami Hiramatsu 
4584e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4585e7d3737eSFrederic Weisbecker 
4586b0fc494fSSteven Rostedt 	ret = __register_ftrace_function(ops);
4587b848914cSSteven Rostedt 	if (!ret)
4588a1cd6173SSteven Rostedt 		ret = ftrace_startup(ops, 0);
4589b848914cSSteven Rostedt 
4590e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
45918d240dd8SBorislav Petkov 
4592b0fc494fSSteven Rostedt 	return ret;
45933d083395SSteven Rostedt }
4594cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(register_ftrace_function);
45953d083395SSteven Rostedt 
45963d083395SSteven Rostedt /**
459732632920SUwe Kleine-Koenig  * unregister_ftrace_function - unregister a function for profiling.
45983d083395SSteven Rostedt  * @ops - ops structure that holds the function to unregister
45993d083395SSteven Rostedt  *
46003d083395SSteven Rostedt  * Unregister a function that was added to be called by ftrace profiling.
46013d083395SSteven Rostedt  */
46023d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops)
46033d083395SSteven Rostedt {
46043d083395SSteven Rostedt 	int ret;
46053d083395SSteven Rostedt 
4606e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
46073d083395SSteven Rostedt 	ret = __unregister_ftrace_function(ops);
4608b848914cSSteven Rostedt 	if (!ret)
4609b848914cSSteven Rostedt 		ftrace_shutdown(ops, 0);
4610e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4611b0fc494fSSteven Rostedt 
4612b0fc494fSSteven Rostedt 	return ret;
4613b0fc494fSSteven Rostedt }
4614cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(unregister_ftrace_function);
4615b0fc494fSSteven Rostedt 
4616e309b41dSIngo Molnar int
4617b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write,
46188d65af78SAlexey Dobriyan 		     void __user *buffer, size_t *lenp,
4619b0fc494fSSteven Rostedt 		     loff_t *ppos)
4620b0fc494fSSteven Rostedt {
462145a4a237SSteven Rostedt 	int ret = -ENODEV;
46224eebcc81SSteven Rostedt 
4623e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4624b0fc494fSSteven Rostedt 
462545a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
462645a4a237SSteven Rostedt 		goto out;
462745a4a237SSteven Rostedt 
46288d65af78SAlexey Dobriyan 	ret = proc_dointvec(table, write, buffer, lenp, ppos);
4629b0fc494fSSteven Rostedt 
4630a32c7765SLi Zefan 	if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
4631b0fc494fSSteven Rostedt 		goto out;
4632b0fc494fSSteven Rostedt 
4633a32c7765SLi Zefan 	last_ftrace_enabled = !!ftrace_enabled;
4634b0fc494fSSteven Rostedt 
4635b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
4636b0fc494fSSteven Rostedt 
4637b0fc494fSSteven Rostedt 		ftrace_startup_sysctl();
4638b0fc494fSSteven Rostedt 
4639b0fc494fSSteven Rostedt 		/* we are starting ftrace again */
46405000c418SJan Kiszka 		if (ftrace_ops_list != &ftrace_list_end)
46415000c418SJan Kiszka 			update_ftrace_function();
4642b0fc494fSSteven Rostedt 
4643b0fc494fSSteven Rostedt 	} else {
4644b0fc494fSSteven Rostedt 		/* stopping ftrace calls (just send to ftrace_stub) */
4645b0fc494fSSteven Rostedt 		ftrace_trace_function = ftrace_stub;
4646b0fc494fSSteven Rostedt 
4647b0fc494fSSteven Rostedt 		ftrace_shutdown_sysctl();
4648b0fc494fSSteven Rostedt 	}
4649b0fc494fSSteven Rostedt 
4650b0fc494fSSteven Rostedt  out:
4651e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
46523d083395SSteven Rostedt 	return ret;
465316444a8aSArnaldo Carvalho de Melo }
4654f17845e5SIngo Molnar 
4655fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER
4656e7d3737eSFrederic Weisbecker 
4657597af815SSteven Rostedt static int ftrace_graph_active;
46584a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier;
4659f201ae23SFrederic Weisbecker 
4660e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
4661e49dc19cSSteven Rostedt {
4662e49dc19cSSteven Rostedt 	return 0;
4663e49dc19cSSteven Rostedt }
4664e49dc19cSSteven Rostedt 
4665287b6e68SFrederic Weisbecker /* The callbacks that hook a function */
4666287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return =
4667287b6e68SFrederic Weisbecker 			(trace_func_graph_ret_t)ftrace_stub;
4668e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
4669f201ae23SFrederic Weisbecker 
4670f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
4671f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
4672f201ae23SFrederic Weisbecker {
4673f201ae23SFrederic Weisbecker 	int i;
4674f201ae23SFrederic Weisbecker 	int ret = 0;
4675f201ae23SFrederic Weisbecker 	unsigned long flags;
4676f201ae23SFrederic Weisbecker 	int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE;
4677f201ae23SFrederic Weisbecker 	struct task_struct *g, *t;
4678f201ae23SFrederic Weisbecker 
4679f201ae23SFrederic Weisbecker 	for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
4680f201ae23SFrederic Weisbecker 		ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
4681f201ae23SFrederic Weisbecker 					* sizeof(struct ftrace_ret_stack),
4682f201ae23SFrederic Weisbecker 					GFP_KERNEL);
4683f201ae23SFrederic Weisbecker 		if (!ret_stack_list[i]) {
4684f201ae23SFrederic Weisbecker 			start = 0;
4685f201ae23SFrederic Weisbecker 			end = i;
4686f201ae23SFrederic Weisbecker 			ret = -ENOMEM;
4687f201ae23SFrederic Weisbecker 			goto free;
4688f201ae23SFrederic Weisbecker 		}
4689f201ae23SFrederic Weisbecker 	}
4690f201ae23SFrederic Weisbecker 
4691f201ae23SFrederic Weisbecker 	read_lock_irqsave(&tasklist_lock, flags);
4692f201ae23SFrederic Weisbecker 	do_each_thread(g, t) {
4693f201ae23SFrederic Weisbecker 		if (start == end) {
4694f201ae23SFrederic Weisbecker 			ret = -EAGAIN;
4695f201ae23SFrederic Weisbecker 			goto unlock;
4696f201ae23SFrederic Weisbecker 		}
4697f201ae23SFrederic Weisbecker 
4698f201ae23SFrederic Weisbecker 		if (t->ret_stack == NULL) {
4699380c4b14SFrederic Weisbecker 			atomic_set(&t->tracing_graph_pause, 0);
4700f201ae23SFrederic Weisbecker 			atomic_set(&t->trace_overrun, 0);
470126c01624SSteven Rostedt 			t->curr_ret_stack = -1;
470226c01624SSteven Rostedt 			/* Make sure the tasks see the -1 first: */
470326c01624SSteven Rostedt 			smp_wmb();
470426c01624SSteven Rostedt 			t->ret_stack = ret_stack_list[start++];
4705f201ae23SFrederic Weisbecker 		}
4706f201ae23SFrederic Weisbecker 	} while_each_thread(g, t);
4707f201ae23SFrederic Weisbecker 
4708f201ae23SFrederic Weisbecker unlock:
4709f201ae23SFrederic Weisbecker 	read_unlock_irqrestore(&tasklist_lock, flags);
4710f201ae23SFrederic Weisbecker free:
4711f201ae23SFrederic Weisbecker 	for (i = start; i < end; i++)
4712f201ae23SFrederic Weisbecker 		kfree(ret_stack_list[i]);
4713f201ae23SFrederic Weisbecker 	return ret;
4714f201ae23SFrederic Weisbecker }
4715f201ae23SFrederic Weisbecker 
47168aef2d28SSteven Rostedt static void
471738516ab5SSteven Rostedt ftrace_graph_probe_sched_switch(void *ignore,
471838516ab5SSteven Rostedt 			struct task_struct *prev, struct task_struct *next)
47198aef2d28SSteven Rostedt {
47208aef2d28SSteven Rostedt 	unsigned long long timestamp;
47218aef2d28SSteven Rostedt 	int index;
47228aef2d28SSteven Rostedt 
4723be6f164aSSteven Rostedt 	/*
4724be6f164aSSteven Rostedt 	 * Does the user want to count the time a function was asleep.
4725be6f164aSSteven Rostedt 	 * If so, do not update the time stamps.
4726be6f164aSSteven Rostedt 	 */
4727be6f164aSSteven Rostedt 	if (trace_flags & TRACE_ITER_SLEEP_TIME)
4728be6f164aSSteven Rostedt 		return;
4729be6f164aSSteven Rostedt 
47308aef2d28SSteven Rostedt 	timestamp = trace_clock_local();
47318aef2d28SSteven Rostedt 
47328aef2d28SSteven Rostedt 	prev->ftrace_timestamp = timestamp;
47338aef2d28SSteven Rostedt 
47348aef2d28SSteven Rostedt 	/* only process tasks that we timestamped */
47358aef2d28SSteven Rostedt 	if (!next->ftrace_timestamp)
47368aef2d28SSteven Rostedt 		return;
47378aef2d28SSteven Rostedt 
47388aef2d28SSteven Rostedt 	/*
47398aef2d28SSteven Rostedt 	 * Update all the counters in next to make up for the
47408aef2d28SSteven Rostedt 	 * time next was sleeping.
47418aef2d28SSteven Rostedt 	 */
47428aef2d28SSteven Rostedt 	timestamp -= next->ftrace_timestamp;
47438aef2d28SSteven Rostedt 
47448aef2d28SSteven Rostedt 	for (index = next->curr_ret_stack; index >= 0; index--)
47458aef2d28SSteven Rostedt 		next->ret_stack[index].calltime += timestamp;
47468aef2d28SSteven Rostedt }
47478aef2d28SSteven Rostedt 
4748f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */
4749fb52607aSFrederic Weisbecker static int start_graph_tracing(void)
4750f201ae23SFrederic Weisbecker {
4751f201ae23SFrederic Weisbecker 	struct ftrace_ret_stack **ret_stack_list;
47525b058bcdSFrederic Weisbecker 	int ret, cpu;
4753f201ae23SFrederic Weisbecker 
4754f201ae23SFrederic Weisbecker 	ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
4755f201ae23SFrederic Weisbecker 				sizeof(struct ftrace_ret_stack *),
4756f201ae23SFrederic Weisbecker 				GFP_KERNEL);
4757f201ae23SFrederic Weisbecker 
4758f201ae23SFrederic Weisbecker 	if (!ret_stack_list)
4759f201ae23SFrederic Weisbecker 		return -ENOMEM;
4760f201ae23SFrederic Weisbecker 
47615b058bcdSFrederic Weisbecker 	/* The cpu_boot init_task->ret_stack will never be freed */
4762179c498aSSteven Rostedt 	for_each_online_cpu(cpu) {
4763179c498aSSteven Rostedt 		if (!idle_task(cpu)->ret_stack)
4764868baf07SSteven Rostedt 			ftrace_graph_init_idle_task(idle_task(cpu), cpu);
4765179c498aSSteven Rostedt 	}
47665b058bcdSFrederic Weisbecker 
4767f201ae23SFrederic Weisbecker 	do {
4768f201ae23SFrederic Weisbecker 		ret = alloc_retstack_tasklist(ret_stack_list);
4769f201ae23SFrederic Weisbecker 	} while (ret == -EAGAIN);
4770f201ae23SFrederic Weisbecker 
47718aef2d28SSteven Rostedt 	if (!ret) {
477238516ab5SSteven Rostedt 		ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
47738aef2d28SSteven Rostedt 		if (ret)
47748aef2d28SSteven Rostedt 			pr_info("ftrace_graph: Couldn't activate tracepoint"
47758aef2d28SSteven Rostedt 				" probe to kernel_sched_switch\n");
47768aef2d28SSteven Rostedt 	}
47778aef2d28SSteven Rostedt 
4778f201ae23SFrederic Weisbecker 	kfree(ret_stack_list);
4779f201ae23SFrederic Weisbecker 	return ret;
4780f201ae23SFrederic Weisbecker }
4781f201ae23SFrederic Weisbecker 
47824a2b8ddaSFrederic Weisbecker /*
47834a2b8ddaSFrederic Weisbecker  * Hibernation protection.
47844a2b8ddaSFrederic Weisbecker  * The state of the current task is too much unstable during
47854a2b8ddaSFrederic Weisbecker  * suspend/restore to disk. We want to protect against that.
47864a2b8ddaSFrederic Weisbecker  */
47874a2b8ddaSFrederic Weisbecker static int
47884a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
47894a2b8ddaSFrederic Weisbecker 							void *unused)
47904a2b8ddaSFrederic Weisbecker {
47914a2b8ddaSFrederic Weisbecker 	switch (state) {
47924a2b8ddaSFrederic Weisbecker 	case PM_HIBERNATION_PREPARE:
47934a2b8ddaSFrederic Weisbecker 		pause_graph_tracing();
47944a2b8ddaSFrederic Weisbecker 		break;
47954a2b8ddaSFrederic Weisbecker 
47964a2b8ddaSFrederic Weisbecker 	case PM_POST_HIBERNATION:
47974a2b8ddaSFrederic Weisbecker 		unpause_graph_tracing();
47984a2b8ddaSFrederic Weisbecker 		break;
47994a2b8ddaSFrederic Weisbecker 	}
48004a2b8ddaSFrederic Weisbecker 	return NOTIFY_DONE;
48014a2b8ddaSFrederic Weisbecker }
48024a2b8ddaSFrederic Weisbecker 
4803287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc,
4804287b6e68SFrederic Weisbecker 			trace_func_graph_ent_t entryfunc)
480515e6cb36SFrederic Weisbecker {
4806e7d3737eSFrederic Weisbecker 	int ret = 0;
4807e7d3737eSFrederic Weisbecker 
4808e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4809e7d3737eSFrederic Weisbecker 
481005ce5818SSteven Rostedt 	/* we currently allow only one tracer registered at a time */
4811597af815SSteven Rostedt 	if (ftrace_graph_active) {
481205ce5818SSteven Rostedt 		ret = -EBUSY;
481305ce5818SSteven Rostedt 		goto out;
481405ce5818SSteven Rostedt 	}
481505ce5818SSteven Rostedt 
48164a2b8ddaSFrederic Weisbecker 	ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call;
48174a2b8ddaSFrederic Weisbecker 	register_pm_notifier(&ftrace_suspend_notifier);
48184a2b8ddaSFrederic Weisbecker 
4819597af815SSteven Rostedt 	ftrace_graph_active++;
4820fb52607aSFrederic Weisbecker 	ret = start_graph_tracing();
4821f201ae23SFrederic Weisbecker 	if (ret) {
4822597af815SSteven Rostedt 		ftrace_graph_active--;
4823f201ae23SFrederic Weisbecker 		goto out;
4824f201ae23SFrederic Weisbecker 	}
4825e53a6319SSteven Rostedt 
4826287b6e68SFrederic Weisbecker 	ftrace_graph_return = retfunc;
4827287b6e68SFrederic Weisbecker 	ftrace_graph_entry = entryfunc;
4828e53a6319SSteven Rostedt 
4829a1cd6173SSteven Rostedt 	ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
4830e7d3737eSFrederic Weisbecker 
4831e7d3737eSFrederic Weisbecker out:
4832e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4833e7d3737eSFrederic Weisbecker 	return ret;
483415e6cb36SFrederic Weisbecker }
483515e6cb36SFrederic Weisbecker 
4836fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void)
483715e6cb36SFrederic Weisbecker {
4838e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4839e7d3737eSFrederic Weisbecker 
4840597af815SSteven Rostedt 	if (unlikely(!ftrace_graph_active))
48412aad1b76SSteven Rostedt 		goto out;
48422aad1b76SSteven Rostedt 
4843597af815SSteven Rostedt 	ftrace_graph_active--;
4844287b6e68SFrederic Weisbecker 	ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
4845e49dc19cSSteven Rostedt 	ftrace_graph_entry = ftrace_graph_entry_stub;
4846bd69c30bSSteven Rostedt 	ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
48474a2b8ddaSFrederic Weisbecker 	unregister_pm_notifier(&ftrace_suspend_notifier);
484838516ab5SSteven Rostedt 	unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
4849e7d3737eSFrederic Weisbecker 
48502aad1b76SSteven Rostedt  out:
4851e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
485215e6cb36SFrederic Weisbecker }
4853f201ae23SFrederic Weisbecker 
4854868baf07SSteven Rostedt static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
4855868baf07SSteven Rostedt 
4856868baf07SSteven Rostedt static void
4857868baf07SSteven Rostedt graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
4858868baf07SSteven Rostedt {
4859868baf07SSteven Rostedt 	atomic_set(&t->tracing_graph_pause, 0);
4860868baf07SSteven Rostedt 	atomic_set(&t->trace_overrun, 0);
4861868baf07SSteven Rostedt 	t->ftrace_timestamp = 0;
486225985edcSLucas De Marchi 	/* make curr_ret_stack visible before we add the ret_stack */
4863868baf07SSteven Rostedt 	smp_wmb();
4864868baf07SSteven Rostedt 	t->ret_stack = ret_stack;
4865868baf07SSteven Rostedt }
4866868baf07SSteven Rostedt 
4867868baf07SSteven Rostedt /*
4868868baf07SSteven Rostedt  * Allocate a return stack for the idle task. May be the first
4869868baf07SSteven Rostedt  * time through, or it may be done by CPU hotplug online.
4870868baf07SSteven Rostedt  */
4871868baf07SSteven Rostedt void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
4872868baf07SSteven Rostedt {
4873868baf07SSteven Rostedt 	t->curr_ret_stack = -1;
4874868baf07SSteven Rostedt 	/*
4875868baf07SSteven Rostedt 	 * The idle task has no parent, it either has its own
4876868baf07SSteven Rostedt 	 * stack or no stack at all.
4877868baf07SSteven Rostedt 	 */
4878868baf07SSteven Rostedt 	if (t->ret_stack)
4879868baf07SSteven Rostedt 		WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
4880868baf07SSteven Rostedt 
4881868baf07SSteven Rostedt 	if (ftrace_graph_active) {
4882868baf07SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
4883868baf07SSteven Rostedt 
4884868baf07SSteven Rostedt 		ret_stack = per_cpu(idle_ret_stack, cpu);
4885868baf07SSteven Rostedt 		if (!ret_stack) {
4886868baf07SSteven Rostedt 			ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4887868baf07SSteven Rostedt 					    * sizeof(struct ftrace_ret_stack),
4888868baf07SSteven Rostedt 					    GFP_KERNEL);
4889868baf07SSteven Rostedt 			if (!ret_stack)
4890868baf07SSteven Rostedt 				return;
4891868baf07SSteven Rostedt 			per_cpu(idle_ret_stack, cpu) = ret_stack;
4892868baf07SSteven Rostedt 		}
4893868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
4894868baf07SSteven Rostedt 	}
4895868baf07SSteven Rostedt }
4896868baf07SSteven Rostedt 
4897f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */
4898fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t)
4899f201ae23SFrederic Weisbecker {
490084047e36SSteven Rostedt 	/* Make sure we do not use the parent ret_stack */
490184047e36SSteven Rostedt 	t->ret_stack = NULL;
4902ea14eb71SSteven Rostedt 	t->curr_ret_stack = -1;
490384047e36SSteven Rostedt 
4904597af815SSteven Rostedt 	if (ftrace_graph_active) {
490582310a32SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
490682310a32SSteven Rostedt 
490782310a32SSteven Rostedt 		ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4908f201ae23SFrederic Weisbecker 				* sizeof(struct ftrace_ret_stack),
4909f201ae23SFrederic Weisbecker 				GFP_KERNEL);
491082310a32SSteven Rostedt 		if (!ret_stack)
4911f201ae23SFrederic Weisbecker 			return;
4912868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
491384047e36SSteven Rostedt 	}
4914f201ae23SFrederic Weisbecker }
4915f201ae23SFrederic Weisbecker 
4916fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t)
4917f201ae23SFrederic Weisbecker {
4918eae849caSFrederic Weisbecker 	struct ftrace_ret_stack	*ret_stack = t->ret_stack;
4919eae849caSFrederic Weisbecker 
4920f201ae23SFrederic Weisbecker 	t->ret_stack = NULL;
4921eae849caSFrederic Weisbecker 	/* NULL must become visible to IRQs before we free it: */
4922eae849caSFrederic Weisbecker 	barrier();
4923eae849caSFrederic Weisbecker 
4924eae849caSFrederic Weisbecker 	kfree(ret_stack);
4925f201ae23SFrederic Weisbecker }
492614a866c5SSteven Rostedt 
492714a866c5SSteven Rostedt void ftrace_graph_stop(void)
492814a866c5SSteven Rostedt {
492914a866c5SSteven Rostedt 	ftrace_stop();
493014a866c5SSteven Rostedt }
493115e6cb36SFrederic Weisbecker #endif
4932