xref: /linux-6.15/kernel/trace/ftrace.c (revision f04f24fb)
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 
67*f04f24fbSMasami Hiramatsu #ifdef CONFIG_DYNAMIC_FTRACE
68*f04f24fbSMasami Hiramatsu #define INIT_REGEX_LOCK(opsname)	\
69*f04f24fbSMasami Hiramatsu 	.regex_lock	= __MUTEX_INITIALIZER(opsname.regex_lock),
70*f04f24fbSMasami Hiramatsu #else
71*f04f24fbSMasami Hiramatsu #define INIT_REGEX_LOCK(opsname)
72*f04f24fbSMasami Hiramatsu #endif
73*f04f24fbSMasami 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
1230a016409SSteven Rostedt  * can use rcu_dereference_raw() is that elements removed from this list
1240a016409SSteven Rostedt  * are simply leaked, so there is no need to interact with a grace-period
1250a016409SSteven Rostedt  * mechanism.  The rcu_dereference_raw() 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)			\
1310a016409SSteven Rostedt 	op = rcu_dereference_raw(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)				\
1380a016409SSteven Rostedt 	while (likely(op = rcu_dereference_raw((op)->next)) &&	\
1390a016409SSteven Rostedt 	       unlikely((op) != &ftrace_list_end))
1400a016409SSteven Rostedt 
141*f04f24fbSMasami Hiramatsu static inline void ftrace_ops_init(struct ftrace_ops *ops)
142*f04f24fbSMasami Hiramatsu {
143*f04f24fbSMasami Hiramatsu #ifdef CONFIG_DYNAMIC_FTRACE
144*f04f24fbSMasami Hiramatsu 	if (!(ops->flags & FTRACE_OPS_FL_INITIALIZED)) {
145*f04f24fbSMasami Hiramatsu 		mutex_init(&ops->regex_lock);
146*f04f24fbSMasami Hiramatsu 		ops->flags |= FTRACE_OPS_FL_INITIALIZED;
147*f04f24fbSMasami Hiramatsu 	}
148*f04f24fbSMasami Hiramatsu #endif
149*f04f24fbSMasami Hiramatsu }
150*f04f24fbSMasami 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 
782b67bfe0dSSasha Levin 	hlist_for_each_entry_rcu(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,
927*f04f24fbSMasami Hiramatsu 	.flags		= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
928*f04f24fbSMasami 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,
1124*f04f24fbSMasami Hiramatsu 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
1125*f04f24fbSMasami 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 
1168b67bfe0dSSasha Levin 	hlist_for_each_entry_rcu(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 {
1267*f04f24fbSMasami 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 
1425b848914cSSteven Rostedt 	filter_hash = rcu_dereference_raw(ops->filter_hash);
1426b848914cSSteven Rostedt 	notrace_hash = rcu_dereference_raw(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) &&
2462647bcd03SSteven Rostedt 		     !(rec->flags & ~FTRACE_FL_MASK))) {
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 
2645*f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
2646*f04f24fbSMasami 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] 
2659f45948e8SSteven Rostedt 	if (flag & FTRACE_ITER_NOTRACE)
2660f45948e8SSteven Rostedt 		hash = ops->notrace_hash;
2661f45948e8SSteven Rostedt 	else
2662f45948e8SSteven Rostedt 		hash = ops->filter_hash;
2663f45948e8SSteven Rostedt 
266433dc9b12SSteven Rostedt 	iter->ops = ops;
266533dc9b12SSteven Rostedt 	iter->flags = flag;
266633dc9b12SSteven Rostedt 
266733dc9b12SSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
266833dc9b12SSteven Rostedt 		mutex_lock(&ftrace_lock);
266933dc9b12SSteven Rostedt 		iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
267033dc9b12SSteven Rostedt 		mutex_unlock(&ftrace_lock);
267133dc9b12SSteven Rostedt 
267233dc9b12SSteven Rostedt 		if (!iter->hash) {
267333dc9b12SSteven Rostedt 			trace_parser_put(&iter->parser);
267433dc9b12SSteven Rostedt 			kfree(iter);
267533dc9b12SSteven Rostedt 			return -ENOMEM;
267633dc9b12SSteven Rostedt 		}
267733dc9b12SSteven Rostedt 	}
26781cf41dd7SSteven Rostedt 
2679*f04f24fbSMasami Hiramatsu 	mutex_lock(&ops->regex_lock);
268033dc9b12SSteven Rostedt 
26815072c59fSSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
26828650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC))
268333dc9b12SSteven Rostedt 		ftrace_filter_reset(iter->hash);
26845072c59fSSteven Rostedt 
26855072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
26865072c59fSSteven Rostedt 		iter->pg = ftrace_pages_start;
26875072c59fSSteven Rostedt 
26885072c59fSSteven Rostedt 		ret = seq_open(file, &show_ftrace_seq_ops);
26895072c59fSSteven Rostedt 		if (!ret) {
26905072c59fSSteven Rostedt 			struct seq_file *m = file->private_data;
26915072c59fSSteven Rostedt 			m->private = iter;
269279fe249cSLi Zefan 		} else {
269333dc9b12SSteven Rostedt 			/* Failed */
269433dc9b12SSteven Rostedt 			free_ftrace_hash(iter->hash);
269579fe249cSLi Zefan 			trace_parser_put(&iter->parser);
26965072c59fSSteven Rostedt 			kfree(iter);
269779fe249cSLi Zefan 		}
26985072c59fSSteven Rostedt 	} else
26995072c59fSSteven Rostedt 		file->private_data = iter;
2700*f04f24fbSMasami 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();
2923b67bfe0dSSasha Levin 	hlist_for_each_entry_rcu(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,
2933*f04f24fbSMasami Hiramatsu 	.flags		= FTRACE_OPS_FL_INITIALIZED,
2934*f04f24fbSMasami 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 
2944b6887d79SSteven Rostedt 	if (ftrace_probe_registered)
294559df055fSSteven Rostedt 		return;
294659df055fSSteven Rostedt 
294759df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
294859df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
294959df055fSSteven Rostedt 		if (hhd->first)
295059df055fSSteven Rostedt 			break;
295159df055fSSteven Rostedt 	}
295259df055fSSteven Rostedt 	/* Nothing registered? */
295359df055fSSteven Rostedt 	if (i == FTRACE_FUNC_HASHSIZE)
295459df055fSSteven Rostedt 		return;
295559df055fSSteven Rostedt 
2956b848914cSSteven Rostedt 	ret = __register_ftrace_function(&trace_probe_ops);
2957b848914cSSteven Rostedt 	if (!ret)
2958a1cd6173SSteven Rostedt 		ret = ftrace_startup(&trace_probe_ops, 0);
2959b848914cSSteven Rostedt 
2960b6887d79SSteven Rostedt 	ftrace_probe_registered = 1;
296159df055fSSteven Rostedt }
296259df055fSSteven Rostedt 
2963b6887d79SSteven Rostedt static void __disable_ftrace_function_probe(void)
296459df055fSSteven Rostedt {
2965b848914cSSteven Rostedt 	int ret;
296659df055fSSteven Rostedt 	int i;
296759df055fSSteven Rostedt 
2968b6887d79SSteven Rostedt 	if (!ftrace_probe_registered)
296959df055fSSteven Rostedt 		return;
297059df055fSSteven Rostedt 
297159df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
297259df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
297359df055fSSteven Rostedt 		if (hhd->first)
297459df055fSSteven Rostedt 			return;
297559df055fSSteven Rostedt 	}
297659df055fSSteven Rostedt 
297759df055fSSteven Rostedt 	/* no more funcs left */
2978b848914cSSteven Rostedt 	ret = __unregister_ftrace_function(&trace_probe_ops);
2979b848914cSSteven Rostedt 	if (!ret)
2980b848914cSSteven Rostedt 		ftrace_shutdown(&trace_probe_ops, 0);
2981b848914cSSteven Rostedt 
2982b6887d79SSteven Rostedt 	ftrace_probe_registered = 0;
298359df055fSSteven Rostedt }
298459df055fSSteven Rostedt 
298559df055fSSteven Rostedt 
29867818b388SSteven Rostedt (Red Hat) static void ftrace_free_entry(struct ftrace_func_probe *entry)
298759df055fSSteven Rostedt {
298859df055fSSteven Rostedt 	if (entry->ops->free)
2989e67efb93SSteven Rostedt (Red Hat) 		entry->ops->free(entry->ops, entry->ip, &entry->data);
299059df055fSSteven Rostedt 	kfree(entry);
299159df055fSSteven Rostedt }
299259df055fSSteven Rostedt 
299359df055fSSteven Rostedt int
2994b6887d79SSteven Rostedt register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
299559df055fSSteven Rostedt 			      void *data)
299659df055fSSteven Rostedt {
2997b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
2998e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
2999e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
300059df055fSSteven Rostedt 	struct ftrace_page *pg;
300159df055fSSteven Rostedt 	struct dyn_ftrace *rec;
300259df055fSSteven Rostedt 	int type, len, not;
30036a24a244SSteven Rostedt 	unsigned long key;
300459df055fSSteven Rostedt 	int count = 0;
300559df055fSSteven Rostedt 	char *search;
3006e1df4cb6SSteven Rostedt (Red Hat) 	int ret;
300759df055fSSteven Rostedt 
30083f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(glob, strlen(glob), &search, &not);
300959df055fSSteven Rostedt 	len = strlen(search);
301059df055fSSteven Rostedt 
3011b6887d79SSteven Rostedt 	/* we do not support '!' for function probes */
301259df055fSSteven Rostedt 	if (WARN_ON(not))
301359df055fSSteven Rostedt 		return -EINVAL;
301459df055fSSteven Rostedt 
301559df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
301659df055fSSteven Rostedt 
3017e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3018e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash) {
3019e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENOMEM;
302045a4a237SSteven Rostedt 		goto out_unlock;
3021e1df4cb6SSteven Rostedt (Red Hat) 	}
3022e1df4cb6SSteven Rostedt (Red Hat) 
3023e1df4cb6SSteven Rostedt (Red Hat) 	if (unlikely(ftrace_disabled)) {
3024e1df4cb6SSteven Rostedt (Red Hat) 		count = -ENODEV;
3025e1df4cb6SSteven Rostedt (Red Hat) 		goto out_unlock;
3026e1df4cb6SSteven Rostedt (Red Hat) 	}
302745a4a237SSteven Rostedt 
302859df055fSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
302959df055fSSteven Rostedt 
3030b9df92d2SSteven Rostedt 		if (!ftrace_match_record(rec, NULL, search, len, type))
303159df055fSSteven Rostedt 			continue;
303259df055fSSteven Rostedt 
303359df055fSSteven Rostedt 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
303459df055fSSteven Rostedt 		if (!entry) {
3035b6887d79SSteven Rostedt 			/* If we did not process any, then return error */
303659df055fSSteven Rostedt 			if (!count)
303759df055fSSteven Rostedt 				count = -ENOMEM;
303859df055fSSteven Rostedt 			goto out_unlock;
303959df055fSSteven Rostedt 		}
304059df055fSSteven Rostedt 
304159df055fSSteven Rostedt 		count++;
304259df055fSSteven Rostedt 
304359df055fSSteven Rostedt 		entry->data = data;
304459df055fSSteven Rostedt 
304559df055fSSteven Rostedt 		/*
304659df055fSSteven Rostedt 		 * The caller might want to do something special
304759df055fSSteven Rostedt 		 * for each function we find. We call the callback
304859df055fSSteven Rostedt 		 * to give the caller an opportunity to do so.
304959df055fSSteven Rostedt 		 */
3050e67efb93SSteven Rostedt (Red Hat) 		if (ops->init) {
3051e67efb93SSteven Rostedt (Red Hat) 			if (ops->init(ops, rec->ip, &entry->data) < 0) {
305259df055fSSteven Rostedt 				/* caller does not like this func */
305359df055fSSteven Rostedt 				kfree(entry);
305459df055fSSteven Rostedt 				continue;
305559df055fSSteven Rostedt 			}
305659df055fSSteven Rostedt 		}
305759df055fSSteven Rostedt 
3058e1df4cb6SSteven Rostedt (Red Hat) 		ret = enter_record(hash, rec, 0);
3059e1df4cb6SSteven Rostedt (Red Hat) 		if (ret < 0) {
3060e1df4cb6SSteven Rostedt (Red Hat) 			kfree(entry);
3061e1df4cb6SSteven Rostedt (Red Hat) 			count = ret;
3062e1df4cb6SSteven Rostedt (Red Hat) 			goto out_unlock;
3063e1df4cb6SSteven Rostedt (Red Hat) 		}
3064e1df4cb6SSteven Rostedt (Red Hat) 
306559df055fSSteven Rostedt 		entry->ops = ops;
306659df055fSSteven Rostedt 		entry->ip = rec->ip;
306759df055fSSteven Rostedt 
306859df055fSSteven Rostedt 		key = hash_long(entry->ip, FTRACE_HASH_BITS);
306959df055fSSteven Rostedt 		hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]);
307059df055fSSteven Rostedt 
307159df055fSSteven Rostedt 	} while_for_each_ftrace_rec();
3072e1df4cb6SSteven Rostedt (Red Hat) 
3073e1df4cb6SSteven Rostedt (Red Hat) 	ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3074e1df4cb6SSteven Rostedt (Red Hat) 	if (ret < 0)
3075e1df4cb6SSteven Rostedt (Red Hat) 		count = ret;
3076e1df4cb6SSteven Rostedt (Red Hat) 
3077b6887d79SSteven Rostedt 	__enable_ftrace_function_probe();
307859df055fSSteven Rostedt 
307959df055fSSteven Rostedt  out_unlock:
308059df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
3081e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
308259df055fSSteven Rostedt 
308359df055fSSteven Rostedt 	return count;
308459df055fSSteven Rostedt }
308559df055fSSteven Rostedt 
308659df055fSSteven Rostedt enum {
3087b6887d79SSteven Rostedt 	PROBE_TEST_FUNC		= 1,
3088b6887d79SSteven Rostedt 	PROBE_TEST_DATA		= 2
308959df055fSSteven Rostedt };
309059df055fSSteven Rostedt 
309159df055fSSteven Rostedt static void
3092b6887d79SSteven Rostedt __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
309359df055fSSteven Rostedt 				  void *data, int flags)
309459df055fSSteven Rostedt {
3095e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_func_entry *rec_entry;
3096b6887d79SSteven Rostedt 	struct ftrace_func_probe *entry;
30977818b388SSteven Rostedt (Red Hat) 	struct ftrace_func_probe *p;
3098e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
30997818b388SSteven Rostedt (Red Hat) 	struct list_head free_list;
3100e1df4cb6SSteven Rostedt (Red Hat) 	struct ftrace_hash *hash;
3101b67bfe0dSSasha Levin 	struct hlist_node *tmp;
310259df055fSSteven Rostedt 	char str[KSYM_SYMBOL_LEN];
310359df055fSSteven Rostedt 	int type = MATCH_FULL;
310459df055fSSteven Rostedt 	int i, len = 0;
310559df055fSSteven Rostedt 	char *search;
310659df055fSSteven Rostedt 
3107b36461daSAtsushi Tsuji 	if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
310859df055fSSteven Rostedt 		glob = NULL;
3109b36461daSAtsushi Tsuji 	else if (glob) {
311059df055fSSteven Rostedt 		int not;
311159df055fSSteven Rostedt 
31123f6fe06dSFrederic Weisbecker 		type = filter_parse_regex(glob, strlen(glob), &search, &not);
311359df055fSSteven Rostedt 		len = strlen(search);
311459df055fSSteven Rostedt 
3115b6887d79SSteven Rostedt 		/* we do not support '!' for function probes */
311659df055fSSteven Rostedt 		if (WARN_ON(not))
311759df055fSSteven Rostedt 			return;
311859df055fSSteven Rostedt 	}
311959df055fSSteven Rostedt 
312059df055fSSteven Rostedt 	mutex_lock(&ftrace_lock);
3121e1df4cb6SSteven Rostedt (Red Hat) 
3122e1df4cb6SSteven Rostedt (Red Hat) 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3123e1df4cb6SSteven Rostedt (Red Hat) 	if (!hash)
3124e1df4cb6SSteven Rostedt (Red Hat) 		/* Hmm, should report this somehow */
3125e1df4cb6SSteven Rostedt (Red Hat) 		goto out_unlock;
3126e1df4cb6SSteven Rostedt (Red Hat) 
31277818b388SSteven Rostedt (Red Hat) 	INIT_LIST_HEAD(&free_list);
31287818b388SSteven Rostedt (Red Hat) 
312959df055fSSteven Rostedt 	for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
313059df055fSSteven Rostedt 		struct hlist_head *hhd = &ftrace_func_hash[i];
313159df055fSSteven Rostedt 
3132b67bfe0dSSasha Levin 		hlist_for_each_entry_safe(entry, tmp, hhd, node) {
313359df055fSSteven Rostedt 
313459df055fSSteven Rostedt 			/* break up if statements for readability */
3135b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_FUNC) && entry->ops != ops)
313659df055fSSteven Rostedt 				continue;
313759df055fSSteven Rostedt 
3138b6887d79SSteven Rostedt 			if ((flags & PROBE_TEST_DATA) && entry->data != data)
313959df055fSSteven Rostedt 				continue;
314059df055fSSteven Rostedt 
314159df055fSSteven Rostedt 			/* do this last, since it is the most expensive */
314259df055fSSteven Rostedt 			if (glob) {
314359df055fSSteven Rostedt 				kallsyms_lookup(entry->ip, NULL, NULL,
314459df055fSSteven Rostedt 						NULL, str);
314559df055fSSteven Rostedt 				if (!ftrace_match(str, glob, len, type))
314659df055fSSteven Rostedt 					continue;
314759df055fSSteven Rostedt 			}
314859df055fSSteven Rostedt 
3149e1df4cb6SSteven Rostedt (Red Hat) 			rec_entry = ftrace_lookup_ip(hash, entry->ip);
3150e1df4cb6SSteven Rostedt (Red Hat) 			/* It is possible more than one entry had this ip */
3151e1df4cb6SSteven Rostedt (Red Hat) 			if (rec_entry)
3152e1df4cb6SSteven Rostedt (Red Hat) 				free_hash_entry(hash, rec_entry);
3153e1df4cb6SSteven Rostedt (Red Hat) 
3154740466bcSSteven Rostedt (Red Hat) 			hlist_del_rcu(&entry->node);
31557818b388SSteven Rostedt (Red Hat) 			list_add(&entry->free_list, &free_list);
315659df055fSSteven Rostedt 		}
315759df055fSSteven Rostedt 	}
3158b6887d79SSteven Rostedt 	__disable_ftrace_function_probe();
3159e1df4cb6SSteven Rostedt (Red Hat) 	/*
3160e1df4cb6SSteven Rostedt (Red Hat) 	 * Remove after the disable is called. Otherwise, if the last
3161e1df4cb6SSteven Rostedt (Red Hat) 	 * probe is removed, a null hash means *all enabled*.
3162e1df4cb6SSteven Rostedt (Red Hat) 	 */
3163e1df4cb6SSteven Rostedt (Red Hat) 	ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
31647818b388SSteven Rostedt (Red Hat) 	synchronize_sched();
31657818b388SSteven Rostedt (Red Hat) 	list_for_each_entry_safe(entry, p, &free_list, free_list) {
31667818b388SSteven Rostedt (Red Hat) 		list_del(&entry->free_list);
31677818b388SSteven Rostedt (Red Hat) 		ftrace_free_entry(entry);
31687818b388SSteven Rostedt (Red Hat) 	}
31697818b388SSteven Rostedt (Red Hat) 
3170e1df4cb6SSteven Rostedt (Red Hat)  out_unlock:
317159df055fSSteven Rostedt 	mutex_unlock(&ftrace_lock);
3172e1df4cb6SSteven Rostedt (Red Hat) 	free_ftrace_hash(hash);
317359df055fSSteven Rostedt }
317459df055fSSteven Rostedt 
317559df055fSSteven Rostedt void
3176b6887d79SSteven Rostedt unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
317759df055fSSteven Rostedt 				void *data)
317859df055fSSteven Rostedt {
3179b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, data,
3180b6887d79SSteven Rostedt 					  PROBE_TEST_FUNC | PROBE_TEST_DATA);
318159df055fSSteven Rostedt }
318259df055fSSteven Rostedt 
318359df055fSSteven Rostedt void
3184b6887d79SSteven Rostedt unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops)
318559df055fSSteven Rostedt {
3186b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC);
318759df055fSSteven Rostedt }
318859df055fSSteven Rostedt 
3189b6887d79SSteven Rostedt void unregister_ftrace_function_probe_all(char *glob)
319059df055fSSteven Rostedt {
3191b6887d79SSteven Rostedt 	__unregister_ftrace_function_probe(glob, NULL, NULL, 0);
319259df055fSSteven Rostedt }
319359df055fSSteven Rostedt 
3194f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands);
3195f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex);
3196f6180773SSteven Rostedt 
3197f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd)
3198f6180773SSteven Rostedt {
3199f6180773SSteven Rostedt 	struct ftrace_func_command *p;
3200f6180773SSteven Rostedt 	int ret = 0;
3201f6180773SSteven Rostedt 
3202f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3203f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3204f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3205f6180773SSteven Rostedt 			ret = -EBUSY;
3206f6180773SSteven Rostedt 			goto out_unlock;
3207f6180773SSteven Rostedt 		}
3208f6180773SSteven Rostedt 	}
3209f6180773SSteven Rostedt 	list_add(&cmd->list, &ftrace_commands);
3210f6180773SSteven Rostedt  out_unlock:
3211f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3212f6180773SSteven Rostedt 
3213f6180773SSteven Rostedt 	return ret;
3214f6180773SSteven Rostedt }
3215f6180773SSteven Rostedt 
3216f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd)
3217f6180773SSteven Rostedt {
3218f6180773SSteven Rostedt 	struct ftrace_func_command *p, *n;
3219f6180773SSteven Rostedt 	int ret = -ENODEV;
3220f6180773SSteven Rostedt 
3221f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3222f6180773SSteven Rostedt 	list_for_each_entry_safe(p, n, &ftrace_commands, list) {
3223f6180773SSteven Rostedt 		if (strcmp(cmd->name, p->name) == 0) {
3224f6180773SSteven Rostedt 			ret = 0;
3225f6180773SSteven Rostedt 			list_del_init(&p->list);
3226f6180773SSteven Rostedt 			goto out_unlock;
3227f6180773SSteven Rostedt 		}
3228f6180773SSteven Rostedt 	}
3229f6180773SSteven Rostedt  out_unlock:
3230f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
3231f6180773SSteven Rostedt 
3232f6180773SSteven Rostedt 	return ret;
3233f6180773SSteven Rostedt }
3234f6180773SSteven Rostedt 
323533dc9b12SSteven Rostedt static int ftrace_process_regex(struct ftrace_hash *hash,
323633dc9b12SSteven Rostedt 				char *buff, int len, int enable)
323764e7c440SSteven Rostedt {
3238f6180773SSteven Rostedt 	char *func, *command, *next = buff;
32396a24a244SSteven Rostedt 	struct ftrace_func_command *p;
32400aff1c0cSGuoWen Li 	int ret = -EINVAL;
324164e7c440SSteven Rostedt 
324264e7c440SSteven Rostedt 	func = strsep(&next, ":");
324364e7c440SSteven Rostedt 
324464e7c440SSteven Rostedt 	if (!next) {
32451cf41dd7SSteven Rostedt 		ret = ftrace_match_records(hash, func, len);
3246b448c4e3SSteven Rostedt 		if (!ret)
3247b448c4e3SSteven Rostedt 			ret = -EINVAL;
3248b448c4e3SSteven Rostedt 		if (ret < 0)
3249311d16daSLi Zefan 			return ret;
3250b448c4e3SSteven Rostedt 		return 0;
325164e7c440SSteven Rostedt 	}
325264e7c440SSteven Rostedt 
3253f6180773SSteven Rostedt 	/* command found */
325464e7c440SSteven Rostedt 
325564e7c440SSteven Rostedt 	command = strsep(&next, ":");
325664e7c440SSteven Rostedt 
3257f6180773SSteven Rostedt 	mutex_lock(&ftrace_cmd_mutex);
3258f6180773SSteven Rostedt 	list_for_each_entry(p, &ftrace_commands, list) {
3259f6180773SSteven Rostedt 		if (strcmp(p->name, command) == 0) {
326043dd61c9SSteven Rostedt 			ret = p->func(hash, func, command, next, enable);
3261f6180773SSteven Rostedt 			goto out_unlock;
326264e7c440SSteven Rostedt 		}
3263f6180773SSteven Rostedt 	}
3264f6180773SSteven Rostedt  out_unlock:
3265f6180773SSteven Rostedt 	mutex_unlock(&ftrace_cmd_mutex);
326664e7c440SSteven Rostedt 
3267f6180773SSteven Rostedt 	return ret;
326864e7c440SSteven Rostedt }
326964e7c440SSteven Rostedt 
3270e309b41dSIngo Molnar static ssize_t
327141c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf,
327241c52c0dSSteven Rostedt 		   size_t cnt, loff_t *ppos, int enable)
32735072c59fSSteven Rostedt {
32745072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
3275689fd8b6S[email protected] 	struct trace_parser *parser;
3276689fd8b6S[email protected] 	ssize_t ret, read;
32775072c59fSSteven Rostedt 
32784ba7978eSLi Zefan 	if (!cnt)
32795072c59fSSteven Rostedt 		return 0;
32805072c59fSSteven Rostedt 
32815072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
32825072c59fSSteven Rostedt 		struct seq_file *m = file->private_data;
32835072c59fSSteven Rostedt 		iter = m->private;
32845072c59fSSteven Rostedt 	} else
32855072c59fSSteven Rostedt 		iter = file->private_data;
32865072c59fSSteven Rostedt 
3287*f04f24fbSMasami Hiramatsu 	mutex_lock(&iter->ops->regex_lock);
3288*f04f24fbSMasami Hiramatsu 
3289*f04f24fbSMasami Hiramatsu 	ret = -ENODEV;
3290*f04f24fbSMasami Hiramatsu 	if (unlikely(ftrace_disabled))
3291*f04f24fbSMasami Hiramatsu 		goto out_unlock;
3292*f04f24fbSMasami Hiramatsu 
3293689fd8b6S[email protected] 	parser = &iter->parser;
3294689fd8b6S[email protected] 	read = trace_get_user(parser, ubuf, cnt, ppos);
32955072c59fSSteven Rostedt 
32964ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded(parser) &&
3297689fd8b6S[email protected] 	    !trace_parser_cont(parser)) {
329833dc9b12SSteven Rostedt 		ret = ftrace_process_regex(iter->hash, parser->buffer,
3299689fd8b6S[email protected] 					   parser->idx, enable);
3300313254a9SLi Zefan 		trace_parser_clear(parser);
33017c088b51SSteven Rostedt (Red Hat) 		if (ret < 0)
3302ed146b25SLi Zefan 			goto out_unlock;
33035072c59fSSteven Rostedt 	}
33045072c59fSSteven Rostedt 
33055072c59fSSteven Rostedt 	ret = read;
3306ed146b25SLi Zefan out_unlock:
3307*f04f24fbSMasami Hiramatsu 	mutex_unlock(&iter->ops->regex_lock);
3308ed146b25SLi Zefan 
33095072c59fSSteven Rostedt 	return ret;
33105072c59fSSteven Rostedt }
33115072c59fSSteven Rostedt 
3312fc13cb0cSSteven Rostedt ssize_t
331341c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf,
331441c52c0dSSteven Rostedt 		    size_t cnt, loff_t *ppos)
331541c52c0dSSteven Rostedt {
331641c52c0dSSteven Rostedt 	return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
331741c52c0dSSteven Rostedt }
331841c52c0dSSteven Rostedt 
3319fc13cb0cSSteven Rostedt ssize_t
332041c52c0dSSteven Rostedt ftrace_notrace_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, 0);
332441c52c0dSSteven Rostedt }
332541c52c0dSSteven Rostedt 
332633dc9b12SSteven Rostedt static int
3327647664eaSMasami Hiramatsu ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
3328647664eaSMasami Hiramatsu {
3329647664eaSMasami Hiramatsu 	struct ftrace_func_entry *entry;
3330647664eaSMasami Hiramatsu 
3331647664eaSMasami Hiramatsu 	if (!ftrace_location(ip))
3332647664eaSMasami Hiramatsu 		return -EINVAL;
3333647664eaSMasami Hiramatsu 
3334647664eaSMasami Hiramatsu 	if (remove) {
3335647664eaSMasami Hiramatsu 		entry = ftrace_lookup_ip(hash, ip);
3336647664eaSMasami Hiramatsu 		if (!entry)
3337647664eaSMasami Hiramatsu 			return -ENOENT;
3338647664eaSMasami Hiramatsu 		free_hash_entry(hash, entry);
3339647664eaSMasami Hiramatsu 		return 0;
3340647664eaSMasami Hiramatsu 	}
3341647664eaSMasami Hiramatsu 
3342647664eaSMasami Hiramatsu 	return add_hash_entry(hash, ip);
3343647664eaSMasami Hiramatsu }
3344647664eaSMasami Hiramatsu 
3345647664eaSMasami Hiramatsu static int
3346647664eaSMasami Hiramatsu ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
3347647664eaSMasami Hiramatsu 		unsigned long ip, int remove, int reset, int enable)
334841c52c0dSSteven Rostedt {
334933dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3350f45948e8SSteven Rostedt 	struct ftrace_hash *hash;
335133dc9b12SSteven Rostedt 	int ret;
3352f45948e8SSteven Rostedt 
3353936e074bSSteven Rostedt 	/* All global ops uses the global ops filters */
3354936e074bSSteven Rostedt 	if (ops->flags & FTRACE_OPS_FL_GLOBAL)
3355936e074bSSteven Rostedt 		ops = &global_ops;
3356936e074bSSteven Rostedt 
335741c52c0dSSteven Rostedt 	if (unlikely(ftrace_disabled))
335833dc9b12SSteven Rostedt 		return -ENODEV;
335941c52c0dSSteven Rostedt 
3360f45948e8SSteven Rostedt 	if (enable)
336133dc9b12SSteven Rostedt 		orig_hash = &ops->filter_hash;
3362f45948e8SSteven Rostedt 	else
336333dc9b12SSteven Rostedt 		orig_hash = &ops->notrace_hash;
336433dc9b12SSteven Rostedt 
336533dc9b12SSteven Rostedt 	hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
336633dc9b12SSteven Rostedt 	if (!hash)
336733dc9b12SSteven Rostedt 		return -ENOMEM;
3368f45948e8SSteven Rostedt 
3369*f04f24fbSMasami Hiramatsu 	mutex_lock(&ops->regex_lock);
337041c52c0dSSteven Rostedt 	if (reset)
33711cf41dd7SSteven Rostedt 		ftrace_filter_reset(hash);
3372ac483c44SJiri Olsa 	if (buf && !ftrace_match_records(hash, buf, len)) {
3373ac483c44SJiri Olsa 		ret = -EINVAL;
3374ac483c44SJiri Olsa 		goto out_regex_unlock;
3375ac483c44SJiri Olsa 	}
3376647664eaSMasami Hiramatsu 	if (ip) {
3377647664eaSMasami Hiramatsu 		ret = ftrace_match_addr(hash, ip, remove);
3378647664eaSMasami Hiramatsu 		if (ret < 0)
3379647664eaSMasami Hiramatsu 			goto out_regex_unlock;
3380647664eaSMasami Hiramatsu 	}
338133dc9b12SSteven Rostedt 
338233dc9b12SSteven Rostedt 	mutex_lock(&ftrace_lock);
338341fb61c2SSteven Rostedt 	ret = ftrace_hash_move(ops, enable, orig_hash, hash);
3384072126f4SSteven Rostedt 	if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED
3385072126f4SSteven Rostedt 	    && ftrace_enabled)
338630fb6aa7SJiri Olsa 		ftrace_run_update_code(FTRACE_UPDATE_CALLS);
3387072126f4SSteven Rostedt 
338833dc9b12SSteven Rostedt 	mutex_unlock(&ftrace_lock);
338933dc9b12SSteven Rostedt 
3390ac483c44SJiri Olsa  out_regex_unlock:
3391*f04f24fbSMasami Hiramatsu 	mutex_unlock(&ops->regex_lock);
339233dc9b12SSteven Rostedt 
339333dc9b12SSteven Rostedt 	free_ftrace_hash(hash);
339433dc9b12SSteven Rostedt 	return ret;
339541c52c0dSSteven Rostedt }
339641c52c0dSSteven Rostedt 
3397647664eaSMasami Hiramatsu static int
3398647664eaSMasami Hiramatsu ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
3399647664eaSMasami Hiramatsu 		int reset, int enable)
3400647664eaSMasami Hiramatsu {
3401647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, 0, 0, ip, remove, reset, enable);
3402647664eaSMasami Hiramatsu }
3403647664eaSMasami Hiramatsu 
3404647664eaSMasami Hiramatsu /**
3405647664eaSMasami Hiramatsu  * ftrace_set_filter_ip - set a function to filter on in ftrace by address
3406647664eaSMasami Hiramatsu  * @ops - the ops to set the filter with
3407647664eaSMasami Hiramatsu  * @ip - the address to add to or remove from the filter.
3408647664eaSMasami Hiramatsu  * @remove - non zero to remove the ip from the filter
3409647664eaSMasami Hiramatsu  * @reset - non zero to reset all filters before applying this filter.
3410647664eaSMasami Hiramatsu  *
3411647664eaSMasami Hiramatsu  * Filters denote which functions should be enabled when tracing is enabled
3412647664eaSMasami Hiramatsu  * If @ip is NULL, it failes to update filter.
3413647664eaSMasami Hiramatsu  */
3414647664eaSMasami Hiramatsu int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
3415647664eaSMasami Hiramatsu 			 int remove, int reset)
3416647664eaSMasami Hiramatsu {
3417*f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3418647664eaSMasami Hiramatsu 	return ftrace_set_addr(ops, ip, remove, reset, 1);
3419647664eaSMasami Hiramatsu }
3420647664eaSMasami Hiramatsu EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
3421647664eaSMasami Hiramatsu 
3422647664eaSMasami Hiramatsu static int
3423647664eaSMasami Hiramatsu ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
3424647664eaSMasami Hiramatsu 		 int reset, int enable)
3425647664eaSMasami Hiramatsu {
3426647664eaSMasami Hiramatsu 	return ftrace_set_hash(ops, buf, len, 0, 0, reset, enable);
3427647664eaSMasami Hiramatsu }
3428647664eaSMasami Hiramatsu 
342977a2b37dSSteven Rostedt /**
343077a2b37dSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3431936e074bSSteven Rostedt  * @ops - the ops to set the filter with
343277a2b37dSSteven Rostedt  * @buf - the string that holds the function filter text.
343377a2b37dSSteven Rostedt  * @len - the length of the string.
343477a2b37dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
343577a2b37dSSteven Rostedt  *
343677a2b37dSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
343777a2b37dSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
343877a2b37dSSteven Rostedt  */
3439ac483c44SJiri Olsa int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
3440936e074bSSteven Rostedt 		       int len, int reset)
344177a2b37dSSteven Rostedt {
3442*f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3443ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 1);
344441c52c0dSSteven Rostedt }
3445936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_filter);
34464eebcc81SSteven Rostedt 
344741c52c0dSSteven Rostedt /**
344841c52c0dSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3449936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
345041c52c0dSSteven Rostedt  * @buf - the string that holds the function notrace text.
345141c52c0dSSteven Rostedt  * @len - the length of the string.
345241c52c0dSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
345341c52c0dSSteven Rostedt  *
345441c52c0dSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
345541c52c0dSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
345641c52c0dSSteven Rostedt  * for tracing.
345741c52c0dSSteven Rostedt  */
3458ac483c44SJiri Olsa int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
3459936e074bSSteven Rostedt 			int len, int reset)
3460936e074bSSteven Rostedt {
3461*f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3462ac483c44SJiri Olsa 	return ftrace_set_regex(ops, buf, len, reset, 0);
3463936e074bSSteven Rostedt }
3464936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_notrace);
3465936e074bSSteven Rostedt /**
3466936e074bSSteven Rostedt  * ftrace_set_filter - set a function to filter on in ftrace
3467936e074bSSteven Rostedt  * @ops - the ops to set the filter with
3468936e074bSSteven Rostedt  * @buf - the string that holds the function filter text.
3469936e074bSSteven Rostedt  * @len - the length of the string.
3470936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3471936e074bSSteven Rostedt  *
3472936e074bSSteven Rostedt  * Filters denote which functions should be enabled when tracing is enabled.
3473936e074bSSteven Rostedt  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
3474936e074bSSteven Rostedt  */
3475936e074bSSteven Rostedt void ftrace_set_global_filter(unsigned char *buf, int len, int reset)
3476936e074bSSteven Rostedt {
3477936e074bSSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 1);
3478936e074bSSteven Rostedt }
3479936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_filter);
3480936e074bSSteven Rostedt 
3481936e074bSSteven Rostedt /**
3482936e074bSSteven Rostedt  * ftrace_set_notrace - set a function to not trace in ftrace
3483936e074bSSteven Rostedt  * @ops - the ops to set the notrace filter with
3484936e074bSSteven Rostedt  * @buf - the string that holds the function notrace text.
3485936e074bSSteven Rostedt  * @len - the length of the string.
3486936e074bSSteven Rostedt  * @reset - non zero to reset all filters before applying this filter.
3487936e074bSSteven Rostedt  *
3488936e074bSSteven Rostedt  * Notrace Filters denote which functions should not be enabled when tracing
3489936e074bSSteven Rostedt  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
3490936e074bSSteven Rostedt  * for tracing.
3491936e074bSSteven Rostedt  */
3492936e074bSSteven Rostedt void ftrace_set_global_notrace(unsigned char *buf, int len, int reset)
349341c52c0dSSteven Rostedt {
3494f45948e8SSteven Rostedt 	ftrace_set_regex(&global_ops, buf, len, reset, 0);
349577a2b37dSSteven Rostedt }
3496936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_notrace);
349777a2b37dSSteven Rostedt 
34982af15d6aSSteven Rostedt /*
34992af15d6aSSteven Rostedt  * command line interface to allow users to set filters on boot up.
35002af15d6aSSteven Rostedt  */
35012af15d6aSSteven Rostedt #define FTRACE_FILTER_SIZE		COMMAND_LINE_SIZE
35022af15d6aSSteven Rostedt static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
35032af15d6aSSteven Rostedt static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;
35042af15d6aSSteven Rostedt 
35052af15d6aSSteven Rostedt static int __init set_ftrace_notrace(char *str)
35062af15d6aSSteven Rostedt {
350775761cc1SChen Gang 	strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
35082af15d6aSSteven Rostedt 	return 1;
35092af15d6aSSteven Rostedt }
35102af15d6aSSteven Rostedt __setup("ftrace_notrace=", set_ftrace_notrace);
35112af15d6aSSteven Rostedt 
35122af15d6aSSteven Rostedt static int __init set_ftrace_filter(char *str)
35132af15d6aSSteven Rostedt {
351475761cc1SChen Gang 	strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
35152af15d6aSSteven Rostedt 	return 1;
35162af15d6aSSteven Rostedt }
35172af15d6aSSteven Rostedt __setup("ftrace_filter=", set_ftrace_filter);
35182af15d6aSSteven Rostedt 
3519369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3520f6060f46SLai Jiangshan static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
3521801c29fdSSteven Rostedt static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
3522801c29fdSSteven Rostedt 
3523369bc18fSStefan Assmann static int __init set_graph_function(char *str)
3524369bc18fSStefan Assmann {
352506f43d66SFrederic Weisbecker 	strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
3526369bc18fSStefan Assmann 	return 1;
3527369bc18fSStefan Assmann }
3528369bc18fSStefan Assmann __setup("ftrace_graph_filter=", set_graph_function);
3529369bc18fSStefan Assmann 
3530369bc18fSStefan Assmann static void __init set_ftrace_early_graph(char *buf)
3531369bc18fSStefan Assmann {
3532369bc18fSStefan Assmann 	int ret;
3533369bc18fSStefan Assmann 	char *func;
3534369bc18fSStefan Assmann 
3535369bc18fSStefan Assmann 	while (buf) {
3536369bc18fSStefan Assmann 		func = strsep(&buf, ",");
3537369bc18fSStefan Assmann 		/* we allow only one expression at a time */
3538369bc18fSStefan Assmann 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3539369bc18fSStefan Assmann 				      func);
3540369bc18fSStefan Assmann 		if (ret)
3541369bc18fSStefan Assmann 			printk(KERN_DEBUG "ftrace: function %s not "
3542369bc18fSStefan Assmann 					  "traceable\n", func);
3543369bc18fSStefan Assmann 	}
3544369bc18fSStefan Assmann }
3545369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3546369bc18fSStefan Assmann 
35472a85a37fSSteven Rostedt void __init
35482a85a37fSSteven Rostedt ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable)
35492af15d6aSSteven Rostedt {
35502af15d6aSSteven Rostedt 	char *func;
35512af15d6aSSteven Rostedt 
3552*f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
3553*f04f24fbSMasami Hiramatsu 
35542af15d6aSSteven Rostedt 	while (buf) {
35552af15d6aSSteven Rostedt 		func = strsep(&buf, ",");
3556f45948e8SSteven Rostedt 		ftrace_set_regex(ops, func, strlen(func), 0, enable);
35572af15d6aSSteven Rostedt 	}
35582af15d6aSSteven Rostedt }
35592af15d6aSSteven Rostedt 
35602af15d6aSSteven Rostedt static void __init set_ftrace_early_filters(void)
35612af15d6aSSteven Rostedt {
35622af15d6aSSteven Rostedt 	if (ftrace_filter_buf[0])
35632a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_filter_buf, 1);
35642af15d6aSSteven Rostedt 	if (ftrace_notrace_buf[0])
35652a85a37fSSteven Rostedt 		ftrace_set_early_filter(&global_ops, ftrace_notrace_buf, 0);
3566369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3567369bc18fSStefan Assmann 	if (ftrace_graph_buf[0])
3568369bc18fSStefan Assmann 		set_ftrace_early_graph(ftrace_graph_buf);
3569369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
35702af15d6aSSteven Rostedt }
35712af15d6aSSteven Rostedt 
3572fc13cb0cSSteven Rostedt int ftrace_regex_release(struct inode *inode, struct file *file)
35735072c59fSSteven Rostedt {
35745072c59fSSteven Rostedt 	struct seq_file *m = (struct seq_file *)file->private_data;
35755072c59fSSteven Rostedt 	struct ftrace_iterator *iter;
357633dc9b12SSteven Rostedt 	struct ftrace_hash **orig_hash;
3577689fd8b6S[email protected] 	struct trace_parser *parser;
3578ed926f9bSSteven Rostedt 	int filter_hash;
357933dc9b12SSteven Rostedt 	int ret;
35805072c59fSSteven Rostedt 
35815072c59fSSteven Rostedt 	if (file->f_mode & FMODE_READ) {
35825072c59fSSteven Rostedt 		iter = m->private;
35835072c59fSSteven Rostedt 		seq_release(inode, file);
35845072c59fSSteven Rostedt 	} else
35855072c59fSSteven Rostedt 		iter = file->private_data;
35865072c59fSSteven Rostedt 
3587*f04f24fbSMasami Hiramatsu 	mutex_lock(&iter->ops->regex_lock);
3588*f04f24fbSMasami Hiramatsu 
3589689fd8b6S[email protected] 	parser = &iter->parser;
3590689fd8b6S[email protected] 	if (trace_parser_loaded(parser)) {
3591689fd8b6S[email protected] 		parser->buffer[parser->idx] = 0;
35921cf41dd7SSteven Rostedt 		ftrace_match_records(iter->hash, parser->buffer, parser->idx);
35935072c59fSSteven Rostedt 	}
35945072c59fSSteven Rostedt 
3595058e297dSSteven Rostedt 	trace_parser_put(parser);
3596058e297dSSteven Rostedt 
3597058e297dSSteven Rostedt 	if (file->f_mode & FMODE_WRITE) {
3598ed926f9bSSteven Rostedt 		filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
3599ed926f9bSSteven Rostedt 
3600ed926f9bSSteven Rostedt 		if (filter_hash)
360133dc9b12SSteven Rostedt 			orig_hash = &iter->ops->filter_hash;
3602ed926f9bSSteven Rostedt 		else
3603ed926f9bSSteven Rostedt 			orig_hash = &iter->ops->notrace_hash;
360433dc9b12SSteven Rostedt 
3605e6ea44e9SSteven Rostedt 		mutex_lock(&ftrace_lock);
360641fb61c2SSteven Rostedt 		ret = ftrace_hash_move(iter->ops, filter_hash,
360741fb61c2SSteven Rostedt 				       orig_hash, iter->hash);
360841fb61c2SSteven Rostedt 		if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED)
3609ed926f9bSSteven Rostedt 		    && ftrace_enabled)
361030fb6aa7SJiri Olsa 			ftrace_run_update_code(FTRACE_UPDATE_CALLS);
361141fb61c2SSteven Rostedt 
3612e6ea44e9SSteven Rostedt 		mutex_unlock(&ftrace_lock);
3613058e297dSSteven Rostedt 	}
361433dc9b12SSteven Rostedt 	free_ftrace_hash(iter->hash);
361533dc9b12SSteven Rostedt 	kfree(iter);
3616689fd8b6S[email protected] 
3617*f04f24fbSMasami Hiramatsu 	mutex_unlock(&iter->ops->regex_lock);
36185072c59fSSteven Rostedt 	return 0;
36195072c59fSSteven Rostedt }
36205072c59fSSteven Rostedt 
36215e2336a0SSteven Rostedt static const struct file_operations ftrace_avail_fops = {
36225072c59fSSteven Rostedt 	.open = ftrace_avail_open,
36235072c59fSSteven Rostedt 	.read = seq_read,
36245072c59fSSteven Rostedt 	.llseek = seq_lseek,
36253be04b47SLi Zefan 	.release = seq_release_private,
36265072c59fSSteven Rostedt };
36275072c59fSSteven Rostedt 
3628647bcd03SSteven Rostedt static const struct file_operations ftrace_enabled_fops = {
3629647bcd03SSteven Rostedt 	.open = ftrace_enabled_open,
3630647bcd03SSteven Rostedt 	.read = seq_read,
3631647bcd03SSteven Rostedt 	.llseek = seq_lseek,
3632647bcd03SSteven Rostedt 	.release = seq_release_private,
3633647bcd03SSteven Rostedt };
3634647bcd03SSteven Rostedt 
36355e2336a0SSteven Rostedt static const struct file_operations ftrace_filter_fops = {
36365072c59fSSteven Rostedt 	.open = ftrace_filter_open,
3637850a80cfSLai Jiangshan 	.read = seq_read,
36385072c59fSSteven Rostedt 	.write = ftrace_filter_write,
36396a76f8c0SNamhyung Kim 	.llseek = ftrace_filter_lseek,
36401cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
36415072c59fSSteven Rostedt };
36425072c59fSSteven Rostedt 
36435e2336a0SSteven Rostedt static const struct file_operations ftrace_notrace_fops = {
364441c52c0dSSteven Rostedt 	.open = ftrace_notrace_open,
3645850a80cfSLai Jiangshan 	.read = seq_read,
364641c52c0dSSteven Rostedt 	.write = ftrace_notrace_write,
36476a76f8c0SNamhyung Kim 	.llseek = ftrace_filter_lseek,
36481cf41dd7SSteven Rostedt 	.release = ftrace_regex_release,
364941c52c0dSSteven Rostedt };
365041c52c0dSSteven Rostedt 
3651ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
3652ea4e2bc4SSteven Rostedt 
3653ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock);
3654ea4e2bc4SSteven Rostedt 
3655ea4e2bc4SSteven Rostedt int ftrace_graph_count;
3656c7c6b1feSLi Zefan int ftrace_graph_filter_enabled;
3657ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
3658ea4e2bc4SSteven Rostedt 
3659ea4e2bc4SSteven Rostedt static void *
366085951842SLi Zefan __g_next(struct seq_file *m, loff_t *pos)
3661ea4e2bc4SSteven Rostedt {
366285951842SLi Zefan 	if (*pos >= ftrace_graph_count)
3663ea4e2bc4SSteven Rostedt 		return NULL;
3664a4ec5e0cSLi Zefan 	return &ftrace_graph_funcs[*pos];
366585951842SLi Zefan }
3666ea4e2bc4SSteven Rostedt 
366785951842SLi Zefan static void *
366885951842SLi Zefan g_next(struct seq_file *m, void *v, loff_t *pos)
366985951842SLi Zefan {
367085951842SLi Zefan 	(*pos)++;
367185951842SLi Zefan 	return __g_next(m, pos);
3672ea4e2bc4SSteven Rostedt }
3673ea4e2bc4SSteven Rostedt 
3674ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos)
3675ea4e2bc4SSteven Rostedt {
3676ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3677ea4e2bc4SSteven Rostedt 
3678f9349a8fSFrederic Weisbecker 	/* Nothing, tell g_show to print all functions are enabled */
3679c7c6b1feSLi Zefan 	if (!ftrace_graph_filter_enabled && !*pos)
3680f9349a8fSFrederic Weisbecker 		return (void *)1;
3681f9349a8fSFrederic Weisbecker 
368285951842SLi Zefan 	return __g_next(m, pos);
3683ea4e2bc4SSteven Rostedt }
3684ea4e2bc4SSteven Rostedt 
3685ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p)
3686ea4e2bc4SSteven Rostedt {
3687ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3688ea4e2bc4SSteven Rostedt }
3689ea4e2bc4SSteven Rostedt 
3690ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v)
3691ea4e2bc4SSteven Rostedt {
3692ea4e2bc4SSteven Rostedt 	unsigned long *ptr = v;
3693ea4e2bc4SSteven Rostedt 
3694ea4e2bc4SSteven Rostedt 	if (!ptr)
3695ea4e2bc4SSteven Rostedt 		return 0;
3696ea4e2bc4SSteven Rostedt 
3697f9349a8fSFrederic Weisbecker 	if (ptr == (unsigned long *)1) {
3698f9349a8fSFrederic Weisbecker 		seq_printf(m, "#### all functions enabled ####\n");
3699f9349a8fSFrederic Weisbecker 		return 0;
3700f9349a8fSFrederic Weisbecker 	}
3701f9349a8fSFrederic Weisbecker 
3702b375a11aSSteven Rostedt 	seq_printf(m, "%ps\n", (void *)*ptr);
3703ea4e2bc4SSteven Rostedt 
3704ea4e2bc4SSteven Rostedt 	return 0;
3705ea4e2bc4SSteven Rostedt }
3706ea4e2bc4SSteven Rostedt 
370788e9d34cSJames Morris static const struct seq_operations ftrace_graph_seq_ops = {
3708ea4e2bc4SSteven Rostedt 	.start = g_start,
3709ea4e2bc4SSteven Rostedt 	.next = g_next,
3710ea4e2bc4SSteven Rostedt 	.stop = g_stop,
3711ea4e2bc4SSteven Rostedt 	.show = g_show,
3712ea4e2bc4SSteven Rostedt };
3713ea4e2bc4SSteven Rostedt 
3714ea4e2bc4SSteven Rostedt static int
3715ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file)
3716ea4e2bc4SSteven Rostedt {
3717ea4e2bc4SSteven Rostedt 	int ret = 0;
3718ea4e2bc4SSteven Rostedt 
3719ea4e2bc4SSteven Rostedt 	if (unlikely(ftrace_disabled))
3720ea4e2bc4SSteven Rostedt 		return -ENODEV;
3721ea4e2bc4SSteven Rostedt 
3722ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3723ea4e2bc4SSteven Rostedt 	if ((file->f_mode & FMODE_WRITE) &&
37248650ae32SSteven Rostedt 	    (file->f_flags & O_TRUNC)) {
3725c7c6b1feSLi Zefan 		ftrace_graph_filter_enabled = 0;
3726ea4e2bc4SSteven Rostedt 		ftrace_graph_count = 0;
3727ea4e2bc4SSteven Rostedt 		memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
3728ea4e2bc4SSteven Rostedt 	}
3729ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3730ea4e2bc4SSteven Rostedt 
3731a4ec5e0cSLi Zefan 	if (file->f_mode & FMODE_READ)
3732a4ec5e0cSLi Zefan 		ret = seq_open(file, &ftrace_graph_seq_ops);
3733a4ec5e0cSLi Zefan 
3734ea4e2bc4SSteven Rostedt 	return ret;
3735ea4e2bc4SSteven Rostedt }
3736ea4e2bc4SSteven Rostedt 
3737ea4e2bc4SSteven Rostedt static int
373887827111SLi Zefan ftrace_graph_release(struct inode *inode, struct file *file)
373987827111SLi Zefan {
374087827111SLi Zefan 	if (file->f_mode & FMODE_READ)
374187827111SLi Zefan 		seq_release(inode, file);
374287827111SLi Zefan 	return 0;
374387827111SLi Zefan }
374487827111SLi Zefan 
374587827111SLi Zefan static int
3746f9349a8fSFrederic Weisbecker ftrace_set_func(unsigned long *array, int *idx, char *buffer)
3747ea4e2bc4SSteven Rostedt {
3748ea4e2bc4SSteven Rostedt 	struct dyn_ftrace *rec;
3749ea4e2bc4SSteven Rostedt 	struct ftrace_page *pg;
3750f9349a8fSFrederic Weisbecker 	int search_len;
3751c7c6b1feSLi Zefan 	int fail = 1;
3752f9349a8fSFrederic Weisbecker 	int type, not;
3753f9349a8fSFrederic Weisbecker 	char *search;
3754f9349a8fSFrederic Weisbecker 	bool exists;
3755f9349a8fSFrederic Weisbecker 	int i;
3756ea4e2bc4SSteven Rostedt 
3757f9349a8fSFrederic Weisbecker 	/* decode regex */
37583f6fe06dSFrederic Weisbecker 	type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
3759c7c6b1feSLi Zefan 	if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS)
3760c7c6b1feSLi Zefan 		return -EBUSY;
3761f9349a8fSFrederic Weisbecker 
3762f9349a8fSFrederic Weisbecker 	search_len = strlen(search);
3763f9349a8fSFrederic Weisbecker 
376452baf119SSteven Rostedt 	mutex_lock(&ftrace_lock);
376545a4a237SSteven Rostedt 
376645a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled)) {
376745a4a237SSteven Rostedt 		mutex_unlock(&ftrace_lock);
376845a4a237SSteven Rostedt 		return -ENODEV;
376945a4a237SSteven Rostedt 	}
377045a4a237SSteven Rostedt 
3771265c831cSSteven Rostedt 	do_for_each_ftrace_rec(pg, rec) {
3772ea4e2bc4SSteven Rostedt 
3773b9df92d2SSteven Rostedt 		if (ftrace_match_record(rec, NULL, search, search_len, type)) {
3774c7c6b1feSLi Zefan 			/* if it is in the array */
3775f9349a8fSFrederic Weisbecker 			exists = false;
3776c7c6b1feSLi Zefan 			for (i = 0; i < *idx; i++) {
3777f9349a8fSFrederic Weisbecker 				if (array[i] == rec->ip) {
3778f9349a8fSFrederic Weisbecker 					exists = true;
3779faec2ec5SLiming Wang 					break;
3780faec2ec5SLiming Wang 				}
3781c7c6b1feSLi Zefan 			}
3782c7c6b1feSLi Zefan 
3783c7c6b1feSLi Zefan 			if (!not) {
3784c7c6b1feSLi Zefan 				fail = 0;
3785c7c6b1feSLi Zefan 				if (!exists) {
3786f9349a8fSFrederic Weisbecker 					array[(*idx)++] = rec->ip;
3787c7c6b1feSLi Zefan 					if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
3788c7c6b1feSLi Zefan 						goto out;
3789c7c6b1feSLi Zefan 				}
3790c7c6b1feSLi Zefan 			} else {
3791c7c6b1feSLi Zefan 				if (exists) {
3792c7c6b1feSLi Zefan 					array[i] = array[--(*idx)];
3793c7c6b1feSLi Zefan 					array[*idx] = 0;
3794c7c6b1feSLi Zefan 					fail = 0;
3795c7c6b1feSLi Zefan 				}
3796c7c6b1feSLi Zefan 			}
3797f9349a8fSFrederic Weisbecker 		}
3798265c831cSSteven Rostedt 	} while_for_each_ftrace_rec();
3799c7c6b1feSLi Zefan out:
380052baf119SSteven Rostedt 	mutex_unlock(&ftrace_lock);
3801ea4e2bc4SSteven Rostedt 
3802c7c6b1feSLi Zefan 	if (fail)
3803c7c6b1feSLi Zefan 		return -EINVAL;
3804c7c6b1feSLi Zefan 
38059f50afccSNamhyung Kim 	ftrace_graph_filter_enabled = !!(*idx);
38069f50afccSNamhyung Kim 
3807c7c6b1feSLi Zefan 	return 0;
3808ea4e2bc4SSteven Rostedt }
3809ea4e2bc4SSteven Rostedt 
3810ea4e2bc4SSteven Rostedt static ssize_t
3811ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf,
3812ea4e2bc4SSteven Rostedt 		   size_t cnt, loff_t *ppos)
3813ea4e2bc4SSteven Rostedt {
3814689fd8b6S[email protected] 	struct trace_parser parser;
38154ba7978eSLi Zefan 	ssize_t read, ret;
3816ea4e2bc4SSteven Rostedt 
3817c7c6b1feSLi Zefan 	if (!cnt)
3818ea4e2bc4SSteven Rostedt 		return 0;
3819ea4e2bc4SSteven Rostedt 
3820ea4e2bc4SSteven Rostedt 	mutex_lock(&graph_lock);
3821ea4e2bc4SSteven Rostedt 
3822689fd8b6S[email protected] 	if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
3823689fd8b6S[email protected] 		ret = -ENOMEM;
38241eb90f13SLi Zefan 		goto out_unlock;
3825ea4e2bc4SSteven Rostedt 	}
3826ea4e2bc4SSteven Rostedt 
3827689fd8b6S[email protected] 	read = trace_get_user(&parser, ubuf, cnt, ppos);
3828689fd8b6S[email protected] 
38294ba7978eSLi Zefan 	if (read >= 0 && trace_parser_loaded((&parser))) {
3830689fd8b6S[email protected] 		parser.buffer[parser.idx] = 0;
3831ea4e2bc4SSteven Rostedt 
3832f9349a8fSFrederic Weisbecker 		/* we allow only one expression at a time */
3833a4ec5e0cSLi Zefan 		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
3834689fd8b6S[email protected] 					parser.buffer);
3835ea4e2bc4SSteven Rostedt 		if (ret)
38361eb90f13SLi Zefan 			goto out_free;
3837689fd8b6S[email protected] 	}
3838ea4e2bc4SSteven Rostedt 
3839ea4e2bc4SSteven Rostedt 	ret = read;
38401eb90f13SLi Zefan 
38411eb90f13SLi Zefan out_free:
3842689fd8b6S[email protected] 	trace_parser_put(&parser);
38431eb90f13SLi Zefan out_unlock:
3844ea4e2bc4SSteven Rostedt 	mutex_unlock(&graph_lock);
3845ea4e2bc4SSteven Rostedt 
3846ea4e2bc4SSteven Rostedt 	return ret;
3847ea4e2bc4SSteven Rostedt }
3848ea4e2bc4SSteven Rostedt 
3849ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = {
3850ea4e2bc4SSteven Rostedt 	.open		= ftrace_graph_open,
3851850a80cfSLai Jiangshan 	.read		= seq_read,
3852ea4e2bc4SSteven Rostedt 	.write		= ftrace_graph_write,
38536a76f8c0SNamhyung Kim 	.llseek		= ftrace_filter_lseek,
385487827111SLi Zefan 	.release	= ftrace_graph_release,
3855ea4e2bc4SSteven Rostedt };
3856ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3857ea4e2bc4SSteven Rostedt 
3858df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
38595072c59fSSteven Rostedt {
38605072c59fSSteven Rostedt 
38615452af66SFrederic Weisbecker 	trace_create_file("available_filter_functions", 0444,
38625072c59fSSteven Rostedt 			d_tracer, NULL, &ftrace_avail_fops);
38635072c59fSSteven Rostedt 
3864647bcd03SSteven Rostedt 	trace_create_file("enabled_functions", 0444,
3865647bcd03SSteven Rostedt 			d_tracer, NULL, &ftrace_enabled_fops);
3866647bcd03SSteven Rostedt 
38675452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_filter", 0644, d_tracer,
38685072c59fSSteven Rostedt 			NULL, &ftrace_filter_fops);
386941c52c0dSSteven Rostedt 
38705452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_notrace", 0644, d_tracer,
387141c52c0dSSteven Rostedt 				    NULL, &ftrace_notrace_fops);
3872ad90c0e3SSteven Rostedt 
3873ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER
38745452af66SFrederic Weisbecker 	trace_create_file("set_graph_function", 0444, d_tracer,
3875ea4e2bc4SSteven Rostedt 				    NULL,
3876ea4e2bc4SSteven Rostedt 				    &ftrace_graph_fops);
3877ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
3878ea4e2bc4SSteven Rostedt 
38795072c59fSSteven Rostedt 	return 0;
38805072c59fSSteven Rostedt }
38815072c59fSSteven Rostedt 
38829fd49328SSteven Rostedt static int ftrace_cmp_ips(const void *a, const void *b)
388368950619SSteven Rostedt {
38849fd49328SSteven Rostedt 	const unsigned long *ipa = a;
38859fd49328SSteven Rostedt 	const unsigned long *ipb = b;
388668950619SSteven Rostedt 
38879fd49328SSteven Rostedt 	if (*ipa > *ipb)
38889fd49328SSteven Rostedt 		return 1;
38899fd49328SSteven Rostedt 	if (*ipa < *ipb)
38909fd49328SSteven Rostedt 		return -1;
38919fd49328SSteven Rostedt 	return 0;
38929fd49328SSteven Rostedt }
38939fd49328SSteven Rostedt 
38949fd49328SSteven Rostedt static void ftrace_swap_ips(void *a, void *b, int size)
38959fd49328SSteven Rostedt {
38969fd49328SSteven Rostedt 	unsigned long *ipa = a;
38979fd49328SSteven Rostedt 	unsigned long *ipb = b;
38989fd49328SSteven Rostedt 	unsigned long t;
38999fd49328SSteven Rostedt 
39009fd49328SSteven Rostedt 	t = *ipa;
39019fd49328SSteven Rostedt 	*ipa = *ipb;
39029fd49328SSteven Rostedt 	*ipb = t;
390368950619SSteven Rostedt }
390468950619SSteven Rostedt 
39055cb084bbSJiri Olsa static int ftrace_process_locs(struct module *mod,
390631e88909SSteven Rostedt 			       unsigned long *start,
390768bf21aaSSteven Rostedt 			       unsigned long *end)
390868bf21aaSSteven Rostedt {
3909706c81f8SSteven Rostedt 	struct ftrace_page *start_pg;
3910a7900875SSteven Rostedt 	struct ftrace_page *pg;
3911706c81f8SSteven Rostedt 	struct dyn_ftrace *rec;
3912a7900875SSteven Rostedt 	unsigned long count;
391368bf21aaSSteven Rostedt 	unsigned long *p;
391468bf21aaSSteven Rostedt 	unsigned long addr;
39154376cac6SSteven Rostedt 	unsigned long flags = 0; /* Shut up gcc */
3916a7900875SSteven Rostedt 	int ret = -ENOMEM;
3917a7900875SSteven Rostedt 
3918a7900875SSteven Rostedt 	count = end - start;
3919a7900875SSteven Rostedt 
3920a7900875SSteven Rostedt 	if (!count)
3921a7900875SSteven Rostedt 		return 0;
3922a7900875SSteven Rostedt 
39239fd49328SSteven Rostedt 	sort(start, count, sizeof(*start),
39249fd49328SSteven Rostedt 	     ftrace_cmp_ips, ftrace_swap_ips);
39259fd49328SSteven Rostedt 
3926706c81f8SSteven Rostedt 	start_pg = ftrace_allocate_pages(count);
3927706c81f8SSteven Rostedt 	if (!start_pg)
3928a7900875SSteven Rostedt 		return -ENOMEM;
392968bf21aaSSteven Rostedt 
3930e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
3931a7900875SSteven Rostedt 
393232082309SSteven Rostedt 	/*
393332082309SSteven Rostedt 	 * Core and each module needs their own pages, as
393432082309SSteven Rostedt 	 * modules will free them when they are removed.
393532082309SSteven Rostedt 	 * Force a new page to be allocated for modules.
393632082309SSteven Rostedt 	 */
3937a7900875SSteven Rostedt 	if (!mod) {
3938a7900875SSteven Rostedt 		WARN_ON(ftrace_pages || ftrace_pages_start);
3939a7900875SSteven Rostedt 		/* First initialization */
3940706c81f8SSteven Rostedt 		ftrace_pages = ftrace_pages_start = start_pg;
3941a7900875SSteven Rostedt 	} else {
394232082309SSteven Rostedt 		if (!ftrace_pages)
3943a7900875SSteven Rostedt 			goto out;
394432082309SSteven Rostedt 
3945a7900875SSteven Rostedt 		if (WARN_ON(ftrace_pages->next)) {
3946a7900875SSteven Rostedt 			/* Hmm, we have free pages? */
3947a7900875SSteven Rostedt 			while (ftrace_pages->next)
394832082309SSteven Rostedt 				ftrace_pages = ftrace_pages->next;
394932082309SSteven Rostedt 		}
3950a7900875SSteven Rostedt 
3951706c81f8SSteven Rostedt 		ftrace_pages->next = start_pg;
395232082309SSteven Rostedt 	}
395332082309SSteven Rostedt 
395468bf21aaSSteven Rostedt 	p = start;
3955706c81f8SSteven Rostedt 	pg = start_pg;
395668bf21aaSSteven Rostedt 	while (p < end) {
395768bf21aaSSteven Rostedt 		addr = ftrace_call_adjust(*p++);
395820e5227eSSteven Rostedt 		/*
395920e5227eSSteven Rostedt 		 * Some architecture linkers will pad between
396020e5227eSSteven Rostedt 		 * the different mcount_loc sections of different
396120e5227eSSteven Rostedt 		 * object files to satisfy alignments.
396220e5227eSSteven Rostedt 		 * Skip any NULL pointers.
396320e5227eSSteven Rostedt 		 */
396420e5227eSSteven Rostedt 		if (!addr)
396520e5227eSSteven Rostedt 			continue;
3966706c81f8SSteven Rostedt 
3967706c81f8SSteven Rostedt 		if (pg->index == pg->size) {
3968706c81f8SSteven Rostedt 			/* We should have allocated enough */
3969706c81f8SSteven Rostedt 			if (WARN_ON(!pg->next))
3970a7900875SSteven Rostedt 				break;
3971706c81f8SSteven Rostedt 			pg = pg->next;
397268bf21aaSSteven Rostedt 		}
397368bf21aaSSteven Rostedt 
3974706c81f8SSteven Rostedt 		rec = &pg->records[pg->index++];
3975706c81f8SSteven Rostedt 		rec->ip = addr;
3976706c81f8SSteven Rostedt 	}
3977706c81f8SSteven Rostedt 
3978706c81f8SSteven Rostedt 	/* We should have used all pages */
3979706c81f8SSteven Rostedt 	WARN_ON(pg->next);
3980706c81f8SSteven Rostedt 
3981706c81f8SSteven Rostedt 	/* Assign the last page to ftrace_pages */
3982706c81f8SSteven Rostedt 	ftrace_pages = pg;
3983706c81f8SSteven Rostedt 
398485ae32aeSSteven Rostedt 	/* These new locations need to be initialized */
3985706c81f8SSteven Rostedt 	ftrace_new_pgs = start_pg;
398685ae32aeSSteven Rostedt 
3987a4f18ed1SSteven Rostedt 	/*
39884376cac6SSteven Rostedt 	 * We only need to disable interrupts on start up
39894376cac6SSteven Rostedt 	 * because we are modifying code that an interrupt
39904376cac6SSteven Rostedt 	 * may execute, and the modification is not atomic.
39914376cac6SSteven Rostedt 	 * But for modules, nothing runs the code we modify
39924376cac6SSteven Rostedt 	 * until we are finished with it, and there's no
39934376cac6SSteven Rostedt 	 * reason to cause large interrupt latencies while we do it.
3994a4f18ed1SSteven Rostedt 	 */
39954376cac6SSteven Rostedt 	if (!mod)
3996a4f18ed1SSteven Rostedt 		local_irq_save(flags);
399731e88909SSteven Rostedt 	ftrace_update_code(mod);
39984376cac6SSteven Rostedt 	if (!mod)
3999a4f18ed1SSteven Rostedt 		local_irq_restore(flags);
4000a7900875SSteven Rostedt 	ret = 0;
4001a7900875SSteven Rostedt  out:
4002e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
400368bf21aaSSteven Rostedt 
4004a7900875SSteven Rostedt 	return ret;
400568bf21aaSSteven Rostedt }
400668bf21aaSSteven Rostedt 
400793eb677dSSteven Rostedt #ifdef CONFIG_MODULES
400832082309SSteven Rostedt 
400932082309SSteven Rostedt #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)
401032082309SSteven Rostedt 
4011e7247a15S[email protected] void ftrace_release_mod(struct module *mod)
401293eb677dSSteven Rostedt {
401393eb677dSSteven Rostedt 	struct dyn_ftrace *rec;
401432082309SSteven Rostedt 	struct ftrace_page **last_pg;
401593eb677dSSteven Rostedt 	struct ftrace_page *pg;
4016a7900875SSteven Rostedt 	int order;
401793eb677dSSteven Rostedt 
401893eb677dSSteven Rostedt 	mutex_lock(&ftrace_lock);
401945a4a237SSteven Rostedt 
402045a4a237SSteven Rostedt 	if (ftrace_disabled)
402145a4a237SSteven Rostedt 		goto out_unlock;
402245a4a237SSteven Rostedt 
402332082309SSteven Rostedt 	/*
402432082309SSteven Rostedt 	 * Each module has its own ftrace_pages, remove
402532082309SSteven Rostedt 	 * them from the list.
402632082309SSteven Rostedt 	 */
402732082309SSteven Rostedt 	last_pg = &ftrace_pages_start;
402832082309SSteven Rostedt 	for (pg = ftrace_pages_start; pg; pg = *last_pg) {
402932082309SSteven Rostedt 		rec = &pg->records[0];
4030e7247a15S[email protected] 		if (within_module_core(rec->ip, mod)) {
403193eb677dSSteven Rostedt 			/*
403232082309SSteven Rostedt 			 * As core pages are first, the first
403332082309SSteven Rostedt 			 * page should never be a module page.
403493eb677dSSteven Rostedt 			 */
403532082309SSteven Rostedt 			if (WARN_ON(pg == ftrace_pages_start))
403632082309SSteven Rostedt 				goto out_unlock;
403732082309SSteven Rostedt 
403832082309SSteven Rostedt 			/* Check if we are deleting the last page */
403932082309SSteven Rostedt 			if (pg == ftrace_pages)
404032082309SSteven Rostedt 				ftrace_pages = next_to_ftrace_page(last_pg);
404132082309SSteven Rostedt 
404232082309SSteven Rostedt 			*last_pg = pg->next;
4043a7900875SSteven Rostedt 			order = get_count_order(pg->size / ENTRIES_PER_PAGE);
4044a7900875SSteven Rostedt 			free_pages((unsigned long)pg->records, order);
4045a7900875SSteven Rostedt 			kfree(pg);
404632082309SSteven Rostedt 		} else
404732082309SSteven Rostedt 			last_pg = &pg->next;
404893eb677dSSteven Rostedt 	}
404945a4a237SSteven Rostedt  out_unlock:
405093eb677dSSteven Rostedt 	mutex_unlock(&ftrace_lock);
405193eb677dSSteven Rostedt }
405293eb677dSSteven Rostedt 
405393eb677dSSteven Rostedt static void ftrace_init_module(struct module *mod,
405431e88909SSteven Rostedt 			       unsigned long *start, unsigned long *end)
405590d595feSSteven Rostedt {
405600fd61aeSSteven Rostedt 	if (ftrace_disabled || start == end)
4057fed1939cSSteven Rostedt 		return;
40585cb084bbSJiri Olsa 	ftrace_process_locs(mod, start, end);
405990d595feSSteven Rostedt }
406090d595feSSteven Rostedt 
40618c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
406293eb677dSSteven Rostedt 				      unsigned long val, void *data)
406393eb677dSSteven Rostedt {
406493eb677dSSteven Rostedt 	struct module *mod = data;
406593eb677dSSteven Rostedt 
40668c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_COMING)
406793eb677dSSteven Rostedt 		ftrace_init_module(mod, mod->ftrace_callsites,
406893eb677dSSteven Rostedt 				   mod->ftrace_callsites +
406993eb677dSSteven Rostedt 				   mod->num_ftrace_callsites);
40708c189ea6SSteven Rostedt (Red Hat) 	return 0;
407193eb677dSSteven Rostedt }
407293eb677dSSteven Rostedt 
40738c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
40748c189ea6SSteven Rostedt (Red Hat) 				     unsigned long val, void *data)
40758c189ea6SSteven Rostedt (Red Hat) {
40768c189ea6SSteven Rostedt (Red Hat) 	struct module *mod = data;
40778c189ea6SSteven Rostedt (Red Hat) 
40788c189ea6SSteven Rostedt (Red Hat) 	if (val == MODULE_STATE_GOING)
40798c189ea6SSteven Rostedt (Red Hat) 		ftrace_release_mod(mod);
40808c189ea6SSteven Rostedt (Red Hat) 
408193eb677dSSteven Rostedt 	return 0;
408293eb677dSSteven Rostedt }
408393eb677dSSteven Rostedt #else
40848c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_enter(struct notifier_block *self,
40858c189ea6SSteven Rostedt (Red Hat) 				      unsigned long val, void *data)
40868c189ea6SSteven Rostedt (Red Hat) {
40878c189ea6SSteven Rostedt (Red Hat) 	return 0;
40888c189ea6SSteven Rostedt (Red Hat) }
40898c189ea6SSteven Rostedt (Red Hat) static int ftrace_module_notify_exit(struct notifier_block *self,
409093eb677dSSteven Rostedt 				     unsigned long val, void *data)
409193eb677dSSteven Rostedt {
409293eb677dSSteven Rostedt 	return 0;
409393eb677dSSteven Rostedt }
409493eb677dSSteven Rostedt #endif /* CONFIG_MODULES */
409593eb677dSSteven Rostedt 
40968c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_enter_nb = {
40978c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_enter,
4098c1bf08acSSteven Rostedt 	.priority = INT_MAX,	/* Run before anything that can use kprobes */
409993eb677dSSteven Rostedt };
410093eb677dSSteven Rostedt 
41018c189ea6SSteven Rostedt (Red Hat) struct notifier_block ftrace_module_exit_nb = {
41028c189ea6SSteven Rostedt (Red Hat) 	.notifier_call = ftrace_module_notify_exit,
41038c189ea6SSteven Rostedt (Red Hat) 	.priority = INT_MIN,	/* Run after anything that can remove kprobes */
41048c189ea6SSteven Rostedt (Red Hat) };
41058c189ea6SSteven Rostedt (Red Hat) 
410668bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[];
410768bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[];
410868bf21aaSSteven Rostedt 
410968bf21aaSSteven Rostedt void __init ftrace_init(void)
411068bf21aaSSteven Rostedt {
411168bf21aaSSteven Rostedt 	unsigned long count, addr, flags;
411268bf21aaSSteven Rostedt 	int ret;
411368bf21aaSSteven Rostedt 
411468bf21aaSSteven Rostedt 	/* Keep the ftrace pointer to the stub */
411568bf21aaSSteven Rostedt 	addr = (unsigned long)ftrace_stub;
411668bf21aaSSteven Rostedt 
411768bf21aaSSteven Rostedt 	local_irq_save(flags);
411868bf21aaSSteven Rostedt 	ftrace_dyn_arch_init(&addr);
411968bf21aaSSteven Rostedt 	local_irq_restore(flags);
412068bf21aaSSteven Rostedt 
412168bf21aaSSteven Rostedt 	/* ftrace_dyn_arch_init places the return code in addr */
412268bf21aaSSteven Rostedt 	if (addr)
412368bf21aaSSteven Rostedt 		goto failed;
412468bf21aaSSteven Rostedt 
412568bf21aaSSteven Rostedt 	count = __stop_mcount_loc - __start_mcount_loc;
412668bf21aaSSteven Rostedt 
412768bf21aaSSteven Rostedt 	ret = ftrace_dyn_table_alloc(count);
412868bf21aaSSteven Rostedt 	if (ret)
412968bf21aaSSteven Rostedt 		goto failed;
413068bf21aaSSteven Rostedt 
413168bf21aaSSteven Rostedt 	last_ftrace_enabled = ftrace_enabled = 1;
413268bf21aaSSteven Rostedt 
41335cb084bbSJiri Olsa 	ret = ftrace_process_locs(NULL,
413431e88909SSteven Rostedt 				  __start_mcount_loc,
413568bf21aaSSteven Rostedt 				  __stop_mcount_loc);
413668bf21aaSSteven Rostedt 
41378c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_enter_nb);
413824ed0c4bSMing Lei 	if (ret)
41398c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module enter notifier\n");
41408c189ea6SSteven Rostedt (Red Hat) 
41418c189ea6SSteven Rostedt (Red Hat) 	ret = register_module_notifier(&ftrace_module_exit_nb);
41428c189ea6SSteven Rostedt (Red Hat) 	if (ret)
41438c189ea6SSteven Rostedt (Red Hat) 		pr_warning("Failed to register trace ftrace module exit notifier\n");
414493eb677dSSteven Rostedt 
41452af15d6aSSteven Rostedt 	set_ftrace_early_filters();
41462af15d6aSSteven Rostedt 
414768bf21aaSSteven Rostedt 	return;
414868bf21aaSSteven Rostedt  failed:
414968bf21aaSSteven Rostedt 	ftrace_disabled = 1;
415068bf21aaSSteven Rostedt }
415168bf21aaSSteven Rostedt 
41523d083395SSteven Rostedt #else
41530b6e4d56SFrederic Weisbecker 
41542b499381SSteven Rostedt static struct ftrace_ops global_ops = {
4155bd69c30bSSteven Rostedt 	.func			= ftrace_stub,
4156*f04f24fbSMasami Hiramatsu 	.flags			= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
4157*f04f24fbSMasami Hiramatsu 	INIT_REGEX_LOCK(global_ops)
4158bd69c30bSSteven Rostedt };
4159bd69c30bSSteven Rostedt 
41600b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void)
41610b6e4d56SFrederic Weisbecker {
41620b6e4d56SFrederic Weisbecker 	ftrace_enabled = 1;
41630b6e4d56SFrederic Weisbecker 	return 0;
41640b6e4d56SFrederic Weisbecker }
41656f415672SSteven Rostedt core_initcall(ftrace_nodyn_init);
41660b6e4d56SFrederic Weisbecker 
4167df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
4168df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { }
41695a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */
41703b6cfdb1SSteven Rostedt # define ftrace_startup(ops, command)			\
41713b6cfdb1SSteven Rostedt 	({						\
41723b6cfdb1SSteven Rostedt 		(ops)->flags |= FTRACE_OPS_FL_ENABLED;	\
41733b6cfdb1SSteven Rostedt 		0;					\
41743b6cfdb1SSteven Rostedt 	})
4175bd69c30bSSteven Rostedt # define ftrace_shutdown(ops, command)	do { } while (0)
4176b0fc494fSSteven Rostedt # define ftrace_startup_sysctl()	do { } while (0)
4177b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl()	do { } while (0)
4178b848914cSSteven Rostedt 
4179b848914cSSteven Rostedt static inline int
4180b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
4181b848914cSSteven Rostedt {
4182b848914cSSteven Rostedt 	return 1;
4183b848914cSSteven Rostedt }
4184b848914cSSteven Rostedt 
41853d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */
41863d083395SSteven Rostedt 
4187b848914cSSteven Rostedt static void
41882f5f6ad9SSteven Rostedt ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
4189a1e2e31dSSteven Rostedt 			struct ftrace_ops *op, struct pt_regs *regs)
4190e248491aSJiri Olsa {
4191e248491aSJiri Olsa 	if (unlikely(trace_recursion_test(TRACE_CONTROL_BIT)))
4192e248491aSJiri Olsa 		return;
4193e248491aSJiri Olsa 
4194e248491aSJiri Olsa 	/*
4195e248491aSJiri Olsa 	 * Some of the ops may be dynamically allocated,
4196e248491aSJiri Olsa 	 * they must be freed after a synchronize_sched().
4197e248491aSJiri Olsa 	 */
4198e248491aSJiri Olsa 	preempt_disable_notrace();
4199e248491aSJiri Olsa 	trace_recursion_set(TRACE_CONTROL_BIT);
42000a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_control_list) {
4201395b97a3SSteven Rostedt (Red Hat) 		if (!(op->flags & FTRACE_OPS_FL_STUB) &&
4202395b97a3SSteven Rostedt (Red Hat) 		    !ftrace_function_local_disabled(op) &&
4203e248491aSJiri Olsa 		    ftrace_ops_test(op, ip))
4204a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
42050a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4206e248491aSJiri Olsa 	trace_recursion_clear(TRACE_CONTROL_BIT);
4207e248491aSJiri Olsa 	preempt_enable_notrace();
4208e248491aSJiri Olsa }
4209e248491aSJiri Olsa 
4210e248491aSJiri Olsa static struct ftrace_ops control_ops = {
4211e248491aSJiri Olsa 	.func	= ftrace_ops_control_func,
4212*f04f24fbSMasami Hiramatsu 	.flags	= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
4213*f04f24fbSMasami Hiramatsu 	INIT_REGEX_LOCK(control_ops)
4214e248491aSJiri Olsa };
4215e248491aSJiri Olsa 
42162f5f6ad9SSteven Rostedt static inline void
42172f5f6ad9SSteven Rostedt __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4218a1e2e31dSSteven Rostedt 		       struct ftrace_ops *ignored, struct pt_regs *regs)
4219b848914cSSteven Rostedt {
4220cdbe61bfSSteven Rostedt 	struct ftrace_ops *op;
4221edc15cafSSteven Rostedt 	int bit;
4222b848914cSSteven Rostedt 
4223ccf3672dSSteven Rostedt 	if (function_trace_stop)
4224ccf3672dSSteven Rostedt 		return;
4225ccf3672dSSteven Rostedt 
4226edc15cafSSteven Rostedt 	bit = trace_test_and_set_recursion(TRACE_LIST_START, TRACE_LIST_MAX);
4227edc15cafSSteven Rostedt 	if (bit < 0)
4228b1cff0adSSteven Rostedt 		return;
4229b1cff0adSSteven Rostedt 
4230cdbe61bfSSteven Rostedt 	/*
4231cdbe61bfSSteven Rostedt 	 * Some of the ops may be dynamically allocated,
4232cdbe61bfSSteven Rostedt 	 * they must be freed after a synchronize_sched().
4233cdbe61bfSSteven Rostedt 	 */
4234cdbe61bfSSteven Rostedt 	preempt_disable_notrace();
42350a016409SSteven Rostedt 	do_for_each_ftrace_op(op, ftrace_ops_list) {
4236b848914cSSteven Rostedt 		if (ftrace_ops_test(op, ip))
4237a1e2e31dSSteven Rostedt 			op->func(ip, parent_ip, op, regs);
42380a016409SSteven Rostedt 	} while_for_each_ftrace_op(op);
4239cdbe61bfSSteven Rostedt 	preempt_enable_notrace();
4240edc15cafSSteven Rostedt 	trace_clear_recursion(bit);
4241b848914cSSteven Rostedt }
4242b848914cSSteven Rostedt 
42432f5f6ad9SSteven Rostedt /*
42442f5f6ad9SSteven Rostedt  * Some archs only support passing ip and parent_ip. Even though
42452f5f6ad9SSteven Rostedt  * the list function ignores the op parameter, we do not want any
42462f5f6ad9SSteven Rostedt  * C side effects, where a function is called without the caller
42472f5f6ad9SSteven Rostedt  * sending a third parameter.
4248a1e2e31dSSteven Rostedt  * Archs are to support both the regs and ftrace_ops at the same time.
4249a1e2e31dSSteven Rostedt  * If they support ftrace_ops, it is assumed they support regs.
4250a1e2e31dSSteven Rostedt  * If call backs want to use regs, they must either check for regs
425106aeaaeaSMasami Hiramatsu  * being NULL, or CONFIG_DYNAMIC_FTRACE_WITH_REGS.
425206aeaaeaSMasami Hiramatsu  * Note, CONFIG_DYNAMIC_FTRACE_WITH_REGS expects a full regs to be saved.
4253a1e2e31dSSteven Rostedt  * An architecture can pass partial regs with ftrace_ops and still
4254a1e2e31dSSteven Rostedt  * set the ARCH_SUPPORT_FTARCE_OPS.
42552f5f6ad9SSteven Rostedt  */
42562f5f6ad9SSteven Rostedt #if ARCH_SUPPORTS_FTRACE_OPS
42572f5f6ad9SSteven Rostedt static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4258a1e2e31dSSteven Rostedt 				 struct ftrace_ops *op, struct pt_regs *regs)
42592f5f6ad9SSteven Rostedt {
4260a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, regs);
42612f5f6ad9SSteven Rostedt }
42622f5f6ad9SSteven Rostedt #else
42632f5f6ad9SSteven Rostedt static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip)
42642f5f6ad9SSteven Rostedt {
4265a1e2e31dSSteven Rostedt 	__ftrace_ops_list_func(ip, parent_ip, NULL, NULL);
42662f5f6ad9SSteven Rostedt }
42672f5f6ad9SSteven Rostedt #endif
42682f5f6ad9SSteven Rostedt 
4269e32d8956SSteven Rostedt static void clear_ftrace_swapper(void)
4270e32d8956SSteven Rostedt {
4271e32d8956SSteven Rostedt 	struct task_struct *p;
4272e32d8956SSteven Rostedt 	int cpu;
4273e32d8956SSteven Rostedt 
4274e32d8956SSteven Rostedt 	get_online_cpus();
4275e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4276e32d8956SSteven Rostedt 		p = idle_task(cpu);
4277e32d8956SSteven Rostedt 		clear_tsk_trace_trace(p);
4278e32d8956SSteven Rostedt 	}
4279e32d8956SSteven Rostedt 	put_online_cpus();
4280e32d8956SSteven Rostedt }
4281e32d8956SSteven Rostedt 
4282e32d8956SSteven Rostedt static void set_ftrace_swapper(void)
4283e32d8956SSteven Rostedt {
4284e32d8956SSteven Rostedt 	struct task_struct *p;
4285e32d8956SSteven Rostedt 	int cpu;
4286e32d8956SSteven Rostedt 
4287e32d8956SSteven Rostedt 	get_online_cpus();
4288e32d8956SSteven Rostedt 	for_each_online_cpu(cpu) {
4289e32d8956SSteven Rostedt 		p = idle_task(cpu);
4290e32d8956SSteven Rostedt 		set_tsk_trace_trace(p);
4291e32d8956SSteven Rostedt 	}
4292e32d8956SSteven Rostedt 	put_online_cpus();
4293e32d8956SSteven Rostedt }
4294e32d8956SSteven Rostedt 
4295e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid)
4296978f3a45SSteven Rostedt {
4297978f3a45SSteven Rostedt 	struct task_struct *p;
4298978f3a45SSteven Rostedt 
4299229c4ef8SOleg Nesterov 	rcu_read_lock();
4300e32d8956SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4301978f3a45SSteven Rostedt 		clear_tsk_trace_trace(p);
4302e32d8956SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4303229c4ef8SOleg Nesterov 	rcu_read_unlock();
4304229c4ef8SOleg Nesterov 
4305e32d8956SSteven Rostedt 	put_pid(pid);
4306978f3a45SSteven Rostedt }
4307978f3a45SSteven Rostedt 
4308e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid)
4309978f3a45SSteven Rostedt {
4310978f3a45SSteven Rostedt 	struct task_struct *p;
4311978f3a45SSteven Rostedt 
4312229c4ef8SOleg Nesterov 	rcu_read_lock();
4313978f3a45SSteven Rostedt 	do_each_pid_task(pid, PIDTYPE_PID, p) {
4314978f3a45SSteven Rostedt 		set_tsk_trace_trace(p);
4315978f3a45SSteven Rostedt 	} while_each_pid_task(pid, PIDTYPE_PID, p);
4316229c4ef8SOleg Nesterov 	rcu_read_unlock();
4317978f3a45SSteven Rostedt }
4318978f3a45SSteven Rostedt 
4319756d17eeS[email protected] static void clear_ftrace_pid_task(struct pid *pid)
4320e32d8956SSteven Rostedt {
4321756d17eeS[email protected] 	if (pid == ftrace_swapper_pid)
4322e32d8956SSteven Rostedt 		clear_ftrace_swapper();
4323e32d8956SSteven Rostedt 	else
4324756d17eeS[email protected] 		clear_ftrace_pid(pid);
4325e32d8956SSteven Rostedt }
4326e32d8956SSteven Rostedt 
4327e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid)
4328e32d8956SSteven Rostedt {
4329e32d8956SSteven Rostedt 	if (pid == ftrace_swapper_pid)
4330e32d8956SSteven Rostedt 		set_ftrace_swapper();
4331e32d8956SSteven Rostedt 	else
4332e32d8956SSteven Rostedt 		set_ftrace_pid(pid);
4333e32d8956SSteven Rostedt }
4334e32d8956SSteven Rostedt 
4335756d17eeS[email protected] static int ftrace_pid_add(int p)
4336756d17eeS[email protected] {
4337756d17eeS[email protected] 	struct pid *pid;
4338756d17eeS[email protected] 	struct ftrace_pid *fpid;
4339756d17eeS[email protected] 	int ret = -EINVAL;
4340756d17eeS[email protected] 
4341756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4342756d17eeS[email protected] 
4343756d17eeS[email protected] 	if (!p)
4344756d17eeS[email protected] 		pid = ftrace_swapper_pid;
4345756d17eeS[email protected] 	else
4346756d17eeS[email protected] 		pid = find_get_pid(p);
4347756d17eeS[email protected] 
4348756d17eeS[email protected] 	if (!pid)
4349756d17eeS[email protected] 		goto out;
4350756d17eeS[email protected] 
4351756d17eeS[email protected] 	ret = 0;
4352756d17eeS[email protected] 
4353756d17eeS[email protected] 	list_for_each_entry(fpid, &ftrace_pids, list)
4354756d17eeS[email protected] 		if (fpid->pid == pid)
4355756d17eeS[email protected] 			goto out_put;
4356756d17eeS[email protected] 
4357756d17eeS[email protected] 	ret = -ENOMEM;
4358756d17eeS[email protected] 
4359756d17eeS[email protected] 	fpid = kmalloc(sizeof(*fpid), GFP_KERNEL);
4360756d17eeS[email protected] 	if (!fpid)
4361756d17eeS[email protected] 		goto out_put;
4362756d17eeS[email protected] 
4363756d17eeS[email protected] 	list_add(&fpid->list, &ftrace_pids);
4364756d17eeS[email protected] 	fpid->pid = pid;
4365756d17eeS[email protected] 
4366756d17eeS[email protected] 	set_ftrace_pid_task(pid);
4367756d17eeS[email protected] 
4368756d17eeS[email protected] 	ftrace_update_pid_func();
4369756d17eeS[email protected] 	ftrace_startup_enable(0);
4370756d17eeS[email protected] 
4371756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4372756d17eeS[email protected] 	return 0;
4373756d17eeS[email protected] 
4374756d17eeS[email protected] out_put:
4375756d17eeS[email protected] 	if (pid != ftrace_swapper_pid)
4376756d17eeS[email protected] 		put_pid(pid);
4377756d17eeS[email protected] 
4378756d17eeS[email protected] out:
4379756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4380756d17eeS[email protected] 	return ret;
4381756d17eeS[email protected] }
4382756d17eeS[email protected] 
4383756d17eeS[email protected] static void ftrace_pid_reset(void)
4384756d17eeS[email protected] {
4385756d17eeS[email protected] 	struct ftrace_pid *fpid, *safe;
4386756d17eeS[email protected] 
4387756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4388756d17eeS[email protected] 	list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) {
4389756d17eeS[email protected] 		struct pid *pid = fpid->pid;
4390756d17eeS[email protected] 
4391756d17eeS[email protected] 		clear_ftrace_pid_task(pid);
4392756d17eeS[email protected] 
4393756d17eeS[email protected] 		list_del(&fpid->list);
4394756d17eeS[email protected] 		kfree(fpid);
4395756d17eeS[email protected] 	}
4396756d17eeS[email protected] 
4397756d17eeS[email protected] 	ftrace_update_pid_func();
4398756d17eeS[email protected] 	ftrace_startup_enable(0);
4399756d17eeS[email protected] 
4400756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4401756d17eeS[email protected] }
4402756d17eeS[email protected] 
4403756d17eeS[email protected] static void *fpid_start(struct seq_file *m, loff_t *pos)
4404756d17eeS[email protected] {
4405756d17eeS[email protected] 	mutex_lock(&ftrace_lock);
4406756d17eeS[email protected] 
4407756d17eeS[email protected] 	if (list_empty(&ftrace_pids) && (!*pos))
4408756d17eeS[email protected] 		return (void *) 1;
4409756d17eeS[email protected] 
4410756d17eeS[email protected] 	return seq_list_start(&ftrace_pids, *pos);
4411756d17eeS[email protected] }
4412756d17eeS[email protected] 
4413756d17eeS[email protected] static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
4414756d17eeS[email protected] {
4415756d17eeS[email protected] 	if (v == (void *)1)
4416756d17eeS[email protected] 		return NULL;
4417756d17eeS[email protected] 
4418756d17eeS[email protected] 	return seq_list_next(v, &ftrace_pids, pos);
4419756d17eeS[email protected] }
4420756d17eeS[email protected] 
4421756d17eeS[email protected] static void fpid_stop(struct seq_file *m, void *p)
4422756d17eeS[email protected] {
4423756d17eeS[email protected] 	mutex_unlock(&ftrace_lock);
4424756d17eeS[email protected] }
4425756d17eeS[email protected] 
4426756d17eeS[email protected] static int fpid_show(struct seq_file *m, void *v)
4427756d17eeS[email protected] {
4428756d17eeS[email protected] 	const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list);
4429756d17eeS[email protected] 
4430756d17eeS[email protected] 	if (v == (void *)1) {
4431756d17eeS[email protected] 		seq_printf(m, "no pid\n");
4432756d17eeS[email protected] 		return 0;
4433756d17eeS[email protected] 	}
4434756d17eeS[email protected] 
4435756d17eeS[email protected] 	if (fpid->pid == ftrace_swapper_pid)
4436756d17eeS[email protected] 		seq_printf(m, "swapper tasks\n");
4437756d17eeS[email protected] 	else
4438756d17eeS[email protected] 		seq_printf(m, "%u\n", pid_vnr(fpid->pid));
4439756d17eeS[email protected] 
4440756d17eeS[email protected] 	return 0;
4441756d17eeS[email protected] }
4442756d17eeS[email protected] 
4443756d17eeS[email protected] static const struct seq_operations ftrace_pid_sops = {
4444756d17eeS[email protected] 	.start = fpid_start,
4445756d17eeS[email protected] 	.next = fpid_next,
4446756d17eeS[email protected] 	.stop = fpid_stop,
4447756d17eeS[email protected] 	.show = fpid_show,
4448756d17eeS[email protected] };
4449756d17eeS[email protected] 
4450756d17eeS[email protected] static int
4451756d17eeS[email protected] ftrace_pid_open(struct inode *inode, struct file *file)
4452756d17eeS[email protected] {
4453756d17eeS[email protected] 	int ret = 0;
4454756d17eeS[email protected] 
4455756d17eeS[email protected] 	if ((file->f_mode & FMODE_WRITE) &&
4456756d17eeS[email protected] 	    (file->f_flags & O_TRUNC))
4457756d17eeS[email protected] 		ftrace_pid_reset();
4458756d17eeS[email protected] 
4459756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4460756d17eeS[email protected] 		ret = seq_open(file, &ftrace_pid_sops);
4461756d17eeS[email protected] 
4462756d17eeS[email protected] 	return ret;
4463756d17eeS[email protected] }
4464756d17eeS[email protected] 
4465df4fc315SSteven Rostedt static ssize_t
4466df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf,
4467df4fc315SSteven Rostedt 		   size_t cnt, loff_t *ppos)
4468df4fc315SSteven Rostedt {
4469457dc928SIngo Molnar 	char buf[64], *tmp;
4470df4fc315SSteven Rostedt 	long val;
4471df4fc315SSteven Rostedt 	int ret;
4472df4fc315SSteven Rostedt 
4473df4fc315SSteven Rostedt 	if (cnt >= sizeof(buf))
4474df4fc315SSteven Rostedt 		return -EINVAL;
4475df4fc315SSteven Rostedt 
4476df4fc315SSteven Rostedt 	if (copy_from_user(&buf, ubuf, cnt))
4477df4fc315SSteven Rostedt 		return -EFAULT;
4478df4fc315SSteven Rostedt 
4479df4fc315SSteven Rostedt 	buf[cnt] = 0;
4480df4fc315SSteven Rostedt 
4481756d17eeS[email protected] 	/*
4482756d17eeS[email protected] 	 * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid"
4483756d17eeS[email protected] 	 * to clean the filter quietly.
4484756d17eeS[email protected] 	 */
4485457dc928SIngo Molnar 	tmp = strstrip(buf);
4486457dc928SIngo Molnar 	if (strlen(tmp) == 0)
4487756d17eeS[email protected] 		return 1;
4488756d17eeS[email protected] 
4489bcd83ea6SDaniel Walter 	ret = kstrtol(tmp, 10, &val);
4490df4fc315SSteven Rostedt 	if (ret < 0)
4491df4fc315SSteven Rostedt 		return ret;
4492df4fc315SSteven Rostedt 
4493756d17eeS[email protected] 	ret = ftrace_pid_add(val);
4494978f3a45SSteven Rostedt 
4495756d17eeS[email protected] 	return ret ? ret : cnt;
4496e32d8956SSteven Rostedt }
4497978f3a45SSteven Rostedt 
4498756d17eeS[email protected] static int
4499756d17eeS[email protected] ftrace_pid_release(struct inode *inode, struct file *file)
4500756d17eeS[email protected] {
4501756d17eeS[email protected] 	if (file->f_mode & FMODE_READ)
4502756d17eeS[email protected] 		seq_release(inode, file);
4503978f3a45SSteven Rostedt 
4504756d17eeS[email protected] 	return 0;
4505df4fc315SSteven Rostedt }
4506df4fc315SSteven Rostedt 
45075e2336a0SSteven Rostedt static const struct file_operations ftrace_pid_fops = {
4508756d17eeS[email protected] 	.open		= ftrace_pid_open,
4509df4fc315SSteven Rostedt 	.write		= ftrace_pid_write,
4510756d17eeS[email protected] 	.read		= seq_read,
45116a76f8c0SNamhyung Kim 	.llseek		= ftrace_filter_lseek,
4512756d17eeS[email protected] 	.release	= ftrace_pid_release,
4513df4fc315SSteven Rostedt };
4514df4fc315SSteven Rostedt 
4515df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void)
4516df4fc315SSteven Rostedt {
4517df4fc315SSteven Rostedt 	struct dentry *d_tracer;
4518df4fc315SSteven Rostedt 
4519df4fc315SSteven Rostedt 	d_tracer = tracing_init_dentry();
4520df4fc315SSteven Rostedt 	if (!d_tracer)
4521df4fc315SSteven Rostedt 		return 0;
4522df4fc315SSteven Rostedt 
4523df4fc315SSteven Rostedt 	ftrace_init_dyn_debugfs(d_tracer);
4524df4fc315SSteven Rostedt 
45255452af66SFrederic Weisbecker 	trace_create_file("set_ftrace_pid", 0644, d_tracer,
4526df4fc315SSteven Rostedt 			    NULL, &ftrace_pid_fops);
4527493762fcSSteven Rostedt 
4528493762fcSSteven Rostedt 	ftrace_profile_debugfs(d_tracer);
4529493762fcSSteven Rostedt 
4530df4fc315SSteven Rostedt 	return 0;
4531df4fc315SSteven Rostedt }
4532df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs);
4533df4fc315SSteven Rostedt 
45343d083395SSteven Rostedt /**
453581adbdc0SSteven Rostedt  * ftrace_kill - kill ftrace
4536a2bb6a3dSSteven Rostedt  *
4537a2bb6a3dSSteven Rostedt  * This function should be used by panic code. It stops ftrace
4538a2bb6a3dSSteven Rostedt  * but in a not so nice way. If you need to simply kill ftrace
4539a2bb6a3dSSteven Rostedt  * from a non-atomic section, use ftrace_kill.
4540a2bb6a3dSSteven Rostedt  */
454181adbdc0SSteven Rostedt void ftrace_kill(void)
4542a2bb6a3dSSteven Rostedt {
4543a2bb6a3dSSteven Rostedt 	ftrace_disabled = 1;
4544a2bb6a3dSSteven Rostedt 	ftrace_enabled = 0;
4545a2bb6a3dSSteven Rostedt 	clear_ftrace_function();
4546a2bb6a3dSSteven Rostedt }
4547a2bb6a3dSSteven Rostedt 
4548a2bb6a3dSSteven Rostedt /**
4549e0a413f6SSteven Rostedt  * Test if ftrace is dead or not.
4550e0a413f6SSteven Rostedt  */
4551e0a413f6SSteven Rostedt int ftrace_is_dead(void)
4552e0a413f6SSteven Rostedt {
4553e0a413f6SSteven Rostedt 	return ftrace_disabled;
4554e0a413f6SSteven Rostedt }
4555e0a413f6SSteven Rostedt 
4556e0a413f6SSteven Rostedt /**
45573d083395SSteven Rostedt  * register_ftrace_function - register a function for profiling
45583d083395SSteven Rostedt  * @ops - ops structure that holds the function for profiling.
45593d083395SSteven Rostedt  *
45603d083395SSteven Rostedt  * Register a function to be called by all functions in the
45613d083395SSteven Rostedt  * kernel.
45623d083395SSteven Rostedt  *
45633d083395SSteven Rostedt  * Note: @ops->func and all the functions it calls must be labeled
45643d083395SSteven Rostedt  *       with "notrace", otherwise it will go into a
45653d083395SSteven Rostedt  *       recursive loop.
45663d083395SSteven Rostedt  */
45673d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops)
45683d083395SSteven Rostedt {
456945a4a237SSteven Rostedt 	int ret = -1;
45704eebcc81SSteven Rostedt 
4571*f04f24fbSMasami Hiramatsu 	ftrace_ops_init(ops);
4572*f04f24fbSMasami Hiramatsu 
4573e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4574e7d3737eSFrederic Weisbecker 
4575b0fc494fSSteven Rostedt 	ret = __register_ftrace_function(ops);
4576b848914cSSteven Rostedt 	if (!ret)
4577a1cd6173SSteven Rostedt 		ret = ftrace_startup(ops, 0);
4578b848914cSSteven Rostedt 
4579e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
45808d240dd8SBorislav Petkov 
4581b0fc494fSSteven Rostedt 	return ret;
45823d083395SSteven Rostedt }
4583cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(register_ftrace_function);
45843d083395SSteven Rostedt 
45853d083395SSteven Rostedt /**
458632632920SUwe Kleine-Koenig  * unregister_ftrace_function - unregister a function for profiling.
45873d083395SSteven Rostedt  * @ops - ops structure that holds the function to unregister
45883d083395SSteven Rostedt  *
45893d083395SSteven Rostedt  * Unregister a function that was added to be called by ftrace profiling.
45903d083395SSteven Rostedt  */
45913d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops)
45923d083395SSteven Rostedt {
45933d083395SSteven Rostedt 	int ret;
45943d083395SSteven Rostedt 
4595e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
45963d083395SSteven Rostedt 	ret = __unregister_ftrace_function(ops);
4597b848914cSSteven Rostedt 	if (!ret)
4598b848914cSSteven Rostedt 		ftrace_shutdown(ops, 0);
4599e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4600b0fc494fSSteven Rostedt 
4601b0fc494fSSteven Rostedt 	return ret;
4602b0fc494fSSteven Rostedt }
4603cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(unregister_ftrace_function);
4604b0fc494fSSteven Rostedt 
4605e309b41dSIngo Molnar int
4606b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write,
46078d65af78SAlexey Dobriyan 		     void __user *buffer, size_t *lenp,
4608b0fc494fSSteven Rostedt 		     loff_t *ppos)
4609b0fc494fSSteven Rostedt {
461045a4a237SSteven Rostedt 	int ret = -ENODEV;
46114eebcc81SSteven Rostedt 
4612e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4613b0fc494fSSteven Rostedt 
461445a4a237SSteven Rostedt 	if (unlikely(ftrace_disabled))
461545a4a237SSteven Rostedt 		goto out;
461645a4a237SSteven Rostedt 
46178d65af78SAlexey Dobriyan 	ret = proc_dointvec(table, write, buffer, lenp, ppos);
4618b0fc494fSSteven Rostedt 
4619a32c7765SLi Zefan 	if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
4620b0fc494fSSteven Rostedt 		goto out;
4621b0fc494fSSteven Rostedt 
4622a32c7765SLi Zefan 	last_ftrace_enabled = !!ftrace_enabled;
4623b0fc494fSSteven Rostedt 
4624b0fc494fSSteven Rostedt 	if (ftrace_enabled) {
4625b0fc494fSSteven Rostedt 
4626b0fc494fSSteven Rostedt 		ftrace_startup_sysctl();
4627b0fc494fSSteven Rostedt 
4628b0fc494fSSteven Rostedt 		/* we are starting ftrace again */
46295000c418SJan Kiszka 		if (ftrace_ops_list != &ftrace_list_end)
46305000c418SJan Kiszka 			update_ftrace_function();
4631b0fc494fSSteven Rostedt 
4632b0fc494fSSteven Rostedt 	} else {
4633b0fc494fSSteven Rostedt 		/* stopping ftrace calls (just send to ftrace_stub) */
4634b0fc494fSSteven Rostedt 		ftrace_trace_function = ftrace_stub;
4635b0fc494fSSteven Rostedt 
4636b0fc494fSSteven Rostedt 		ftrace_shutdown_sysctl();
4637b0fc494fSSteven Rostedt 	}
4638b0fc494fSSteven Rostedt 
4639b0fc494fSSteven Rostedt  out:
4640e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
46413d083395SSteven Rostedt 	return ret;
464216444a8aSArnaldo Carvalho de Melo }
4643f17845e5SIngo Molnar 
4644fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER
4645e7d3737eSFrederic Weisbecker 
4646597af815SSteven Rostedt static int ftrace_graph_active;
46474a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier;
4648f201ae23SFrederic Weisbecker 
4649e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
4650e49dc19cSSteven Rostedt {
4651e49dc19cSSteven Rostedt 	return 0;
4652e49dc19cSSteven Rostedt }
4653e49dc19cSSteven Rostedt 
4654287b6e68SFrederic Weisbecker /* The callbacks that hook a function */
4655287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return =
4656287b6e68SFrederic Weisbecker 			(trace_func_graph_ret_t)ftrace_stub;
4657e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
4658f201ae23SFrederic Weisbecker 
4659f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
4660f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
4661f201ae23SFrederic Weisbecker {
4662f201ae23SFrederic Weisbecker 	int i;
4663f201ae23SFrederic Weisbecker 	int ret = 0;
4664f201ae23SFrederic Weisbecker 	unsigned long flags;
4665f201ae23SFrederic Weisbecker 	int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE;
4666f201ae23SFrederic Weisbecker 	struct task_struct *g, *t;
4667f201ae23SFrederic Weisbecker 
4668f201ae23SFrederic Weisbecker 	for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
4669f201ae23SFrederic Weisbecker 		ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
4670f201ae23SFrederic Weisbecker 					* sizeof(struct ftrace_ret_stack),
4671f201ae23SFrederic Weisbecker 					GFP_KERNEL);
4672f201ae23SFrederic Weisbecker 		if (!ret_stack_list[i]) {
4673f201ae23SFrederic Weisbecker 			start = 0;
4674f201ae23SFrederic Weisbecker 			end = i;
4675f201ae23SFrederic Weisbecker 			ret = -ENOMEM;
4676f201ae23SFrederic Weisbecker 			goto free;
4677f201ae23SFrederic Weisbecker 		}
4678f201ae23SFrederic Weisbecker 	}
4679f201ae23SFrederic Weisbecker 
4680f201ae23SFrederic Weisbecker 	read_lock_irqsave(&tasklist_lock, flags);
4681f201ae23SFrederic Weisbecker 	do_each_thread(g, t) {
4682f201ae23SFrederic Weisbecker 		if (start == end) {
4683f201ae23SFrederic Weisbecker 			ret = -EAGAIN;
4684f201ae23SFrederic Weisbecker 			goto unlock;
4685f201ae23SFrederic Weisbecker 		}
4686f201ae23SFrederic Weisbecker 
4687f201ae23SFrederic Weisbecker 		if (t->ret_stack == NULL) {
4688380c4b14SFrederic Weisbecker 			atomic_set(&t->tracing_graph_pause, 0);
4689f201ae23SFrederic Weisbecker 			atomic_set(&t->trace_overrun, 0);
469026c01624SSteven Rostedt 			t->curr_ret_stack = -1;
469126c01624SSteven Rostedt 			/* Make sure the tasks see the -1 first: */
469226c01624SSteven Rostedt 			smp_wmb();
469326c01624SSteven Rostedt 			t->ret_stack = ret_stack_list[start++];
4694f201ae23SFrederic Weisbecker 		}
4695f201ae23SFrederic Weisbecker 	} while_each_thread(g, t);
4696f201ae23SFrederic Weisbecker 
4697f201ae23SFrederic Weisbecker unlock:
4698f201ae23SFrederic Weisbecker 	read_unlock_irqrestore(&tasklist_lock, flags);
4699f201ae23SFrederic Weisbecker free:
4700f201ae23SFrederic Weisbecker 	for (i = start; i < end; i++)
4701f201ae23SFrederic Weisbecker 		kfree(ret_stack_list[i]);
4702f201ae23SFrederic Weisbecker 	return ret;
4703f201ae23SFrederic Weisbecker }
4704f201ae23SFrederic Weisbecker 
47058aef2d28SSteven Rostedt static void
470638516ab5SSteven Rostedt ftrace_graph_probe_sched_switch(void *ignore,
470738516ab5SSteven Rostedt 			struct task_struct *prev, struct task_struct *next)
47088aef2d28SSteven Rostedt {
47098aef2d28SSteven Rostedt 	unsigned long long timestamp;
47108aef2d28SSteven Rostedt 	int index;
47118aef2d28SSteven Rostedt 
4712be6f164aSSteven Rostedt 	/*
4713be6f164aSSteven Rostedt 	 * Does the user want to count the time a function was asleep.
4714be6f164aSSteven Rostedt 	 * If so, do not update the time stamps.
4715be6f164aSSteven Rostedt 	 */
4716be6f164aSSteven Rostedt 	if (trace_flags & TRACE_ITER_SLEEP_TIME)
4717be6f164aSSteven Rostedt 		return;
4718be6f164aSSteven Rostedt 
47198aef2d28SSteven Rostedt 	timestamp = trace_clock_local();
47208aef2d28SSteven Rostedt 
47218aef2d28SSteven Rostedt 	prev->ftrace_timestamp = timestamp;
47228aef2d28SSteven Rostedt 
47238aef2d28SSteven Rostedt 	/* only process tasks that we timestamped */
47248aef2d28SSteven Rostedt 	if (!next->ftrace_timestamp)
47258aef2d28SSteven Rostedt 		return;
47268aef2d28SSteven Rostedt 
47278aef2d28SSteven Rostedt 	/*
47288aef2d28SSteven Rostedt 	 * Update all the counters in next to make up for the
47298aef2d28SSteven Rostedt 	 * time next was sleeping.
47308aef2d28SSteven Rostedt 	 */
47318aef2d28SSteven Rostedt 	timestamp -= next->ftrace_timestamp;
47328aef2d28SSteven Rostedt 
47338aef2d28SSteven Rostedt 	for (index = next->curr_ret_stack; index >= 0; index--)
47348aef2d28SSteven Rostedt 		next->ret_stack[index].calltime += timestamp;
47358aef2d28SSteven Rostedt }
47368aef2d28SSteven Rostedt 
4737f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */
4738fb52607aSFrederic Weisbecker static int start_graph_tracing(void)
4739f201ae23SFrederic Weisbecker {
4740f201ae23SFrederic Weisbecker 	struct ftrace_ret_stack **ret_stack_list;
47415b058bcdSFrederic Weisbecker 	int ret, cpu;
4742f201ae23SFrederic Weisbecker 
4743f201ae23SFrederic Weisbecker 	ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
4744f201ae23SFrederic Weisbecker 				sizeof(struct ftrace_ret_stack *),
4745f201ae23SFrederic Weisbecker 				GFP_KERNEL);
4746f201ae23SFrederic Weisbecker 
4747f201ae23SFrederic Weisbecker 	if (!ret_stack_list)
4748f201ae23SFrederic Weisbecker 		return -ENOMEM;
4749f201ae23SFrederic Weisbecker 
47505b058bcdSFrederic Weisbecker 	/* The cpu_boot init_task->ret_stack will never be freed */
4751179c498aSSteven Rostedt 	for_each_online_cpu(cpu) {
4752179c498aSSteven Rostedt 		if (!idle_task(cpu)->ret_stack)
4753868baf07SSteven Rostedt 			ftrace_graph_init_idle_task(idle_task(cpu), cpu);
4754179c498aSSteven Rostedt 	}
47555b058bcdSFrederic Weisbecker 
4756f201ae23SFrederic Weisbecker 	do {
4757f201ae23SFrederic Weisbecker 		ret = alloc_retstack_tasklist(ret_stack_list);
4758f201ae23SFrederic Weisbecker 	} while (ret == -EAGAIN);
4759f201ae23SFrederic Weisbecker 
47608aef2d28SSteven Rostedt 	if (!ret) {
476138516ab5SSteven Rostedt 		ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
47628aef2d28SSteven Rostedt 		if (ret)
47638aef2d28SSteven Rostedt 			pr_info("ftrace_graph: Couldn't activate tracepoint"
47648aef2d28SSteven Rostedt 				" probe to kernel_sched_switch\n");
47658aef2d28SSteven Rostedt 	}
47668aef2d28SSteven Rostedt 
4767f201ae23SFrederic Weisbecker 	kfree(ret_stack_list);
4768f201ae23SFrederic Weisbecker 	return ret;
4769f201ae23SFrederic Weisbecker }
4770f201ae23SFrederic Weisbecker 
47714a2b8ddaSFrederic Weisbecker /*
47724a2b8ddaSFrederic Weisbecker  * Hibernation protection.
47734a2b8ddaSFrederic Weisbecker  * The state of the current task is too much unstable during
47744a2b8ddaSFrederic Weisbecker  * suspend/restore to disk. We want to protect against that.
47754a2b8ddaSFrederic Weisbecker  */
47764a2b8ddaSFrederic Weisbecker static int
47774a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
47784a2b8ddaSFrederic Weisbecker 							void *unused)
47794a2b8ddaSFrederic Weisbecker {
47804a2b8ddaSFrederic Weisbecker 	switch (state) {
47814a2b8ddaSFrederic Weisbecker 	case PM_HIBERNATION_PREPARE:
47824a2b8ddaSFrederic Weisbecker 		pause_graph_tracing();
47834a2b8ddaSFrederic Weisbecker 		break;
47844a2b8ddaSFrederic Weisbecker 
47854a2b8ddaSFrederic Weisbecker 	case PM_POST_HIBERNATION:
47864a2b8ddaSFrederic Weisbecker 		unpause_graph_tracing();
47874a2b8ddaSFrederic Weisbecker 		break;
47884a2b8ddaSFrederic Weisbecker 	}
47894a2b8ddaSFrederic Weisbecker 	return NOTIFY_DONE;
47904a2b8ddaSFrederic Weisbecker }
47914a2b8ddaSFrederic Weisbecker 
4792287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc,
4793287b6e68SFrederic Weisbecker 			trace_func_graph_ent_t entryfunc)
479415e6cb36SFrederic Weisbecker {
4795e7d3737eSFrederic Weisbecker 	int ret = 0;
4796e7d3737eSFrederic Weisbecker 
4797e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4798e7d3737eSFrederic Weisbecker 
479905ce5818SSteven Rostedt 	/* we currently allow only one tracer registered at a time */
4800597af815SSteven Rostedt 	if (ftrace_graph_active) {
480105ce5818SSteven Rostedt 		ret = -EBUSY;
480205ce5818SSteven Rostedt 		goto out;
480305ce5818SSteven Rostedt 	}
480405ce5818SSteven Rostedt 
48054a2b8ddaSFrederic Weisbecker 	ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call;
48064a2b8ddaSFrederic Weisbecker 	register_pm_notifier(&ftrace_suspend_notifier);
48074a2b8ddaSFrederic Weisbecker 
4808597af815SSteven Rostedt 	ftrace_graph_active++;
4809fb52607aSFrederic Weisbecker 	ret = start_graph_tracing();
4810f201ae23SFrederic Weisbecker 	if (ret) {
4811597af815SSteven Rostedt 		ftrace_graph_active--;
4812f201ae23SFrederic Weisbecker 		goto out;
4813f201ae23SFrederic Weisbecker 	}
4814e53a6319SSteven Rostedt 
4815287b6e68SFrederic Weisbecker 	ftrace_graph_return = retfunc;
4816287b6e68SFrederic Weisbecker 	ftrace_graph_entry = entryfunc;
4817e53a6319SSteven Rostedt 
4818a1cd6173SSteven Rostedt 	ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
4819e7d3737eSFrederic Weisbecker 
4820e7d3737eSFrederic Weisbecker out:
4821e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
4822e7d3737eSFrederic Weisbecker 	return ret;
482315e6cb36SFrederic Weisbecker }
482415e6cb36SFrederic Weisbecker 
4825fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void)
482615e6cb36SFrederic Weisbecker {
4827e6ea44e9SSteven Rostedt 	mutex_lock(&ftrace_lock);
4828e7d3737eSFrederic Weisbecker 
4829597af815SSteven Rostedt 	if (unlikely(!ftrace_graph_active))
48302aad1b76SSteven Rostedt 		goto out;
48312aad1b76SSteven Rostedt 
4832597af815SSteven Rostedt 	ftrace_graph_active--;
4833287b6e68SFrederic Weisbecker 	ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
4834e49dc19cSSteven Rostedt 	ftrace_graph_entry = ftrace_graph_entry_stub;
4835bd69c30bSSteven Rostedt 	ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
48364a2b8ddaSFrederic Weisbecker 	unregister_pm_notifier(&ftrace_suspend_notifier);
483738516ab5SSteven Rostedt 	unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
4838e7d3737eSFrederic Weisbecker 
48392aad1b76SSteven Rostedt  out:
4840e6ea44e9SSteven Rostedt 	mutex_unlock(&ftrace_lock);
484115e6cb36SFrederic Weisbecker }
4842f201ae23SFrederic Weisbecker 
4843868baf07SSteven Rostedt static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
4844868baf07SSteven Rostedt 
4845868baf07SSteven Rostedt static void
4846868baf07SSteven Rostedt graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
4847868baf07SSteven Rostedt {
4848868baf07SSteven Rostedt 	atomic_set(&t->tracing_graph_pause, 0);
4849868baf07SSteven Rostedt 	atomic_set(&t->trace_overrun, 0);
4850868baf07SSteven Rostedt 	t->ftrace_timestamp = 0;
485125985edcSLucas De Marchi 	/* make curr_ret_stack visible before we add the ret_stack */
4852868baf07SSteven Rostedt 	smp_wmb();
4853868baf07SSteven Rostedt 	t->ret_stack = ret_stack;
4854868baf07SSteven Rostedt }
4855868baf07SSteven Rostedt 
4856868baf07SSteven Rostedt /*
4857868baf07SSteven Rostedt  * Allocate a return stack for the idle task. May be the first
4858868baf07SSteven Rostedt  * time through, or it may be done by CPU hotplug online.
4859868baf07SSteven Rostedt  */
4860868baf07SSteven Rostedt void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
4861868baf07SSteven Rostedt {
4862868baf07SSteven Rostedt 	t->curr_ret_stack = -1;
4863868baf07SSteven Rostedt 	/*
4864868baf07SSteven Rostedt 	 * The idle task has no parent, it either has its own
4865868baf07SSteven Rostedt 	 * stack or no stack at all.
4866868baf07SSteven Rostedt 	 */
4867868baf07SSteven Rostedt 	if (t->ret_stack)
4868868baf07SSteven Rostedt 		WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
4869868baf07SSteven Rostedt 
4870868baf07SSteven Rostedt 	if (ftrace_graph_active) {
4871868baf07SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
4872868baf07SSteven Rostedt 
4873868baf07SSteven Rostedt 		ret_stack = per_cpu(idle_ret_stack, cpu);
4874868baf07SSteven Rostedt 		if (!ret_stack) {
4875868baf07SSteven Rostedt 			ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4876868baf07SSteven Rostedt 					    * sizeof(struct ftrace_ret_stack),
4877868baf07SSteven Rostedt 					    GFP_KERNEL);
4878868baf07SSteven Rostedt 			if (!ret_stack)
4879868baf07SSteven Rostedt 				return;
4880868baf07SSteven Rostedt 			per_cpu(idle_ret_stack, cpu) = ret_stack;
4881868baf07SSteven Rostedt 		}
4882868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
4883868baf07SSteven Rostedt 	}
4884868baf07SSteven Rostedt }
4885868baf07SSteven Rostedt 
4886f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */
4887fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t)
4888f201ae23SFrederic Weisbecker {
488984047e36SSteven Rostedt 	/* Make sure we do not use the parent ret_stack */
489084047e36SSteven Rostedt 	t->ret_stack = NULL;
4891ea14eb71SSteven Rostedt 	t->curr_ret_stack = -1;
489284047e36SSteven Rostedt 
4893597af815SSteven Rostedt 	if (ftrace_graph_active) {
489482310a32SSteven Rostedt 		struct ftrace_ret_stack *ret_stack;
489582310a32SSteven Rostedt 
489682310a32SSteven Rostedt 		ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
4897f201ae23SFrederic Weisbecker 				* sizeof(struct ftrace_ret_stack),
4898f201ae23SFrederic Weisbecker 				GFP_KERNEL);
489982310a32SSteven Rostedt 		if (!ret_stack)
4900f201ae23SFrederic Weisbecker 			return;
4901868baf07SSteven Rostedt 		graph_init_task(t, ret_stack);
490284047e36SSteven Rostedt 	}
4903f201ae23SFrederic Weisbecker }
4904f201ae23SFrederic Weisbecker 
4905fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t)
4906f201ae23SFrederic Weisbecker {
4907eae849caSFrederic Weisbecker 	struct ftrace_ret_stack	*ret_stack = t->ret_stack;
4908eae849caSFrederic Weisbecker 
4909f201ae23SFrederic Weisbecker 	t->ret_stack = NULL;
4910eae849caSFrederic Weisbecker 	/* NULL must become visible to IRQs before we free it: */
4911eae849caSFrederic Weisbecker 	barrier();
4912eae849caSFrederic Weisbecker 
4913eae849caSFrederic Weisbecker 	kfree(ret_stack);
4914f201ae23SFrederic Weisbecker }
491514a866c5SSteven Rostedt 
491614a866c5SSteven Rostedt void ftrace_graph_stop(void)
491714a866c5SSteven Rostedt {
491814a866c5SSteven Rostedt 	ftrace_stop();
491914a866c5SSteven Rostedt }
492015e6cb36SFrederic Weisbecker #endif
4921