116444a8aSArnaldo Carvalho de Melo /* 216444a8aSArnaldo Carvalho de Melo * Infrastructure for profiling code inserted by 'gcc -pg'. 316444a8aSArnaldo Carvalho de Melo * 416444a8aSArnaldo Carvalho de Melo * Copyright (C) 2007-2008 Steven Rostedt <[email protected]> 516444a8aSArnaldo Carvalho de Melo * Copyright (C) 2004-2008 Ingo Molnar <[email protected]> 616444a8aSArnaldo Carvalho de Melo * 716444a8aSArnaldo Carvalho de Melo * Originally ported from the -rt patch by: 816444a8aSArnaldo Carvalho de Melo * Copyright (C) 2007 Arnaldo Carvalho de Melo <[email protected]> 916444a8aSArnaldo Carvalho de Melo * 1016444a8aSArnaldo Carvalho de Melo * Based on code in the latency_tracer, that is: 1116444a8aSArnaldo Carvalho de Melo * 1216444a8aSArnaldo Carvalho de Melo * Copyright (C) 2004-2006 Ingo Molnar 1316444a8aSArnaldo Carvalho de Melo * Copyright (C) 2004 William Lee Irwin III 1416444a8aSArnaldo Carvalho de Melo */ 1516444a8aSArnaldo Carvalho de Melo 163d083395SSteven Rostedt #include <linux/stop_machine.h> 173d083395SSteven Rostedt #include <linux/clocksource.h> 183d083395SSteven Rostedt #include <linux/kallsyms.h> 195072c59fSSteven Rostedt #include <linux/seq_file.h> 204a2b8ddaSFrederic Weisbecker #include <linux/suspend.h> 215072c59fSSteven Rostedt #include <linux/debugfs.h> 223d083395SSteven Rostedt #include <linux/hardirq.h> 232d8b820bSIngo Molnar #include <linux/kthread.h> 245072c59fSSteven Rostedt #include <linux/uaccess.h> 252d8b820bSIngo Molnar #include <linux/ftrace.h> 26b0fc494fSSteven Rostedt #include <linux/sysctl.h> 275a0e3ad6STejun Heo #include <linux/slab.h> 285072c59fSSteven Rostedt #include <linux/ctype.h> 293d083395SSteven Rostedt #include <linux/list.h> 3059df055fSSteven Rostedt #include <linux/hash.h> 313f379b03SPaul E. McKenney #include <linux/rcupdate.h> 3216444a8aSArnaldo Carvalho de Melo 33ad8d75ffSSteven Rostedt #include <trace/events/sched.h> 348aef2d28SSteven Rostedt 35395a59d0SAbhishek Sagar #include <asm/ftrace.h> 362af15d6aSSteven Rostedt #include <asm/setup.h> 37395a59d0SAbhishek Sagar 380706f1c4SSteven Rostedt #include "trace_output.h" 39bac429f0SSteven Rostedt #include "trace_stat.h" 403d083395SSteven Rostedt 416912896eSSteven Rostedt #define FTRACE_WARN_ON(cond) \ 420778d9adSSteven Rostedt ({ \ 430778d9adSSteven Rostedt int ___r = cond; \ 440778d9adSSteven Rostedt if (WARN_ON(___r)) \ 456912896eSSteven Rostedt ftrace_kill(); \ 460778d9adSSteven Rostedt ___r; \ 470778d9adSSteven Rostedt }) 486912896eSSteven Rostedt 496912896eSSteven Rostedt #define FTRACE_WARN_ON_ONCE(cond) \ 500778d9adSSteven Rostedt ({ \ 510778d9adSSteven Rostedt int ___r = cond; \ 520778d9adSSteven Rostedt if (WARN_ON_ONCE(___r)) \ 536912896eSSteven Rostedt ftrace_kill(); \ 540778d9adSSteven Rostedt ___r; \ 550778d9adSSteven Rostedt }) 566912896eSSteven Rostedt 578fc0c701SSteven Rostedt /* hash bits for specific function selection */ 588fc0c701SSteven Rostedt #define FTRACE_HASH_BITS 7 598fc0c701SSteven Rostedt #define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS) 6033dc9b12SSteven Rostedt #define FTRACE_HASH_DEFAULT_BITS 10 6133dc9b12SSteven Rostedt #define FTRACE_HASH_MAX_BITS 12 628fc0c701SSteven Rostedt 634eebcc81SSteven Rostedt /* ftrace_enabled is a method to turn ftrace on or off */ 644eebcc81SSteven Rostedt int ftrace_enabled __read_mostly; 65d61f82d0SSteven Rostedt static int last_ftrace_enabled; 66b0fc494fSSteven Rostedt 6760a7ecf4SSteven Rostedt /* Quick disabling of function tracer. */ 6860a7ecf4SSteven Rostedt int function_trace_stop; 6960a7ecf4SSteven Rostedt 70756d17eeS[email protected] /* List for set_ftrace_pid's pids. */ 71756d17eeS[email protected] LIST_HEAD(ftrace_pids); 72756d17eeS[email protected] struct ftrace_pid { 73756d17eeS[email protected] struct list_head list; 74756d17eeS[email protected] struct pid *pid; 75756d17eeS[email protected] }; 76756d17eeS[email protected] 774eebcc81SSteven Rostedt /* 784eebcc81SSteven Rostedt * ftrace_disabled is set when an anomaly is discovered. 794eebcc81SSteven Rostedt * ftrace_disabled is much stronger than ftrace_enabled. 804eebcc81SSteven Rostedt */ 814eebcc81SSteven Rostedt static int ftrace_disabled __read_mostly; 824eebcc81SSteven Rostedt 8352baf119SSteven Rostedt static DEFINE_MUTEX(ftrace_lock); 84b0fc494fSSteven Rostedt 8516444a8aSArnaldo Carvalho de Melo static struct ftrace_ops ftrace_list_end __read_mostly = 8616444a8aSArnaldo Carvalho de Melo { 8716444a8aSArnaldo Carvalho de Melo .func = ftrace_stub, 8816444a8aSArnaldo Carvalho de Melo }; 8916444a8aSArnaldo Carvalho de Melo 9016444a8aSArnaldo Carvalho de Melo static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end; 9116444a8aSArnaldo Carvalho de Melo ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; 9260a7ecf4SSteven Rostedt ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub; 93df4fc315SSteven Rostedt ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; 942b499381SSteven Rostedt static struct ftrace_ops global_ops; 9516444a8aSArnaldo Carvalho de Melo 963f379b03SPaul E. McKenney /* 973f379b03SPaul E. McKenney * Traverse the ftrace_list, invoking all entries. The reason that we 983f379b03SPaul E. McKenney * can use rcu_dereference_raw() is that elements removed from this list 993f379b03SPaul E. McKenney * are simply leaked, so there is no need to interact with a grace-period 1003f379b03SPaul E. McKenney * mechanism. The rcu_dereference_raw() calls are needed to handle 1013f379b03SPaul E. McKenney * concurrent insertions into the ftrace_list. 1023f379b03SPaul E. McKenney * 1033f379b03SPaul E. McKenney * Silly Alpha and silly pointer-speculation compiler optimizations! 1043f379b03SPaul E. McKenney */ 105f2252935SIngo Molnar static void ftrace_list_func(unsigned long ip, unsigned long parent_ip) 10616444a8aSArnaldo Carvalho de Melo { 1073f379b03SPaul E. McKenney struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/ 10816444a8aSArnaldo Carvalho de Melo 10916444a8aSArnaldo Carvalho de Melo while (op != &ftrace_list_end) { 11016444a8aSArnaldo Carvalho de Melo op->func(ip, parent_ip); 1113f379b03SPaul E. McKenney op = rcu_dereference_raw(op->next); /*see above*/ 11216444a8aSArnaldo Carvalho de Melo }; 11316444a8aSArnaldo Carvalho de Melo } 11416444a8aSArnaldo Carvalho de Melo 115df4fc315SSteven Rostedt static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip) 116df4fc315SSteven Rostedt { 1170ef8cde5SSteven Rostedt if (!test_tsk_trace_trace(current)) 118df4fc315SSteven Rostedt return; 119df4fc315SSteven Rostedt 120df4fc315SSteven Rostedt ftrace_pid_function(ip, parent_ip); 121df4fc315SSteven Rostedt } 122df4fc315SSteven Rostedt 123df4fc315SSteven Rostedt static void set_ftrace_pid_function(ftrace_func_t func) 124df4fc315SSteven Rostedt { 125df4fc315SSteven Rostedt /* do not set ftrace_pid_function to itself! */ 126df4fc315SSteven Rostedt if (func != ftrace_pid_func) 127df4fc315SSteven Rostedt ftrace_pid_function = func; 128df4fc315SSteven Rostedt } 129df4fc315SSteven Rostedt 13016444a8aSArnaldo Carvalho de Melo /** 1313d083395SSteven Rostedt * clear_ftrace_function - reset the ftrace function 13216444a8aSArnaldo Carvalho de Melo * 1333d083395SSteven Rostedt * This NULLs the ftrace function and in essence stops 1343d083395SSteven Rostedt * tracing. There may be lag 13516444a8aSArnaldo Carvalho de Melo */ 1363d083395SSteven Rostedt void clear_ftrace_function(void) 13716444a8aSArnaldo Carvalho de Melo { 1383d083395SSteven Rostedt ftrace_trace_function = ftrace_stub; 13960a7ecf4SSteven Rostedt __ftrace_trace_function = ftrace_stub; 140df4fc315SSteven Rostedt ftrace_pid_function = ftrace_stub; 1413d083395SSteven Rostedt } 14216444a8aSArnaldo Carvalho de Melo 14360a7ecf4SSteven Rostedt #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 14460a7ecf4SSteven Rostedt /* 14560a7ecf4SSteven Rostedt * For those archs that do not test ftrace_trace_stop in their 14660a7ecf4SSteven Rostedt * mcount call site, we need to do it from C. 14760a7ecf4SSteven Rostedt */ 14860a7ecf4SSteven Rostedt static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip) 14960a7ecf4SSteven Rostedt { 15060a7ecf4SSteven Rostedt if (function_trace_stop) 15160a7ecf4SSteven Rostedt return; 15260a7ecf4SSteven Rostedt 15360a7ecf4SSteven Rostedt __ftrace_trace_function(ip, parent_ip); 15460a7ecf4SSteven Rostedt } 15560a7ecf4SSteven Rostedt #endif 15660a7ecf4SSteven Rostedt 1572b499381SSteven Rostedt static void update_global_ops(void) 158491d0dcfSSteven Rostedt { 159491d0dcfSSteven Rostedt ftrace_func_t func; 160491d0dcfSSteven Rostedt 161491d0dcfSSteven Rostedt /* 162491d0dcfSSteven Rostedt * If there's only one function registered, then call that 163491d0dcfSSteven Rostedt * function directly. Otherwise, we need to iterate over the 164491d0dcfSSteven Rostedt * registered callers. 165491d0dcfSSteven Rostedt */ 166491d0dcfSSteven Rostedt if (ftrace_list == &ftrace_list_end || 167491d0dcfSSteven Rostedt ftrace_list->next == &ftrace_list_end) 168491d0dcfSSteven Rostedt func = ftrace_list->func; 169491d0dcfSSteven Rostedt else 170491d0dcfSSteven Rostedt func = ftrace_list_func; 171491d0dcfSSteven Rostedt 172491d0dcfSSteven Rostedt /* If we filter on pids, update to use the pid function */ 173491d0dcfSSteven Rostedt if (!list_empty(&ftrace_pids)) { 174491d0dcfSSteven Rostedt set_ftrace_pid_function(func); 175491d0dcfSSteven Rostedt func = ftrace_pid_func; 176491d0dcfSSteven Rostedt } 1772b499381SSteven Rostedt 1782b499381SSteven Rostedt global_ops.func = func; 1792b499381SSteven Rostedt } 1802b499381SSteven Rostedt 1812b499381SSteven Rostedt static void update_ftrace_function(void) 1822b499381SSteven Rostedt { 1832b499381SSteven Rostedt ftrace_func_t func; 1842b499381SSteven Rostedt 1852b499381SSteven Rostedt update_global_ops(); 1862b499381SSteven Rostedt 1872b499381SSteven Rostedt func = global_ops.func; 1882b499381SSteven Rostedt 189491d0dcfSSteven Rostedt #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 190491d0dcfSSteven Rostedt ftrace_trace_function = func; 191491d0dcfSSteven Rostedt #else 192491d0dcfSSteven Rostedt __ftrace_trace_function = func; 193491d0dcfSSteven Rostedt ftrace_trace_function = ftrace_test_stop_func; 194491d0dcfSSteven Rostedt #endif 195491d0dcfSSteven Rostedt } 196491d0dcfSSteven Rostedt 1972b499381SSteven Rostedt static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops) 1983d083395SSteven Rostedt { 1992b499381SSteven Rostedt ops->next = *list; 20016444a8aSArnaldo Carvalho de Melo /* 20116444a8aSArnaldo Carvalho de Melo * We are entering ops into the ftrace_list but another 20216444a8aSArnaldo Carvalho de Melo * CPU might be walking that list. We need to make sure 20316444a8aSArnaldo Carvalho de Melo * the ops->next pointer is valid before another CPU sees 20416444a8aSArnaldo Carvalho de Melo * the ops pointer included into the ftrace_list. 20516444a8aSArnaldo Carvalho de Melo */ 2062b499381SSteven Rostedt rcu_assign_pointer(*list, ops); 2072b499381SSteven Rostedt } 2083d083395SSteven Rostedt 2092b499381SSteven Rostedt static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops) 2102b499381SSteven Rostedt { 2112b499381SSteven Rostedt struct ftrace_ops **p; 2122b499381SSteven Rostedt 2132b499381SSteven Rostedt /* 2142b499381SSteven Rostedt * If we are removing the last function, then simply point 2152b499381SSteven Rostedt * to the ftrace_stub. 2162b499381SSteven Rostedt */ 2172b499381SSteven Rostedt if (*list == ops && ops->next == &ftrace_list_end) { 2182b499381SSteven Rostedt *list = &ftrace_list_end; 2192b499381SSteven Rostedt return 0; 2202b499381SSteven Rostedt } 2212b499381SSteven Rostedt 2222b499381SSteven Rostedt for (p = list; *p != &ftrace_list_end; p = &(*p)->next) 2232b499381SSteven Rostedt if (*p == ops) 2242b499381SSteven Rostedt break; 2252b499381SSteven Rostedt 2262b499381SSteven Rostedt if (*p != ops) 2272b499381SSteven Rostedt return -1; 2282b499381SSteven Rostedt 2292b499381SSteven Rostedt *p = (*p)->next; 2302b499381SSteven Rostedt return 0; 2312b499381SSteven Rostedt } 2322b499381SSteven Rostedt 2332b499381SSteven Rostedt static int __register_ftrace_function(struct ftrace_ops *ops) 2342b499381SSteven Rostedt { 2352b499381SSteven Rostedt if (ftrace_disabled) 2362b499381SSteven Rostedt return -ENODEV; 2372b499381SSteven Rostedt 2382b499381SSteven Rostedt if (FTRACE_WARN_ON(ops == &global_ops)) 2392b499381SSteven Rostedt return -EINVAL; 2402b499381SSteven Rostedt 2412b499381SSteven Rostedt add_ftrace_ops(&ftrace_list, ops); 242491d0dcfSSteven Rostedt if (ftrace_enabled) 243491d0dcfSSteven Rostedt update_ftrace_function(); 2443d083395SSteven Rostedt 24516444a8aSArnaldo Carvalho de Melo return 0; 24616444a8aSArnaldo Carvalho de Melo } 24716444a8aSArnaldo Carvalho de Melo 248e309b41dSIngo Molnar static int __unregister_ftrace_function(struct ftrace_ops *ops) 24916444a8aSArnaldo Carvalho de Melo { 2502b499381SSteven Rostedt int ret; 25116444a8aSArnaldo Carvalho de Melo 2522b499381SSteven Rostedt if (ftrace_disabled) 2532b499381SSteven Rostedt return -ENODEV; 25416444a8aSArnaldo Carvalho de Melo 2552b499381SSteven Rostedt if (FTRACE_WARN_ON(ops == &global_ops)) 2562b499381SSteven Rostedt return -EINVAL; 25716444a8aSArnaldo Carvalho de Melo 2582b499381SSteven Rostedt ret = remove_ftrace_ops(&ftrace_list, ops); 2592b499381SSteven Rostedt if (ret < 0) 2602b499381SSteven Rostedt return ret; 261491d0dcfSSteven Rostedt if (ftrace_enabled) 262491d0dcfSSteven Rostedt update_ftrace_function(); 26316444a8aSArnaldo Carvalho de Melo 264e6ea44e9SSteven Rostedt return 0; 2653d083395SSteven Rostedt } 2663d083395SSteven Rostedt 267df4fc315SSteven Rostedt static void ftrace_update_pid_func(void) 268df4fc315SSteven Rostedt { 269491d0dcfSSteven Rostedt /* Only do something if we are tracing something */ 270df4fc315SSteven Rostedt if (ftrace_trace_function == ftrace_stub) 27110dd3ebeSKOSAKI Motohiro return; 272df4fc315SSteven Rostedt 273491d0dcfSSteven Rostedt update_ftrace_function(); 274df4fc315SSteven Rostedt } 275df4fc315SSteven Rostedt 276493762fcSSteven Rostedt #ifdef CONFIG_FUNCTION_PROFILER 277493762fcSSteven Rostedt struct ftrace_profile { 278493762fcSSteven Rostedt struct hlist_node node; 279493762fcSSteven Rostedt unsigned long ip; 280493762fcSSteven Rostedt unsigned long counter; 2810706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 2820706f1c4SSteven Rostedt unsigned long long time; 283e330b3bcSChase Douglas unsigned long long time_squared; 2840706f1c4SSteven Rostedt #endif 285493762fcSSteven Rostedt }; 286493762fcSSteven Rostedt 287493762fcSSteven Rostedt struct ftrace_profile_page { 288493762fcSSteven Rostedt struct ftrace_profile_page *next; 289493762fcSSteven Rostedt unsigned long index; 290493762fcSSteven Rostedt struct ftrace_profile records[]; 291493762fcSSteven Rostedt }; 292493762fcSSteven Rostedt 293cafb168aSSteven Rostedt struct ftrace_profile_stat { 294cafb168aSSteven Rostedt atomic_t disabled; 295cafb168aSSteven Rostedt struct hlist_head *hash; 296cafb168aSSteven Rostedt struct ftrace_profile_page *pages; 297cafb168aSSteven Rostedt struct ftrace_profile_page *start; 298cafb168aSSteven Rostedt struct tracer_stat stat; 299cafb168aSSteven Rostedt }; 300cafb168aSSteven Rostedt 301493762fcSSteven Rostedt #define PROFILE_RECORDS_SIZE \ 302493762fcSSteven Rostedt (PAGE_SIZE - offsetof(struct ftrace_profile_page, records)) 303493762fcSSteven Rostedt 304493762fcSSteven Rostedt #define PROFILES_PER_PAGE \ 305493762fcSSteven Rostedt (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile)) 306493762fcSSteven Rostedt 307fb9fb015SSteven Rostedt static int ftrace_profile_bits __read_mostly; 308fb9fb015SSteven Rostedt static int ftrace_profile_enabled __read_mostly; 309fb9fb015SSteven Rostedt 310fb9fb015SSteven Rostedt /* ftrace_profile_lock - synchronize the enable and disable of the profiler */ 311493762fcSSteven Rostedt static DEFINE_MUTEX(ftrace_profile_lock); 312493762fcSSteven Rostedt 313cafb168aSSteven Rostedt static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats); 314493762fcSSteven Rostedt 315493762fcSSteven Rostedt #define FTRACE_PROFILE_HASH_SIZE 1024 /* must be power of 2 */ 316493762fcSSteven Rostedt 317493762fcSSteven Rostedt static void * 318493762fcSSteven Rostedt function_stat_next(void *v, int idx) 319493762fcSSteven Rostedt { 320493762fcSSteven Rostedt struct ftrace_profile *rec = v; 321493762fcSSteven Rostedt struct ftrace_profile_page *pg; 322493762fcSSteven Rostedt 323493762fcSSteven Rostedt pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK); 324493762fcSSteven Rostedt 325493762fcSSteven Rostedt again: 3260296e425SLi Zefan if (idx != 0) 327493762fcSSteven Rostedt rec++; 3280296e425SLi Zefan 329493762fcSSteven Rostedt if ((void *)rec >= (void *)&pg->records[pg->index]) { 330493762fcSSteven Rostedt pg = pg->next; 331493762fcSSteven Rostedt if (!pg) 332493762fcSSteven Rostedt return NULL; 333493762fcSSteven Rostedt rec = &pg->records[0]; 334493762fcSSteven Rostedt if (!rec->counter) 335493762fcSSteven Rostedt goto again; 336493762fcSSteven Rostedt } 337493762fcSSteven Rostedt 338493762fcSSteven Rostedt return rec; 339493762fcSSteven Rostedt } 340493762fcSSteven Rostedt 341493762fcSSteven Rostedt static void *function_stat_start(struct tracer_stat *trace) 342493762fcSSteven Rostedt { 343cafb168aSSteven Rostedt struct ftrace_profile_stat *stat = 344cafb168aSSteven Rostedt container_of(trace, struct ftrace_profile_stat, stat); 345cafb168aSSteven Rostedt 346cafb168aSSteven Rostedt if (!stat || !stat->start) 347cafb168aSSteven Rostedt return NULL; 348cafb168aSSteven Rostedt 349cafb168aSSteven Rostedt return function_stat_next(&stat->start->records[0], 0); 350493762fcSSteven Rostedt } 351493762fcSSteven Rostedt 3520706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 3530706f1c4SSteven Rostedt /* function graph compares on total time */ 3540706f1c4SSteven Rostedt static int function_stat_cmp(void *p1, void *p2) 3550706f1c4SSteven Rostedt { 3560706f1c4SSteven Rostedt struct ftrace_profile *a = p1; 3570706f1c4SSteven Rostedt struct ftrace_profile *b = p2; 3580706f1c4SSteven Rostedt 3590706f1c4SSteven Rostedt if (a->time < b->time) 3600706f1c4SSteven Rostedt return -1; 3610706f1c4SSteven Rostedt if (a->time > b->time) 3620706f1c4SSteven Rostedt return 1; 3630706f1c4SSteven Rostedt else 3640706f1c4SSteven Rostedt return 0; 3650706f1c4SSteven Rostedt } 3660706f1c4SSteven Rostedt #else 3670706f1c4SSteven Rostedt /* not function graph compares against hits */ 368493762fcSSteven Rostedt static int function_stat_cmp(void *p1, void *p2) 369493762fcSSteven Rostedt { 370493762fcSSteven Rostedt struct ftrace_profile *a = p1; 371493762fcSSteven Rostedt struct ftrace_profile *b = p2; 372493762fcSSteven Rostedt 373493762fcSSteven Rostedt if (a->counter < b->counter) 374493762fcSSteven Rostedt return -1; 375493762fcSSteven Rostedt if (a->counter > b->counter) 376493762fcSSteven Rostedt return 1; 377493762fcSSteven Rostedt else 378493762fcSSteven Rostedt return 0; 379493762fcSSteven Rostedt } 3800706f1c4SSteven Rostedt #endif 381493762fcSSteven Rostedt 382493762fcSSteven Rostedt static int function_stat_headers(struct seq_file *m) 383493762fcSSteven Rostedt { 3840706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 38534886c8bSSteven Rostedt seq_printf(m, " Function " 386e330b3bcSChase Douglas "Hit Time Avg s^2\n" 38734886c8bSSteven Rostedt " -------- " 388e330b3bcSChase Douglas "--- ---- --- ---\n"); 3890706f1c4SSteven Rostedt #else 390493762fcSSteven Rostedt seq_printf(m, " Function Hit\n" 391493762fcSSteven Rostedt " -------- ---\n"); 3920706f1c4SSteven Rostedt #endif 393493762fcSSteven Rostedt return 0; 394493762fcSSteven Rostedt } 395493762fcSSteven Rostedt 396493762fcSSteven Rostedt static int function_stat_show(struct seq_file *m, void *v) 397493762fcSSteven Rostedt { 398493762fcSSteven Rostedt struct ftrace_profile *rec = v; 399493762fcSSteven Rostedt char str[KSYM_SYMBOL_LEN]; 4003aaba20fSLi Zefan int ret = 0; 4010706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 40234886c8bSSteven Rostedt static struct trace_seq s; 40334886c8bSSteven Rostedt unsigned long long avg; 404e330b3bcSChase Douglas unsigned long long stddev; 4050706f1c4SSteven Rostedt #endif 4063aaba20fSLi Zefan mutex_lock(&ftrace_profile_lock); 4073aaba20fSLi Zefan 4083aaba20fSLi Zefan /* we raced with function_profile_reset() */ 4093aaba20fSLi Zefan if (unlikely(rec->counter == 0)) { 4103aaba20fSLi Zefan ret = -EBUSY; 4113aaba20fSLi Zefan goto out; 4123aaba20fSLi Zefan } 413493762fcSSteven Rostedt 414493762fcSSteven Rostedt kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); 4150706f1c4SSteven Rostedt seq_printf(m, " %-30.30s %10lu", str, rec->counter); 416493762fcSSteven Rostedt 4170706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 4180706f1c4SSteven Rostedt seq_printf(m, " "); 41934886c8bSSteven Rostedt avg = rec->time; 42034886c8bSSteven Rostedt do_div(avg, rec->counter); 42134886c8bSSteven Rostedt 422e330b3bcSChase Douglas /* Sample standard deviation (s^2) */ 423e330b3bcSChase Douglas if (rec->counter <= 1) 424e330b3bcSChase Douglas stddev = 0; 425e330b3bcSChase Douglas else { 426e330b3bcSChase Douglas stddev = rec->time_squared - rec->counter * avg * avg; 427e330b3bcSChase Douglas /* 428e330b3bcSChase Douglas * Divide only 1000 for ns^2 -> us^2 conversion. 429e330b3bcSChase Douglas * trace_print_graph_duration will divide 1000 again. 430e330b3bcSChase Douglas */ 431e330b3bcSChase Douglas do_div(stddev, (rec->counter - 1) * 1000); 432e330b3bcSChase Douglas } 433e330b3bcSChase Douglas 43434886c8bSSteven Rostedt trace_seq_init(&s); 43534886c8bSSteven Rostedt trace_print_graph_duration(rec->time, &s); 43634886c8bSSteven Rostedt trace_seq_puts(&s, " "); 43734886c8bSSteven Rostedt trace_print_graph_duration(avg, &s); 438e330b3bcSChase Douglas trace_seq_puts(&s, " "); 439e330b3bcSChase Douglas trace_print_graph_duration(stddev, &s); 4400706f1c4SSteven Rostedt trace_print_seq(m, &s); 4410706f1c4SSteven Rostedt #endif 4420706f1c4SSteven Rostedt seq_putc(m, '\n'); 4433aaba20fSLi Zefan out: 4443aaba20fSLi Zefan mutex_unlock(&ftrace_profile_lock); 4450706f1c4SSteven Rostedt 4463aaba20fSLi Zefan return ret; 447493762fcSSteven Rostedt } 448493762fcSSteven Rostedt 449cafb168aSSteven Rostedt static void ftrace_profile_reset(struct ftrace_profile_stat *stat) 450493762fcSSteven Rostedt { 451493762fcSSteven Rostedt struct ftrace_profile_page *pg; 452493762fcSSteven Rostedt 453cafb168aSSteven Rostedt pg = stat->pages = stat->start; 454493762fcSSteven Rostedt 455493762fcSSteven Rostedt while (pg) { 456493762fcSSteven Rostedt memset(pg->records, 0, PROFILE_RECORDS_SIZE); 457493762fcSSteven Rostedt pg->index = 0; 458493762fcSSteven Rostedt pg = pg->next; 459493762fcSSteven Rostedt } 460493762fcSSteven Rostedt 461cafb168aSSteven Rostedt memset(stat->hash, 0, 462493762fcSSteven Rostedt FTRACE_PROFILE_HASH_SIZE * sizeof(struct hlist_head)); 463493762fcSSteven Rostedt } 464493762fcSSteven Rostedt 465cafb168aSSteven Rostedt int ftrace_profile_pages_init(struct ftrace_profile_stat *stat) 466493762fcSSteven Rostedt { 467493762fcSSteven Rostedt struct ftrace_profile_page *pg; 468318e0a73SSteven Rostedt int functions; 469318e0a73SSteven Rostedt int pages; 470493762fcSSteven Rostedt int i; 471493762fcSSteven Rostedt 472493762fcSSteven Rostedt /* If we already allocated, do nothing */ 473cafb168aSSteven Rostedt if (stat->pages) 474493762fcSSteven Rostedt return 0; 475493762fcSSteven Rostedt 476cafb168aSSteven Rostedt stat->pages = (void *)get_zeroed_page(GFP_KERNEL); 477cafb168aSSteven Rostedt if (!stat->pages) 478493762fcSSteven Rostedt return -ENOMEM; 479493762fcSSteven Rostedt 480318e0a73SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE 481318e0a73SSteven Rostedt functions = ftrace_update_tot_cnt; 482318e0a73SSteven Rostedt #else 483318e0a73SSteven Rostedt /* 484318e0a73SSteven Rostedt * We do not know the number of functions that exist because 485318e0a73SSteven Rostedt * dynamic tracing is what counts them. With past experience 486318e0a73SSteven Rostedt * we have around 20K functions. That should be more than enough. 487318e0a73SSteven Rostedt * It is highly unlikely we will execute every function in 488318e0a73SSteven Rostedt * the kernel. 489318e0a73SSteven Rostedt */ 490318e0a73SSteven Rostedt functions = 20000; 491318e0a73SSteven Rostedt #endif 492318e0a73SSteven Rostedt 493cafb168aSSteven Rostedt pg = stat->start = stat->pages; 494493762fcSSteven Rostedt 495318e0a73SSteven Rostedt pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE); 496318e0a73SSteven Rostedt 497318e0a73SSteven Rostedt for (i = 0; i < pages; i++) { 498493762fcSSteven Rostedt pg->next = (void *)get_zeroed_page(GFP_KERNEL); 499493762fcSSteven Rostedt if (!pg->next) 500318e0a73SSteven Rostedt goto out_free; 501493762fcSSteven Rostedt pg = pg->next; 502493762fcSSteven Rostedt } 503493762fcSSteven Rostedt 504493762fcSSteven Rostedt return 0; 505318e0a73SSteven Rostedt 506318e0a73SSteven Rostedt out_free: 507318e0a73SSteven Rostedt pg = stat->start; 508318e0a73SSteven Rostedt while (pg) { 509318e0a73SSteven Rostedt unsigned long tmp = (unsigned long)pg; 510318e0a73SSteven Rostedt 511318e0a73SSteven Rostedt pg = pg->next; 512318e0a73SSteven Rostedt free_page(tmp); 513318e0a73SSteven Rostedt } 514318e0a73SSteven Rostedt 515318e0a73SSteven Rostedt free_page((unsigned long)stat->pages); 516318e0a73SSteven Rostedt stat->pages = NULL; 517318e0a73SSteven Rostedt stat->start = NULL; 518318e0a73SSteven Rostedt 519318e0a73SSteven Rostedt return -ENOMEM; 520493762fcSSteven Rostedt } 521493762fcSSteven Rostedt 522cafb168aSSteven Rostedt static int ftrace_profile_init_cpu(int cpu) 523493762fcSSteven Rostedt { 524cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 525493762fcSSteven Rostedt int size; 526493762fcSSteven Rostedt 527cafb168aSSteven Rostedt stat = &per_cpu(ftrace_profile_stats, cpu); 528cafb168aSSteven Rostedt 529cafb168aSSteven Rostedt if (stat->hash) { 530493762fcSSteven Rostedt /* If the profile is already created, simply reset it */ 531cafb168aSSteven Rostedt ftrace_profile_reset(stat); 532493762fcSSteven Rostedt return 0; 533493762fcSSteven Rostedt } 534493762fcSSteven Rostedt 535493762fcSSteven Rostedt /* 536493762fcSSteven Rostedt * We are profiling all functions, but usually only a few thousand 537493762fcSSteven Rostedt * functions are hit. We'll make a hash of 1024 items. 538493762fcSSteven Rostedt */ 539493762fcSSteven Rostedt size = FTRACE_PROFILE_HASH_SIZE; 540493762fcSSteven Rostedt 541cafb168aSSteven Rostedt stat->hash = kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL); 542493762fcSSteven Rostedt 543cafb168aSSteven Rostedt if (!stat->hash) 544493762fcSSteven Rostedt return -ENOMEM; 545493762fcSSteven Rostedt 546cafb168aSSteven Rostedt if (!ftrace_profile_bits) { 547493762fcSSteven Rostedt size--; 548493762fcSSteven Rostedt 549493762fcSSteven Rostedt for (; size; size >>= 1) 550493762fcSSteven Rostedt ftrace_profile_bits++; 551cafb168aSSteven Rostedt } 552493762fcSSteven Rostedt 553318e0a73SSteven Rostedt /* Preallocate the function profiling pages */ 554cafb168aSSteven Rostedt if (ftrace_profile_pages_init(stat) < 0) { 555cafb168aSSteven Rostedt kfree(stat->hash); 556cafb168aSSteven Rostedt stat->hash = NULL; 557493762fcSSteven Rostedt return -ENOMEM; 558493762fcSSteven Rostedt } 559493762fcSSteven Rostedt 560493762fcSSteven Rostedt return 0; 561493762fcSSteven Rostedt } 562493762fcSSteven Rostedt 563cafb168aSSteven Rostedt static int ftrace_profile_init(void) 564cafb168aSSteven Rostedt { 565cafb168aSSteven Rostedt int cpu; 566cafb168aSSteven Rostedt int ret = 0; 567cafb168aSSteven Rostedt 568cafb168aSSteven Rostedt for_each_online_cpu(cpu) { 569cafb168aSSteven Rostedt ret = ftrace_profile_init_cpu(cpu); 570cafb168aSSteven Rostedt if (ret) 571cafb168aSSteven Rostedt break; 572cafb168aSSteven Rostedt } 573cafb168aSSteven Rostedt 574cafb168aSSteven Rostedt return ret; 575cafb168aSSteven Rostedt } 576cafb168aSSteven Rostedt 577493762fcSSteven Rostedt /* interrupts must be disabled */ 578cafb168aSSteven Rostedt static struct ftrace_profile * 579cafb168aSSteven Rostedt ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip) 580493762fcSSteven Rostedt { 581493762fcSSteven Rostedt struct ftrace_profile *rec; 582493762fcSSteven Rostedt struct hlist_head *hhd; 583493762fcSSteven Rostedt struct hlist_node *n; 584493762fcSSteven Rostedt unsigned long key; 585493762fcSSteven Rostedt 586493762fcSSteven Rostedt key = hash_long(ip, ftrace_profile_bits); 587cafb168aSSteven Rostedt hhd = &stat->hash[key]; 588493762fcSSteven Rostedt 589493762fcSSteven Rostedt if (hlist_empty(hhd)) 590493762fcSSteven Rostedt return NULL; 591493762fcSSteven Rostedt 592493762fcSSteven Rostedt hlist_for_each_entry_rcu(rec, n, hhd, node) { 593493762fcSSteven Rostedt if (rec->ip == ip) 594493762fcSSteven Rostedt return rec; 595493762fcSSteven Rostedt } 596493762fcSSteven Rostedt 597493762fcSSteven Rostedt return NULL; 598493762fcSSteven Rostedt } 599493762fcSSteven Rostedt 600cafb168aSSteven Rostedt static void ftrace_add_profile(struct ftrace_profile_stat *stat, 601cafb168aSSteven Rostedt struct ftrace_profile *rec) 602493762fcSSteven Rostedt { 603493762fcSSteven Rostedt unsigned long key; 604493762fcSSteven Rostedt 605493762fcSSteven Rostedt key = hash_long(rec->ip, ftrace_profile_bits); 606cafb168aSSteven Rostedt hlist_add_head_rcu(&rec->node, &stat->hash[key]); 607493762fcSSteven Rostedt } 608493762fcSSteven Rostedt 609318e0a73SSteven Rostedt /* 610318e0a73SSteven Rostedt * The memory is already allocated, this simply finds a new record to use. 611318e0a73SSteven Rostedt */ 612493762fcSSteven Rostedt static struct ftrace_profile * 613318e0a73SSteven Rostedt ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip) 614493762fcSSteven Rostedt { 615493762fcSSteven Rostedt struct ftrace_profile *rec = NULL; 616493762fcSSteven Rostedt 617318e0a73SSteven Rostedt /* prevent recursion (from NMIs) */ 618cafb168aSSteven Rostedt if (atomic_inc_return(&stat->disabled) != 1) 619493762fcSSteven Rostedt goto out; 620493762fcSSteven Rostedt 621493762fcSSteven Rostedt /* 622318e0a73SSteven Rostedt * Try to find the function again since an NMI 623318e0a73SSteven Rostedt * could have added it 624493762fcSSteven Rostedt */ 625cafb168aSSteven Rostedt rec = ftrace_find_profiled_func(stat, ip); 626493762fcSSteven Rostedt if (rec) 627cafb168aSSteven Rostedt goto out; 628493762fcSSteven Rostedt 629cafb168aSSteven Rostedt if (stat->pages->index == PROFILES_PER_PAGE) { 630cafb168aSSteven Rostedt if (!stat->pages->next) 631cafb168aSSteven Rostedt goto out; 632cafb168aSSteven Rostedt stat->pages = stat->pages->next; 633493762fcSSteven Rostedt } 634493762fcSSteven Rostedt 635cafb168aSSteven Rostedt rec = &stat->pages->records[stat->pages->index++]; 636493762fcSSteven Rostedt rec->ip = ip; 637cafb168aSSteven Rostedt ftrace_add_profile(stat, rec); 638493762fcSSteven Rostedt 639493762fcSSteven Rostedt out: 640cafb168aSSteven Rostedt atomic_dec(&stat->disabled); 641493762fcSSteven Rostedt 642493762fcSSteven Rostedt return rec; 643493762fcSSteven Rostedt } 644493762fcSSteven Rostedt 645493762fcSSteven Rostedt static void 646493762fcSSteven Rostedt function_profile_call(unsigned long ip, unsigned long parent_ip) 647493762fcSSteven Rostedt { 648cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 649493762fcSSteven Rostedt struct ftrace_profile *rec; 650493762fcSSteven Rostedt unsigned long flags; 651493762fcSSteven Rostedt 652493762fcSSteven Rostedt if (!ftrace_profile_enabled) 653493762fcSSteven Rostedt return; 654493762fcSSteven Rostedt 655493762fcSSteven Rostedt local_irq_save(flags); 656cafb168aSSteven Rostedt 657cafb168aSSteven Rostedt stat = &__get_cpu_var(ftrace_profile_stats); 6580f6ce3deSSteven Rostedt if (!stat->hash || !ftrace_profile_enabled) 659cafb168aSSteven Rostedt goto out; 660cafb168aSSteven Rostedt 661cafb168aSSteven Rostedt rec = ftrace_find_profiled_func(stat, ip); 662493762fcSSteven Rostedt if (!rec) { 663318e0a73SSteven Rostedt rec = ftrace_profile_alloc(stat, ip); 664493762fcSSteven Rostedt if (!rec) 665493762fcSSteven Rostedt goto out; 666493762fcSSteven Rostedt } 667493762fcSSteven Rostedt 668493762fcSSteven Rostedt rec->counter++; 669493762fcSSteven Rostedt out: 670493762fcSSteven Rostedt local_irq_restore(flags); 671493762fcSSteven Rostedt } 672493762fcSSteven Rostedt 6730706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 6740706f1c4SSteven Rostedt static int profile_graph_entry(struct ftrace_graph_ent *trace) 6750706f1c4SSteven Rostedt { 6760706f1c4SSteven Rostedt function_profile_call(trace->func, 0); 6770706f1c4SSteven Rostedt return 1; 6780706f1c4SSteven Rostedt } 6790706f1c4SSteven Rostedt 6800706f1c4SSteven Rostedt static void profile_graph_return(struct ftrace_graph_ret *trace) 6810706f1c4SSteven Rostedt { 682cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 683a2a16d6aSSteven Rostedt unsigned long long calltime; 6840706f1c4SSteven Rostedt struct ftrace_profile *rec; 685cafb168aSSteven Rostedt unsigned long flags; 6860706f1c4SSteven Rostedt 6870706f1c4SSteven Rostedt local_irq_save(flags); 688cafb168aSSteven Rostedt stat = &__get_cpu_var(ftrace_profile_stats); 6890f6ce3deSSteven Rostedt if (!stat->hash || !ftrace_profile_enabled) 690cafb168aSSteven Rostedt goto out; 691cafb168aSSteven Rostedt 69237e44bc5SSteven Rostedt /* If the calltime was zero'd ignore it */ 69337e44bc5SSteven Rostedt if (!trace->calltime) 69437e44bc5SSteven Rostedt goto out; 69537e44bc5SSteven Rostedt 696a2a16d6aSSteven Rostedt calltime = trace->rettime - trace->calltime; 697a2a16d6aSSteven Rostedt 698a2a16d6aSSteven Rostedt if (!(trace_flags & TRACE_ITER_GRAPH_TIME)) { 699a2a16d6aSSteven Rostedt int index; 700a2a16d6aSSteven Rostedt 701a2a16d6aSSteven Rostedt index = trace->depth; 702a2a16d6aSSteven Rostedt 703a2a16d6aSSteven Rostedt /* Append this call time to the parent time to subtract */ 704a2a16d6aSSteven Rostedt if (index) 705a2a16d6aSSteven Rostedt current->ret_stack[index - 1].subtime += calltime; 706a2a16d6aSSteven Rostedt 707a2a16d6aSSteven Rostedt if (current->ret_stack[index].subtime < calltime) 708a2a16d6aSSteven Rostedt calltime -= current->ret_stack[index].subtime; 709a2a16d6aSSteven Rostedt else 710a2a16d6aSSteven Rostedt calltime = 0; 711a2a16d6aSSteven Rostedt } 712a2a16d6aSSteven Rostedt 713cafb168aSSteven Rostedt rec = ftrace_find_profiled_func(stat, trace->func); 714e330b3bcSChase Douglas if (rec) { 715a2a16d6aSSteven Rostedt rec->time += calltime; 716e330b3bcSChase Douglas rec->time_squared += calltime * calltime; 717e330b3bcSChase Douglas } 718a2a16d6aSSteven Rostedt 719cafb168aSSteven Rostedt out: 7200706f1c4SSteven Rostedt local_irq_restore(flags); 7210706f1c4SSteven Rostedt } 7220706f1c4SSteven Rostedt 7230706f1c4SSteven Rostedt static int register_ftrace_profiler(void) 7240706f1c4SSteven Rostedt { 7250706f1c4SSteven Rostedt return register_ftrace_graph(&profile_graph_return, 7260706f1c4SSteven Rostedt &profile_graph_entry); 7270706f1c4SSteven Rostedt } 7280706f1c4SSteven Rostedt 7290706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void) 7300706f1c4SSteven Rostedt { 7310706f1c4SSteven Rostedt unregister_ftrace_graph(); 7320706f1c4SSteven Rostedt } 7330706f1c4SSteven Rostedt #else 734493762fcSSteven Rostedt static struct ftrace_ops ftrace_profile_ops __read_mostly = 735493762fcSSteven Rostedt { 736493762fcSSteven Rostedt .func = function_profile_call, 737493762fcSSteven Rostedt }; 738493762fcSSteven Rostedt 7390706f1c4SSteven Rostedt static int register_ftrace_profiler(void) 7400706f1c4SSteven Rostedt { 7410706f1c4SSteven Rostedt return register_ftrace_function(&ftrace_profile_ops); 7420706f1c4SSteven Rostedt } 7430706f1c4SSteven Rostedt 7440706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void) 7450706f1c4SSteven Rostedt { 7460706f1c4SSteven Rostedt unregister_ftrace_function(&ftrace_profile_ops); 7470706f1c4SSteven Rostedt } 7480706f1c4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 7490706f1c4SSteven Rostedt 750493762fcSSteven Rostedt static ssize_t 751493762fcSSteven Rostedt ftrace_profile_write(struct file *filp, const char __user *ubuf, 752493762fcSSteven Rostedt size_t cnt, loff_t *ppos) 753493762fcSSteven Rostedt { 754493762fcSSteven Rostedt unsigned long val; 755fb9fb015SSteven Rostedt char buf[64]; /* big enough to hold a number */ 756493762fcSSteven Rostedt int ret; 757493762fcSSteven Rostedt 758493762fcSSteven Rostedt if (cnt >= sizeof(buf)) 759493762fcSSteven Rostedt return -EINVAL; 760493762fcSSteven Rostedt 761493762fcSSteven Rostedt if (copy_from_user(&buf, ubuf, cnt)) 762493762fcSSteven Rostedt return -EFAULT; 763493762fcSSteven Rostedt 764493762fcSSteven Rostedt buf[cnt] = 0; 765493762fcSSteven Rostedt 766493762fcSSteven Rostedt ret = strict_strtoul(buf, 10, &val); 767493762fcSSteven Rostedt if (ret < 0) 768493762fcSSteven Rostedt return ret; 769493762fcSSteven Rostedt 770493762fcSSteven Rostedt val = !!val; 771493762fcSSteven Rostedt 772493762fcSSteven Rostedt mutex_lock(&ftrace_profile_lock); 773493762fcSSteven Rostedt if (ftrace_profile_enabled ^ val) { 774493762fcSSteven Rostedt if (val) { 775493762fcSSteven Rostedt ret = ftrace_profile_init(); 776493762fcSSteven Rostedt if (ret < 0) { 777493762fcSSteven Rostedt cnt = ret; 778493762fcSSteven Rostedt goto out; 779493762fcSSteven Rostedt } 780493762fcSSteven Rostedt 7810706f1c4SSteven Rostedt ret = register_ftrace_profiler(); 7820706f1c4SSteven Rostedt if (ret < 0) { 7830706f1c4SSteven Rostedt cnt = ret; 7840706f1c4SSteven Rostedt goto out; 7850706f1c4SSteven Rostedt } 786493762fcSSteven Rostedt ftrace_profile_enabled = 1; 787493762fcSSteven Rostedt } else { 788493762fcSSteven Rostedt ftrace_profile_enabled = 0; 7890f6ce3deSSteven Rostedt /* 7900f6ce3deSSteven Rostedt * unregister_ftrace_profiler calls stop_machine 7910f6ce3deSSteven Rostedt * so this acts like an synchronize_sched. 7920f6ce3deSSteven Rostedt */ 7930706f1c4SSteven Rostedt unregister_ftrace_profiler(); 794493762fcSSteven Rostedt } 795493762fcSSteven Rostedt } 796493762fcSSteven Rostedt out: 797493762fcSSteven Rostedt mutex_unlock(&ftrace_profile_lock); 798493762fcSSteven Rostedt 799cf8517cfSJiri Olsa *ppos += cnt; 800493762fcSSteven Rostedt 801493762fcSSteven Rostedt return cnt; 802493762fcSSteven Rostedt } 803493762fcSSteven Rostedt 804493762fcSSteven Rostedt static ssize_t 805493762fcSSteven Rostedt ftrace_profile_read(struct file *filp, char __user *ubuf, 806493762fcSSteven Rostedt size_t cnt, loff_t *ppos) 807493762fcSSteven Rostedt { 808fb9fb015SSteven Rostedt char buf[64]; /* big enough to hold a number */ 809493762fcSSteven Rostedt int r; 810493762fcSSteven Rostedt 811493762fcSSteven Rostedt r = sprintf(buf, "%u\n", ftrace_profile_enabled); 812493762fcSSteven Rostedt return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 813493762fcSSteven Rostedt } 814493762fcSSteven Rostedt 815493762fcSSteven Rostedt static const struct file_operations ftrace_profile_fops = { 816493762fcSSteven Rostedt .open = tracing_open_generic, 817493762fcSSteven Rostedt .read = ftrace_profile_read, 818493762fcSSteven Rostedt .write = ftrace_profile_write, 8196038f373SArnd Bergmann .llseek = default_llseek, 820493762fcSSteven Rostedt }; 821493762fcSSteven Rostedt 822cafb168aSSteven Rostedt /* used to initialize the real stat files */ 823cafb168aSSteven Rostedt static struct tracer_stat function_stats __initdata = { 824cafb168aSSteven Rostedt .name = "functions", 825cafb168aSSteven Rostedt .stat_start = function_stat_start, 826cafb168aSSteven Rostedt .stat_next = function_stat_next, 827cafb168aSSteven Rostedt .stat_cmp = function_stat_cmp, 828cafb168aSSteven Rostedt .stat_headers = function_stat_headers, 829cafb168aSSteven Rostedt .stat_show = function_stat_show 830cafb168aSSteven Rostedt }; 831cafb168aSSteven Rostedt 8326ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer) 833493762fcSSteven Rostedt { 834cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 835493762fcSSteven Rostedt struct dentry *entry; 836cafb168aSSteven Rostedt char *name; 837493762fcSSteven Rostedt int ret; 838cafb168aSSteven Rostedt int cpu; 839493762fcSSteven Rostedt 840cafb168aSSteven Rostedt for_each_possible_cpu(cpu) { 841cafb168aSSteven Rostedt stat = &per_cpu(ftrace_profile_stats, cpu); 842cafb168aSSteven Rostedt 843cafb168aSSteven Rostedt /* allocate enough for function name + cpu number */ 844cafb168aSSteven Rostedt name = kmalloc(32, GFP_KERNEL); 845cafb168aSSteven Rostedt if (!name) { 846cafb168aSSteven Rostedt /* 847cafb168aSSteven Rostedt * The files created are permanent, if something happens 848cafb168aSSteven Rostedt * we still do not free memory. 849cafb168aSSteven Rostedt */ 850cafb168aSSteven Rostedt WARN(1, 851cafb168aSSteven Rostedt "Could not allocate stat file for cpu %d\n", 852cafb168aSSteven Rostedt cpu); 853493762fcSSteven Rostedt return; 854493762fcSSteven Rostedt } 855cafb168aSSteven Rostedt stat->stat = function_stats; 856cafb168aSSteven Rostedt snprintf(name, 32, "function%d", cpu); 857cafb168aSSteven Rostedt stat->stat.name = name; 858cafb168aSSteven Rostedt ret = register_stat_tracer(&stat->stat); 859cafb168aSSteven Rostedt if (ret) { 860cafb168aSSteven Rostedt WARN(1, 861cafb168aSSteven Rostedt "Could not register function stat for cpu %d\n", 862cafb168aSSteven Rostedt cpu); 863cafb168aSSteven Rostedt kfree(name); 864cafb168aSSteven Rostedt return; 865cafb168aSSteven Rostedt } 866cafb168aSSteven Rostedt } 867493762fcSSteven Rostedt 868493762fcSSteven Rostedt entry = debugfs_create_file("function_profile_enabled", 0644, 869493762fcSSteven Rostedt d_tracer, NULL, &ftrace_profile_fops); 870493762fcSSteven Rostedt if (!entry) 871493762fcSSteven Rostedt pr_warning("Could not create debugfs " 872493762fcSSteven Rostedt "'function_profile_enabled' entry\n"); 873493762fcSSteven Rostedt } 874493762fcSSteven Rostedt 875493762fcSSteven Rostedt #else /* CONFIG_FUNCTION_PROFILER */ 8766ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer) 877493762fcSSteven Rostedt { 878493762fcSSteven Rostedt } 879493762fcSSteven Rostedt #endif /* CONFIG_FUNCTION_PROFILER */ 880493762fcSSteven Rostedt 88173d3fd96SIngo Molnar static struct pid * const ftrace_swapper_pid = &init_struct_pid; 88273d3fd96SIngo Molnar 8833d083395SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE 88473d3fd96SIngo Molnar 88599ecdc43SSteven Rostedt #ifndef CONFIG_FTRACE_MCOUNT_RECORD 886cb7be3b2SSteven Rostedt # error Dynamic ftrace depends on MCOUNT_RECORD 88799ecdc43SSteven Rostedt #endif 88899ecdc43SSteven Rostedt 8898fc0c701SSteven Rostedt static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly; 8908fc0c701SSteven Rostedt 891b6887d79SSteven Rostedt struct ftrace_func_probe { 8928fc0c701SSteven Rostedt struct hlist_node node; 893b6887d79SSteven Rostedt struct ftrace_probe_ops *ops; 8948fc0c701SSteven Rostedt unsigned long flags; 8958fc0c701SSteven Rostedt unsigned long ip; 8968fc0c701SSteven Rostedt void *data; 8978fc0c701SSteven Rostedt struct rcu_head rcu; 8988fc0c701SSteven Rostedt }; 8998fc0c701SSteven Rostedt 900d61f82d0SSteven Rostedt enum { 901d61f82d0SSteven Rostedt FTRACE_ENABLE_CALLS = (1 << 0), 902d61f82d0SSteven Rostedt FTRACE_DISABLE_CALLS = (1 << 1), 903d61f82d0SSteven Rostedt FTRACE_UPDATE_TRACE_FUNC = (1 << 2), 90479e406d7SSteven Rostedt FTRACE_START_FUNC_RET = (1 << 3), 90579e406d7SSteven Rostedt FTRACE_STOP_FUNC_RET = (1 << 4), 906d61f82d0SSteven Rostedt }; 907b448c4e3SSteven Rostedt struct ftrace_func_entry { 908b448c4e3SSteven Rostedt struct hlist_node hlist; 909b448c4e3SSteven Rostedt unsigned long ip; 910b448c4e3SSteven Rostedt }; 911b448c4e3SSteven Rostedt 912b448c4e3SSteven Rostedt struct ftrace_hash { 913b448c4e3SSteven Rostedt unsigned long size_bits; 914b448c4e3SSteven Rostedt struct hlist_head *buckets; 915b448c4e3SSteven Rostedt unsigned long count; 916*07fd5515SSteven Rostedt struct rcu_head rcu; 917b448c4e3SSteven Rostedt }; 918b448c4e3SSteven Rostedt 91933dc9b12SSteven Rostedt /* 92033dc9b12SSteven Rostedt * We make these constant because no one should touch them, 92133dc9b12SSteven Rostedt * but they are used as the default "empty hash", to avoid allocating 92233dc9b12SSteven Rostedt * it all the time. These are in a read only section such that if 92333dc9b12SSteven Rostedt * anyone does try to modify it, it will cause an exception. 92433dc9b12SSteven Rostedt */ 92533dc9b12SSteven Rostedt static const struct hlist_head empty_buckets[1]; 92633dc9b12SSteven Rostedt static const struct ftrace_hash empty_hash = { 92733dc9b12SSteven Rostedt .buckets = (struct hlist_head *)empty_buckets, 928b448c4e3SSteven Rostedt }; 92933dc9b12SSteven Rostedt #define EMPTY_HASH ((struct ftrace_hash *)&empty_hash) 9305072c59fSSteven Rostedt 931ed926f9bSSteven Rostedt enum { 932ed926f9bSSteven Rostedt FTRACE_OPS_FL_ENABLED = 1, 933ed926f9bSSteven Rostedt }; 934ed926f9bSSteven Rostedt 9352b499381SSteven Rostedt static struct ftrace_ops global_ops = { 936f45948e8SSteven Rostedt .func = ftrace_stub, 93733dc9b12SSteven Rostedt .notrace_hash = EMPTY_HASH, 93833dc9b12SSteven Rostedt .filter_hash = EMPTY_HASH, 939f45948e8SSteven Rostedt }; 940f45948e8SSteven Rostedt 941e94142a6SLai Jiangshan static struct dyn_ftrace *ftrace_new_addrs; 9423d083395SSteven Rostedt 94341c52c0dSSteven Rostedt static DEFINE_MUTEX(ftrace_regex_lock); 9443d083395SSteven Rostedt 9453c1720f0SSteven Rostedt struct ftrace_page { 9463c1720f0SSteven Rostedt struct ftrace_page *next; 947431aa3fbSSteven Rostedt int index; 9483c1720f0SSteven Rostedt struct dyn_ftrace records[]; 949aa5e5ceaSDavid Miller }; 9503c1720f0SSteven Rostedt 9513c1720f0SSteven Rostedt #define ENTRIES_PER_PAGE \ 9523c1720f0SSteven Rostedt ((PAGE_SIZE - sizeof(struct ftrace_page)) / sizeof(struct dyn_ftrace)) 9533c1720f0SSteven Rostedt 9543c1720f0SSteven Rostedt /* estimate from running different kernels */ 9553c1720f0SSteven Rostedt #define NR_TO_INIT 10000 9563c1720f0SSteven Rostedt 9573c1720f0SSteven Rostedt static struct ftrace_page *ftrace_pages_start; 9583c1720f0SSteven Rostedt static struct ftrace_page *ftrace_pages; 9593c1720f0SSteven Rostedt 96037ad5084SSteven Rostedt static struct dyn_ftrace *ftrace_free_records; 96137ad5084SSteven Rostedt 962b448c4e3SSteven Rostedt static struct ftrace_func_entry * 963b448c4e3SSteven Rostedt ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip) 964b448c4e3SSteven Rostedt { 965b448c4e3SSteven Rostedt unsigned long key; 966b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 967b448c4e3SSteven Rostedt struct hlist_head *hhd; 968b448c4e3SSteven Rostedt struct hlist_node *n; 969b448c4e3SSteven Rostedt 970b448c4e3SSteven Rostedt if (!hash->count) 971b448c4e3SSteven Rostedt return NULL; 972b448c4e3SSteven Rostedt 973b448c4e3SSteven Rostedt if (hash->size_bits > 0) 974b448c4e3SSteven Rostedt key = hash_long(ip, hash->size_bits); 975b448c4e3SSteven Rostedt else 976b448c4e3SSteven Rostedt key = 0; 977b448c4e3SSteven Rostedt 978b448c4e3SSteven Rostedt hhd = &hash->buckets[key]; 979b448c4e3SSteven Rostedt 980b448c4e3SSteven Rostedt hlist_for_each_entry_rcu(entry, n, hhd, hlist) { 981b448c4e3SSteven Rostedt if (entry->ip == ip) 982b448c4e3SSteven Rostedt return entry; 983b448c4e3SSteven Rostedt } 984b448c4e3SSteven Rostedt return NULL; 985b448c4e3SSteven Rostedt } 986b448c4e3SSteven Rostedt 98733dc9b12SSteven Rostedt static void __add_hash_entry(struct ftrace_hash *hash, 98833dc9b12SSteven Rostedt struct ftrace_func_entry *entry) 98933dc9b12SSteven Rostedt { 99033dc9b12SSteven Rostedt struct hlist_head *hhd; 99133dc9b12SSteven Rostedt unsigned long key; 99233dc9b12SSteven Rostedt 99333dc9b12SSteven Rostedt if (hash->size_bits) 99433dc9b12SSteven Rostedt key = hash_long(entry->ip, hash->size_bits); 99533dc9b12SSteven Rostedt else 99633dc9b12SSteven Rostedt key = 0; 99733dc9b12SSteven Rostedt 99833dc9b12SSteven Rostedt hhd = &hash->buckets[key]; 99933dc9b12SSteven Rostedt hlist_add_head(&entry->hlist, hhd); 100033dc9b12SSteven Rostedt hash->count++; 100133dc9b12SSteven Rostedt } 100233dc9b12SSteven Rostedt 1003b448c4e3SSteven Rostedt static int add_hash_entry(struct ftrace_hash *hash, unsigned long ip) 1004b448c4e3SSteven Rostedt { 1005b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 1006b448c4e3SSteven Rostedt 1007b448c4e3SSteven Rostedt entry = kmalloc(sizeof(*entry), GFP_KERNEL); 1008b448c4e3SSteven Rostedt if (!entry) 1009b448c4e3SSteven Rostedt return -ENOMEM; 1010b448c4e3SSteven Rostedt 1011b448c4e3SSteven Rostedt entry->ip = ip; 101233dc9b12SSteven Rostedt __add_hash_entry(hash, entry); 1013b448c4e3SSteven Rostedt 1014b448c4e3SSteven Rostedt return 0; 1015b448c4e3SSteven Rostedt } 1016b448c4e3SSteven Rostedt 1017b448c4e3SSteven Rostedt static void 101833dc9b12SSteven Rostedt free_hash_entry(struct ftrace_hash *hash, 101933dc9b12SSteven Rostedt struct ftrace_func_entry *entry) 102033dc9b12SSteven Rostedt { 102133dc9b12SSteven Rostedt hlist_del(&entry->hlist); 102233dc9b12SSteven Rostedt kfree(entry); 102333dc9b12SSteven Rostedt hash->count--; 102433dc9b12SSteven Rostedt } 102533dc9b12SSteven Rostedt 102633dc9b12SSteven Rostedt static void 1027b448c4e3SSteven Rostedt remove_hash_entry(struct ftrace_hash *hash, 1028b448c4e3SSteven Rostedt struct ftrace_func_entry *entry) 1029b448c4e3SSteven Rostedt { 1030b448c4e3SSteven Rostedt hlist_del(&entry->hlist); 1031b448c4e3SSteven Rostedt hash->count--; 1032b448c4e3SSteven Rostedt } 1033b448c4e3SSteven Rostedt 1034b448c4e3SSteven Rostedt static void ftrace_hash_clear(struct ftrace_hash *hash) 1035b448c4e3SSteven Rostedt { 1036b448c4e3SSteven Rostedt struct hlist_head *hhd; 1037b448c4e3SSteven Rostedt struct hlist_node *tp, *tn; 1038b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 1039b448c4e3SSteven Rostedt int size = 1 << hash->size_bits; 1040b448c4e3SSteven Rostedt int i; 1041b448c4e3SSteven Rostedt 104233dc9b12SSteven Rostedt if (!hash->count) 104333dc9b12SSteven Rostedt return; 104433dc9b12SSteven Rostedt 1045b448c4e3SSteven Rostedt for (i = 0; i < size; i++) { 1046b448c4e3SSteven Rostedt hhd = &hash->buckets[i]; 1047b448c4e3SSteven Rostedt hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) 104833dc9b12SSteven Rostedt free_hash_entry(hash, entry); 1049b448c4e3SSteven Rostedt } 1050b448c4e3SSteven Rostedt FTRACE_WARN_ON(hash->count); 1051b448c4e3SSteven Rostedt } 1052b448c4e3SSteven Rostedt 105333dc9b12SSteven Rostedt static void free_ftrace_hash(struct ftrace_hash *hash) 105433dc9b12SSteven Rostedt { 105533dc9b12SSteven Rostedt if (!hash || hash == EMPTY_HASH) 105633dc9b12SSteven Rostedt return; 105733dc9b12SSteven Rostedt ftrace_hash_clear(hash); 105833dc9b12SSteven Rostedt kfree(hash->buckets); 105933dc9b12SSteven Rostedt kfree(hash); 106033dc9b12SSteven Rostedt } 106133dc9b12SSteven Rostedt 1062*07fd5515SSteven Rostedt static void __free_ftrace_hash_rcu(struct rcu_head *rcu) 1063*07fd5515SSteven Rostedt { 1064*07fd5515SSteven Rostedt struct ftrace_hash *hash; 1065*07fd5515SSteven Rostedt 1066*07fd5515SSteven Rostedt hash = container_of(rcu, struct ftrace_hash, rcu); 1067*07fd5515SSteven Rostedt free_ftrace_hash(hash); 1068*07fd5515SSteven Rostedt } 1069*07fd5515SSteven Rostedt 1070*07fd5515SSteven Rostedt static void free_ftrace_hash_rcu(struct ftrace_hash *hash) 1071*07fd5515SSteven Rostedt { 1072*07fd5515SSteven Rostedt if (!hash || hash == EMPTY_HASH) 1073*07fd5515SSteven Rostedt return; 1074*07fd5515SSteven Rostedt call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu); 1075*07fd5515SSteven Rostedt } 1076*07fd5515SSteven Rostedt 107733dc9b12SSteven Rostedt static struct ftrace_hash *alloc_ftrace_hash(int size_bits) 107833dc9b12SSteven Rostedt { 107933dc9b12SSteven Rostedt struct ftrace_hash *hash; 108033dc9b12SSteven Rostedt int size; 108133dc9b12SSteven Rostedt 108233dc9b12SSteven Rostedt hash = kzalloc(sizeof(*hash), GFP_KERNEL); 108333dc9b12SSteven Rostedt if (!hash) 108433dc9b12SSteven Rostedt return NULL; 108533dc9b12SSteven Rostedt 108633dc9b12SSteven Rostedt size = 1 << size_bits; 108733dc9b12SSteven Rostedt hash->buckets = kzalloc(sizeof(*hash->buckets) * size, GFP_KERNEL); 108833dc9b12SSteven Rostedt 108933dc9b12SSteven Rostedt if (!hash->buckets) { 109033dc9b12SSteven Rostedt kfree(hash); 109133dc9b12SSteven Rostedt return NULL; 109233dc9b12SSteven Rostedt } 109333dc9b12SSteven Rostedt 109433dc9b12SSteven Rostedt hash->size_bits = size_bits; 109533dc9b12SSteven Rostedt 109633dc9b12SSteven Rostedt return hash; 109733dc9b12SSteven Rostedt } 109833dc9b12SSteven Rostedt 109933dc9b12SSteven Rostedt static struct ftrace_hash * 110033dc9b12SSteven Rostedt alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) 110133dc9b12SSteven Rostedt { 110233dc9b12SSteven Rostedt struct ftrace_func_entry *entry; 110333dc9b12SSteven Rostedt struct ftrace_hash *new_hash; 110433dc9b12SSteven Rostedt struct hlist_node *tp; 110533dc9b12SSteven Rostedt int size; 110633dc9b12SSteven Rostedt int ret; 110733dc9b12SSteven Rostedt int i; 110833dc9b12SSteven Rostedt 110933dc9b12SSteven Rostedt new_hash = alloc_ftrace_hash(size_bits); 111033dc9b12SSteven Rostedt if (!new_hash) 111133dc9b12SSteven Rostedt return NULL; 111233dc9b12SSteven Rostedt 111333dc9b12SSteven Rostedt /* Empty hash? */ 111433dc9b12SSteven Rostedt if (!hash || !hash->count) 111533dc9b12SSteven Rostedt return new_hash; 111633dc9b12SSteven Rostedt 111733dc9b12SSteven Rostedt size = 1 << hash->size_bits; 111833dc9b12SSteven Rostedt for (i = 0; i < size; i++) { 111933dc9b12SSteven Rostedt hlist_for_each_entry(entry, tp, &hash->buckets[i], hlist) { 112033dc9b12SSteven Rostedt ret = add_hash_entry(new_hash, entry->ip); 112133dc9b12SSteven Rostedt if (ret < 0) 112233dc9b12SSteven Rostedt goto free_hash; 112333dc9b12SSteven Rostedt } 112433dc9b12SSteven Rostedt } 112533dc9b12SSteven Rostedt 112633dc9b12SSteven Rostedt FTRACE_WARN_ON(new_hash->count != hash->count); 112733dc9b12SSteven Rostedt 112833dc9b12SSteven Rostedt return new_hash; 112933dc9b12SSteven Rostedt 113033dc9b12SSteven Rostedt free_hash: 113133dc9b12SSteven Rostedt free_ftrace_hash(new_hash); 113233dc9b12SSteven Rostedt return NULL; 113333dc9b12SSteven Rostedt } 113433dc9b12SSteven Rostedt 113533dc9b12SSteven Rostedt static int 113633dc9b12SSteven Rostedt ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src) 113733dc9b12SSteven Rostedt { 113833dc9b12SSteven Rostedt struct ftrace_func_entry *entry; 113933dc9b12SSteven Rostedt struct hlist_node *tp, *tn; 114033dc9b12SSteven Rostedt struct hlist_head *hhd; 1141*07fd5515SSteven Rostedt struct ftrace_hash *old_hash; 1142*07fd5515SSteven Rostedt struct ftrace_hash *new_hash; 114333dc9b12SSteven Rostedt unsigned long key; 114433dc9b12SSteven Rostedt int size = src->count; 114533dc9b12SSteven Rostedt int bits = 0; 114633dc9b12SSteven Rostedt int i; 114733dc9b12SSteven Rostedt 114833dc9b12SSteven Rostedt /* 114933dc9b12SSteven Rostedt * If the new source is empty, just free dst and assign it 115033dc9b12SSteven Rostedt * the empty_hash. 115133dc9b12SSteven Rostedt */ 115233dc9b12SSteven Rostedt if (!src->count) { 1153*07fd5515SSteven Rostedt free_ftrace_hash_rcu(*dst); 1154*07fd5515SSteven Rostedt rcu_assign_pointer(*dst, EMPTY_HASH); 115533dc9b12SSteven Rostedt return 0; 115633dc9b12SSteven Rostedt } 115733dc9b12SSteven Rostedt 115833dc9b12SSteven Rostedt /* 115933dc9b12SSteven Rostedt * Make the hash size about 1/2 the # found 116033dc9b12SSteven Rostedt */ 116133dc9b12SSteven Rostedt for (size /= 2; size; size >>= 1) 116233dc9b12SSteven Rostedt bits++; 116333dc9b12SSteven Rostedt 116433dc9b12SSteven Rostedt /* Don't allocate too much */ 116533dc9b12SSteven Rostedt if (bits > FTRACE_HASH_MAX_BITS) 116633dc9b12SSteven Rostedt bits = FTRACE_HASH_MAX_BITS; 116733dc9b12SSteven Rostedt 1168*07fd5515SSteven Rostedt new_hash = alloc_ftrace_hash(bits); 1169*07fd5515SSteven Rostedt if (!new_hash) 117033dc9b12SSteven Rostedt return -ENOMEM; 117133dc9b12SSteven Rostedt 117233dc9b12SSteven Rostedt size = 1 << src->size_bits; 117333dc9b12SSteven Rostedt for (i = 0; i < size; i++) { 117433dc9b12SSteven Rostedt hhd = &src->buckets[i]; 117533dc9b12SSteven Rostedt hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) { 117633dc9b12SSteven Rostedt if (bits > 0) 117733dc9b12SSteven Rostedt key = hash_long(entry->ip, bits); 117833dc9b12SSteven Rostedt else 117933dc9b12SSteven Rostedt key = 0; 118033dc9b12SSteven Rostedt remove_hash_entry(src, entry); 1181*07fd5515SSteven Rostedt __add_hash_entry(new_hash, entry); 118233dc9b12SSteven Rostedt } 118333dc9b12SSteven Rostedt } 118433dc9b12SSteven Rostedt 1185*07fd5515SSteven Rostedt old_hash = *dst; 1186*07fd5515SSteven Rostedt rcu_assign_pointer(*dst, new_hash); 1187*07fd5515SSteven Rostedt free_ftrace_hash_rcu(old_hash); 1188*07fd5515SSteven Rostedt 118933dc9b12SSteven Rostedt return 0; 119033dc9b12SSteven Rostedt } 119133dc9b12SSteven Rostedt 1192265c831cSSteven Rostedt /* 1193265c831cSSteven Rostedt * This is a double for. Do not use 'break' to break out of the loop, 1194265c831cSSteven Rostedt * you must use a goto. 1195265c831cSSteven Rostedt */ 1196265c831cSSteven Rostedt #define do_for_each_ftrace_rec(pg, rec) \ 1197265c831cSSteven Rostedt for (pg = ftrace_pages_start; pg; pg = pg->next) { \ 1198265c831cSSteven Rostedt int _____i; \ 1199265c831cSSteven Rostedt for (_____i = 0; _____i < pg->index; _____i++) { \ 1200265c831cSSteven Rostedt rec = &pg->records[_____i]; 1201265c831cSSteven Rostedt 1202265c831cSSteven Rostedt #define while_for_each_ftrace_rec() \ 1203265c831cSSteven Rostedt } \ 1204265c831cSSteven Rostedt } 1205ecea656dSAbhishek Sagar 1206ed926f9bSSteven Rostedt static void __ftrace_hash_rec_update(struct ftrace_ops *ops, 1207ed926f9bSSteven Rostedt int filter_hash, 1208ed926f9bSSteven Rostedt bool inc) 1209ed926f9bSSteven Rostedt { 1210ed926f9bSSteven Rostedt struct ftrace_hash *hash; 1211ed926f9bSSteven Rostedt struct ftrace_hash *other_hash; 1212ed926f9bSSteven Rostedt struct ftrace_page *pg; 1213ed926f9bSSteven Rostedt struct dyn_ftrace *rec; 1214ed926f9bSSteven Rostedt int count = 0; 1215ed926f9bSSteven Rostedt int all = 0; 1216ed926f9bSSteven Rostedt 1217ed926f9bSSteven Rostedt /* Only update if the ops has been registered */ 1218ed926f9bSSteven Rostedt if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) 1219ed926f9bSSteven Rostedt return; 1220ed926f9bSSteven Rostedt 1221ed926f9bSSteven Rostedt /* 1222ed926f9bSSteven Rostedt * In the filter_hash case: 1223ed926f9bSSteven Rostedt * If the count is zero, we update all records. 1224ed926f9bSSteven Rostedt * Otherwise we just update the items in the hash. 1225ed926f9bSSteven Rostedt * 1226ed926f9bSSteven Rostedt * In the notrace_hash case: 1227ed926f9bSSteven Rostedt * We enable the update in the hash. 1228ed926f9bSSteven Rostedt * As disabling notrace means enabling the tracing, 1229ed926f9bSSteven Rostedt * and enabling notrace means disabling, the inc variable 1230ed926f9bSSteven Rostedt * gets inversed. 1231ed926f9bSSteven Rostedt */ 1232ed926f9bSSteven Rostedt if (filter_hash) { 1233ed926f9bSSteven Rostedt hash = ops->filter_hash; 1234ed926f9bSSteven Rostedt other_hash = ops->notrace_hash; 1235ed926f9bSSteven Rostedt if (!hash->count) 1236ed926f9bSSteven Rostedt all = 1; 1237ed926f9bSSteven Rostedt } else { 1238ed926f9bSSteven Rostedt inc = !inc; 1239ed926f9bSSteven Rostedt hash = ops->notrace_hash; 1240ed926f9bSSteven Rostedt other_hash = ops->filter_hash; 1241ed926f9bSSteven Rostedt /* 1242ed926f9bSSteven Rostedt * If the notrace hash has no items, 1243ed926f9bSSteven Rostedt * then there's nothing to do. 1244ed926f9bSSteven Rostedt */ 1245ed926f9bSSteven Rostedt if (!hash->count) 1246ed926f9bSSteven Rostedt return; 1247ed926f9bSSteven Rostedt } 1248ed926f9bSSteven Rostedt 1249ed926f9bSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 1250ed926f9bSSteven Rostedt int in_other_hash = 0; 1251ed926f9bSSteven Rostedt int in_hash = 0; 1252ed926f9bSSteven Rostedt int match = 0; 1253ed926f9bSSteven Rostedt 1254ed926f9bSSteven Rostedt if (all) { 1255ed926f9bSSteven Rostedt /* 1256ed926f9bSSteven Rostedt * Only the filter_hash affects all records. 1257ed926f9bSSteven Rostedt * Update if the record is not in the notrace hash. 1258ed926f9bSSteven Rostedt */ 1259ed926f9bSSteven Rostedt if (!ftrace_lookup_ip(other_hash, rec->ip)) 1260ed926f9bSSteven Rostedt match = 1; 1261ed926f9bSSteven Rostedt } else { 1262ed926f9bSSteven Rostedt in_hash = !!ftrace_lookup_ip(hash, rec->ip); 1263ed926f9bSSteven Rostedt in_other_hash = !!ftrace_lookup_ip(other_hash, rec->ip); 1264ed926f9bSSteven Rostedt 1265ed926f9bSSteven Rostedt /* 1266ed926f9bSSteven Rostedt * 1267ed926f9bSSteven Rostedt */ 1268ed926f9bSSteven Rostedt if (filter_hash && in_hash && !in_other_hash) 1269ed926f9bSSteven Rostedt match = 1; 1270ed926f9bSSteven Rostedt else if (!filter_hash && in_hash && 1271ed926f9bSSteven Rostedt (in_other_hash || !other_hash->count)) 1272ed926f9bSSteven Rostedt match = 1; 1273ed926f9bSSteven Rostedt } 1274ed926f9bSSteven Rostedt if (!match) 1275ed926f9bSSteven Rostedt continue; 1276ed926f9bSSteven Rostedt 1277ed926f9bSSteven Rostedt if (inc) { 1278ed926f9bSSteven Rostedt rec->flags++; 1279ed926f9bSSteven Rostedt if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX)) 1280ed926f9bSSteven Rostedt return; 1281ed926f9bSSteven Rostedt } else { 1282ed926f9bSSteven Rostedt if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0)) 1283ed926f9bSSteven Rostedt return; 1284ed926f9bSSteven Rostedt rec->flags--; 1285ed926f9bSSteven Rostedt } 1286ed926f9bSSteven Rostedt count++; 1287ed926f9bSSteven Rostedt /* Shortcut, if we handled all records, we are done. */ 1288ed926f9bSSteven Rostedt if (!all && count == hash->count) 1289ed926f9bSSteven Rostedt return; 1290ed926f9bSSteven Rostedt } while_for_each_ftrace_rec(); 1291ed926f9bSSteven Rostedt } 1292ed926f9bSSteven Rostedt 1293ed926f9bSSteven Rostedt static void ftrace_hash_rec_disable(struct ftrace_ops *ops, 1294ed926f9bSSteven Rostedt int filter_hash) 1295ed926f9bSSteven Rostedt { 1296ed926f9bSSteven Rostedt __ftrace_hash_rec_update(ops, filter_hash, 0); 1297ed926f9bSSteven Rostedt } 1298ed926f9bSSteven Rostedt 1299ed926f9bSSteven Rostedt static void ftrace_hash_rec_enable(struct ftrace_ops *ops, 1300ed926f9bSSteven Rostedt int filter_hash) 1301ed926f9bSSteven Rostedt { 1302ed926f9bSSteven Rostedt __ftrace_hash_rec_update(ops, filter_hash, 1); 1303ed926f9bSSteven Rostedt } 1304ed926f9bSSteven Rostedt 1305e309b41dSIngo Molnar static void ftrace_free_rec(struct dyn_ftrace *rec) 130637ad5084SSteven Rostedt { 1307ee000b7fSLai Jiangshan rec->freelist = ftrace_free_records; 130837ad5084SSteven Rostedt ftrace_free_records = rec; 130937ad5084SSteven Rostedt rec->flags |= FTRACE_FL_FREE; 131037ad5084SSteven Rostedt } 131137ad5084SSteven Rostedt 1312e309b41dSIngo Molnar static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip) 13133c1720f0SSteven Rostedt { 131437ad5084SSteven Rostedt struct dyn_ftrace *rec; 131537ad5084SSteven Rostedt 131637ad5084SSteven Rostedt /* First check for freed records */ 131737ad5084SSteven Rostedt if (ftrace_free_records) { 131837ad5084SSteven Rostedt rec = ftrace_free_records; 131937ad5084SSteven Rostedt 132037ad5084SSteven Rostedt if (unlikely(!(rec->flags & FTRACE_FL_FREE))) { 13216912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 132237ad5084SSteven Rostedt ftrace_free_records = NULL; 132337ad5084SSteven Rostedt return NULL; 132437ad5084SSteven Rostedt } 132537ad5084SSteven Rostedt 1326ee000b7fSLai Jiangshan ftrace_free_records = rec->freelist; 132737ad5084SSteven Rostedt memset(rec, 0, sizeof(*rec)); 132837ad5084SSteven Rostedt return rec; 132937ad5084SSteven Rostedt } 133037ad5084SSteven Rostedt 13313c1720f0SSteven Rostedt if (ftrace_pages->index == ENTRIES_PER_PAGE) { 133208f5ac90SSteven Rostedt if (!ftrace_pages->next) { 133308f5ac90SSteven Rostedt /* allocate another page */ 133408f5ac90SSteven Rostedt ftrace_pages->next = 133508f5ac90SSteven Rostedt (void *)get_zeroed_page(GFP_KERNEL); 13363c1720f0SSteven Rostedt if (!ftrace_pages->next) 13373c1720f0SSteven Rostedt return NULL; 133808f5ac90SSteven Rostedt } 13393c1720f0SSteven Rostedt ftrace_pages = ftrace_pages->next; 13403c1720f0SSteven Rostedt } 13413c1720f0SSteven Rostedt 13423c1720f0SSteven Rostedt return &ftrace_pages->records[ftrace_pages->index++]; 13433c1720f0SSteven Rostedt } 13443c1720f0SSteven Rostedt 134508f5ac90SSteven Rostedt static struct dyn_ftrace * 1346d61f82d0SSteven Rostedt ftrace_record_ip(unsigned long ip) 13473d083395SSteven Rostedt { 134808f5ac90SSteven Rostedt struct dyn_ftrace *rec; 13493d083395SSteven Rostedt 1350f3c7ac40SSteven Rostedt if (ftrace_disabled) 135108f5ac90SSteven Rostedt return NULL; 1352d61f82d0SSteven Rostedt 135308f5ac90SSteven Rostedt rec = ftrace_alloc_dyn_node(ip); 135408f5ac90SSteven Rostedt if (!rec) 135508f5ac90SSteven Rostedt return NULL; 13563d083395SSteven Rostedt 135708f5ac90SSteven Rostedt rec->ip = ip; 1358ee000b7fSLai Jiangshan rec->newlist = ftrace_new_addrs; 1359e94142a6SLai Jiangshan ftrace_new_addrs = rec; 13603d083395SSteven Rostedt 136108f5ac90SSteven Rostedt return rec; 13623d083395SSteven Rostedt } 13633d083395SSteven Rostedt 136405736a42SSteven Rostedt static void print_ip_ins(const char *fmt, unsigned char *p) 136505736a42SSteven Rostedt { 136605736a42SSteven Rostedt int i; 136705736a42SSteven Rostedt 136805736a42SSteven Rostedt printk(KERN_CONT "%s", fmt); 136905736a42SSteven Rostedt 137005736a42SSteven Rostedt for (i = 0; i < MCOUNT_INSN_SIZE; i++) 137105736a42SSteven Rostedt printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]); 137205736a42SSteven Rostedt } 137305736a42SSteven Rostedt 137431e88909SSteven Rostedt static void ftrace_bug(int failed, unsigned long ip) 13753c1720f0SSteven Rostedt { 1376b17e8a37SSteven Rostedt switch (failed) { 1377593eb8a2SSteven Rostedt case -EFAULT: 13786912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 137905736a42SSteven Rostedt pr_info("ftrace faulted on modifying "); 138005736a42SSteven Rostedt print_ip_sym(ip); 138105736a42SSteven Rostedt break; 1382593eb8a2SSteven Rostedt case -EINVAL: 13836912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 138405736a42SSteven Rostedt pr_info("ftrace failed to modify "); 138505736a42SSteven Rostedt print_ip_sym(ip); 138605736a42SSteven Rostedt print_ip_ins(" actual: ", (unsigned char *)ip); 138705736a42SSteven Rostedt printk(KERN_CONT "\n"); 138805736a42SSteven Rostedt break; 1389593eb8a2SSteven Rostedt case -EPERM: 13906912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 1391593eb8a2SSteven Rostedt pr_info("ftrace faulted on writing "); 1392593eb8a2SSteven Rostedt print_ip_sym(ip); 1393593eb8a2SSteven Rostedt break; 1394593eb8a2SSteven Rostedt default: 13956912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 1396593eb8a2SSteven Rostedt pr_info("ftrace faulted on unknown error "); 1397593eb8a2SSteven Rostedt print_ip_sym(ip); 139805736a42SSteven Rostedt } 1399b17e8a37SSteven Rostedt } 140005736a42SSteven Rostedt 14013d083395SSteven Rostedt 14022cfa1978SMasami Hiramatsu /* Return 1 if the address range is reserved for ftrace */ 14032cfa1978SMasami Hiramatsu int ftrace_text_reserved(void *start, void *end) 14042cfa1978SMasami Hiramatsu { 14052cfa1978SMasami Hiramatsu struct dyn_ftrace *rec; 14062cfa1978SMasami Hiramatsu struct ftrace_page *pg; 14072cfa1978SMasami Hiramatsu 14082cfa1978SMasami Hiramatsu do_for_each_ftrace_rec(pg, rec) { 14092cfa1978SMasami Hiramatsu if (rec->ip <= (unsigned long)end && 14102cfa1978SMasami Hiramatsu rec->ip + MCOUNT_INSN_SIZE > (unsigned long)start) 14112cfa1978SMasami Hiramatsu return 1; 14122cfa1978SMasami Hiramatsu } while_for_each_ftrace_rec(); 14132cfa1978SMasami Hiramatsu return 0; 14142cfa1978SMasami Hiramatsu } 14152cfa1978SMasami Hiramatsu 14162cfa1978SMasami Hiramatsu 14173d083395SSteven Rostedt static int 141831e88909SSteven Rostedt __ftrace_replace_code(struct dyn_ftrace *rec, int enable) 14193d083395SSteven Rostedt { 1420e7d3737eSFrederic Weisbecker unsigned long ftrace_addr; 142164fbcd16SXiao Guangrong unsigned long flag = 0UL; 1422e7d3737eSFrederic Weisbecker 1423f0001207SShaohua Li ftrace_addr = (unsigned long)FTRACE_ADDR; 14243d083395SSteven Rostedt 14253d083395SSteven Rostedt /* 1426ed926f9bSSteven Rostedt * If we are enabling tracing: 14273d083395SSteven Rostedt * 1428ed926f9bSSteven Rostedt * If the record has a ref count, then we need to enable it 1429ed926f9bSSteven Rostedt * because someone is using it. 14303d083395SSteven Rostedt * 1431ed926f9bSSteven Rostedt * Otherwise we make sure its disabled. 1432ed926f9bSSteven Rostedt * 1433ed926f9bSSteven Rostedt * If we are disabling tracing, then disable all records that 1434ed926f9bSSteven Rostedt * are enabled. 14353d083395SSteven Rostedt */ 1436ed926f9bSSteven Rostedt if (enable && (rec->flags & ~FTRACE_FL_MASK)) 143764fbcd16SXiao Guangrong flag = FTRACE_FL_ENABLED; 14383d083395SSteven Rostedt 143964fbcd16SXiao Guangrong /* If the state of this record hasn't changed, then do nothing */ 144064fbcd16SXiao Guangrong if ((rec->flags & FTRACE_FL_ENABLED) == flag) 144164fbcd16SXiao Guangrong return 0; 144264fbcd16SXiao Guangrong 144364fbcd16SXiao Guangrong if (flag) { 144464fbcd16SXiao Guangrong rec->flags |= FTRACE_FL_ENABLED; 1445e7d3737eSFrederic Weisbecker return ftrace_make_call(rec, ftrace_addr); 144664fbcd16SXiao Guangrong } 144764fbcd16SXiao Guangrong 144864fbcd16SXiao Guangrong rec->flags &= ~FTRACE_FL_ENABLED; 1449e7d3737eSFrederic Weisbecker return ftrace_make_nop(NULL, rec, ftrace_addr); 14503d083395SSteven Rostedt } 14513d083395SSteven Rostedt 14523d083395SSteven Rostedt static void ftrace_replace_code(int enable) 14533d083395SSteven Rostedt { 14543d083395SSteven Rostedt struct dyn_ftrace *rec; 14553d083395SSteven Rostedt struct ftrace_page *pg; 14566a24a244SSteven Rostedt int failed; 14573d083395SSteven Rostedt 145845a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 145945a4a237SSteven Rostedt return; 146045a4a237SSteven Rostedt 1461265c831cSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 1462d2c8c3eaSSteven Rostedt /* Skip over free records */ 1463d2c8c3eaSSteven Rostedt if (rec->flags & FTRACE_FL_FREE) 14643d083395SSteven Rostedt continue; 14653d083395SSteven Rostedt 146631e88909SSteven Rostedt failed = __ftrace_replace_code(rec, enable); 1467fa9d13cfSZhaolei if (failed) { 146831e88909SSteven Rostedt ftrace_bug(failed, rec->ip); 14694377245aSSteven Rostedt /* Stop processing */ 14704377245aSSteven Rostedt return; 14714377245aSSteven Rostedt } 1472265c831cSSteven Rostedt } while_for_each_ftrace_rec(); 14733d083395SSteven Rostedt } 14743c1720f0SSteven Rostedt 14753b47bfc1SSteven Rostedt static int 147631e88909SSteven Rostedt ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec) 14773c1720f0SSteven Rostedt { 147837ad5084SSteven Rostedt unsigned long ip; 1479492a7ea5SAbhishek Sagar int ret; 148037ad5084SSteven Rostedt 1481492a7ea5SAbhishek Sagar ip = rec->ip; 14823c1720f0SSteven Rostedt 148345a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 148445a4a237SSteven Rostedt return 0; 148545a4a237SSteven Rostedt 148625aac9dcSShaohua Li ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR); 14873d083395SSteven Rostedt if (ret) { 148831e88909SSteven Rostedt ftrace_bug(ret, ip); 14893d083395SSteven Rostedt return 0; 1490d61f82d0SSteven Rostedt } 1491d61f82d0SSteven Rostedt return 1; 14923d083395SSteven Rostedt } 14933d083395SSteven Rostedt 1494000ab691SSteven Rostedt /* 1495000ab691SSteven Rostedt * archs can override this function if they must do something 1496000ab691SSteven Rostedt * before the modifying code is performed. 1497000ab691SSteven Rostedt */ 1498000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_prepare(void) 1499000ab691SSteven Rostedt { 1500000ab691SSteven Rostedt return 0; 1501000ab691SSteven Rostedt } 1502000ab691SSteven Rostedt 1503000ab691SSteven Rostedt /* 1504000ab691SSteven Rostedt * archs can override this function if they must do something 1505000ab691SSteven Rostedt * after the modifying code is performed. 1506000ab691SSteven Rostedt */ 1507000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_post_process(void) 1508000ab691SSteven Rostedt { 1509000ab691SSteven Rostedt return 0; 1510000ab691SSteven Rostedt } 1511000ab691SSteven Rostedt 15123d083395SSteven Rostedt static int __ftrace_modify_code(void *data) 15133d083395SSteven Rostedt { 15143d083395SSteven Rostedt int *command = data; 15153d083395SSteven Rostedt 1516a3583244SSteven Rostedt if (*command & FTRACE_ENABLE_CALLS) 15173d083395SSteven Rostedt ftrace_replace_code(1); 1518a3583244SSteven Rostedt else if (*command & FTRACE_DISABLE_CALLS) 15193d083395SSteven Rostedt ftrace_replace_code(0); 15203d083395SSteven Rostedt 15213d083395SSteven Rostedt if (*command & FTRACE_UPDATE_TRACE_FUNC) 15223d083395SSteven Rostedt ftrace_update_ftrace_func(ftrace_trace_function); 15233d083395SSteven Rostedt 15245a45cfe1SSteven Rostedt if (*command & FTRACE_START_FUNC_RET) 15255a45cfe1SSteven Rostedt ftrace_enable_ftrace_graph_caller(); 15265a45cfe1SSteven Rostedt else if (*command & FTRACE_STOP_FUNC_RET) 15275a45cfe1SSteven Rostedt ftrace_disable_ftrace_graph_caller(); 15285a45cfe1SSteven Rostedt 15293d083395SSteven Rostedt return 0; 15303d083395SSteven Rostedt } 15313d083395SSteven Rostedt 1532e309b41dSIngo Molnar static void ftrace_run_update_code(int command) 15333d083395SSteven Rostedt { 1534000ab691SSteven Rostedt int ret; 1535000ab691SSteven Rostedt 1536000ab691SSteven Rostedt ret = ftrace_arch_code_modify_prepare(); 1537000ab691SSteven Rostedt FTRACE_WARN_ON(ret); 1538000ab691SSteven Rostedt if (ret) 1539000ab691SSteven Rostedt return; 1540000ab691SSteven Rostedt 1541784e2d76SRusty Russell stop_machine(__ftrace_modify_code, &command, NULL); 1542000ab691SSteven Rostedt 1543000ab691SSteven Rostedt ret = ftrace_arch_code_modify_post_process(); 1544000ab691SSteven Rostedt FTRACE_WARN_ON(ret); 15453d083395SSteven Rostedt } 15463d083395SSteven Rostedt 15473d083395SSteven Rostedt static ftrace_func_t saved_ftrace_func; 154860a7ecf4SSteven Rostedt static int ftrace_start_up; 1549df4fc315SSteven Rostedt 1550df4fc315SSteven Rostedt static void ftrace_startup_enable(int command) 1551df4fc315SSteven Rostedt { 1552df4fc315SSteven Rostedt if (saved_ftrace_func != ftrace_trace_function) { 1553df4fc315SSteven Rostedt saved_ftrace_func = ftrace_trace_function; 1554df4fc315SSteven Rostedt command |= FTRACE_UPDATE_TRACE_FUNC; 1555df4fc315SSteven Rostedt } 1556df4fc315SSteven Rostedt 1557df4fc315SSteven Rostedt if (!command || !ftrace_enabled) 1558df4fc315SSteven Rostedt return; 1559df4fc315SSteven Rostedt 1560df4fc315SSteven Rostedt ftrace_run_update_code(command); 1561df4fc315SSteven Rostedt } 15623d083395SSteven Rostedt 1563bd69c30bSSteven Rostedt static void ftrace_startup(struct ftrace_ops *ops, int command) 15643d083395SSteven Rostedt { 15654eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 15664eebcc81SSteven Rostedt return; 15674eebcc81SSteven Rostedt 156860a7ecf4SSteven Rostedt ftrace_start_up++; 1569d61f82d0SSteven Rostedt command |= FTRACE_ENABLE_CALLS; 15703d083395SSteven Rostedt 1571ed926f9bSSteven Rostedt ops->flags |= FTRACE_OPS_FL_ENABLED; 1572ed926f9bSSteven Rostedt if (ftrace_start_up == 1) 1573ed926f9bSSteven Rostedt ftrace_hash_rec_enable(ops, 1); 1574ed926f9bSSteven Rostedt 1575df4fc315SSteven Rostedt ftrace_startup_enable(command); 15763d083395SSteven Rostedt } 15773d083395SSteven Rostedt 1578bd69c30bSSteven Rostedt static void ftrace_shutdown(struct ftrace_ops *ops, int command) 15793d083395SSteven Rostedt { 15804eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 15814eebcc81SSteven Rostedt return; 15824eebcc81SSteven Rostedt 158360a7ecf4SSteven Rostedt ftrace_start_up--; 15849ea1a153SFrederic Weisbecker /* 15859ea1a153SFrederic Weisbecker * Just warn in case of unbalance, no need to kill ftrace, it's not 15869ea1a153SFrederic Weisbecker * critical but the ftrace_call callers may be never nopped again after 15879ea1a153SFrederic Weisbecker * further ftrace uses. 15889ea1a153SFrederic Weisbecker */ 15899ea1a153SFrederic Weisbecker WARN_ON_ONCE(ftrace_start_up < 0); 15909ea1a153SFrederic Weisbecker 159160a7ecf4SSteven Rostedt if (!ftrace_start_up) 1592ed926f9bSSteven Rostedt ftrace_hash_rec_disable(ops, 1); 1593ed926f9bSSteven Rostedt 1594ed926f9bSSteven Rostedt if (!ftrace_start_up) { 1595d61f82d0SSteven Rostedt command |= FTRACE_DISABLE_CALLS; 1596ed926f9bSSteven Rostedt ops->flags &= ~FTRACE_OPS_FL_ENABLED; 1597ed926f9bSSteven Rostedt } 1598d61f82d0SSteven Rostedt 1599d61f82d0SSteven Rostedt if (saved_ftrace_func != ftrace_trace_function) { 1600d61f82d0SSteven Rostedt saved_ftrace_func = ftrace_trace_function; 1601d61f82d0SSteven Rostedt command |= FTRACE_UPDATE_TRACE_FUNC; 1602d61f82d0SSteven Rostedt } 1603d61f82d0SSteven Rostedt 1604d61f82d0SSteven Rostedt if (!command || !ftrace_enabled) 1605e6ea44e9SSteven Rostedt return; 16063d083395SSteven Rostedt 1607d61f82d0SSteven Rostedt ftrace_run_update_code(command); 16083d083395SSteven Rostedt } 16093d083395SSteven Rostedt 1610e309b41dSIngo Molnar static void ftrace_startup_sysctl(void) 1611b0fc494fSSteven Rostedt { 16124eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 16134eebcc81SSteven Rostedt return; 16144eebcc81SSteven Rostedt 1615d61f82d0SSteven Rostedt /* Force update next time */ 1616d61f82d0SSteven Rostedt saved_ftrace_func = NULL; 161760a7ecf4SSteven Rostedt /* ftrace_start_up is true if we want ftrace running */ 161860a7ecf4SSteven Rostedt if (ftrace_start_up) 161979e406d7SSteven Rostedt ftrace_run_update_code(FTRACE_ENABLE_CALLS); 1620b0fc494fSSteven Rostedt } 1621b0fc494fSSteven Rostedt 1622e309b41dSIngo Molnar static void ftrace_shutdown_sysctl(void) 1623b0fc494fSSteven Rostedt { 16244eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 16254eebcc81SSteven Rostedt return; 16264eebcc81SSteven Rostedt 162760a7ecf4SSteven Rostedt /* ftrace_start_up is true if ftrace is running */ 162860a7ecf4SSteven Rostedt if (ftrace_start_up) 162979e406d7SSteven Rostedt ftrace_run_update_code(FTRACE_DISABLE_CALLS); 1630b0fc494fSSteven Rostedt } 1631b0fc494fSSteven Rostedt 16323d083395SSteven Rostedt static cycle_t ftrace_update_time; 16333d083395SSteven Rostedt static unsigned long ftrace_update_cnt; 16343d083395SSteven Rostedt unsigned long ftrace_update_tot_cnt; 16353d083395SSteven Rostedt 163631e88909SSteven Rostedt static int ftrace_update_code(struct module *mod) 16373d083395SSteven Rostedt { 1638e94142a6SLai Jiangshan struct dyn_ftrace *p; 1639f22f9a89SAbhishek Sagar cycle_t start, stop; 16403d083395SSteven Rostedt 1641750ed1a4SIngo Molnar start = ftrace_now(raw_smp_processor_id()); 16423d083395SSteven Rostedt ftrace_update_cnt = 0; 16433d083395SSteven Rostedt 1644e94142a6SLai Jiangshan while (ftrace_new_addrs) { 1645f22f9a89SAbhishek Sagar 164608f5ac90SSteven Rostedt /* If something went wrong, bail without enabling anything */ 164708f5ac90SSteven Rostedt if (unlikely(ftrace_disabled)) 164808f5ac90SSteven Rostedt return -1; 16493d083395SSteven Rostedt 1650e94142a6SLai Jiangshan p = ftrace_new_addrs; 1651ee000b7fSLai Jiangshan ftrace_new_addrs = p->newlist; 1652e94142a6SLai Jiangshan p->flags = 0L; 1653f22f9a89SAbhishek Sagar 16545cb084bbSJiri Olsa /* 165525985edcSLucas De Marchi * Do the initial record conversion from mcount jump 16565cb084bbSJiri Olsa * to the NOP instructions. 16575cb084bbSJiri Olsa */ 16585cb084bbSJiri Olsa if (!ftrace_code_disable(mod, p)) { 16595cb084bbSJiri Olsa ftrace_free_rec(p); 1660d2c8c3eaSSteven Rostedt /* Game over */ 1661d2c8c3eaSSteven Rostedt break; 16625cb084bbSJiri Olsa } 16635cb084bbSJiri Olsa 16643d083395SSteven Rostedt ftrace_update_cnt++; 16655cb084bbSJiri Olsa 16665cb084bbSJiri Olsa /* 16675cb084bbSJiri Olsa * If the tracing is enabled, go ahead and enable the record. 16685cb084bbSJiri Olsa * 16695cb084bbSJiri Olsa * The reason not to enable the record immediatelly is the 16705cb084bbSJiri Olsa * inherent check of ftrace_make_nop/ftrace_make_call for 16715cb084bbSJiri Olsa * correct previous instructions. Making first the NOP 16725cb084bbSJiri Olsa * conversion puts the module to the correct state, thus 16735cb084bbSJiri Olsa * passing the ftrace_make_call check. 16745cb084bbSJiri Olsa */ 16755cb084bbSJiri Olsa if (ftrace_start_up) { 16765cb084bbSJiri Olsa int failed = __ftrace_replace_code(p, 1); 16775cb084bbSJiri Olsa if (failed) { 16785cb084bbSJiri Olsa ftrace_bug(failed, p->ip); 16790eb96701SAbhishek Sagar ftrace_free_rec(p); 16803d083395SSteven Rostedt } 16815cb084bbSJiri Olsa } 16825cb084bbSJiri Olsa } 16833d083395SSteven Rostedt 1684750ed1a4SIngo Molnar stop = ftrace_now(raw_smp_processor_id()); 16853d083395SSteven Rostedt ftrace_update_time = stop - start; 16863d083395SSteven Rostedt ftrace_update_tot_cnt += ftrace_update_cnt; 16873d083395SSteven Rostedt 168816444a8aSArnaldo Carvalho de Melo return 0; 168916444a8aSArnaldo Carvalho de Melo } 169016444a8aSArnaldo Carvalho de Melo 169168bf21aaSSteven Rostedt static int __init ftrace_dyn_table_alloc(unsigned long num_to_init) 16923c1720f0SSteven Rostedt { 16933c1720f0SSteven Rostedt struct ftrace_page *pg; 16943c1720f0SSteven Rostedt int cnt; 16953c1720f0SSteven Rostedt int i; 16963c1720f0SSteven Rostedt 16973c1720f0SSteven Rostedt /* allocate a few pages */ 16983c1720f0SSteven Rostedt ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL); 16993c1720f0SSteven Rostedt if (!ftrace_pages_start) 17003c1720f0SSteven Rostedt return -1; 17013c1720f0SSteven Rostedt 17023c1720f0SSteven Rostedt /* 17033c1720f0SSteven Rostedt * Allocate a few more pages. 17043c1720f0SSteven Rostedt * 17053c1720f0SSteven Rostedt * TODO: have some parser search vmlinux before 17063c1720f0SSteven Rostedt * final linking to find all calls to ftrace. 17073c1720f0SSteven Rostedt * Then we can: 17083c1720f0SSteven Rostedt * a) know how many pages to allocate. 17093c1720f0SSteven Rostedt * and/or 17103c1720f0SSteven Rostedt * b) set up the table then. 17113c1720f0SSteven Rostedt * 17123c1720f0SSteven Rostedt * The dynamic code is still necessary for 17133c1720f0SSteven Rostedt * modules. 17143c1720f0SSteven Rostedt */ 17153c1720f0SSteven Rostedt 17163c1720f0SSteven Rostedt pg = ftrace_pages = ftrace_pages_start; 17173c1720f0SSteven Rostedt 171868bf21aaSSteven Rostedt cnt = num_to_init / ENTRIES_PER_PAGE; 171908f5ac90SSteven Rostedt pr_info("ftrace: allocating %ld entries in %d pages\n", 17205821e1b7Swalimis num_to_init, cnt + 1); 17213c1720f0SSteven Rostedt 17223c1720f0SSteven Rostedt for (i = 0; i < cnt; i++) { 17233c1720f0SSteven Rostedt pg->next = (void *)get_zeroed_page(GFP_KERNEL); 17243c1720f0SSteven Rostedt 17253c1720f0SSteven Rostedt /* If we fail, we'll try later anyway */ 17263c1720f0SSteven Rostedt if (!pg->next) 17273c1720f0SSteven Rostedt break; 17283c1720f0SSteven Rostedt 17293c1720f0SSteven Rostedt pg = pg->next; 17303c1720f0SSteven Rostedt } 17313c1720f0SSteven Rostedt 17323c1720f0SSteven Rostedt return 0; 17333c1720f0SSteven Rostedt } 17343c1720f0SSteven Rostedt 17355072c59fSSteven Rostedt enum { 17365072c59fSSteven Rostedt FTRACE_ITER_FILTER = (1 << 0), 1737689fd8b6S[email protected] FTRACE_ITER_NOTRACE = (1 << 1), 17383499e461SSteven Rostedt FTRACE_ITER_PRINTALL = (1 << 2), 17393499e461SSteven Rostedt FTRACE_ITER_HASH = (1 << 3), 1740647bcd03SSteven Rostedt FTRACE_ITER_ENABLED = (1 << 4), 17415072c59fSSteven Rostedt }; 17425072c59fSSteven Rostedt 17435072c59fSSteven Rostedt #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ 17445072c59fSSteven Rostedt 17455072c59fSSteven Rostedt struct ftrace_iterator { 174698c4fd04SSteven Rostedt loff_t pos; 17472bccfffdSSteven Rostedt loff_t func_pos; 17485072c59fSSteven Rostedt struct ftrace_page *pg; 17494aeb6967SSteven Rostedt struct dyn_ftrace *func; 17504aeb6967SSteven Rostedt struct ftrace_func_probe *probe; 17514aeb6967SSteven Rostedt struct trace_parser parser; 17521cf41dd7SSteven Rostedt struct ftrace_hash *hash; 175333dc9b12SSteven Rostedt struct ftrace_ops *ops; 17548fc0c701SSteven Rostedt int hidx; 1755431aa3fbSSteven Rostedt int idx; 17565072c59fSSteven Rostedt unsigned flags; 17575072c59fSSteven Rostedt }; 17585072c59fSSteven Rostedt 1759e309b41dSIngo Molnar static void * 17604aeb6967SSteven Rostedt t_hash_next(struct seq_file *m, loff_t *pos) 17618fc0c701SSteven Rostedt { 17628fc0c701SSteven Rostedt struct ftrace_iterator *iter = m->private; 17634aeb6967SSteven Rostedt struct hlist_node *hnd = NULL; 17648fc0c701SSteven Rostedt struct hlist_head *hhd; 17658fc0c701SSteven Rostedt 17668fc0c701SSteven Rostedt (*pos)++; 176798c4fd04SSteven Rostedt iter->pos = *pos; 17688fc0c701SSteven Rostedt 17694aeb6967SSteven Rostedt if (iter->probe) 17704aeb6967SSteven Rostedt hnd = &iter->probe->node; 17718fc0c701SSteven Rostedt retry: 17728fc0c701SSteven Rostedt if (iter->hidx >= FTRACE_FUNC_HASHSIZE) 17738fc0c701SSteven Rostedt return NULL; 17748fc0c701SSteven Rostedt 17758fc0c701SSteven Rostedt hhd = &ftrace_func_hash[iter->hidx]; 17768fc0c701SSteven Rostedt 17778fc0c701SSteven Rostedt if (hlist_empty(hhd)) { 17788fc0c701SSteven Rostedt iter->hidx++; 17798fc0c701SSteven Rostedt hnd = NULL; 17808fc0c701SSteven Rostedt goto retry; 17818fc0c701SSteven Rostedt } 17828fc0c701SSteven Rostedt 17838fc0c701SSteven Rostedt if (!hnd) 17848fc0c701SSteven Rostedt hnd = hhd->first; 17858fc0c701SSteven Rostedt else { 17868fc0c701SSteven Rostedt hnd = hnd->next; 17878fc0c701SSteven Rostedt if (!hnd) { 17888fc0c701SSteven Rostedt iter->hidx++; 17898fc0c701SSteven Rostedt goto retry; 17908fc0c701SSteven Rostedt } 17918fc0c701SSteven Rostedt } 17928fc0c701SSteven Rostedt 17934aeb6967SSteven Rostedt if (WARN_ON_ONCE(!hnd)) 17944aeb6967SSteven Rostedt return NULL; 17954aeb6967SSteven Rostedt 17964aeb6967SSteven Rostedt iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node); 17974aeb6967SSteven Rostedt 17984aeb6967SSteven Rostedt return iter; 17998fc0c701SSteven Rostedt } 18008fc0c701SSteven Rostedt 18018fc0c701SSteven Rostedt static void *t_hash_start(struct seq_file *m, loff_t *pos) 18028fc0c701SSteven Rostedt { 18038fc0c701SSteven Rostedt struct ftrace_iterator *iter = m->private; 18048fc0c701SSteven Rostedt void *p = NULL; 1805d82d6244SLi Zefan loff_t l; 1806d82d6244SLi Zefan 18072bccfffdSSteven Rostedt if (iter->func_pos > *pos) 18082bccfffdSSteven Rostedt return NULL; 18098fc0c701SSteven Rostedt 1810d82d6244SLi Zefan iter->hidx = 0; 18112bccfffdSSteven Rostedt for (l = 0; l <= (*pos - iter->func_pos); ) { 18124aeb6967SSteven Rostedt p = t_hash_next(m, &l); 1813d82d6244SLi Zefan if (!p) 1814d82d6244SLi Zefan break; 1815d82d6244SLi Zefan } 18164aeb6967SSteven Rostedt if (!p) 18174aeb6967SSteven Rostedt return NULL; 18184aeb6967SSteven Rostedt 181998c4fd04SSteven Rostedt /* Only set this if we have an item */ 182098c4fd04SSteven Rostedt iter->flags |= FTRACE_ITER_HASH; 182198c4fd04SSteven Rostedt 18224aeb6967SSteven Rostedt return iter; 18238fc0c701SSteven Rostedt } 18248fc0c701SSteven Rostedt 18254aeb6967SSteven Rostedt static int 18264aeb6967SSteven Rostedt t_hash_show(struct seq_file *m, struct ftrace_iterator *iter) 18278fc0c701SSteven Rostedt { 1828b6887d79SSteven Rostedt struct ftrace_func_probe *rec; 18298fc0c701SSteven Rostedt 18304aeb6967SSteven Rostedt rec = iter->probe; 18314aeb6967SSteven Rostedt if (WARN_ON_ONCE(!rec)) 18324aeb6967SSteven Rostedt return -EIO; 18338fc0c701SSteven Rostedt 1834809dcf29SSteven Rostedt if (rec->ops->print) 1835809dcf29SSteven Rostedt return rec->ops->print(m, rec->ip, rec->ops, rec->data); 1836809dcf29SSteven Rostedt 1837b375a11aSSteven Rostedt seq_printf(m, "%ps:%ps", (void *)rec->ip, (void *)rec->ops->func); 18388fc0c701SSteven Rostedt 18398fc0c701SSteven Rostedt if (rec->data) 18408fc0c701SSteven Rostedt seq_printf(m, ":%p", rec->data); 18418fc0c701SSteven Rostedt seq_putc(m, '\n'); 18428fc0c701SSteven Rostedt 18438fc0c701SSteven Rostedt return 0; 18448fc0c701SSteven Rostedt } 18458fc0c701SSteven Rostedt 18468fc0c701SSteven Rostedt static void * 18475072c59fSSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos) 18485072c59fSSteven Rostedt { 18495072c59fSSteven Rostedt struct ftrace_iterator *iter = m->private; 1850f45948e8SSteven Rostedt struct ftrace_ops *ops = &global_ops; 18515072c59fSSteven Rostedt struct dyn_ftrace *rec = NULL; 18525072c59fSSteven Rostedt 185345a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 185445a4a237SSteven Rostedt return NULL; 185545a4a237SSteven Rostedt 18568fc0c701SSteven Rostedt if (iter->flags & FTRACE_ITER_HASH) 18574aeb6967SSteven Rostedt return t_hash_next(m, pos); 18588fc0c701SSteven Rostedt 18595072c59fSSteven Rostedt (*pos)++; 18601106b699SJiri Olsa iter->pos = iter->func_pos = *pos; 18615072c59fSSteven Rostedt 18620c75a3edSSteven Rostedt if (iter->flags & FTRACE_ITER_PRINTALL) 186357c072c7SSteven Rostedt return t_hash_start(m, pos); 18640c75a3edSSteven Rostedt 18655072c59fSSteven Rostedt retry: 18665072c59fSSteven Rostedt if (iter->idx >= iter->pg->index) { 18675072c59fSSteven Rostedt if (iter->pg->next) { 18685072c59fSSteven Rostedt iter->pg = iter->pg->next; 18695072c59fSSteven Rostedt iter->idx = 0; 18705072c59fSSteven Rostedt goto retry; 18715072c59fSSteven Rostedt } 18725072c59fSSteven Rostedt } else { 18735072c59fSSteven Rostedt rec = &iter->pg->records[iter->idx++]; 1874a9fdda33SSteven Rostedt if ((rec->flags & FTRACE_FL_FREE) || 1875a9fdda33SSteven Rostedt 18760183fb1cSSteven Rostedt ((iter->flags & FTRACE_ITER_FILTER) && 1877f45948e8SSteven Rostedt !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) || 18780183fb1cSSteven Rostedt 187941c52c0dSSteven Rostedt ((iter->flags & FTRACE_ITER_NOTRACE) && 1880647bcd03SSteven Rostedt !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) || 1881647bcd03SSteven Rostedt 1882647bcd03SSteven Rostedt ((iter->flags & FTRACE_ITER_ENABLED) && 1883647bcd03SSteven Rostedt !(rec->flags & ~FTRACE_FL_MASK))) { 1884647bcd03SSteven Rostedt 18855072c59fSSteven Rostedt rec = NULL; 18865072c59fSSteven Rostedt goto retry; 18875072c59fSSteven Rostedt } 18885072c59fSSteven Rostedt } 18895072c59fSSteven Rostedt 18904aeb6967SSteven Rostedt if (!rec) 189157c072c7SSteven Rostedt return t_hash_start(m, pos); 18924aeb6967SSteven Rostedt 18934aeb6967SSteven Rostedt iter->func = rec; 18944aeb6967SSteven Rostedt 18954aeb6967SSteven Rostedt return iter; 18965072c59fSSteven Rostedt } 18975072c59fSSteven Rostedt 189898c4fd04SSteven Rostedt static void reset_iter_read(struct ftrace_iterator *iter) 189998c4fd04SSteven Rostedt { 190098c4fd04SSteven Rostedt iter->pos = 0; 190198c4fd04SSteven Rostedt iter->func_pos = 0; 190298c4fd04SSteven Rostedt iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH); 19035072c59fSSteven Rostedt } 19045072c59fSSteven Rostedt 19055072c59fSSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos) 19065072c59fSSteven Rostedt { 19075072c59fSSteven Rostedt struct ftrace_iterator *iter = m->private; 1908f45948e8SSteven Rostedt struct ftrace_ops *ops = &global_ops; 19095072c59fSSteven Rostedt void *p = NULL; 1910694ce0a5SLi Zefan loff_t l; 19115072c59fSSteven Rostedt 19128fc0c701SSteven Rostedt mutex_lock(&ftrace_lock); 191345a4a237SSteven Rostedt 191445a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 191545a4a237SSteven Rostedt return NULL; 191645a4a237SSteven Rostedt 19170c75a3edSSteven Rostedt /* 191898c4fd04SSteven Rostedt * If an lseek was done, then reset and start from beginning. 191998c4fd04SSteven Rostedt */ 192098c4fd04SSteven Rostedt if (*pos < iter->pos) 192198c4fd04SSteven Rostedt reset_iter_read(iter); 192298c4fd04SSteven Rostedt 192398c4fd04SSteven Rostedt /* 19240c75a3edSSteven Rostedt * For set_ftrace_filter reading, if we have the filter 19250c75a3edSSteven Rostedt * off, we can short cut and just print out that all 19260c75a3edSSteven Rostedt * functions are enabled. 19270c75a3edSSteven Rostedt */ 1928f45948e8SSteven Rostedt if (iter->flags & FTRACE_ITER_FILTER && !ops->filter_hash->count) { 19290c75a3edSSteven Rostedt if (*pos > 0) 19308fc0c701SSteven Rostedt return t_hash_start(m, pos); 19310c75a3edSSteven Rostedt iter->flags |= FTRACE_ITER_PRINTALL; 1932df091625SChris Wright /* reset in case of seek/pread */ 1933df091625SChris Wright iter->flags &= ~FTRACE_ITER_HASH; 19340c75a3edSSteven Rostedt return iter; 19350c75a3edSSteven Rostedt } 19360c75a3edSSteven Rostedt 19378fc0c701SSteven Rostedt if (iter->flags & FTRACE_ITER_HASH) 19388fc0c701SSteven Rostedt return t_hash_start(m, pos); 19398fc0c701SSteven Rostedt 194098c4fd04SSteven Rostedt /* 194198c4fd04SSteven Rostedt * Unfortunately, we need to restart at ftrace_pages_start 194298c4fd04SSteven Rostedt * every time we let go of the ftrace_mutex. This is because 194398c4fd04SSteven Rostedt * those pointers can change without the lock. 194498c4fd04SSteven Rostedt */ 1945694ce0a5SLi Zefan iter->pg = ftrace_pages_start; 1946694ce0a5SLi Zefan iter->idx = 0; 1947694ce0a5SLi Zefan for (l = 0; l <= *pos; ) { 1948694ce0a5SLi Zefan p = t_next(m, p, &l); 1949694ce0a5SLi Zefan if (!p) 1950694ce0a5SLi Zefan break; 195150cdaf08SLiming Wang } 19525821e1b7Swalimis 19534aeb6967SSteven Rostedt if (!p) { 19544aeb6967SSteven Rostedt if (iter->flags & FTRACE_ITER_FILTER) 19558fc0c701SSteven Rostedt return t_hash_start(m, pos); 19568fc0c701SSteven Rostedt 19574aeb6967SSteven Rostedt return NULL; 19584aeb6967SSteven Rostedt } 19594aeb6967SSteven Rostedt 19604aeb6967SSteven Rostedt return iter; 19615072c59fSSteven Rostedt } 19625072c59fSSteven Rostedt 19635072c59fSSteven Rostedt static void t_stop(struct seq_file *m, void *p) 19645072c59fSSteven Rostedt { 19658fc0c701SSteven Rostedt mutex_unlock(&ftrace_lock); 19665072c59fSSteven Rostedt } 19675072c59fSSteven Rostedt 19685072c59fSSteven Rostedt static int t_show(struct seq_file *m, void *v) 19695072c59fSSteven Rostedt { 19700c75a3edSSteven Rostedt struct ftrace_iterator *iter = m->private; 19714aeb6967SSteven Rostedt struct dyn_ftrace *rec; 19725072c59fSSteven Rostedt 19738fc0c701SSteven Rostedt if (iter->flags & FTRACE_ITER_HASH) 19744aeb6967SSteven Rostedt return t_hash_show(m, iter); 19758fc0c701SSteven Rostedt 19760c75a3edSSteven Rostedt if (iter->flags & FTRACE_ITER_PRINTALL) { 19770c75a3edSSteven Rostedt seq_printf(m, "#### all functions enabled ####\n"); 19780c75a3edSSteven Rostedt return 0; 19790c75a3edSSteven Rostedt } 19800c75a3edSSteven Rostedt 19814aeb6967SSteven Rostedt rec = iter->func; 19824aeb6967SSteven Rostedt 19835072c59fSSteven Rostedt if (!rec) 19845072c59fSSteven Rostedt return 0; 19855072c59fSSteven Rostedt 1986647bcd03SSteven Rostedt seq_printf(m, "%ps", (void *)rec->ip); 1987647bcd03SSteven Rostedt if (iter->flags & FTRACE_ITER_ENABLED) 1988647bcd03SSteven Rostedt seq_printf(m, " (%ld)", 1989647bcd03SSteven Rostedt rec->flags & ~FTRACE_FL_MASK); 1990647bcd03SSteven Rostedt seq_printf(m, "\n"); 19915072c59fSSteven Rostedt 19925072c59fSSteven Rostedt return 0; 19935072c59fSSteven Rostedt } 19945072c59fSSteven Rostedt 199588e9d34cSJames Morris static const struct seq_operations show_ftrace_seq_ops = { 19965072c59fSSteven Rostedt .start = t_start, 19975072c59fSSteven Rostedt .next = t_next, 19985072c59fSSteven Rostedt .stop = t_stop, 19995072c59fSSteven Rostedt .show = t_show, 20005072c59fSSteven Rostedt }; 20015072c59fSSteven Rostedt 2002e309b41dSIngo Molnar static int 20035072c59fSSteven Rostedt ftrace_avail_open(struct inode *inode, struct file *file) 20045072c59fSSteven Rostedt { 20055072c59fSSteven Rostedt struct ftrace_iterator *iter; 20065072c59fSSteven Rostedt int ret; 20075072c59fSSteven Rostedt 20084eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 20094eebcc81SSteven Rostedt return -ENODEV; 20104eebcc81SSteven Rostedt 20115072c59fSSteven Rostedt iter = kzalloc(sizeof(*iter), GFP_KERNEL); 20125072c59fSSteven Rostedt if (!iter) 20135072c59fSSteven Rostedt return -ENOMEM; 20145072c59fSSteven Rostedt 20155072c59fSSteven Rostedt iter->pg = ftrace_pages_start; 20165072c59fSSteven Rostedt 20175072c59fSSteven Rostedt ret = seq_open(file, &show_ftrace_seq_ops); 20185072c59fSSteven Rostedt if (!ret) { 20195072c59fSSteven Rostedt struct seq_file *m = file->private_data; 20204bf39a94SIngo Molnar 20215072c59fSSteven Rostedt m->private = iter; 20224bf39a94SIngo Molnar } else { 20235072c59fSSteven Rostedt kfree(iter); 20244bf39a94SIngo Molnar } 20255072c59fSSteven Rostedt 20265072c59fSSteven Rostedt return ret; 20275072c59fSSteven Rostedt } 20285072c59fSSteven Rostedt 2029647bcd03SSteven Rostedt static int 2030647bcd03SSteven Rostedt ftrace_enabled_open(struct inode *inode, struct file *file) 2031647bcd03SSteven Rostedt { 2032647bcd03SSteven Rostedt struct ftrace_iterator *iter; 2033647bcd03SSteven Rostedt int ret; 2034647bcd03SSteven Rostedt 2035647bcd03SSteven Rostedt if (unlikely(ftrace_disabled)) 2036647bcd03SSteven Rostedt return -ENODEV; 2037647bcd03SSteven Rostedt 2038647bcd03SSteven Rostedt iter = kzalloc(sizeof(*iter), GFP_KERNEL); 2039647bcd03SSteven Rostedt if (!iter) 2040647bcd03SSteven Rostedt return -ENOMEM; 2041647bcd03SSteven Rostedt 2042647bcd03SSteven Rostedt iter->pg = ftrace_pages_start; 2043647bcd03SSteven Rostedt iter->flags = FTRACE_ITER_ENABLED; 2044647bcd03SSteven Rostedt 2045647bcd03SSteven Rostedt ret = seq_open(file, &show_ftrace_seq_ops); 2046647bcd03SSteven Rostedt if (!ret) { 2047647bcd03SSteven Rostedt struct seq_file *m = file->private_data; 2048647bcd03SSteven Rostedt 2049647bcd03SSteven Rostedt m->private = iter; 2050647bcd03SSteven Rostedt } else { 2051647bcd03SSteven Rostedt kfree(iter); 2052647bcd03SSteven Rostedt } 2053647bcd03SSteven Rostedt 2054647bcd03SSteven Rostedt return ret; 2055647bcd03SSteven Rostedt } 2056647bcd03SSteven Rostedt 20571cf41dd7SSteven Rostedt static void ftrace_filter_reset(struct ftrace_hash *hash) 20585072c59fSSteven Rostedt { 205952baf119SSteven Rostedt mutex_lock(&ftrace_lock); 20601cf41dd7SSteven Rostedt ftrace_hash_clear(hash); 206152baf119SSteven Rostedt mutex_unlock(&ftrace_lock); 20625072c59fSSteven Rostedt } 20635072c59fSSteven Rostedt 2064e309b41dSIngo Molnar static int 2065f45948e8SSteven Rostedt ftrace_regex_open(struct ftrace_ops *ops, int flag, 20661cf41dd7SSteven Rostedt struct inode *inode, struct file *file) 20675072c59fSSteven Rostedt { 20685072c59fSSteven Rostedt struct ftrace_iterator *iter; 2069f45948e8SSteven Rostedt struct ftrace_hash *hash; 20705072c59fSSteven Rostedt int ret = 0; 20715072c59fSSteven Rostedt 20724eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 20734eebcc81SSteven Rostedt return -ENODEV; 20744eebcc81SSteven Rostedt 20755072c59fSSteven Rostedt iter = kzalloc(sizeof(*iter), GFP_KERNEL); 20765072c59fSSteven Rostedt if (!iter) 20775072c59fSSteven Rostedt return -ENOMEM; 20785072c59fSSteven Rostedt 2079689fd8b6S[email protected] if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) { 2080689fd8b6S[email protected] kfree(iter); 2081689fd8b6S[email protected] return -ENOMEM; 2082689fd8b6S[email protected] } 2083689fd8b6S[email protected] 2084f45948e8SSteven Rostedt if (flag & FTRACE_ITER_NOTRACE) 2085f45948e8SSteven Rostedt hash = ops->notrace_hash; 2086f45948e8SSteven Rostedt else 2087f45948e8SSteven Rostedt hash = ops->filter_hash; 2088f45948e8SSteven Rostedt 208933dc9b12SSteven Rostedt iter->ops = ops; 209033dc9b12SSteven Rostedt iter->flags = flag; 209133dc9b12SSteven Rostedt 209233dc9b12SSteven Rostedt if (file->f_mode & FMODE_WRITE) { 209333dc9b12SSteven Rostedt mutex_lock(&ftrace_lock); 209433dc9b12SSteven Rostedt iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); 209533dc9b12SSteven Rostedt mutex_unlock(&ftrace_lock); 209633dc9b12SSteven Rostedt 209733dc9b12SSteven Rostedt if (!iter->hash) { 209833dc9b12SSteven Rostedt trace_parser_put(&iter->parser); 209933dc9b12SSteven Rostedt kfree(iter); 210033dc9b12SSteven Rostedt return -ENOMEM; 210133dc9b12SSteven Rostedt } 210233dc9b12SSteven Rostedt } 21031cf41dd7SSteven Rostedt 210441c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 210533dc9b12SSteven Rostedt 21065072c59fSSteven Rostedt if ((file->f_mode & FMODE_WRITE) && 21078650ae32SSteven Rostedt (file->f_flags & O_TRUNC)) 210833dc9b12SSteven Rostedt ftrace_filter_reset(iter->hash); 21095072c59fSSteven Rostedt 21105072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) { 21115072c59fSSteven Rostedt iter->pg = ftrace_pages_start; 21125072c59fSSteven Rostedt 21135072c59fSSteven Rostedt ret = seq_open(file, &show_ftrace_seq_ops); 21145072c59fSSteven Rostedt if (!ret) { 21155072c59fSSteven Rostedt struct seq_file *m = file->private_data; 21165072c59fSSteven Rostedt m->private = iter; 211779fe249cSLi Zefan } else { 211833dc9b12SSteven Rostedt /* Failed */ 211933dc9b12SSteven Rostedt free_ftrace_hash(iter->hash); 212079fe249cSLi Zefan trace_parser_put(&iter->parser); 21215072c59fSSteven Rostedt kfree(iter); 212279fe249cSLi Zefan } 21235072c59fSSteven Rostedt } else 21245072c59fSSteven Rostedt file->private_data = iter; 212541c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 21265072c59fSSteven Rostedt 21275072c59fSSteven Rostedt return ret; 21285072c59fSSteven Rostedt } 21295072c59fSSteven Rostedt 213041c52c0dSSteven Rostedt static int 213141c52c0dSSteven Rostedt ftrace_filter_open(struct inode *inode, struct file *file) 213241c52c0dSSteven Rostedt { 2133f45948e8SSteven Rostedt return ftrace_regex_open(&global_ops, FTRACE_ITER_FILTER, 21341cf41dd7SSteven Rostedt inode, file); 213541c52c0dSSteven Rostedt } 213641c52c0dSSteven Rostedt 213741c52c0dSSteven Rostedt static int 213841c52c0dSSteven Rostedt ftrace_notrace_open(struct inode *inode, struct file *file) 213941c52c0dSSteven Rostedt { 2140f45948e8SSteven Rostedt return ftrace_regex_open(&global_ops, FTRACE_ITER_NOTRACE, 21411cf41dd7SSteven Rostedt inode, file); 214241c52c0dSSteven Rostedt } 214341c52c0dSSteven Rostedt 2144e309b41dSIngo Molnar static loff_t 214541c52c0dSSteven Rostedt ftrace_regex_lseek(struct file *file, loff_t offset, int origin) 21465072c59fSSteven Rostedt { 21475072c59fSSteven Rostedt loff_t ret; 21485072c59fSSteven Rostedt 21495072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) 21505072c59fSSteven Rostedt ret = seq_lseek(file, offset, origin); 21515072c59fSSteven Rostedt else 21525072c59fSSteven Rostedt file->f_pos = ret = 1; 21535072c59fSSteven Rostedt 21545072c59fSSteven Rostedt return ret; 21555072c59fSSteven Rostedt } 21565072c59fSSteven Rostedt 215764e7c440SSteven Rostedt static int ftrace_match(char *str, char *regex, int len, int type) 21589f4801e3SSteven Rostedt { 21599f4801e3SSteven Rostedt int matched = 0; 2160751e9983SLi Zefan int slen; 21619f4801e3SSteven Rostedt 21629f4801e3SSteven Rostedt switch (type) { 21639f4801e3SSteven Rostedt case MATCH_FULL: 21649f4801e3SSteven Rostedt if (strcmp(str, regex) == 0) 21659f4801e3SSteven Rostedt matched = 1; 21669f4801e3SSteven Rostedt break; 21679f4801e3SSteven Rostedt case MATCH_FRONT_ONLY: 21689f4801e3SSteven Rostedt if (strncmp(str, regex, len) == 0) 21699f4801e3SSteven Rostedt matched = 1; 21709f4801e3SSteven Rostedt break; 21719f4801e3SSteven Rostedt case MATCH_MIDDLE_ONLY: 21729f4801e3SSteven Rostedt if (strstr(str, regex)) 21739f4801e3SSteven Rostedt matched = 1; 21749f4801e3SSteven Rostedt break; 21759f4801e3SSteven Rostedt case MATCH_END_ONLY: 2176751e9983SLi Zefan slen = strlen(str); 2177751e9983SLi Zefan if (slen >= len && memcmp(str + slen - len, regex, len) == 0) 21789f4801e3SSteven Rostedt matched = 1; 21799f4801e3SSteven Rostedt break; 21809f4801e3SSteven Rostedt } 21819f4801e3SSteven Rostedt 21829f4801e3SSteven Rostedt return matched; 21839f4801e3SSteven Rostedt } 21849f4801e3SSteven Rostedt 2185b448c4e3SSteven Rostedt static int 21861cf41dd7SSteven Rostedt enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not) 218764e7c440SSteven Rostedt { 2188b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 2189b448c4e3SSteven Rostedt int ret = 0; 2190b448c4e3SSteven Rostedt 21911cf41dd7SSteven Rostedt entry = ftrace_lookup_ip(hash, rec->ip); 2192b448c4e3SSteven Rostedt if (not) { 2193b448c4e3SSteven Rostedt /* Do nothing if it doesn't exist */ 2194b448c4e3SSteven Rostedt if (!entry) 2195b448c4e3SSteven Rostedt return 0; 2196b448c4e3SSteven Rostedt 219733dc9b12SSteven Rostedt free_hash_entry(hash, entry); 2198b448c4e3SSteven Rostedt } else { 2199b448c4e3SSteven Rostedt /* Do nothing if it exists */ 2200b448c4e3SSteven Rostedt if (entry) 2201b448c4e3SSteven Rostedt return 0; 2202b448c4e3SSteven Rostedt 2203b448c4e3SSteven Rostedt ret = add_hash_entry(hash, rec->ip); 2204b448c4e3SSteven Rostedt } 2205b448c4e3SSteven Rostedt return ret; 2206996e87beSSteven Rostedt } 2207996e87beSSteven Rostedt 220864e7c440SSteven Rostedt static int 2209b9df92d2SSteven Rostedt ftrace_match_record(struct dyn_ftrace *rec, char *mod, 2210b9df92d2SSteven Rostedt char *regex, int len, int type) 221164e7c440SSteven Rostedt { 221264e7c440SSteven Rostedt char str[KSYM_SYMBOL_LEN]; 2213b9df92d2SSteven Rostedt char *modname; 221464e7c440SSteven Rostedt 2215b9df92d2SSteven Rostedt kallsyms_lookup(rec->ip, NULL, NULL, &modname, str); 2216b9df92d2SSteven Rostedt 2217b9df92d2SSteven Rostedt if (mod) { 2218b9df92d2SSteven Rostedt /* module lookup requires matching the module */ 2219b9df92d2SSteven Rostedt if (!modname || strcmp(modname, mod)) 2220b9df92d2SSteven Rostedt return 0; 2221b9df92d2SSteven Rostedt 2222b9df92d2SSteven Rostedt /* blank search means to match all funcs in the mod */ 2223b9df92d2SSteven Rostedt if (!len) 2224b9df92d2SSteven Rostedt return 1; 2225b9df92d2SSteven Rostedt } 2226b9df92d2SSteven Rostedt 222764e7c440SSteven Rostedt return ftrace_match(str, regex, len, type); 222864e7c440SSteven Rostedt } 222964e7c440SSteven Rostedt 22301cf41dd7SSteven Rostedt static int 22311cf41dd7SSteven Rostedt match_records(struct ftrace_hash *hash, char *buff, 22321cf41dd7SSteven Rostedt int len, char *mod, int not) 22339f4801e3SSteven Rostedt { 2234b9df92d2SSteven Rostedt unsigned search_len = 0; 22359f4801e3SSteven Rostedt struct ftrace_page *pg; 22369f4801e3SSteven Rostedt struct dyn_ftrace *rec; 2237b9df92d2SSteven Rostedt int type = MATCH_FULL; 2238b9df92d2SSteven Rostedt char *search = buff; 2239311d16daSLi Zefan int found = 0; 2240b448c4e3SSteven Rostedt int ret; 22419f4801e3SSteven Rostedt 2242b9df92d2SSteven Rostedt if (len) { 22433f6fe06dSFrederic Weisbecker type = filter_parse_regex(buff, len, &search, ¬); 22449f4801e3SSteven Rostedt search_len = strlen(search); 2245b9df92d2SSteven Rostedt } 2246b9df92d2SSteven Rostedt 224752baf119SSteven Rostedt mutex_lock(&ftrace_lock); 2248b9df92d2SSteven Rostedt 2249b9df92d2SSteven Rostedt if (unlikely(ftrace_disabled)) 2250b9df92d2SSteven Rostedt goto out_unlock; 2251b9df92d2SSteven Rostedt 2252265c831cSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 22535072c59fSSteven Rostedt 2254b9df92d2SSteven Rostedt if (ftrace_match_record(rec, mod, search, search_len, type)) { 22551cf41dd7SSteven Rostedt ret = enter_record(hash, rec, not); 2256b448c4e3SSteven Rostedt if (ret < 0) { 2257b448c4e3SSteven Rostedt found = ret; 2258b448c4e3SSteven Rostedt goto out_unlock; 2259b448c4e3SSteven Rostedt } 2260311d16daSLi Zefan found = 1; 22615072c59fSSteven Rostedt } 2262265c831cSSteven Rostedt } while_for_each_ftrace_rec(); 2263b9df92d2SSteven Rostedt out_unlock: 226452baf119SSteven Rostedt mutex_unlock(&ftrace_lock); 2265311d16daSLi Zefan 2266311d16daSLi Zefan return found; 22675072c59fSSteven Rostedt } 22685072c59fSSteven Rostedt 226964e7c440SSteven Rostedt static int 22701cf41dd7SSteven Rostedt ftrace_match_records(struct ftrace_hash *hash, char *buff, int len) 227164e7c440SSteven Rostedt { 22721cf41dd7SSteven Rostedt return match_records(hash, buff, len, NULL, 0); 227364e7c440SSteven Rostedt } 227464e7c440SSteven Rostedt 22751cf41dd7SSteven Rostedt static int 22761cf41dd7SSteven Rostedt ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod) 227764e7c440SSteven Rostedt { 227864e7c440SSteven Rostedt int not = 0; 22796a24a244SSteven Rostedt 228064e7c440SSteven Rostedt /* blank or '*' mean the same */ 228164e7c440SSteven Rostedt if (strcmp(buff, "*") == 0) 228264e7c440SSteven Rostedt buff[0] = 0; 228364e7c440SSteven Rostedt 228464e7c440SSteven Rostedt /* handle the case of 'dont filter this module' */ 228564e7c440SSteven Rostedt if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) { 228664e7c440SSteven Rostedt buff[0] = 0; 228764e7c440SSteven Rostedt not = 1; 228864e7c440SSteven Rostedt } 228964e7c440SSteven Rostedt 22901cf41dd7SSteven Rostedt return match_records(hash, buff, strlen(buff), mod, not); 229164e7c440SSteven Rostedt } 229264e7c440SSteven Rostedt 2293f6180773SSteven Rostedt /* 2294f6180773SSteven Rostedt * We register the module command as a template to show others how 2295f6180773SSteven Rostedt * to register the a command as well. 2296f6180773SSteven Rostedt */ 2297f6180773SSteven Rostedt 2298f6180773SSteven Rostedt static int 2299f6180773SSteven Rostedt ftrace_mod_callback(char *func, char *cmd, char *param, int enable) 2300f6180773SSteven Rostedt { 2301f45948e8SSteven Rostedt struct ftrace_ops *ops = &global_ops; 23021cf41dd7SSteven Rostedt struct ftrace_hash *hash; 2303f6180773SSteven Rostedt char *mod; 2304b448c4e3SSteven Rostedt int ret = -EINVAL; 2305f6180773SSteven Rostedt 2306f6180773SSteven Rostedt /* 2307f6180773SSteven Rostedt * cmd == 'mod' because we only registered this func 2308f6180773SSteven Rostedt * for the 'mod' ftrace_func_command. 2309f6180773SSteven Rostedt * But if you register one func with multiple commands, 2310f6180773SSteven Rostedt * you can tell which command was used by the cmd 2311f6180773SSteven Rostedt * parameter. 2312f6180773SSteven Rostedt */ 2313f6180773SSteven Rostedt 2314f6180773SSteven Rostedt /* we must have a module name */ 2315f6180773SSteven Rostedt if (!param) 2316b448c4e3SSteven Rostedt return ret; 2317f6180773SSteven Rostedt 2318f6180773SSteven Rostedt mod = strsep(¶m, ":"); 2319f6180773SSteven Rostedt if (!strlen(mod)) 2320b448c4e3SSteven Rostedt return ret; 2321f6180773SSteven Rostedt 23221cf41dd7SSteven Rostedt if (enable) 2323f45948e8SSteven Rostedt hash = ops->filter_hash; 23241cf41dd7SSteven Rostedt else 2325f45948e8SSteven Rostedt hash = ops->notrace_hash; 23261cf41dd7SSteven Rostedt 23271cf41dd7SSteven Rostedt ret = ftrace_match_module_records(hash, func, mod); 2328b448c4e3SSteven Rostedt if (!ret) 2329b448c4e3SSteven Rostedt ret = -EINVAL; 2330b448c4e3SSteven Rostedt if (ret < 0) 2331b448c4e3SSteven Rostedt return ret; 2332b448c4e3SSteven Rostedt 2333f6180773SSteven Rostedt return 0; 2334f6180773SSteven Rostedt } 2335f6180773SSteven Rostedt 2336f6180773SSteven Rostedt static struct ftrace_func_command ftrace_mod_cmd = { 2337f6180773SSteven Rostedt .name = "mod", 2338f6180773SSteven Rostedt .func = ftrace_mod_callback, 2339f6180773SSteven Rostedt }; 2340f6180773SSteven Rostedt 2341f6180773SSteven Rostedt static int __init ftrace_mod_cmd_init(void) 2342f6180773SSteven Rostedt { 2343f6180773SSteven Rostedt return register_ftrace_command(&ftrace_mod_cmd); 2344f6180773SSteven Rostedt } 2345f6180773SSteven Rostedt device_initcall(ftrace_mod_cmd_init); 2346f6180773SSteven Rostedt 234759df055fSSteven Rostedt static void 2348b6887d79SSteven Rostedt function_trace_probe_call(unsigned long ip, unsigned long parent_ip) 234959df055fSSteven Rostedt { 2350b6887d79SSteven Rostedt struct ftrace_func_probe *entry; 235159df055fSSteven Rostedt struct hlist_head *hhd; 235259df055fSSteven Rostedt struct hlist_node *n; 235359df055fSSteven Rostedt unsigned long key; 235459df055fSSteven Rostedt 235559df055fSSteven Rostedt key = hash_long(ip, FTRACE_HASH_BITS); 235659df055fSSteven Rostedt 235759df055fSSteven Rostedt hhd = &ftrace_func_hash[key]; 235859df055fSSteven Rostedt 235959df055fSSteven Rostedt if (hlist_empty(hhd)) 236059df055fSSteven Rostedt return; 236159df055fSSteven Rostedt 236259df055fSSteven Rostedt /* 236359df055fSSteven Rostedt * Disable preemption for these calls to prevent a RCU grace 236459df055fSSteven Rostedt * period. This syncs the hash iteration and freeing of items 236559df055fSSteven Rostedt * on the hash. rcu_read_lock is too dangerous here. 236659df055fSSteven Rostedt */ 23675168ae50SSteven Rostedt preempt_disable_notrace(); 236859df055fSSteven Rostedt hlist_for_each_entry_rcu(entry, n, hhd, node) { 236959df055fSSteven Rostedt if (entry->ip == ip) 237059df055fSSteven Rostedt entry->ops->func(ip, parent_ip, &entry->data); 237159df055fSSteven Rostedt } 23725168ae50SSteven Rostedt preempt_enable_notrace(); 237359df055fSSteven Rostedt } 237459df055fSSteven Rostedt 2375b6887d79SSteven Rostedt static struct ftrace_ops trace_probe_ops __read_mostly = 237659df055fSSteven Rostedt { 2377b6887d79SSteven Rostedt .func = function_trace_probe_call, 237859df055fSSteven Rostedt }; 237959df055fSSteven Rostedt 2380b6887d79SSteven Rostedt static int ftrace_probe_registered; 238159df055fSSteven Rostedt 2382b6887d79SSteven Rostedt static void __enable_ftrace_function_probe(void) 238359df055fSSteven Rostedt { 238459df055fSSteven Rostedt int i; 238559df055fSSteven Rostedt 2386b6887d79SSteven Rostedt if (ftrace_probe_registered) 238759df055fSSteven Rostedt return; 238859df055fSSteven Rostedt 238959df055fSSteven Rostedt for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 239059df055fSSteven Rostedt struct hlist_head *hhd = &ftrace_func_hash[i]; 239159df055fSSteven Rostedt if (hhd->first) 239259df055fSSteven Rostedt break; 239359df055fSSteven Rostedt } 239459df055fSSteven Rostedt /* Nothing registered? */ 239559df055fSSteven Rostedt if (i == FTRACE_FUNC_HASHSIZE) 239659df055fSSteven Rostedt return; 239759df055fSSteven Rostedt 2398b6887d79SSteven Rostedt __register_ftrace_function(&trace_probe_ops); 2399bd69c30bSSteven Rostedt ftrace_startup(&global_ops, 0); 2400b6887d79SSteven Rostedt ftrace_probe_registered = 1; 240159df055fSSteven Rostedt } 240259df055fSSteven Rostedt 2403b6887d79SSteven Rostedt static void __disable_ftrace_function_probe(void) 240459df055fSSteven Rostedt { 240559df055fSSteven Rostedt int i; 240659df055fSSteven Rostedt 2407b6887d79SSteven Rostedt if (!ftrace_probe_registered) 240859df055fSSteven Rostedt return; 240959df055fSSteven Rostedt 241059df055fSSteven Rostedt for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 241159df055fSSteven Rostedt struct hlist_head *hhd = &ftrace_func_hash[i]; 241259df055fSSteven Rostedt if (hhd->first) 241359df055fSSteven Rostedt return; 241459df055fSSteven Rostedt } 241559df055fSSteven Rostedt 241659df055fSSteven Rostedt /* no more funcs left */ 2417b6887d79SSteven Rostedt __unregister_ftrace_function(&trace_probe_ops); 2418bd69c30bSSteven Rostedt ftrace_shutdown(&global_ops, 0); 2419b6887d79SSteven Rostedt ftrace_probe_registered = 0; 242059df055fSSteven Rostedt } 242159df055fSSteven Rostedt 242259df055fSSteven Rostedt 242359df055fSSteven Rostedt static void ftrace_free_entry_rcu(struct rcu_head *rhp) 242459df055fSSteven Rostedt { 2425b6887d79SSteven Rostedt struct ftrace_func_probe *entry = 2426b6887d79SSteven Rostedt container_of(rhp, struct ftrace_func_probe, rcu); 242759df055fSSteven Rostedt 242859df055fSSteven Rostedt if (entry->ops->free) 242959df055fSSteven Rostedt entry->ops->free(&entry->data); 243059df055fSSteven Rostedt kfree(entry); 243159df055fSSteven Rostedt } 243259df055fSSteven Rostedt 243359df055fSSteven Rostedt 243459df055fSSteven Rostedt int 2435b6887d79SSteven Rostedt register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 243659df055fSSteven Rostedt void *data) 243759df055fSSteven Rostedt { 2438b6887d79SSteven Rostedt struct ftrace_func_probe *entry; 243959df055fSSteven Rostedt struct ftrace_page *pg; 244059df055fSSteven Rostedt struct dyn_ftrace *rec; 244159df055fSSteven Rostedt int type, len, not; 24426a24a244SSteven Rostedt unsigned long key; 244359df055fSSteven Rostedt int count = 0; 244459df055fSSteven Rostedt char *search; 244559df055fSSteven Rostedt 24463f6fe06dSFrederic Weisbecker type = filter_parse_regex(glob, strlen(glob), &search, ¬); 244759df055fSSteven Rostedt len = strlen(search); 244859df055fSSteven Rostedt 2449b6887d79SSteven Rostedt /* we do not support '!' for function probes */ 245059df055fSSteven Rostedt if (WARN_ON(not)) 245159df055fSSteven Rostedt return -EINVAL; 245259df055fSSteven Rostedt 245359df055fSSteven Rostedt mutex_lock(&ftrace_lock); 245459df055fSSteven Rostedt 245545a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 245645a4a237SSteven Rostedt goto out_unlock; 245745a4a237SSteven Rostedt 245859df055fSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 245959df055fSSteven Rostedt 2460b9df92d2SSteven Rostedt if (!ftrace_match_record(rec, NULL, search, len, type)) 246159df055fSSteven Rostedt continue; 246259df055fSSteven Rostedt 246359df055fSSteven Rostedt entry = kmalloc(sizeof(*entry), GFP_KERNEL); 246459df055fSSteven Rostedt if (!entry) { 2465b6887d79SSteven Rostedt /* If we did not process any, then return error */ 246659df055fSSteven Rostedt if (!count) 246759df055fSSteven Rostedt count = -ENOMEM; 246859df055fSSteven Rostedt goto out_unlock; 246959df055fSSteven Rostedt } 247059df055fSSteven Rostedt 247159df055fSSteven Rostedt count++; 247259df055fSSteven Rostedt 247359df055fSSteven Rostedt entry->data = data; 247459df055fSSteven Rostedt 247559df055fSSteven Rostedt /* 247659df055fSSteven Rostedt * The caller might want to do something special 247759df055fSSteven Rostedt * for each function we find. We call the callback 247859df055fSSteven Rostedt * to give the caller an opportunity to do so. 247959df055fSSteven Rostedt */ 248059df055fSSteven Rostedt if (ops->callback) { 248159df055fSSteven Rostedt if (ops->callback(rec->ip, &entry->data) < 0) { 248259df055fSSteven Rostedt /* caller does not like this func */ 248359df055fSSteven Rostedt kfree(entry); 248459df055fSSteven Rostedt continue; 248559df055fSSteven Rostedt } 248659df055fSSteven Rostedt } 248759df055fSSteven Rostedt 248859df055fSSteven Rostedt entry->ops = ops; 248959df055fSSteven Rostedt entry->ip = rec->ip; 249059df055fSSteven Rostedt 249159df055fSSteven Rostedt key = hash_long(entry->ip, FTRACE_HASH_BITS); 249259df055fSSteven Rostedt hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]); 249359df055fSSteven Rostedt 249459df055fSSteven Rostedt } while_for_each_ftrace_rec(); 2495b6887d79SSteven Rostedt __enable_ftrace_function_probe(); 249659df055fSSteven Rostedt 249759df055fSSteven Rostedt out_unlock: 249859df055fSSteven Rostedt mutex_unlock(&ftrace_lock); 249959df055fSSteven Rostedt 250059df055fSSteven Rostedt return count; 250159df055fSSteven Rostedt } 250259df055fSSteven Rostedt 250359df055fSSteven Rostedt enum { 2504b6887d79SSteven Rostedt PROBE_TEST_FUNC = 1, 2505b6887d79SSteven Rostedt PROBE_TEST_DATA = 2 250659df055fSSteven Rostedt }; 250759df055fSSteven Rostedt 250859df055fSSteven Rostedt static void 2509b6887d79SSteven Rostedt __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 251059df055fSSteven Rostedt void *data, int flags) 251159df055fSSteven Rostedt { 2512b6887d79SSteven Rostedt struct ftrace_func_probe *entry; 251359df055fSSteven Rostedt struct hlist_node *n, *tmp; 251459df055fSSteven Rostedt char str[KSYM_SYMBOL_LEN]; 251559df055fSSteven Rostedt int type = MATCH_FULL; 251659df055fSSteven Rostedt int i, len = 0; 251759df055fSSteven Rostedt char *search; 251859df055fSSteven Rostedt 2519b36461daSAtsushi Tsuji if (glob && (strcmp(glob, "*") == 0 || !strlen(glob))) 252059df055fSSteven Rostedt glob = NULL; 2521b36461daSAtsushi Tsuji else if (glob) { 252259df055fSSteven Rostedt int not; 252359df055fSSteven Rostedt 25243f6fe06dSFrederic Weisbecker type = filter_parse_regex(glob, strlen(glob), &search, ¬); 252559df055fSSteven Rostedt len = strlen(search); 252659df055fSSteven Rostedt 2527b6887d79SSteven Rostedt /* we do not support '!' for function probes */ 252859df055fSSteven Rostedt if (WARN_ON(not)) 252959df055fSSteven Rostedt return; 253059df055fSSteven Rostedt } 253159df055fSSteven Rostedt 253259df055fSSteven Rostedt mutex_lock(&ftrace_lock); 253359df055fSSteven Rostedt for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 253459df055fSSteven Rostedt struct hlist_head *hhd = &ftrace_func_hash[i]; 253559df055fSSteven Rostedt 253659df055fSSteven Rostedt hlist_for_each_entry_safe(entry, n, tmp, hhd, node) { 253759df055fSSteven Rostedt 253859df055fSSteven Rostedt /* break up if statements for readability */ 2539b6887d79SSteven Rostedt if ((flags & PROBE_TEST_FUNC) && entry->ops != ops) 254059df055fSSteven Rostedt continue; 254159df055fSSteven Rostedt 2542b6887d79SSteven Rostedt if ((flags & PROBE_TEST_DATA) && entry->data != data) 254359df055fSSteven Rostedt continue; 254459df055fSSteven Rostedt 254559df055fSSteven Rostedt /* do this last, since it is the most expensive */ 254659df055fSSteven Rostedt if (glob) { 254759df055fSSteven Rostedt kallsyms_lookup(entry->ip, NULL, NULL, 254859df055fSSteven Rostedt NULL, str); 254959df055fSSteven Rostedt if (!ftrace_match(str, glob, len, type)) 255059df055fSSteven Rostedt continue; 255159df055fSSteven Rostedt } 255259df055fSSteven Rostedt 255359df055fSSteven Rostedt hlist_del(&entry->node); 255459df055fSSteven Rostedt call_rcu(&entry->rcu, ftrace_free_entry_rcu); 255559df055fSSteven Rostedt } 255659df055fSSteven Rostedt } 2557b6887d79SSteven Rostedt __disable_ftrace_function_probe(); 255859df055fSSteven Rostedt mutex_unlock(&ftrace_lock); 255959df055fSSteven Rostedt } 256059df055fSSteven Rostedt 256159df055fSSteven Rostedt void 2562b6887d79SSteven Rostedt unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 256359df055fSSteven Rostedt void *data) 256459df055fSSteven Rostedt { 2565b6887d79SSteven Rostedt __unregister_ftrace_function_probe(glob, ops, data, 2566b6887d79SSteven Rostedt PROBE_TEST_FUNC | PROBE_TEST_DATA); 256759df055fSSteven Rostedt } 256859df055fSSteven Rostedt 256959df055fSSteven Rostedt void 2570b6887d79SSteven Rostedt unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops) 257159df055fSSteven Rostedt { 2572b6887d79SSteven Rostedt __unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC); 257359df055fSSteven Rostedt } 257459df055fSSteven Rostedt 2575b6887d79SSteven Rostedt void unregister_ftrace_function_probe_all(char *glob) 257659df055fSSteven Rostedt { 2577b6887d79SSteven Rostedt __unregister_ftrace_function_probe(glob, NULL, NULL, 0); 257859df055fSSteven Rostedt } 257959df055fSSteven Rostedt 2580f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands); 2581f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex); 2582f6180773SSteven Rostedt 2583f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd) 2584f6180773SSteven Rostedt { 2585f6180773SSteven Rostedt struct ftrace_func_command *p; 2586f6180773SSteven Rostedt int ret = 0; 2587f6180773SSteven Rostedt 2588f6180773SSteven Rostedt mutex_lock(&ftrace_cmd_mutex); 2589f6180773SSteven Rostedt list_for_each_entry(p, &ftrace_commands, list) { 2590f6180773SSteven Rostedt if (strcmp(cmd->name, p->name) == 0) { 2591f6180773SSteven Rostedt ret = -EBUSY; 2592f6180773SSteven Rostedt goto out_unlock; 2593f6180773SSteven Rostedt } 2594f6180773SSteven Rostedt } 2595f6180773SSteven Rostedt list_add(&cmd->list, &ftrace_commands); 2596f6180773SSteven Rostedt out_unlock: 2597f6180773SSteven Rostedt mutex_unlock(&ftrace_cmd_mutex); 2598f6180773SSteven Rostedt 2599f6180773SSteven Rostedt return ret; 2600f6180773SSteven Rostedt } 2601f6180773SSteven Rostedt 2602f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd) 2603f6180773SSteven Rostedt { 2604f6180773SSteven Rostedt struct ftrace_func_command *p, *n; 2605f6180773SSteven Rostedt int ret = -ENODEV; 2606f6180773SSteven Rostedt 2607f6180773SSteven Rostedt mutex_lock(&ftrace_cmd_mutex); 2608f6180773SSteven Rostedt list_for_each_entry_safe(p, n, &ftrace_commands, list) { 2609f6180773SSteven Rostedt if (strcmp(cmd->name, p->name) == 0) { 2610f6180773SSteven Rostedt ret = 0; 2611f6180773SSteven Rostedt list_del_init(&p->list); 2612f6180773SSteven Rostedt goto out_unlock; 2613f6180773SSteven Rostedt } 2614f6180773SSteven Rostedt } 2615f6180773SSteven Rostedt out_unlock: 2616f6180773SSteven Rostedt mutex_unlock(&ftrace_cmd_mutex); 2617f6180773SSteven Rostedt 2618f6180773SSteven Rostedt return ret; 2619f6180773SSteven Rostedt } 2620f6180773SSteven Rostedt 262133dc9b12SSteven Rostedt static int ftrace_process_regex(struct ftrace_hash *hash, 262233dc9b12SSteven Rostedt char *buff, int len, int enable) 262364e7c440SSteven Rostedt { 2624f6180773SSteven Rostedt char *func, *command, *next = buff; 26256a24a244SSteven Rostedt struct ftrace_func_command *p; 2626b448c4e3SSteven Rostedt int ret; 262764e7c440SSteven Rostedt 262864e7c440SSteven Rostedt func = strsep(&next, ":"); 262964e7c440SSteven Rostedt 263064e7c440SSteven Rostedt if (!next) { 26311cf41dd7SSteven Rostedt ret = ftrace_match_records(hash, func, len); 2632b448c4e3SSteven Rostedt if (!ret) 2633b448c4e3SSteven Rostedt ret = -EINVAL; 2634b448c4e3SSteven Rostedt if (ret < 0) 2635311d16daSLi Zefan return ret; 2636b448c4e3SSteven Rostedt return 0; 263764e7c440SSteven Rostedt } 263864e7c440SSteven Rostedt 2639f6180773SSteven Rostedt /* command found */ 264064e7c440SSteven Rostedt 264164e7c440SSteven Rostedt command = strsep(&next, ":"); 264264e7c440SSteven Rostedt 2643f6180773SSteven Rostedt mutex_lock(&ftrace_cmd_mutex); 2644f6180773SSteven Rostedt list_for_each_entry(p, &ftrace_commands, list) { 2645f6180773SSteven Rostedt if (strcmp(p->name, command) == 0) { 2646f6180773SSteven Rostedt ret = p->func(func, command, next, enable); 2647f6180773SSteven Rostedt goto out_unlock; 264864e7c440SSteven Rostedt } 2649f6180773SSteven Rostedt } 2650f6180773SSteven Rostedt out_unlock: 2651f6180773SSteven Rostedt mutex_unlock(&ftrace_cmd_mutex); 265264e7c440SSteven Rostedt 2653f6180773SSteven Rostedt return ret; 265464e7c440SSteven Rostedt } 265564e7c440SSteven Rostedt 2656e309b41dSIngo Molnar static ssize_t 265741c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf, 265841c52c0dSSteven Rostedt size_t cnt, loff_t *ppos, int enable) 26595072c59fSSteven Rostedt { 26605072c59fSSteven Rostedt struct ftrace_iterator *iter; 2661689fd8b6S[email protected] struct trace_parser *parser; 2662689fd8b6S[email protected] ssize_t ret, read; 26635072c59fSSteven Rostedt 26644ba7978eSLi Zefan if (!cnt) 26655072c59fSSteven Rostedt return 0; 26665072c59fSSteven Rostedt 266741c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 26685072c59fSSteven Rostedt 266945a4a237SSteven Rostedt ret = -ENODEV; 267045a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 267145a4a237SSteven Rostedt goto out_unlock; 267245a4a237SSteven Rostedt 26735072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) { 26745072c59fSSteven Rostedt struct seq_file *m = file->private_data; 26755072c59fSSteven Rostedt iter = m->private; 26765072c59fSSteven Rostedt } else 26775072c59fSSteven Rostedt iter = file->private_data; 26785072c59fSSteven Rostedt 2679689fd8b6S[email protected] parser = &iter->parser; 2680689fd8b6S[email protected] read = trace_get_user(parser, ubuf, cnt, ppos); 26815072c59fSSteven Rostedt 26824ba7978eSLi Zefan if (read >= 0 && trace_parser_loaded(parser) && 2683689fd8b6S[email protected] !trace_parser_cont(parser)) { 268433dc9b12SSteven Rostedt ret = ftrace_process_regex(iter->hash, parser->buffer, 2685689fd8b6S[email protected] parser->idx, enable); 2686313254a9SLi Zefan trace_parser_clear(parser); 26875072c59fSSteven Rostedt if (ret) 2688ed146b25SLi Zefan goto out_unlock; 26895072c59fSSteven Rostedt } 26905072c59fSSteven Rostedt 26915072c59fSSteven Rostedt ret = read; 2692ed146b25SLi Zefan out_unlock: 269341c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 2694ed146b25SLi Zefan 26955072c59fSSteven Rostedt return ret; 26965072c59fSSteven Rostedt } 26975072c59fSSteven Rostedt 269841c52c0dSSteven Rostedt static ssize_t 269941c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf, 270041c52c0dSSteven Rostedt size_t cnt, loff_t *ppos) 270141c52c0dSSteven Rostedt { 270241c52c0dSSteven Rostedt return ftrace_regex_write(file, ubuf, cnt, ppos, 1); 270341c52c0dSSteven Rostedt } 270441c52c0dSSteven Rostedt 270541c52c0dSSteven Rostedt static ssize_t 270641c52c0dSSteven Rostedt ftrace_notrace_write(struct file *file, const char __user *ubuf, 270741c52c0dSSteven Rostedt size_t cnt, loff_t *ppos) 270841c52c0dSSteven Rostedt { 270941c52c0dSSteven Rostedt return ftrace_regex_write(file, ubuf, cnt, ppos, 0); 271041c52c0dSSteven Rostedt } 271141c52c0dSSteven Rostedt 271233dc9b12SSteven Rostedt static int 2713f45948e8SSteven Rostedt ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, 2714f45948e8SSteven Rostedt int reset, int enable) 271541c52c0dSSteven Rostedt { 271633dc9b12SSteven Rostedt struct ftrace_hash **orig_hash; 2717f45948e8SSteven Rostedt struct ftrace_hash *hash; 271833dc9b12SSteven Rostedt int ret; 2719f45948e8SSteven Rostedt 272041c52c0dSSteven Rostedt if (unlikely(ftrace_disabled)) 272133dc9b12SSteven Rostedt return -ENODEV; 272241c52c0dSSteven Rostedt 2723f45948e8SSteven Rostedt if (enable) 272433dc9b12SSteven Rostedt orig_hash = &ops->filter_hash; 2725f45948e8SSteven Rostedt else 272633dc9b12SSteven Rostedt orig_hash = &ops->notrace_hash; 272733dc9b12SSteven Rostedt 272833dc9b12SSteven Rostedt hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 272933dc9b12SSteven Rostedt if (!hash) 273033dc9b12SSteven Rostedt return -ENOMEM; 2731f45948e8SSteven Rostedt 273241c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 273341c52c0dSSteven Rostedt if (reset) 27341cf41dd7SSteven Rostedt ftrace_filter_reset(hash); 273541c52c0dSSteven Rostedt if (buf) 27361cf41dd7SSteven Rostedt ftrace_match_records(hash, buf, len); 273733dc9b12SSteven Rostedt 273833dc9b12SSteven Rostedt mutex_lock(&ftrace_lock); 273933dc9b12SSteven Rostedt ret = ftrace_hash_move(orig_hash, hash); 274033dc9b12SSteven Rostedt mutex_unlock(&ftrace_lock); 274133dc9b12SSteven Rostedt 274241c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 274333dc9b12SSteven Rostedt 274433dc9b12SSteven Rostedt free_ftrace_hash(hash); 274533dc9b12SSteven Rostedt return ret; 274641c52c0dSSteven Rostedt } 274741c52c0dSSteven Rostedt 274877a2b37dSSteven Rostedt /** 274977a2b37dSSteven Rostedt * ftrace_set_filter - set a function to filter on in ftrace 275077a2b37dSSteven Rostedt * @buf - the string that holds the function filter text. 275177a2b37dSSteven Rostedt * @len - the length of the string. 275277a2b37dSSteven Rostedt * @reset - non zero to reset all filters before applying this filter. 275377a2b37dSSteven Rostedt * 275477a2b37dSSteven Rostedt * Filters denote which functions should be enabled when tracing is enabled. 275577a2b37dSSteven Rostedt * If @buf is NULL and reset is set, all functions will be enabled for tracing. 275677a2b37dSSteven Rostedt */ 2757e309b41dSIngo Molnar void ftrace_set_filter(unsigned char *buf, int len, int reset) 275877a2b37dSSteven Rostedt { 2759f45948e8SSteven Rostedt ftrace_set_regex(&global_ops, buf, len, reset, 1); 276041c52c0dSSteven Rostedt } 27614eebcc81SSteven Rostedt 276241c52c0dSSteven Rostedt /** 276341c52c0dSSteven Rostedt * ftrace_set_notrace - set a function to not trace in ftrace 276441c52c0dSSteven Rostedt * @buf - the string that holds the function notrace text. 276541c52c0dSSteven Rostedt * @len - the length of the string. 276641c52c0dSSteven Rostedt * @reset - non zero to reset all filters before applying this filter. 276741c52c0dSSteven Rostedt * 276841c52c0dSSteven Rostedt * Notrace Filters denote which functions should not be enabled when tracing 276941c52c0dSSteven Rostedt * is enabled. If @buf is NULL and reset is set, all functions will be enabled 277041c52c0dSSteven Rostedt * for tracing. 277141c52c0dSSteven Rostedt */ 277241c52c0dSSteven Rostedt void ftrace_set_notrace(unsigned char *buf, int len, int reset) 277341c52c0dSSteven Rostedt { 2774f45948e8SSteven Rostedt ftrace_set_regex(&global_ops, buf, len, reset, 0); 277577a2b37dSSteven Rostedt } 277677a2b37dSSteven Rostedt 27772af15d6aSSteven Rostedt /* 27782af15d6aSSteven Rostedt * command line interface to allow users to set filters on boot up. 27792af15d6aSSteven Rostedt */ 27802af15d6aSSteven Rostedt #define FTRACE_FILTER_SIZE COMMAND_LINE_SIZE 27812af15d6aSSteven Rostedt static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata; 27822af15d6aSSteven Rostedt static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata; 27832af15d6aSSteven Rostedt 27842af15d6aSSteven Rostedt static int __init set_ftrace_notrace(char *str) 27852af15d6aSSteven Rostedt { 27862af15d6aSSteven Rostedt strncpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE); 27872af15d6aSSteven Rostedt return 1; 27882af15d6aSSteven Rostedt } 27892af15d6aSSteven Rostedt __setup("ftrace_notrace=", set_ftrace_notrace); 27902af15d6aSSteven Rostedt 27912af15d6aSSteven Rostedt static int __init set_ftrace_filter(char *str) 27922af15d6aSSteven Rostedt { 27932af15d6aSSteven Rostedt strncpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE); 27942af15d6aSSteven Rostedt return 1; 27952af15d6aSSteven Rostedt } 27962af15d6aSSteven Rostedt __setup("ftrace_filter=", set_ftrace_filter); 27972af15d6aSSteven Rostedt 2798369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER 2799f6060f46SLai Jiangshan static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata; 2800801c29fdSSteven Rostedt static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); 2801801c29fdSSteven Rostedt 2802369bc18fSStefan Assmann static int __init set_graph_function(char *str) 2803369bc18fSStefan Assmann { 280406f43d66SFrederic Weisbecker strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE); 2805369bc18fSStefan Assmann return 1; 2806369bc18fSStefan Assmann } 2807369bc18fSStefan Assmann __setup("ftrace_graph_filter=", set_graph_function); 2808369bc18fSStefan Assmann 2809369bc18fSStefan Assmann static void __init set_ftrace_early_graph(char *buf) 2810369bc18fSStefan Assmann { 2811369bc18fSStefan Assmann int ret; 2812369bc18fSStefan Assmann char *func; 2813369bc18fSStefan Assmann 2814369bc18fSStefan Assmann while (buf) { 2815369bc18fSStefan Assmann func = strsep(&buf, ","); 2816369bc18fSStefan Assmann /* we allow only one expression at a time */ 2817369bc18fSStefan Assmann ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, 2818369bc18fSStefan Assmann func); 2819369bc18fSStefan Assmann if (ret) 2820369bc18fSStefan Assmann printk(KERN_DEBUG "ftrace: function %s not " 2821369bc18fSStefan Assmann "traceable\n", func); 2822369bc18fSStefan Assmann } 2823369bc18fSStefan Assmann } 2824369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 2825369bc18fSStefan Assmann 2826f45948e8SSteven Rostedt static void __init 2827f45948e8SSteven Rostedt set_ftrace_early_filter(struct ftrace_ops *ops, char *buf, int enable) 28282af15d6aSSteven Rostedt { 28292af15d6aSSteven Rostedt char *func; 28302af15d6aSSteven Rostedt 28312af15d6aSSteven Rostedt while (buf) { 28322af15d6aSSteven Rostedt func = strsep(&buf, ","); 2833f45948e8SSteven Rostedt ftrace_set_regex(ops, func, strlen(func), 0, enable); 28342af15d6aSSteven Rostedt } 28352af15d6aSSteven Rostedt } 28362af15d6aSSteven Rostedt 28372af15d6aSSteven Rostedt static void __init set_ftrace_early_filters(void) 28382af15d6aSSteven Rostedt { 28392af15d6aSSteven Rostedt if (ftrace_filter_buf[0]) 2840f45948e8SSteven Rostedt set_ftrace_early_filter(&global_ops, ftrace_filter_buf, 1); 28412af15d6aSSteven Rostedt if (ftrace_notrace_buf[0]) 2842f45948e8SSteven Rostedt set_ftrace_early_filter(&global_ops, ftrace_notrace_buf, 0); 2843369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER 2844369bc18fSStefan Assmann if (ftrace_graph_buf[0]) 2845369bc18fSStefan Assmann set_ftrace_early_graph(ftrace_graph_buf); 2846369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 28472af15d6aSSteven Rostedt } 28482af15d6aSSteven Rostedt 2849e309b41dSIngo Molnar static int 28501cf41dd7SSteven Rostedt ftrace_regex_release(struct inode *inode, struct file *file) 28515072c59fSSteven Rostedt { 28525072c59fSSteven Rostedt struct seq_file *m = (struct seq_file *)file->private_data; 28535072c59fSSteven Rostedt struct ftrace_iterator *iter; 285433dc9b12SSteven Rostedt struct ftrace_hash **orig_hash; 2855689fd8b6S[email protected] struct trace_parser *parser; 2856ed926f9bSSteven Rostedt int filter_hash; 285733dc9b12SSteven Rostedt int ret; 28585072c59fSSteven Rostedt 285941c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 28605072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) { 28615072c59fSSteven Rostedt iter = m->private; 28625072c59fSSteven Rostedt 28635072c59fSSteven Rostedt seq_release(inode, file); 28645072c59fSSteven Rostedt } else 28655072c59fSSteven Rostedt iter = file->private_data; 28665072c59fSSteven Rostedt 2867689fd8b6S[email protected] parser = &iter->parser; 2868689fd8b6S[email protected] if (trace_parser_loaded(parser)) { 2869689fd8b6S[email protected] parser->buffer[parser->idx] = 0; 28701cf41dd7SSteven Rostedt ftrace_match_records(iter->hash, parser->buffer, parser->idx); 28715072c59fSSteven Rostedt } 28725072c59fSSteven Rostedt 2873058e297dSSteven Rostedt trace_parser_put(parser); 2874058e297dSSteven Rostedt 2875058e297dSSteven Rostedt if (file->f_mode & FMODE_WRITE) { 2876ed926f9bSSteven Rostedt filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); 2877ed926f9bSSteven Rostedt 2878ed926f9bSSteven Rostedt if (filter_hash) 287933dc9b12SSteven Rostedt orig_hash = &iter->ops->filter_hash; 2880ed926f9bSSteven Rostedt else 2881ed926f9bSSteven Rostedt orig_hash = &iter->ops->notrace_hash; 288233dc9b12SSteven Rostedt 2883e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 2884ed926f9bSSteven Rostedt /* 2885ed926f9bSSteven Rostedt * Remove the current set, update the hash and add 2886ed926f9bSSteven Rostedt * them back. 2887ed926f9bSSteven Rostedt */ 2888ed926f9bSSteven Rostedt ftrace_hash_rec_disable(iter->ops, filter_hash); 288933dc9b12SSteven Rostedt ret = ftrace_hash_move(orig_hash, iter->hash); 2890ed926f9bSSteven Rostedt if (!ret) { 2891ed926f9bSSteven Rostedt ftrace_hash_rec_enable(iter->ops, filter_hash); 2892ed926f9bSSteven Rostedt if (iter->ops->flags & FTRACE_OPS_FL_ENABLED 2893ed926f9bSSteven Rostedt && ftrace_enabled) 28945072c59fSSteven Rostedt ftrace_run_update_code(FTRACE_ENABLE_CALLS); 2895ed926f9bSSteven Rostedt } 2896e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 2897058e297dSSteven Rostedt } 289833dc9b12SSteven Rostedt free_ftrace_hash(iter->hash); 289933dc9b12SSteven Rostedt kfree(iter); 2900689fd8b6S[email protected] 290141c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 29025072c59fSSteven Rostedt return 0; 29035072c59fSSteven Rostedt } 29045072c59fSSteven Rostedt 29055e2336a0SSteven Rostedt static const struct file_operations ftrace_avail_fops = { 29065072c59fSSteven Rostedt .open = ftrace_avail_open, 29075072c59fSSteven Rostedt .read = seq_read, 29085072c59fSSteven Rostedt .llseek = seq_lseek, 29093be04b47SLi Zefan .release = seq_release_private, 29105072c59fSSteven Rostedt }; 29115072c59fSSteven Rostedt 2912647bcd03SSteven Rostedt static const struct file_operations ftrace_enabled_fops = { 2913647bcd03SSteven Rostedt .open = ftrace_enabled_open, 2914647bcd03SSteven Rostedt .read = seq_read, 2915647bcd03SSteven Rostedt .llseek = seq_lseek, 2916647bcd03SSteven Rostedt .release = seq_release_private, 2917647bcd03SSteven Rostedt }; 2918647bcd03SSteven Rostedt 29195e2336a0SSteven Rostedt static const struct file_operations ftrace_filter_fops = { 29205072c59fSSteven Rostedt .open = ftrace_filter_open, 2921850a80cfSLai Jiangshan .read = seq_read, 29225072c59fSSteven Rostedt .write = ftrace_filter_write, 292398c4fd04SSteven Rostedt .llseek = ftrace_regex_lseek, 29241cf41dd7SSteven Rostedt .release = ftrace_regex_release, 29255072c59fSSteven Rostedt }; 29265072c59fSSteven Rostedt 29275e2336a0SSteven Rostedt static const struct file_operations ftrace_notrace_fops = { 292841c52c0dSSteven Rostedt .open = ftrace_notrace_open, 2929850a80cfSLai Jiangshan .read = seq_read, 293041c52c0dSSteven Rostedt .write = ftrace_notrace_write, 293141c52c0dSSteven Rostedt .llseek = ftrace_regex_lseek, 29321cf41dd7SSteven Rostedt .release = ftrace_regex_release, 293341c52c0dSSteven Rostedt }; 293441c52c0dSSteven Rostedt 2935ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 2936ea4e2bc4SSteven Rostedt 2937ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock); 2938ea4e2bc4SSteven Rostedt 2939ea4e2bc4SSteven Rostedt int ftrace_graph_count; 2940c7c6b1feSLi Zefan int ftrace_graph_filter_enabled; 2941ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; 2942ea4e2bc4SSteven Rostedt 2943ea4e2bc4SSteven Rostedt static void * 294485951842SLi Zefan __g_next(struct seq_file *m, loff_t *pos) 2945ea4e2bc4SSteven Rostedt { 294685951842SLi Zefan if (*pos >= ftrace_graph_count) 2947ea4e2bc4SSteven Rostedt return NULL; 2948a4ec5e0cSLi Zefan return &ftrace_graph_funcs[*pos]; 294985951842SLi Zefan } 2950ea4e2bc4SSteven Rostedt 295185951842SLi Zefan static void * 295285951842SLi Zefan g_next(struct seq_file *m, void *v, loff_t *pos) 295385951842SLi Zefan { 295485951842SLi Zefan (*pos)++; 295585951842SLi Zefan return __g_next(m, pos); 2956ea4e2bc4SSteven Rostedt } 2957ea4e2bc4SSteven Rostedt 2958ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos) 2959ea4e2bc4SSteven Rostedt { 2960ea4e2bc4SSteven Rostedt mutex_lock(&graph_lock); 2961ea4e2bc4SSteven Rostedt 2962f9349a8fSFrederic Weisbecker /* Nothing, tell g_show to print all functions are enabled */ 2963c7c6b1feSLi Zefan if (!ftrace_graph_filter_enabled && !*pos) 2964f9349a8fSFrederic Weisbecker return (void *)1; 2965f9349a8fSFrederic Weisbecker 296685951842SLi Zefan return __g_next(m, pos); 2967ea4e2bc4SSteven Rostedt } 2968ea4e2bc4SSteven Rostedt 2969ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p) 2970ea4e2bc4SSteven Rostedt { 2971ea4e2bc4SSteven Rostedt mutex_unlock(&graph_lock); 2972ea4e2bc4SSteven Rostedt } 2973ea4e2bc4SSteven Rostedt 2974ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v) 2975ea4e2bc4SSteven Rostedt { 2976ea4e2bc4SSteven Rostedt unsigned long *ptr = v; 2977ea4e2bc4SSteven Rostedt 2978ea4e2bc4SSteven Rostedt if (!ptr) 2979ea4e2bc4SSteven Rostedt return 0; 2980ea4e2bc4SSteven Rostedt 2981f9349a8fSFrederic Weisbecker if (ptr == (unsigned long *)1) { 2982f9349a8fSFrederic Weisbecker seq_printf(m, "#### all functions enabled ####\n"); 2983f9349a8fSFrederic Weisbecker return 0; 2984f9349a8fSFrederic Weisbecker } 2985f9349a8fSFrederic Weisbecker 2986b375a11aSSteven Rostedt seq_printf(m, "%ps\n", (void *)*ptr); 2987ea4e2bc4SSteven Rostedt 2988ea4e2bc4SSteven Rostedt return 0; 2989ea4e2bc4SSteven Rostedt } 2990ea4e2bc4SSteven Rostedt 299188e9d34cSJames Morris static const struct seq_operations ftrace_graph_seq_ops = { 2992ea4e2bc4SSteven Rostedt .start = g_start, 2993ea4e2bc4SSteven Rostedt .next = g_next, 2994ea4e2bc4SSteven Rostedt .stop = g_stop, 2995ea4e2bc4SSteven Rostedt .show = g_show, 2996ea4e2bc4SSteven Rostedt }; 2997ea4e2bc4SSteven Rostedt 2998ea4e2bc4SSteven Rostedt static int 2999ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file) 3000ea4e2bc4SSteven Rostedt { 3001ea4e2bc4SSteven Rostedt int ret = 0; 3002ea4e2bc4SSteven Rostedt 3003ea4e2bc4SSteven Rostedt if (unlikely(ftrace_disabled)) 3004ea4e2bc4SSteven Rostedt return -ENODEV; 3005ea4e2bc4SSteven Rostedt 3006ea4e2bc4SSteven Rostedt mutex_lock(&graph_lock); 3007ea4e2bc4SSteven Rostedt if ((file->f_mode & FMODE_WRITE) && 30088650ae32SSteven Rostedt (file->f_flags & O_TRUNC)) { 3009c7c6b1feSLi Zefan ftrace_graph_filter_enabled = 0; 3010ea4e2bc4SSteven Rostedt ftrace_graph_count = 0; 3011ea4e2bc4SSteven Rostedt memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs)); 3012ea4e2bc4SSteven Rostedt } 3013ea4e2bc4SSteven Rostedt mutex_unlock(&graph_lock); 3014ea4e2bc4SSteven Rostedt 3015a4ec5e0cSLi Zefan if (file->f_mode & FMODE_READ) 3016a4ec5e0cSLi Zefan ret = seq_open(file, &ftrace_graph_seq_ops); 3017a4ec5e0cSLi Zefan 3018ea4e2bc4SSteven Rostedt return ret; 3019ea4e2bc4SSteven Rostedt } 3020ea4e2bc4SSteven Rostedt 3021ea4e2bc4SSteven Rostedt static int 302287827111SLi Zefan ftrace_graph_release(struct inode *inode, struct file *file) 302387827111SLi Zefan { 302487827111SLi Zefan if (file->f_mode & FMODE_READ) 302587827111SLi Zefan seq_release(inode, file); 302687827111SLi Zefan return 0; 302787827111SLi Zefan } 302887827111SLi Zefan 302987827111SLi Zefan static int 3030f9349a8fSFrederic Weisbecker ftrace_set_func(unsigned long *array, int *idx, char *buffer) 3031ea4e2bc4SSteven Rostedt { 3032ea4e2bc4SSteven Rostedt struct dyn_ftrace *rec; 3033ea4e2bc4SSteven Rostedt struct ftrace_page *pg; 3034f9349a8fSFrederic Weisbecker int search_len; 3035c7c6b1feSLi Zefan int fail = 1; 3036f9349a8fSFrederic Weisbecker int type, not; 3037f9349a8fSFrederic Weisbecker char *search; 3038f9349a8fSFrederic Weisbecker bool exists; 3039f9349a8fSFrederic Weisbecker int i; 3040ea4e2bc4SSteven Rostedt 3041f9349a8fSFrederic Weisbecker /* decode regex */ 30423f6fe06dSFrederic Weisbecker type = filter_parse_regex(buffer, strlen(buffer), &search, ¬); 3043c7c6b1feSLi Zefan if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) 3044c7c6b1feSLi Zefan return -EBUSY; 3045f9349a8fSFrederic Weisbecker 3046f9349a8fSFrederic Weisbecker search_len = strlen(search); 3047f9349a8fSFrederic Weisbecker 304852baf119SSteven Rostedt mutex_lock(&ftrace_lock); 304945a4a237SSteven Rostedt 305045a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) { 305145a4a237SSteven Rostedt mutex_unlock(&ftrace_lock); 305245a4a237SSteven Rostedt return -ENODEV; 305345a4a237SSteven Rostedt } 305445a4a237SSteven Rostedt 3055265c831cSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 3056ea4e2bc4SSteven Rostedt 305745a4a237SSteven Rostedt if (rec->flags & FTRACE_FL_FREE) 3058ea4e2bc4SSteven Rostedt continue; 3059ea4e2bc4SSteven Rostedt 3060b9df92d2SSteven Rostedt if (ftrace_match_record(rec, NULL, search, search_len, type)) { 3061c7c6b1feSLi Zefan /* if it is in the array */ 3062f9349a8fSFrederic Weisbecker exists = false; 3063c7c6b1feSLi Zefan for (i = 0; i < *idx; i++) { 3064f9349a8fSFrederic Weisbecker if (array[i] == rec->ip) { 3065f9349a8fSFrederic Weisbecker exists = true; 3066faec2ec5SLiming Wang break; 3067faec2ec5SLiming Wang } 3068c7c6b1feSLi Zefan } 3069c7c6b1feSLi Zefan 3070c7c6b1feSLi Zefan if (!not) { 3071c7c6b1feSLi Zefan fail = 0; 3072c7c6b1feSLi Zefan if (!exists) { 3073f9349a8fSFrederic Weisbecker array[(*idx)++] = rec->ip; 3074c7c6b1feSLi Zefan if (*idx >= FTRACE_GRAPH_MAX_FUNCS) 3075c7c6b1feSLi Zefan goto out; 3076c7c6b1feSLi Zefan } 3077c7c6b1feSLi Zefan } else { 3078c7c6b1feSLi Zefan if (exists) { 3079c7c6b1feSLi Zefan array[i] = array[--(*idx)]; 3080c7c6b1feSLi Zefan array[*idx] = 0; 3081c7c6b1feSLi Zefan fail = 0; 3082c7c6b1feSLi Zefan } 3083c7c6b1feSLi Zefan } 3084f9349a8fSFrederic Weisbecker } 3085265c831cSSteven Rostedt } while_for_each_ftrace_rec(); 3086c7c6b1feSLi Zefan out: 308752baf119SSteven Rostedt mutex_unlock(&ftrace_lock); 3088ea4e2bc4SSteven Rostedt 3089c7c6b1feSLi Zefan if (fail) 3090c7c6b1feSLi Zefan return -EINVAL; 3091c7c6b1feSLi Zefan 3092c7c6b1feSLi Zefan ftrace_graph_filter_enabled = 1; 3093c7c6b1feSLi Zefan return 0; 3094ea4e2bc4SSteven Rostedt } 3095ea4e2bc4SSteven Rostedt 3096ea4e2bc4SSteven Rostedt static ssize_t 3097ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf, 3098ea4e2bc4SSteven Rostedt size_t cnt, loff_t *ppos) 3099ea4e2bc4SSteven Rostedt { 3100689fd8b6S[email protected] struct trace_parser parser; 31014ba7978eSLi Zefan ssize_t read, ret; 3102ea4e2bc4SSteven Rostedt 3103c7c6b1feSLi Zefan if (!cnt) 3104ea4e2bc4SSteven Rostedt return 0; 3105ea4e2bc4SSteven Rostedt 3106ea4e2bc4SSteven Rostedt mutex_lock(&graph_lock); 3107ea4e2bc4SSteven Rostedt 3108689fd8b6S[email protected] if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) { 3109689fd8b6S[email protected] ret = -ENOMEM; 31101eb90f13SLi Zefan goto out_unlock; 3111ea4e2bc4SSteven Rostedt } 3112ea4e2bc4SSteven Rostedt 3113689fd8b6S[email protected] read = trace_get_user(&parser, ubuf, cnt, ppos); 3114689fd8b6S[email protected] 31154ba7978eSLi Zefan if (read >= 0 && trace_parser_loaded((&parser))) { 3116689fd8b6S[email protected] parser.buffer[parser.idx] = 0; 3117ea4e2bc4SSteven Rostedt 3118f9349a8fSFrederic Weisbecker /* we allow only one expression at a time */ 3119a4ec5e0cSLi Zefan ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, 3120689fd8b6S[email protected] parser.buffer); 3121ea4e2bc4SSteven Rostedt if (ret) 31221eb90f13SLi Zefan goto out_free; 3123689fd8b6S[email protected] } 3124ea4e2bc4SSteven Rostedt 3125ea4e2bc4SSteven Rostedt ret = read; 31261eb90f13SLi Zefan 31271eb90f13SLi Zefan out_free: 3128689fd8b6S[email protected] trace_parser_put(&parser); 31291eb90f13SLi Zefan out_unlock: 3130ea4e2bc4SSteven Rostedt mutex_unlock(&graph_lock); 3131ea4e2bc4SSteven Rostedt 3132ea4e2bc4SSteven Rostedt return ret; 3133ea4e2bc4SSteven Rostedt } 3134ea4e2bc4SSteven Rostedt 3135ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = { 3136ea4e2bc4SSteven Rostedt .open = ftrace_graph_open, 3137850a80cfSLai Jiangshan .read = seq_read, 3138ea4e2bc4SSteven Rostedt .write = ftrace_graph_write, 313987827111SLi Zefan .release = ftrace_graph_release, 31406038f373SArnd Bergmann .llseek = seq_lseek, 3141ea4e2bc4SSteven Rostedt }; 3142ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 3143ea4e2bc4SSteven Rostedt 3144df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer) 31455072c59fSSteven Rostedt { 31465072c59fSSteven Rostedt 31475452af66SFrederic Weisbecker trace_create_file("available_filter_functions", 0444, 31485072c59fSSteven Rostedt d_tracer, NULL, &ftrace_avail_fops); 31495072c59fSSteven Rostedt 3150647bcd03SSteven Rostedt trace_create_file("enabled_functions", 0444, 3151647bcd03SSteven Rostedt d_tracer, NULL, &ftrace_enabled_fops); 3152647bcd03SSteven Rostedt 31535452af66SFrederic Weisbecker trace_create_file("set_ftrace_filter", 0644, d_tracer, 31545072c59fSSteven Rostedt NULL, &ftrace_filter_fops); 315541c52c0dSSteven Rostedt 31565452af66SFrederic Weisbecker trace_create_file("set_ftrace_notrace", 0644, d_tracer, 315741c52c0dSSteven Rostedt NULL, &ftrace_notrace_fops); 3158ad90c0e3SSteven Rostedt 3159ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 31605452af66SFrederic Weisbecker trace_create_file("set_graph_function", 0444, d_tracer, 3161ea4e2bc4SSteven Rostedt NULL, 3162ea4e2bc4SSteven Rostedt &ftrace_graph_fops); 3163ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 3164ea4e2bc4SSteven Rostedt 31655072c59fSSteven Rostedt return 0; 31665072c59fSSteven Rostedt } 31675072c59fSSteven Rostedt 31685cb084bbSJiri Olsa static int ftrace_process_locs(struct module *mod, 316931e88909SSteven Rostedt unsigned long *start, 317068bf21aaSSteven Rostedt unsigned long *end) 317168bf21aaSSteven Rostedt { 317268bf21aaSSteven Rostedt unsigned long *p; 317368bf21aaSSteven Rostedt unsigned long addr; 317468bf21aaSSteven Rostedt 3175e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 317668bf21aaSSteven Rostedt p = start; 317768bf21aaSSteven Rostedt while (p < end) { 317868bf21aaSSteven Rostedt addr = ftrace_call_adjust(*p++); 317920e5227eSSteven Rostedt /* 318020e5227eSSteven Rostedt * Some architecture linkers will pad between 318120e5227eSSteven Rostedt * the different mcount_loc sections of different 318220e5227eSSteven Rostedt * object files to satisfy alignments. 318320e5227eSSteven Rostedt * Skip any NULL pointers. 318420e5227eSSteven Rostedt */ 318520e5227eSSteven Rostedt if (!addr) 318620e5227eSSteven Rostedt continue; 318768bf21aaSSteven Rostedt ftrace_record_ip(addr); 318868bf21aaSSteven Rostedt } 318968bf21aaSSteven Rostedt 319031e88909SSteven Rostedt ftrace_update_code(mod); 3191e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 319268bf21aaSSteven Rostedt 319368bf21aaSSteven Rostedt return 0; 319468bf21aaSSteven Rostedt } 319568bf21aaSSteven Rostedt 319693eb677dSSteven Rostedt #ifdef CONFIG_MODULES 3197e7247a15S[email protected] void ftrace_release_mod(struct module *mod) 319893eb677dSSteven Rostedt { 319993eb677dSSteven Rostedt struct dyn_ftrace *rec; 320093eb677dSSteven Rostedt struct ftrace_page *pg; 320193eb677dSSteven Rostedt 320293eb677dSSteven Rostedt mutex_lock(&ftrace_lock); 320345a4a237SSteven Rostedt 320445a4a237SSteven Rostedt if (ftrace_disabled) 320545a4a237SSteven Rostedt goto out_unlock; 320645a4a237SSteven Rostedt 320793eb677dSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 3208e7247a15S[email protected] if (within_module_core(rec->ip, mod)) { 320993eb677dSSteven Rostedt /* 321093eb677dSSteven Rostedt * rec->ip is changed in ftrace_free_rec() 321193eb677dSSteven Rostedt * It should not between s and e if record was freed. 321293eb677dSSteven Rostedt */ 321393eb677dSSteven Rostedt FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE); 321493eb677dSSteven Rostedt ftrace_free_rec(rec); 321593eb677dSSteven Rostedt } 321693eb677dSSteven Rostedt } while_for_each_ftrace_rec(); 321745a4a237SSteven Rostedt out_unlock: 321893eb677dSSteven Rostedt mutex_unlock(&ftrace_lock); 321993eb677dSSteven Rostedt } 322093eb677dSSteven Rostedt 322193eb677dSSteven Rostedt static void ftrace_init_module(struct module *mod, 322231e88909SSteven Rostedt unsigned long *start, unsigned long *end) 322390d595feSSteven Rostedt { 322400fd61aeSSteven Rostedt if (ftrace_disabled || start == end) 3225fed1939cSSteven Rostedt return; 32265cb084bbSJiri Olsa ftrace_process_locs(mod, start, end); 322790d595feSSteven Rostedt } 322890d595feSSteven Rostedt 322993eb677dSSteven Rostedt static int ftrace_module_notify(struct notifier_block *self, 323093eb677dSSteven Rostedt unsigned long val, void *data) 323193eb677dSSteven Rostedt { 323293eb677dSSteven Rostedt struct module *mod = data; 323393eb677dSSteven Rostedt 323493eb677dSSteven Rostedt switch (val) { 323593eb677dSSteven Rostedt case MODULE_STATE_COMING: 323693eb677dSSteven Rostedt ftrace_init_module(mod, mod->ftrace_callsites, 323793eb677dSSteven Rostedt mod->ftrace_callsites + 323893eb677dSSteven Rostedt mod->num_ftrace_callsites); 323993eb677dSSteven Rostedt break; 324093eb677dSSteven Rostedt case MODULE_STATE_GOING: 3241e7247a15S[email protected] ftrace_release_mod(mod); 324293eb677dSSteven Rostedt break; 324393eb677dSSteven Rostedt } 324493eb677dSSteven Rostedt 324593eb677dSSteven Rostedt return 0; 324693eb677dSSteven Rostedt } 324793eb677dSSteven Rostedt #else 324893eb677dSSteven Rostedt static int ftrace_module_notify(struct notifier_block *self, 324993eb677dSSteven Rostedt unsigned long val, void *data) 325093eb677dSSteven Rostedt { 325193eb677dSSteven Rostedt return 0; 325293eb677dSSteven Rostedt } 325393eb677dSSteven Rostedt #endif /* CONFIG_MODULES */ 325493eb677dSSteven Rostedt 325593eb677dSSteven Rostedt struct notifier_block ftrace_module_nb = { 325693eb677dSSteven Rostedt .notifier_call = ftrace_module_notify, 325793eb677dSSteven Rostedt .priority = 0, 325893eb677dSSteven Rostedt }; 325993eb677dSSteven Rostedt 326068bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[]; 326168bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[]; 326268bf21aaSSteven Rostedt 326368bf21aaSSteven Rostedt void __init ftrace_init(void) 326468bf21aaSSteven Rostedt { 326568bf21aaSSteven Rostedt unsigned long count, addr, flags; 326668bf21aaSSteven Rostedt int ret; 326768bf21aaSSteven Rostedt 326868bf21aaSSteven Rostedt /* Keep the ftrace pointer to the stub */ 326968bf21aaSSteven Rostedt addr = (unsigned long)ftrace_stub; 327068bf21aaSSteven Rostedt 327168bf21aaSSteven Rostedt local_irq_save(flags); 327268bf21aaSSteven Rostedt ftrace_dyn_arch_init(&addr); 327368bf21aaSSteven Rostedt local_irq_restore(flags); 327468bf21aaSSteven Rostedt 327568bf21aaSSteven Rostedt /* ftrace_dyn_arch_init places the return code in addr */ 327668bf21aaSSteven Rostedt if (addr) 327768bf21aaSSteven Rostedt goto failed; 327868bf21aaSSteven Rostedt 327968bf21aaSSteven Rostedt count = __stop_mcount_loc - __start_mcount_loc; 328068bf21aaSSteven Rostedt 328168bf21aaSSteven Rostedt ret = ftrace_dyn_table_alloc(count); 328268bf21aaSSteven Rostedt if (ret) 328368bf21aaSSteven Rostedt goto failed; 328468bf21aaSSteven Rostedt 328568bf21aaSSteven Rostedt last_ftrace_enabled = ftrace_enabled = 1; 328668bf21aaSSteven Rostedt 32875cb084bbSJiri Olsa ret = ftrace_process_locs(NULL, 328831e88909SSteven Rostedt __start_mcount_loc, 328968bf21aaSSteven Rostedt __stop_mcount_loc); 329068bf21aaSSteven Rostedt 329193eb677dSSteven Rostedt ret = register_module_notifier(&ftrace_module_nb); 329224ed0c4bSMing Lei if (ret) 329393eb677dSSteven Rostedt pr_warning("Failed to register trace ftrace module notifier\n"); 329493eb677dSSteven Rostedt 32952af15d6aSSteven Rostedt set_ftrace_early_filters(); 32962af15d6aSSteven Rostedt 329768bf21aaSSteven Rostedt return; 329868bf21aaSSteven Rostedt failed: 329968bf21aaSSteven Rostedt ftrace_disabled = 1; 330068bf21aaSSteven Rostedt } 330168bf21aaSSteven Rostedt 33023d083395SSteven Rostedt #else 33030b6e4d56SFrederic Weisbecker 33042b499381SSteven Rostedt static struct ftrace_ops global_ops = { 3305bd69c30bSSteven Rostedt .func = ftrace_stub, 3306bd69c30bSSteven Rostedt }; 3307bd69c30bSSteven Rostedt 33080b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void) 33090b6e4d56SFrederic Weisbecker { 33100b6e4d56SFrederic Weisbecker ftrace_enabled = 1; 33110b6e4d56SFrederic Weisbecker return 0; 33120b6e4d56SFrederic Weisbecker } 33130b6e4d56SFrederic Weisbecker device_initcall(ftrace_nodyn_init); 33140b6e4d56SFrederic Weisbecker 3315df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; } 3316df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { } 33175a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */ 3318bd69c30bSSteven Rostedt # define ftrace_startup(ops, command) do { } while (0) 3319bd69c30bSSteven Rostedt # define ftrace_shutdown(ops, command) do { } while (0) 3320b0fc494fSSteven Rostedt # define ftrace_startup_sysctl() do { } while (0) 3321b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl() do { } while (0) 33223d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */ 33233d083395SSteven Rostedt 3324e32d8956SSteven Rostedt static void clear_ftrace_swapper(void) 3325e32d8956SSteven Rostedt { 3326e32d8956SSteven Rostedt struct task_struct *p; 3327e32d8956SSteven Rostedt int cpu; 3328e32d8956SSteven Rostedt 3329e32d8956SSteven Rostedt get_online_cpus(); 3330e32d8956SSteven Rostedt for_each_online_cpu(cpu) { 3331e32d8956SSteven Rostedt p = idle_task(cpu); 3332e32d8956SSteven Rostedt clear_tsk_trace_trace(p); 3333e32d8956SSteven Rostedt } 3334e32d8956SSteven Rostedt put_online_cpus(); 3335e32d8956SSteven Rostedt } 3336e32d8956SSteven Rostedt 3337e32d8956SSteven Rostedt static void set_ftrace_swapper(void) 3338e32d8956SSteven Rostedt { 3339e32d8956SSteven Rostedt struct task_struct *p; 3340e32d8956SSteven Rostedt int cpu; 3341e32d8956SSteven Rostedt 3342e32d8956SSteven Rostedt get_online_cpus(); 3343e32d8956SSteven Rostedt for_each_online_cpu(cpu) { 3344e32d8956SSteven Rostedt p = idle_task(cpu); 3345e32d8956SSteven Rostedt set_tsk_trace_trace(p); 3346e32d8956SSteven Rostedt } 3347e32d8956SSteven Rostedt put_online_cpus(); 3348e32d8956SSteven Rostedt } 3349e32d8956SSteven Rostedt 3350e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid) 3351978f3a45SSteven Rostedt { 3352978f3a45SSteven Rostedt struct task_struct *p; 3353978f3a45SSteven Rostedt 3354229c4ef8SOleg Nesterov rcu_read_lock(); 3355e32d8956SSteven Rostedt do_each_pid_task(pid, PIDTYPE_PID, p) { 3356978f3a45SSteven Rostedt clear_tsk_trace_trace(p); 3357e32d8956SSteven Rostedt } while_each_pid_task(pid, PIDTYPE_PID, p); 3358229c4ef8SOleg Nesterov rcu_read_unlock(); 3359229c4ef8SOleg Nesterov 3360e32d8956SSteven Rostedt put_pid(pid); 3361978f3a45SSteven Rostedt } 3362978f3a45SSteven Rostedt 3363e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid) 3364978f3a45SSteven Rostedt { 3365978f3a45SSteven Rostedt struct task_struct *p; 3366978f3a45SSteven Rostedt 3367229c4ef8SOleg Nesterov rcu_read_lock(); 3368978f3a45SSteven Rostedt do_each_pid_task(pid, PIDTYPE_PID, p) { 3369978f3a45SSteven Rostedt set_tsk_trace_trace(p); 3370978f3a45SSteven Rostedt } while_each_pid_task(pid, PIDTYPE_PID, p); 3371229c4ef8SOleg Nesterov rcu_read_unlock(); 3372978f3a45SSteven Rostedt } 3373978f3a45SSteven Rostedt 3374756d17eeS[email protected] static void clear_ftrace_pid_task(struct pid *pid) 3375e32d8956SSteven Rostedt { 3376756d17eeS[email protected] if (pid == ftrace_swapper_pid) 3377e32d8956SSteven Rostedt clear_ftrace_swapper(); 3378e32d8956SSteven Rostedt else 3379756d17eeS[email protected] clear_ftrace_pid(pid); 3380e32d8956SSteven Rostedt } 3381e32d8956SSteven Rostedt 3382e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid) 3383e32d8956SSteven Rostedt { 3384e32d8956SSteven Rostedt if (pid == ftrace_swapper_pid) 3385e32d8956SSteven Rostedt set_ftrace_swapper(); 3386e32d8956SSteven Rostedt else 3387e32d8956SSteven Rostedt set_ftrace_pid(pid); 3388e32d8956SSteven Rostedt } 3389e32d8956SSteven Rostedt 3390756d17eeS[email protected] static int ftrace_pid_add(int p) 3391756d17eeS[email protected] { 3392756d17eeS[email protected] struct pid *pid; 3393756d17eeS[email protected] struct ftrace_pid *fpid; 3394756d17eeS[email protected] int ret = -EINVAL; 3395756d17eeS[email protected] 3396756d17eeS[email protected] mutex_lock(&ftrace_lock); 3397756d17eeS[email protected] 3398756d17eeS[email protected] if (!p) 3399756d17eeS[email protected] pid = ftrace_swapper_pid; 3400756d17eeS[email protected] else 3401756d17eeS[email protected] pid = find_get_pid(p); 3402756d17eeS[email protected] 3403756d17eeS[email protected] if (!pid) 3404756d17eeS[email protected] goto out; 3405756d17eeS[email protected] 3406756d17eeS[email protected] ret = 0; 3407756d17eeS[email protected] 3408756d17eeS[email protected] list_for_each_entry(fpid, &ftrace_pids, list) 3409756d17eeS[email protected] if (fpid->pid == pid) 3410756d17eeS[email protected] goto out_put; 3411756d17eeS[email protected] 3412756d17eeS[email protected] ret = -ENOMEM; 3413756d17eeS[email protected] 3414756d17eeS[email protected] fpid = kmalloc(sizeof(*fpid), GFP_KERNEL); 3415756d17eeS[email protected] if (!fpid) 3416756d17eeS[email protected] goto out_put; 3417756d17eeS[email protected] 3418756d17eeS[email protected] list_add(&fpid->list, &ftrace_pids); 3419756d17eeS[email protected] fpid->pid = pid; 3420756d17eeS[email protected] 3421756d17eeS[email protected] set_ftrace_pid_task(pid); 3422756d17eeS[email protected] 3423756d17eeS[email protected] ftrace_update_pid_func(); 3424756d17eeS[email protected] ftrace_startup_enable(0); 3425756d17eeS[email protected] 3426756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3427756d17eeS[email protected] return 0; 3428756d17eeS[email protected] 3429756d17eeS[email protected] out_put: 3430756d17eeS[email protected] if (pid != ftrace_swapper_pid) 3431756d17eeS[email protected] put_pid(pid); 3432756d17eeS[email protected] 3433756d17eeS[email protected] out: 3434756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3435756d17eeS[email protected] return ret; 3436756d17eeS[email protected] } 3437756d17eeS[email protected] 3438756d17eeS[email protected] static void ftrace_pid_reset(void) 3439756d17eeS[email protected] { 3440756d17eeS[email protected] struct ftrace_pid *fpid, *safe; 3441756d17eeS[email protected] 3442756d17eeS[email protected] mutex_lock(&ftrace_lock); 3443756d17eeS[email protected] list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) { 3444756d17eeS[email protected] struct pid *pid = fpid->pid; 3445756d17eeS[email protected] 3446756d17eeS[email protected] clear_ftrace_pid_task(pid); 3447756d17eeS[email protected] 3448756d17eeS[email protected] list_del(&fpid->list); 3449756d17eeS[email protected] kfree(fpid); 3450756d17eeS[email protected] } 3451756d17eeS[email protected] 3452756d17eeS[email protected] ftrace_update_pid_func(); 3453756d17eeS[email protected] ftrace_startup_enable(0); 3454756d17eeS[email protected] 3455756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3456756d17eeS[email protected] } 3457756d17eeS[email protected] 3458756d17eeS[email protected] static void *fpid_start(struct seq_file *m, loff_t *pos) 3459756d17eeS[email protected] { 3460756d17eeS[email protected] mutex_lock(&ftrace_lock); 3461756d17eeS[email protected] 3462756d17eeS[email protected] if (list_empty(&ftrace_pids) && (!*pos)) 3463756d17eeS[email protected] return (void *) 1; 3464756d17eeS[email protected] 3465756d17eeS[email protected] return seq_list_start(&ftrace_pids, *pos); 3466756d17eeS[email protected] } 3467756d17eeS[email protected] 3468756d17eeS[email protected] static void *fpid_next(struct seq_file *m, void *v, loff_t *pos) 3469756d17eeS[email protected] { 3470756d17eeS[email protected] if (v == (void *)1) 3471756d17eeS[email protected] return NULL; 3472756d17eeS[email protected] 3473756d17eeS[email protected] return seq_list_next(v, &ftrace_pids, pos); 3474756d17eeS[email protected] } 3475756d17eeS[email protected] 3476756d17eeS[email protected] static void fpid_stop(struct seq_file *m, void *p) 3477756d17eeS[email protected] { 3478756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3479756d17eeS[email protected] } 3480756d17eeS[email protected] 3481756d17eeS[email protected] static int fpid_show(struct seq_file *m, void *v) 3482756d17eeS[email protected] { 3483756d17eeS[email protected] const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list); 3484756d17eeS[email protected] 3485756d17eeS[email protected] if (v == (void *)1) { 3486756d17eeS[email protected] seq_printf(m, "no pid\n"); 3487756d17eeS[email protected] return 0; 3488756d17eeS[email protected] } 3489756d17eeS[email protected] 3490756d17eeS[email protected] if (fpid->pid == ftrace_swapper_pid) 3491756d17eeS[email protected] seq_printf(m, "swapper tasks\n"); 3492756d17eeS[email protected] else 3493756d17eeS[email protected] seq_printf(m, "%u\n", pid_vnr(fpid->pid)); 3494756d17eeS[email protected] 3495756d17eeS[email protected] return 0; 3496756d17eeS[email protected] } 3497756d17eeS[email protected] 3498756d17eeS[email protected] static const struct seq_operations ftrace_pid_sops = { 3499756d17eeS[email protected] .start = fpid_start, 3500756d17eeS[email protected] .next = fpid_next, 3501756d17eeS[email protected] .stop = fpid_stop, 3502756d17eeS[email protected] .show = fpid_show, 3503756d17eeS[email protected] }; 3504756d17eeS[email protected] 3505756d17eeS[email protected] static int 3506756d17eeS[email protected] ftrace_pid_open(struct inode *inode, struct file *file) 3507756d17eeS[email protected] { 3508756d17eeS[email protected] int ret = 0; 3509756d17eeS[email protected] 3510756d17eeS[email protected] if ((file->f_mode & FMODE_WRITE) && 3511756d17eeS[email protected] (file->f_flags & O_TRUNC)) 3512756d17eeS[email protected] ftrace_pid_reset(); 3513756d17eeS[email protected] 3514756d17eeS[email protected] if (file->f_mode & FMODE_READ) 3515756d17eeS[email protected] ret = seq_open(file, &ftrace_pid_sops); 3516756d17eeS[email protected] 3517756d17eeS[email protected] return ret; 3518756d17eeS[email protected] } 3519756d17eeS[email protected] 3520df4fc315SSteven Rostedt static ssize_t 3521df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf, 3522df4fc315SSteven Rostedt size_t cnt, loff_t *ppos) 3523df4fc315SSteven Rostedt { 3524457dc928SIngo Molnar char buf[64], *tmp; 3525df4fc315SSteven Rostedt long val; 3526df4fc315SSteven Rostedt int ret; 3527df4fc315SSteven Rostedt 3528df4fc315SSteven Rostedt if (cnt >= sizeof(buf)) 3529df4fc315SSteven Rostedt return -EINVAL; 3530df4fc315SSteven Rostedt 3531df4fc315SSteven Rostedt if (copy_from_user(&buf, ubuf, cnt)) 3532df4fc315SSteven Rostedt return -EFAULT; 3533df4fc315SSteven Rostedt 3534df4fc315SSteven Rostedt buf[cnt] = 0; 3535df4fc315SSteven Rostedt 3536756d17eeS[email protected] /* 3537756d17eeS[email protected] * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid" 3538756d17eeS[email protected] * to clean the filter quietly. 3539756d17eeS[email protected] */ 3540457dc928SIngo Molnar tmp = strstrip(buf); 3541457dc928SIngo Molnar if (strlen(tmp) == 0) 3542756d17eeS[email protected] return 1; 3543756d17eeS[email protected] 3544457dc928SIngo Molnar ret = strict_strtol(tmp, 10, &val); 3545df4fc315SSteven Rostedt if (ret < 0) 3546df4fc315SSteven Rostedt return ret; 3547df4fc315SSteven Rostedt 3548756d17eeS[email protected] ret = ftrace_pid_add(val); 3549978f3a45SSteven Rostedt 3550756d17eeS[email protected] return ret ? ret : cnt; 3551e32d8956SSteven Rostedt } 3552978f3a45SSteven Rostedt 3553756d17eeS[email protected] static int 3554756d17eeS[email protected] ftrace_pid_release(struct inode *inode, struct file *file) 3555756d17eeS[email protected] { 3556756d17eeS[email protected] if (file->f_mode & FMODE_READ) 3557756d17eeS[email protected] seq_release(inode, file); 3558978f3a45SSteven Rostedt 3559756d17eeS[email protected] return 0; 3560df4fc315SSteven Rostedt } 3561df4fc315SSteven Rostedt 35625e2336a0SSteven Rostedt static const struct file_operations ftrace_pid_fops = { 3563756d17eeS[email protected] .open = ftrace_pid_open, 3564df4fc315SSteven Rostedt .write = ftrace_pid_write, 3565756d17eeS[email protected] .read = seq_read, 3566756d17eeS[email protected] .llseek = seq_lseek, 3567756d17eeS[email protected] .release = ftrace_pid_release, 3568df4fc315SSteven Rostedt }; 3569df4fc315SSteven Rostedt 3570df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void) 3571df4fc315SSteven Rostedt { 3572df4fc315SSteven Rostedt struct dentry *d_tracer; 3573df4fc315SSteven Rostedt 3574df4fc315SSteven Rostedt d_tracer = tracing_init_dentry(); 3575df4fc315SSteven Rostedt if (!d_tracer) 3576df4fc315SSteven Rostedt return 0; 3577df4fc315SSteven Rostedt 3578df4fc315SSteven Rostedt ftrace_init_dyn_debugfs(d_tracer); 3579df4fc315SSteven Rostedt 35805452af66SFrederic Weisbecker trace_create_file("set_ftrace_pid", 0644, d_tracer, 3581df4fc315SSteven Rostedt NULL, &ftrace_pid_fops); 3582493762fcSSteven Rostedt 3583493762fcSSteven Rostedt ftrace_profile_debugfs(d_tracer); 3584493762fcSSteven Rostedt 3585df4fc315SSteven Rostedt return 0; 3586df4fc315SSteven Rostedt } 3587df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs); 3588df4fc315SSteven Rostedt 35893d083395SSteven Rostedt /** 359081adbdc0SSteven Rostedt * ftrace_kill - kill ftrace 3591a2bb6a3dSSteven Rostedt * 3592a2bb6a3dSSteven Rostedt * This function should be used by panic code. It stops ftrace 3593a2bb6a3dSSteven Rostedt * but in a not so nice way. If you need to simply kill ftrace 3594a2bb6a3dSSteven Rostedt * from a non-atomic section, use ftrace_kill. 3595a2bb6a3dSSteven Rostedt */ 359681adbdc0SSteven Rostedt void ftrace_kill(void) 3597a2bb6a3dSSteven Rostedt { 3598a2bb6a3dSSteven Rostedt ftrace_disabled = 1; 3599a2bb6a3dSSteven Rostedt ftrace_enabled = 0; 3600a2bb6a3dSSteven Rostedt clear_ftrace_function(); 3601a2bb6a3dSSteven Rostedt } 3602a2bb6a3dSSteven Rostedt 3603a2bb6a3dSSteven Rostedt /** 36043d083395SSteven Rostedt * register_ftrace_function - register a function for profiling 36053d083395SSteven Rostedt * @ops - ops structure that holds the function for profiling. 36063d083395SSteven Rostedt * 36073d083395SSteven Rostedt * Register a function to be called by all functions in the 36083d083395SSteven Rostedt * kernel. 36093d083395SSteven Rostedt * 36103d083395SSteven Rostedt * Note: @ops->func and all the functions it calls must be labeled 36113d083395SSteven Rostedt * with "notrace", otherwise it will go into a 36123d083395SSteven Rostedt * recursive loop. 36133d083395SSteven Rostedt */ 36143d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops) 36153d083395SSteven Rostedt { 361645a4a237SSteven Rostedt int ret = -1; 36174eebcc81SSteven Rostedt 3618e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 3619e7d3737eSFrederic Weisbecker 362045a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 362145a4a237SSteven Rostedt goto out_unlock; 362245a4a237SSteven Rostedt 3623b0fc494fSSteven Rostedt ret = __register_ftrace_function(ops); 3624bd69c30bSSteven Rostedt ftrace_startup(&global_ops, 0); 3625b0fc494fSSteven Rostedt 362645a4a237SSteven Rostedt out_unlock: 3627e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 3628b0fc494fSSteven Rostedt return ret; 36293d083395SSteven Rostedt } 36303d083395SSteven Rostedt 36313d083395SSteven Rostedt /** 363232632920SUwe Kleine-Koenig * unregister_ftrace_function - unregister a function for profiling. 36333d083395SSteven Rostedt * @ops - ops structure that holds the function to unregister 36343d083395SSteven Rostedt * 36353d083395SSteven Rostedt * Unregister a function that was added to be called by ftrace profiling. 36363d083395SSteven Rostedt */ 36373d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops) 36383d083395SSteven Rostedt { 36393d083395SSteven Rostedt int ret; 36403d083395SSteven Rostedt 3641e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 36423d083395SSteven Rostedt ret = __unregister_ftrace_function(ops); 3643bd69c30bSSteven Rostedt ftrace_shutdown(&global_ops, 0); 3644e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 3645b0fc494fSSteven Rostedt 3646b0fc494fSSteven Rostedt return ret; 3647b0fc494fSSteven Rostedt } 3648b0fc494fSSteven Rostedt 3649e309b41dSIngo Molnar int 3650b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write, 36518d65af78SAlexey Dobriyan void __user *buffer, size_t *lenp, 3652b0fc494fSSteven Rostedt loff_t *ppos) 3653b0fc494fSSteven Rostedt { 365445a4a237SSteven Rostedt int ret = -ENODEV; 36554eebcc81SSteven Rostedt 3656e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 3657b0fc494fSSteven Rostedt 365845a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 365945a4a237SSteven Rostedt goto out; 366045a4a237SSteven Rostedt 36618d65af78SAlexey Dobriyan ret = proc_dointvec(table, write, buffer, lenp, ppos); 3662b0fc494fSSteven Rostedt 3663a32c7765SLi Zefan if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) 3664b0fc494fSSteven Rostedt goto out; 3665b0fc494fSSteven Rostedt 3666a32c7765SLi Zefan last_ftrace_enabled = !!ftrace_enabled; 3667b0fc494fSSteven Rostedt 3668b0fc494fSSteven Rostedt if (ftrace_enabled) { 3669b0fc494fSSteven Rostedt 3670b0fc494fSSteven Rostedt ftrace_startup_sysctl(); 3671b0fc494fSSteven Rostedt 3672b0fc494fSSteven Rostedt /* we are starting ftrace again */ 3673b0fc494fSSteven Rostedt if (ftrace_list != &ftrace_list_end) { 3674b0fc494fSSteven Rostedt if (ftrace_list->next == &ftrace_list_end) 3675b0fc494fSSteven Rostedt ftrace_trace_function = ftrace_list->func; 3676b0fc494fSSteven Rostedt else 3677b0fc494fSSteven Rostedt ftrace_trace_function = ftrace_list_func; 3678b0fc494fSSteven Rostedt } 3679b0fc494fSSteven Rostedt 3680b0fc494fSSteven Rostedt } else { 3681b0fc494fSSteven Rostedt /* stopping ftrace calls (just send to ftrace_stub) */ 3682b0fc494fSSteven Rostedt ftrace_trace_function = ftrace_stub; 3683b0fc494fSSteven Rostedt 3684b0fc494fSSteven Rostedt ftrace_shutdown_sysctl(); 3685b0fc494fSSteven Rostedt } 3686b0fc494fSSteven Rostedt 3687b0fc494fSSteven Rostedt out: 3688e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 36893d083395SSteven Rostedt return ret; 369016444a8aSArnaldo Carvalho de Melo } 3691f17845e5SIngo Molnar 3692fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER 3693e7d3737eSFrederic Weisbecker 3694597af815SSteven Rostedt static int ftrace_graph_active; 36954a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier; 3696f201ae23SFrederic Weisbecker 3697e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) 3698e49dc19cSSteven Rostedt { 3699e49dc19cSSteven Rostedt return 0; 3700e49dc19cSSteven Rostedt } 3701e49dc19cSSteven Rostedt 3702287b6e68SFrederic Weisbecker /* The callbacks that hook a function */ 3703287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return = 3704287b6e68SFrederic Weisbecker (trace_func_graph_ret_t)ftrace_stub; 3705e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub; 3706f201ae23SFrederic Weisbecker 3707f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */ 3708f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) 3709f201ae23SFrederic Weisbecker { 3710f201ae23SFrederic Weisbecker int i; 3711f201ae23SFrederic Weisbecker int ret = 0; 3712f201ae23SFrederic Weisbecker unsigned long flags; 3713f201ae23SFrederic Weisbecker int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE; 3714f201ae23SFrederic Weisbecker struct task_struct *g, *t; 3715f201ae23SFrederic Weisbecker 3716f201ae23SFrederic Weisbecker for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) { 3717f201ae23SFrederic Weisbecker ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH 3718f201ae23SFrederic Weisbecker * sizeof(struct ftrace_ret_stack), 3719f201ae23SFrederic Weisbecker GFP_KERNEL); 3720f201ae23SFrederic Weisbecker if (!ret_stack_list[i]) { 3721f201ae23SFrederic Weisbecker start = 0; 3722f201ae23SFrederic Weisbecker end = i; 3723f201ae23SFrederic Weisbecker ret = -ENOMEM; 3724f201ae23SFrederic Weisbecker goto free; 3725f201ae23SFrederic Weisbecker } 3726f201ae23SFrederic Weisbecker } 3727f201ae23SFrederic Weisbecker 3728f201ae23SFrederic Weisbecker read_lock_irqsave(&tasklist_lock, flags); 3729f201ae23SFrederic Weisbecker do_each_thread(g, t) { 3730f201ae23SFrederic Weisbecker if (start == end) { 3731f201ae23SFrederic Weisbecker ret = -EAGAIN; 3732f201ae23SFrederic Weisbecker goto unlock; 3733f201ae23SFrederic Weisbecker } 3734f201ae23SFrederic Weisbecker 3735f201ae23SFrederic Weisbecker if (t->ret_stack == NULL) { 3736380c4b14SFrederic Weisbecker atomic_set(&t->tracing_graph_pause, 0); 3737f201ae23SFrederic Weisbecker atomic_set(&t->trace_overrun, 0); 373826c01624SSteven Rostedt t->curr_ret_stack = -1; 373926c01624SSteven Rostedt /* Make sure the tasks see the -1 first: */ 374026c01624SSteven Rostedt smp_wmb(); 374126c01624SSteven Rostedt t->ret_stack = ret_stack_list[start++]; 3742f201ae23SFrederic Weisbecker } 3743f201ae23SFrederic Weisbecker } while_each_thread(g, t); 3744f201ae23SFrederic Weisbecker 3745f201ae23SFrederic Weisbecker unlock: 3746f201ae23SFrederic Weisbecker read_unlock_irqrestore(&tasklist_lock, flags); 3747f201ae23SFrederic Weisbecker free: 3748f201ae23SFrederic Weisbecker for (i = start; i < end; i++) 3749f201ae23SFrederic Weisbecker kfree(ret_stack_list[i]); 3750f201ae23SFrederic Weisbecker return ret; 3751f201ae23SFrederic Weisbecker } 3752f201ae23SFrederic Weisbecker 37538aef2d28SSteven Rostedt static void 375438516ab5SSteven Rostedt ftrace_graph_probe_sched_switch(void *ignore, 375538516ab5SSteven Rostedt struct task_struct *prev, struct task_struct *next) 37568aef2d28SSteven Rostedt { 37578aef2d28SSteven Rostedt unsigned long long timestamp; 37588aef2d28SSteven Rostedt int index; 37598aef2d28SSteven Rostedt 3760be6f164aSSteven Rostedt /* 3761be6f164aSSteven Rostedt * Does the user want to count the time a function was asleep. 3762be6f164aSSteven Rostedt * If so, do not update the time stamps. 3763be6f164aSSteven Rostedt */ 3764be6f164aSSteven Rostedt if (trace_flags & TRACE_ITER_SLEEP_TIME) 3765be6f164aSSteven Rostedt return; 3766be6f164aSSteven Rostedt 37678aef2d28SSteven Rostedt timestamp = trace_clock_local(); 37688aef2d28SSteven Rostedt 37698aef2d28SSteven Rostedt prev->ftrace_timestamp = timestamp; 37708aef2d28SSteven Rostedt 37718aef2d28SSteven Rostedt /* only process tasks that we timestamped */ 37728aef2d28SSteven Rostedt if (!next->ftrace_timestamp) 37738aef2d28SSteven Rostedt return; 37748aef2d28SSteven Rostedt 37758aef2d28SSteven Rostedt /* 37768aef2d28SSteven Rostedt * Update all the counters in next to make up for the 37778aef2d28SSteven Rostedt * time next was sleeping. 37788aef2d28SSteven Rostedt */ 37798aef2d28SSteven Rostedt timestamp -= next->ftrace_timestamp; 37808aef2d28SSteven Rostedt 37818aef2d28SSteven Rostedt for (index = next->curr_ret_stack; index >= 0; index--) 37828aef2d28SSteven Rostedt next->ret_stack[index].calltime += timestamp; 37838aef2d28SSteven Rostedt } 37848aef2d28SSteven Rostedt 3785f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */ 3786fb52607aSFrederic Weisbecker static int start_graph_tracing(void) 3787f201ae23SFrederic Weisbecker { 3788f201ae23SFrederic Weisbecker struct ftrace_ret_stack **ret_stack_list; 37895b058bcdSFrederic Weisbecker int ret, cpu; 3790f201ae23SFrederic Weisbecker 3791f201ae23SFrederic Weisbecker ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE * 3792f201ae23SFrederic Weisbecker sizeof(struct ftrace_ret_stack *), 3793f201ae23SFrederic Weisbecker GFP_KERNEL); 3794f201ae23SFrederic Weisbecker 3795f201ae23SFrederic Weisbecker if (!ret_stack_list) 3796f201ae23SFrederic Weisbecker return -ENOMEM; 3797f201ae23SFrederic Weisbecker 37985b058bcdSFrederic Weisbecker /* The cpu_boot init_task->ret_stack will never be freed */ 3799179c498aSSteven Rostedt for_each_online_cpu(cpu) { 3800179c498aSSteven Rostedt if (!idle_task(cpu)->ret_stack) 3801868baf07SSteven Rostedt ftrace_graph_init_idle_task(idle_task(cpu), cpu); 3802179c498aSSteven Rostedt } 38035b058bcdSFrederic Weisbecker 3804f201ae23SFrederic Weisbecker do { 3805f201ae23SFrederic Weisbecker ret = alloc_retstack_tasklist(ret_stack_list); 3806f201ae23SFrederic Weisbecker } while (ret == -EAGAIN); 3807f201ae23SFrederic Weisbecker 38088aef2d28SSteven Rostedt if (!ret) { 380938516ab5SSteven Rostedt ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); 38108aef2d28SSteven Rostedt if (ret) 38118aef2d28SSteven Rostedt pr_info("ftrace_graph: Couldn't activate tracepoint" 38128aef2d28SSteven Rostedt " probe to kernel_sched_switch\n"); 38138aef2d28SSteven Rostedt } 38148aef2d28SSteven Rostedt 3815f201ae23SFrederic Weisbecker kfree(ret_stack_list); 3816f201ae23SFrederic Weisbecker return ret; 3817f201ae23SFrederic Weisbecker } 3818f201ae23SFrederic Weisbecker 38194a2b8ddaSFrederic Weisbecker /* 38204a2b8ddaSFrederic Weisbecker * Hibernation protection. 38214a2b8ddaSFrederic Weisbecker * The state of the current task is too much unstable during 38224a2b8ddaSFrederic Weisbecker * suspend/restore to disk. We want to protect against that. 38234a2b8ddaSFrederic Weisbecker */ 38244a2b8ddaSFrederic Weisbecker static int 38254a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state, 38264a2b8ddaSFrederic Weisbecker void *unused) 38274a2b8ddaSFrederic Weisbecker { 38284a2b8ddaSFrederic Weisbecker switch (state) { 38294a2b8ddaSFrederic Weisbecker case PM_HIBERNATION_PREPARE: 38304a2b8ddaSFrederic Weisbecker pause_graph_tracing(); 38314a2b8ddaSFrederic Weisbecker break; 38324a2b8ddaSFrederic Weisbecker 38334a2b8ddaSFrederic Weisbecker case PM_POST_HIBERNATION: 38344a2b8ddaSFrederic Weisbecker unpause_graph_tracing(); 38354a2b8ddaSFrederic Weisbecker break; 38364a2b8ddaSFrederic Weisbecker } 38374a2b8ddaSFrederic Weisbecker return NOTIFY_DONE; 38384a2b8ddaSFrederic Weisbecker } 38394a2b8ddaSFrederic Weisbecker 3840287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc, 3841287b6e68SFrederic Weisbecker trace_func_graph_ent_t entryfunc) 384215e6cb36SFrederic Weisbecker { 3843e7d3737eSFrederic Weisbecker int ret = 0; 3844e7d3737eSFrederic Weisbecker 3845e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 3846e7d3737eSFrederic Weisbecker 384705ce5818SSteven Rostedt /* we currently allow only one tracer registered at a time */ 3848597af815SSteven Rostedt if (ftrace_graph_active) { 384905ce5818SSteven Rostedt ret = -EBUSY; 385005ce5818SSteven Rostedt goto out; 385105ce5818SSteven Rostedt } 385205ce5818SSteven Rostedt 38534a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call; 38544a2b8ddaSFrederic Weisbecker register_pm_notifier(&ftrace_suspend_notifier); 38554a2b8ddaSFrederic Weisbecker 3856597af815SSteven Rostedt ftrace_graph_active++; 3857fb52607aSFrederic Weisbecker ret = start_graph_tracing(); 3858f201ae23SFrederic Weisbecker if (ret) { 3859597af815SSteven Rostedt ftrace_graph_active--; 3860f201ae23SFrederic Weisbecker goto out; 3861f201ae23SFrederic Weisbecker } 3862e53a6319SSteven Rostedt 3863287b6e68SFrederic Weisbecker ftrace_graph_return = retfunc; 3864287b6e68SFrederic Weisbecker ftrace_graph_entry = entryfunc; 3865e53a6319SSteven Rostedt 3866bd69c30bSSteven Rostedt ftrace_startup(&global_ops, FTRACE_START_FUNC_RET); 3867e7d3737eSFrederic Weisbecker 3868e7d3737eSFrederic Weisbecker out: 3869e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 3870e7d3737eSFrederic Weisbecker return ret; 387115e6cb36SFrederic Weisbecker } 387215e6cb36SFrederic Weisbecker 3873fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void) 387415e6cb36SFrederic Weisbecker { 3875e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 3876e7d3737eSFrederic Weisbecker 3877597af815SSteven Rostedt if (unlikely(!ftrace_graph_active)) 38782aad1b76SSteven Rostedt goto out; 38792aad1b76SSteven Rostedt 3880597af815SSteven Rostedt ftrace_graph_active--; 3881287b6e68SFrederic Weisbecker ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; 3882e49dc19cSSteven Rostedt ftrace_graph_entry = ftrace_graph_entry_stub; 3883bd69c30bSSteven Rostedt ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET); 38844a2b8ddaSFrederic Weisbecker unregister_pm_notifier(&ftrace_suspend_notifier); 388538516ab5SSteven Rostedt unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); 3886e7d3737eSFrederic Weisbecker 38872aad1b76SSteven Rostedt out: 3888e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 388915e6cb36SFrederic Weisbecker } 3890f201ae23SFrederic Weisbecker 3891868baf07SSteven Rostedt static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); 3892868baf07SSteven Rostedt 3893868baf07SSteven Rostedt static void 3894868baf07SSteven Rostedt graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) 3895868baf07SSteven Rostedt { 3896868baf07SSteven Rostedt atomic_set(&t->tracing_graph_pause, 0); 3897868baf07SSteven Rostedt atomic_set(&t->trace_overrun, 0); 3898868baf07SSteven Rostedt t->ftrace_timestamp = 0; 389925985edcSLucas De Marchi /* make curr_ret_stack visible before we add the ret_stack */ 3900868baf07SSteven Rostedt smp_wmb(); 3901868baf07SSteven Rostedt t->ret_stack = ret_stack; 3902868baf07SSteven Rostedt } 3903868baf07SSteven Rostedt 3904868baf07SSteven Rostedt /* 3905868baf07SSteven Rostedt * Allocate a return stack for the idle task. May be the first 3906868baf07SSteven Rostedt * time through, or it may be done by CPU hotplug online. 3907868baf07SSteven Rostedt */ 3908868baf07SSteven Rostedt void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) 3909868baf07SSteven Rostedt { 3910868baf07SSteven Rostedt t->curr_ret_stack = -1; 3911868baf07SSteven Rostedt /* 3912868baf07SSteven Rostedt * The idle task has no parent, it either has its own 3913868baf07SSteven Rostedt * stack or no stack at all. 3914868baf07SSteven Rostedt */ 3915868baf07SSteven Rostedt if (t->ret_stack) 3916868baf07SSteven Rostedt WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu)); 3917868baf07SSteven Rostedt 3918868baf07SSteven Rostedt if (ftrace_graph_active) { 3919868baf07SSteven Rostedt struct ftrace_ret_stack *ret_stack; 3920868baf07SSteven Rostedt 3921868baf07SSteven Rostedt ret_stack = per_cpu(idle_ret_stack, cpu); 3922868baf07SSteven Rostedt if (!ret_stack) { 3923868baf07SSteven Rostedt ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH 3924868baf07SSteven Rostedt * sizeof(struct ftrace_ret_stack), 3925868baf07SSteven Rostedt GFP_KERNEL); 3926868baf07SSteven Rostedt if (!ret_stack) 3927868baf07SSteven Rostedt return; 3928868baf07SSteven Rostedt per_cpu(idle_ret_stack, cpu) = ret_stack; 3929868baf07SSteven Rostedt } 3930868baf07SSteven Rostedt graph_init_task(t, ret_stack); 3931868baf07SSteven Rostedt } 3932868baf07SSteven Rostedt } 3933868baf07SSteven Rostedt 3934f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */ 3935fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t) 3936f201ae23SFrederic Weisbecker { 393784047e36SSteven Rostedt /* Make sure we do not use the parent ret_stack */ 393884047e36SSteven Rostedt t->ret_stack = NULL; 3939ea14eb71SSteven Rostedt t->curr_ret_stack = -1; 394084047e36SSteven Rostedt 3941597af815SSteven Rostedt if (ftrace_graph_active) { 394282310a32SSteven Rostedt struct ftrace_ret_stack *ret_stack; 394382310a32SSteven Rostedt 394482310a32SSteven Rostedt ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH 3945f201ae23SFrederic Weisbecker * sizeof(struct ftrace_ret_stack), 3946f201ae23SFrederic Weisbecker GFP_KERNEL); 394782310a32SSteven Rostedt if (!ret_stack) 3948f201ae23SFrederic Weisbecker return; 3949868baf07SSteven Rostedt graph_init_task(t, ret_stack); 395084047e36SSteven Rostedt } 3951f201ae23SFrederic Weisbecker } 3952f201ae23SFrederic Weisbecker 3953fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t) 3954f201ae23SFrederic Weisbecker { 3955eae849caSFrederic Weisbecker struct ftrace_ret_stack *ret_stack = t->ret_stack; 3956eae849caSFrederic Weisbecker 3957f201ae23SFrederic Weisbecker t->ret_stack = NULL; 3958eae849caSFrederic Weisbecker /* NULL must become visible to IRQs before we free it: */ 3959eae849caSFrederic Weisbecker barrier(); 3960eae849caSFrederic Weisbecker 3961eae849caSFrederic Weisbecker kfree(ret_stack); 3962f201ae23SFrederic Weisbecker } 396314a866c5SSteven Rostedt 396414a866c5SSteven Rostedt void ftrace_graph_stop(void) 396514a866c5SSteven Rostedt { 396614a866c5SSteven Rostedt ftrace_stop(); 396714a866c5SSteven Rostedt } 396815e6cb36SFrederic Weisbecker #endif 3969