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 352af15d6aSSteven Rostedt #include <asm/setup.h> 36395a59d0SAbhishek Sagar 370706f1c4SSteven Rostedt #include "trace_output.h" 38bac429f0SSteven Rostedt #include "trace_stat.h" 393d083395SSteven Rostedt 406912896eSSteven Rostedt #define FTRACE_WARN_ON(cond) \ 410778d9adSSteven Rostedt ({ \ 420778d9adSSteven Rostedt int ___r = cond; \ 430778d9adSSteven Rostedt if (WARN_ON(___r)) \ 446912896eSSteven Rostedt ftrace_kill(); \ 450778d9adSSteven Rostedt ___r; \ 460778d9adSSteven Rostedt }) 476912896eSSteven Rostedt 486912896eSSteven Rostedt #define FTRACE_WARN_ON_ONCE(cond) \ 490778d9adSSteven Rostedt ({ \ 500778d9adSSteven Rostedt int ___r = cond; \ 510778d9adSSteven Rostedt if (WARN_ON_ONCE(___r)) \ 526912896eSSteven Rostedt ftrace_kill(); \ 530778d9adSSteven Rostedt ___r; \ 540778d9adSSteven Rostedt }) 556912896eSSteven Rostedt 568fc0c701SSteven Rostedt /* hash bits for specific function selection */ 578fc0c701SSteven Rostedt #define FTRACE_HASH_BITS 7 588fc0c701SSteven Rostedt #define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS) 5933dc9b12SSteven Rostedt #define FTRACE_HASH_DEFAULT_BITS 10 6033dc9b12SSteven Rostedt #define FTRACE_HASH_MAX_BITS 12 618fc0c701SSteven Rostedt 624eebcc81SSteven Rostedt /* ftrace_enabled is a method to turn ftrace on or off */ 634eebcc81SSteven Rostedt int ftrace_enabled __read_mostly; 64d61f82d0SSteven Rostedt static int last_ftrace_enabled; 65b0fc494fSSteven Rostedt 6660a7ecf4SSteven Rostedt /* Quick disabling of function tracer. */ 6760a7ecf4SSteven Rostedt int function_trace_stop; 6860a7ecf4SSteven Rostedt 69756d17eeS[email protected] /* List for set_ftrace_pid's pids. */ 70756d17eeS[email protected] LIST_HEAD(ftrace_pids); 71756d17eeS[email protected] struct ftrace_pid { 72756d17eeS[email protected] struct list_head list; 73756d17eeS[email protected] struct pid *pid; 74756d17eeS[email protected] }; 75756d17eeS[email protected] 764eebcc81SSteven Rostedt /* 774eebcc81SSteven Rostedt * ftrace_disabled is set when an anomaly is discovered. 784eebcc81SSteven Rostedt * ftrace_disabled is much stronger than ftrace_enabled. 794eebcc81SSteven Rostedt */ 804eebcc81SSteven Rostedt static int ftrace_disabled __read_mostly; 814eebcc81SSteven Rostedt 8252baf119SSteven Rostedt static DEFINE_MUTEX(ftrace_lock); 83b0fc494fSSteven Rostedt 84bd38c0e6SPaul McQuade static struct ftrace_ops ftrace_list_end __read_mostly = { 8516444a8aSArnaldo Carvalho de Melo .func = ftrace_stub, 8616444a8aSArnaldo Carvalho de Melo }; 8716444a8aSArnaldo Carvalho de Melo 88b848914cSSteven Rostedt static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end; 89b848914cSSteven Rostedt static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end; 9016444a8aSArnaldo Carvalho de Melo ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; 916331c28cSSteven Rostedt static ftrace_func_t __ftrace_trace_function_delay __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 96b848914cSSteven Rostedt static void 97b848914cSSteven Rostedt ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip); 98b848914cSSteven Rostedt 993f379b03SPaul E. McKenney /* 100b848914cSSteven Rostedt * Traverse the ftrace_global_list, invoking all entries. The reason that we 1013f379b03SPaul E. McKenney * can use rcu_dereference_raw() is that elements removed from this list 1023f379b03SPaul E. McKenney * are simply leaked, so there is no need to interact with a grace-period 1033f379b03SPaul E. McKenney * mechanism. The rcu_dereference_raw() calls are needed to handle 104b848914cSSteven Rostedt * concurrent insertions into the ftrace_global_list. 1053f379b03SPaul E. McKenney * 1063f379b03SPaul E. McKenney * Silly Alpha and silly pointer-speculation compiler optimizations! 1073f379b03SPaul E. McKenney */ 108b848914cSSteven Rostedt static void ftrace_global_list_func(unsigned long ip, 109b848914cSSteven Rostedt unsigned long parent_ip) 11016444a8aSArnaldo Carvalho de Melo { 111b1cff0adSSteven Rostedt struct ftrace_ops *op; 11216444a8aSArnaldo Carvalho de Melo 113b1cff0adSSteven Rostedt if (unlikely(trace_recursion_test(TRACE_GLOBAL_BIT))) 114b1cff0adSSteven Rostedt return; 115b1cff0adSSteven Rostedt 116b1cff0adSSteven Rostedt trace_recursion_set(TRACE_GLOBAL_BIT); 117b1cff0adSSteven Rostedt op = rcu_dereference_raw(ftrace_global_list); /*see above*/ 11816444a8aSArnaldo Carvalho de Melo while (op != &ftrace_list_end) { 11916444a8aSArnaldo Carvalho de Melo op->func(ip, parent_ip); 1203f379b03SPaul E. McKenney op = rcu_dereference_raw(op->next); /*see above*/ 12116444a8aSArnaldo Carvalho de Melo }; 122b1cff0adSSteven Rostedt trace_recursion_clear(TRACE_GLOBAL_BIT); 12316444a8aSArnaldo Carvalho de Melo } 12416444a8aSArnaldo Carvalho de Melo 125df4fc315SSteven Rostedt static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip) 126df4fc315SSteven Rostedt { 1270ef8cde5SSteven Rostedt if (!test_tsk_trace_trace(current)) 128df4fc315SSteven Rostedt return; 129df4fc315SSteven Rostedt 130df4fc315SSteven Rostedt ftrace_pid_function(ip, parent_ip); 131df4fc315SSteven Rostedt } 132df4fc315SSteven Rostedt 133df4fc315SSteven Rostedt static void set_ftrace_pid_function(ftrace_func_t func) 134df4fc315SSteven Rostedt { 135df4fc315SSteven Rostedt /* do not set ftrace_pid_function to itself! */ 136df4fc315SSteven Rostedt if (func != ftrace_pid_func) 137df4fc315SSteven Rostedt ftrace_pid_function = func; 138df4fc315SSteven Rostedt } 139df4fc315SSteven Rostedt 14016444a8aSArnaldo Carvalho de Melo /** 1413d083395SSteven Rostedt * clear_ftrace_function - reset the ftrace function 14216444a8aSArnaldo Carvalho de Melo * 1433d083395SSteven Rostedt * This NULLs the ftrace function and in essence stops 1443d083395SSteven Rostedt * tracing. There may be lag 14516444a8aSArnaldo Carvalho de Melo */ 1463d083395SSteven Rostedt void clear_ftrace_function(void) 14716444a8aSArnaldo Carvalho de Melo { 1483d083395SSteven Rostedt ftrace_trace_function = ftrace_stub; 14960a7ecf4SSteven Rostedt __ftrace_trace_function = ftrace_stub; 1506331c28cSSteven Rostedt __ftrace_trace_function_delay = ftrace_stub; 151df4fc315SSteven Rostedt ftrace_pid_function = ftrace_stub; 1523d083395SSteven Rostedt } 15316444a8aSArnaldo Carvalho de Melo 1546331c28cSSteven Rostedt #undef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 15560a7ecf4SSteven Rostedt #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 15660a7ecf4SSteven Rostedt /* 15760a7ecf4SSteven Rostedt * For those archs that do not test ftrace_trace_stop in their 15860a7ecf4SSteven Rostedt * mcount call site, we need to do it from C. 15960a7ecf4SSteven Rostedt */ 16060a7ecf4SSteven Rostedt static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip) 16160a7ecf4SSteven Rostedt { 16260a7ecf4SSteven Rostedt if (function_trace_stop) 16360a7ecf4SSteven Rostedt return; 16460a7ecf4SSteven Rostedt 16560a7ecf4SSteven Rostedt __ftrace_trace_function(ip, parent_ip); 16660a7ecf4SSteven Rostedt } 16760a7ecf4SSteven Rostedt #endif 16860a7ecf4SSteven Rostedt 1692b499381SSteven Rostedt static void update_global_ops(void) 170491d0dcfSSteven Rostedt { 171491d0dcfSSteven Rostedt ftrace_func_t func; 172491d0dcfSSteven Rostedt 173491d0dcfSSteven Rostedt /* 174491d0dcfSSteven Rostedt * If there's only one function registered, then call that 175491d0dcfSSteven Rostedt * function directly. Otherwise, we need to iterate over the 176491d0dcfSSteven Rostedt * registered callers. 177491d0dcfSSteven Rostedt */ 178b848914cSSteven Rostedt if (ftrace_global_list == &ftrace_list_end || 179b848914cSSteven Rostedt ftrace_global_list->next == &ftrace_list_end) 180b848914cSSteven Rostedt func = ftrace_global_list->func; 181491d0dcfSSteven Rostedt else 182b848914cSSteven Rostedt func = ftrace_global_list_func; 183491d0dcfSSteven Rostedt 184491d0dcfSSteven Rostedt /* If we filter on pids, update to use the pid function */ 185491d0dcfSSteven Rostedt if (!list_empty(&ftrace_pids)) { 186491d0dcfSSteven Rostedt set_ftrace_pid_function(func); 187491d0dcfSSteven Rostedt func = ftrace_pid_func; 188491d0dcfSSteven Rostedt } 1892b499381SSteven Rostedt 1902b499381SSteven Rostedt global_ops.func = func; 1912b499381SSteven Rostedt } 1922b499381SSteven Rostedt 1932b499381SSteven Rostedt static void update_ftrace_function(void) 1942b499381SSteven Rostedt { 1952b499381SSteven Rostedt ftrace_func_t func; 1962b499381SSteven Rostedt 1972b499381SSteven Rostedt update_global_ops(); 1982b499381SSteven Rostedt 199cdbe61bfSSteven Rostedt /* 200cdbe61bfSSteven Rostedt * If we are at the end of the list and this ops is 201cdbe61bfSSteven Rostedt * not dynamic, then have the mcount trampoline call 202cdbe61bfSSteven Rostedt * the function directly 203cdbe61bfSSteven Rostedt */ 204b848914cSSteven Rostedt if (ftrace_ops_list == &ftrace_list_end || 205cdbe61bfSSteven Rostedt (ftrace_ops_list->next == &ftrace_list_end && 206cdbe61bfSSteven Rostedt !(ftrace_ops_list->flags & FTRACE_OPS_FL_DYNAMIC))) 207b848914cSSteven Rostedt func = ftrace_ops_list->func; 208b848914cSSteven Rostedt else 209b848914cSSteven Rostedt func = ftrace_ops_list_func; 2102b499381SSteven Rostedt 211491d0dcfSSteven Rostedt #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 212491d0dcfSSteven Rostedt ftrace_trace_function = func; 213491d0dcfSSteven Rostedt #else 2146331c28cSSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE 2156331c28cSSteven Rostedt /* do not update till all functions have been modified */ 2166331c28cSSteven Rostedt __ftrace_trace_function_delay = func; 2176331c28cSSteven Rostedt #else 218491d0dcfSSteven Rostedt __ftrace_trace_function = func; 2196331c28cSSteven Rostedt #endif 220491d0dcfSSteven Rostedt ftrace_trace_function = ftrace_test_stop_func; 221491d0dcfSSteven Rostedt #endif 222491d0dcfSSteven Rostedt } 223491d0dcfSSteven Rostedt 2242b499381SSteven Rostedt static void add_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops) 2253d083395SSteven Rostedt { 2262b499381SSteven Rostedt ops->next = *list; 22716444a8aSArnaldo Carvalho de Melo /* 228b848914cSSteven Rostedt * We are entering ops into the list but another 22916444a8aSArnaldo Carvalho de Melo * CPU might be walking that list. We need to make sure 23016444a8aSArnaldo Carvalho de Melo * the ops->next pointer is valid before another CPU sees 231b848914cSSteven Rostedt * the ops pointer included into the list. 23216444a8aSArnaldo Carvalho de Melo */ 2332b499381SSteven Rostedt rcu_assign_pointer(*list, ops); 2342b499381SSteven Rostedt } 2353d083395SSteven Rostedt 2362b499381SSteven Rostedt static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops) 2372b499381SSteven Rostedt { 2382b499381SSteven Rostedt struct ftrace_ops **p; 2392b499381SSteven Rostedt 2402b499381SSteven Rostedt /* 2412b499381SSteven Rostedt * If we are removing the last function, then simply point 2422b499381SSteven Rostedt * to the ftrace_stub. 2432b499381SSteven Rostedt */ 2442b499381SSteven Rostedt if (*list == ops && ops->next == &ftrace_list_end) { 2452b499381SSteven Rostedt *list = &ftrace_list_end; 2462b499381SSteven Rostedt return 0; 2472b499381SSteven Rostedt } 2482b499381SSteven Rostedt 2492b499381SSteven Rostedt for (p = list; *p != &ftrace_list_end; p = &(*p)->next) 2502b499381SSteven Rostedt if (*p == ops) 2512b499381SSteven Rostedt break; 2522b499381SSteven Rostedt 2532b499381SSteven Rostedt if (*p != ops) 2542b499381SSteven Rostedt return -1; 2552b499381SSteven Rostedt 2562b499381SSteven Rostedt *p = (*p)->next; 2572b499381SSteven Rostedt return 0; 2582b499381SSteven Rostedt } 2592b499381SSteven Rostedt 2602b499381SSteven Rostedt static int __register_ftrace_function(struct ftrace_ops *ops) 2612b499381SSteven Rostedt { 2622b499381SSteven Rostedt if (ftrace_disabled) 2632b499381SSteven Rostedt return -ENODEV; 2642b499381SSteven Rostedt 2652b499381SSteven Rostedt if (FTRACE_WARN_ON(ops == &global_ops)) 2662b499381SSteven Rostedt return -EINVAL; 2672b499381SSteven Rostedt 268b848914cSSteven Rostedt if (WARN_ON(ops->flags & FTRACE_OPS_FL_ENABLED)) 269b848914cSSteven Rostedt return -EBUSY; 270b848914cSSteven Rostedt 271cdbe61bfSSteven Rostedt if (!core_kernel_data((unsigned long)ops)) 272cdbe61bfSSteven Rostedt ops->flags |= FTRACE_OPS_FL_DYNAMIC; 273cdbe61bfSSteven Rostedt 274b848914cSSteven Rostedt if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 275b848914cSSteven Rostedt int first = ftrace_global_list == &ftrace_list_end; 276b848914cSSteven Rostedt add_ftrace_ops(&ftrace_global_list, ops); 277b848914cSSteven Rostedt ops->flags |= FTRACE_OPS_FL_ENABLED; 278b848914cSSteven Rostedt if (first) 279b848914cSSteven Rostedt add_ftrace_ops(&ftrace_ops_list, &global_ops); 280b848914cSSteven Rostedt } else 281b848914cSSteven Rostedt add_ftrace_ops(&ftrace_ops_list, ops); 282b848914cSSteven Rostedt 283491d0dcfSSteven Rostedt if (ftrace_enabled) 284491d0dcfSSteven Rostedt update_ftrace_function(); 2853d083395SSteven Rostedt 28616444a8aSArnaldo Carvalho de Melo return 0; 28716444a8aSArnaldo Carvalho de Melo } 28816444a8aSArnaldo Carvalho de Melo 289e309b41dSIngo Molnar static int __unregister_ftrace_function(struct ftrace_ops *ops) 29016444a8aSArnaldo Carvalho de Melo { 2912b499381SSteven Rostedt int ret; 29216444a8aSArnaldo Carvalho de Melo 2932b499381SSteven Rostedt if (ftrace_disabled) 2942b499381SSteven Rostedt return -ENODEV; 29516444a8aSArnaldo Carvalho de Melo 296b848914cSSteven Rostedt if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED))) 297b848914cSSteven Rostedt return -EBUSY; 298b848914cSSteven Rostedt 2992b499381SSteven Rostedt if (FTRACE_WARN_ON(ops == &global_ops)) 3002b499381SSteven Rostedt return -EINVAL; 30116444a8aSArnaldo Carvalho de Melo 302b848914cSSteven Rostedt if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 303b848914cSSteven Rostedt ret = remove_ftrace_ops(&ftrace_global_list, ops); 304b848914cSSteven Rostedt if (!ret && ftrace_global_list == &ftrace_list_end) 305b848914cSSteven Rostedt ret = remove_ftrace_ops(&ftrace_ops_list, &global_ops); 306b848914cSSteven Rostedt if (!ret) 307b848914cSSteven Rostedt ops->flags &= ~FTRACE_OPS_FL_ENABLED; 308b848914cSSteven Rostedt } else 309b848914cSSteven Rostedt ret = remove_ftrace_ops(&ftrace_ops_list, ops); 310b848914cSSteven Rostedt 3112b499381SSteven Rostedt if (ret < 0) 3122b499381SSteven Rostedt return ret; 313b848914cSSteven Rostedt 314491d0dcfSSteven Rostedt if (ftrace_enabled) 315491d0dcfSSteven Rostedt update_ftrace_function(); 31616444a8aSArnaldo Carvalho de Melo 317cdbe61bfSSteven Rostedt /* 318cdbe61bfSSteven Rostedt * Dynamic ops may be freed, we must make sure that all 319cdbe61bfSSteven Rostedt * callers are done before leaving this function. 320cdbe61bfSSteven Rostedt */ 321cdbe61bfSSteven Rostedt if (ops->flags & FTRACE_OPS_FL_DYNAMIC) 322cdbe61bfSSteven Rostedt synchronize_sched(); 323cdbe61bfSSteven Rostedt 324e6ea44e9SSteven Rostedt return 0; 3253d083395SSteven Rostedt } 3263d083395SSteven Rostedt 327df4fc315SSteven Rostedt static void ftrace_update_pid_func(void) 328df4fc315SSteven Rostedt { 329491d0dcfSSteven Rostedt /* Only do something if we are tracing something */ 330df4fc315SSteven Rostedt if (ftrace_trace_function == ftrace_stub) 33110dd3ebeSKOSAKI Motohiro return; 332df4fc315SSteven Rostedt 333491d0dcfSSteven Rostedt update_ftrace_function(); 334df4fc315SSteven Rostedt } 335df4fc315SSteven Rostedt 336493762fcSSteven Rostedt #ifdef CONFIG_FUNCTION_PROFILER 337493762fcSSteven Rostedt struct ftrace_profile { 338493762fcSSteven Rostedt struct hlist_node node; 339493762fcSSteven Rostedt unsigned long ip; 340493762fcSSteven Rostedt unsigned long counter; 3410706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 3420706f1c4SSteven Rostedt unsigned long long time; 343e330b3bcSChase Douglas unsigned long long time_squared; 3440706f1c4SSteven Rostedt #endif 345493762fcSSteven Rostedt }; 346493762fcSSteven Rostedt 347493762fcSSteven Rostedt struct ftrace_profile_page { 348493762fcSSteven Rostedt struct ftrace_profile_page *next; 349493762fcSSteven Rostedt unsigned long index; 350493762fcSSteven Rostedt struct ftrace_profile records[]; 351493762fcSSteven Rostedt }; 352493762fcSSteven Rostedt 353cafb168aSSteven Rostedt struct ftrace_profile_stat { 354cafb168aSSteven Rostedt atomic_t disabled; 355cafb168aSSteven Rostedt struct hlist_head *hash; 356cafb168aSSteven Rostedt struct ftrace_profile_page *pages; 357cafb168aSSteven Rostedt struct ftrace_profile_page *start; 358cafb168aSSteven Rostedt struct tracer_stat stat; 359cafb168aSSteven Rostedt }; 360cafb168aSSteven Rostedt 361493762fcSSteven Rostedt #define PROFILE_RECORDS_SIZE \ 362493762fcSSteven Rostedt (PAGE_SIZE - offsetof(struct ftrace_profile_page, records)) 363493762fcSSteven Rostedt 364493762fcSSteven Rostedt #define PROFILES_PER_PAGE \ 365493762fcSSteven Rostedt (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile)) 366493762fcSSteven Rostedt 367fb9fb015SSteven Rostedt static int ftrace_profile_bits __read_mostly; 368fb9fb015SSteven Rostedt static int ftrace_profile_enabled __read_mostly; 369fb9fb015SSteven Rostedt 370fb9fb015SSteven Rostedt /* ftrace_profile_lock - synchronize the enable and disable of the profiler */ 371493762fcSSteven Rostedt static DEFINE_MUTEX(ftrace_profile_lock); 372493762fcSSteven Rostedt 373cafb168aSSteven Rostedt static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats); 374493762fcSSteven Rostedt 375493762fcSSteven Rostedt #define FTRACE_PROFILE_HASH_SIZE 1024 /* must be power of 2 */ 376493762fcSSteven Rostedt 377493762fcSSteven Rostedt static void * 378493762fcSSteven Rostedt function_stat_next(void *v, int idx) 379493762fcSSteven Rostedt { 380493762fcSSteven Rostedt struct ftrace_profile *rec = v; 381493762fcSSteven Rostedt struct ftrace_profile_page *pg; 382493762fcSSteven Rostedt 383493762fcSSteven Rostedt pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK); 384493762fcSSteven Rostedt 385493762fcSSteven Rostedt again: 3860296e425SLi Zefan if (idx != 0) 387493762fcSSteven Rostedt rec++; 3880296e425SLi Zefan 389493762fcSSteven Rostedt if ((void *)rec >= (void *)&pg->records[pg->index]) { 390493762fcSSteven Rostedt pg = pg->next; 391493762fcSSteven Rostedt if (!pg) 392493762fcSSteven Rostedt return NULL; 393493762fcSSteven Rostedt rec = &pg->records[0]; 394493762fcSSteven Rostedt if (!rec->counter) 395493762fcSSteven Rostedt goto again; 396493762fcSSteven Rostedt } 397493762fcSSteven Rostedt 398493762fcSSteven Rostedt return rec; 399493762fcSSteven Rostedt } 400493762fcSSteven Rostedt 401493762fcSSteven Rostedt static void *function_stat_start(struct tracer_stat *trace) 402493762fcSSteven Rostedt { 403cafb168aSSteven Rostedt struct ftrace_profile_stat *stat = 404cafb168aSSteven Rostedt container_of(trace, struct ftrace_profile_stat, stat); 405cafb168aSSteven Rostedt 406cafb168aSSteven Rostedt if (!stat || !stat->start) 407cafb168aSSteven Rostedt return NULL; 408cafb168aSSteven Rostedt 409cafb168aSSteven Rostedt return function_stat_next(&stat->start->records[0], 0); 410493762fcSSteven Rostedt } 411493762fcSSteven Rostedt 4120706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 4130706f1c4SSteven Rostedt /* function graph compares on total time */ 4140706f1c4SSteven Rostedt static int function_stat_cmp(void *p1, void *p2) 4150706f1c4SSteven Rostedt { 4160706f1c4SSteven Rostedt struct ftrace_profile *a = p1; 4170706f1c4SSteven Rostedt struct ftrace_profile *b = p2; 4180706f1c4SSteven Rostedt 4190706f1c4SSteven Rostedt if (a->time < b->time) 4200706f1c4SSteven Rostedt return -1; 4210706f1c4SSteven Rostedt if (a->time > b->time) 4220706f1c4SSteven Rostedt return 1; 4230706f1c4SSteven Rostedt else 4240706f1c4SSteven Rostedt return 0; 4250706f1c4SSteven Rostedt } 4260706f1c4SSteven Rostedt #else 4270706f1c4SSteven Rostedt /* not function graph compares against hits */ 428493762fcSSteven Rostedt static int function_stat_cmp(void *p1, void *p2) 429493762fcSSteven Rostedt { 430493762fcSSteven Rostedt struct ftrace_profile *a = p1; 431493762fcSSteven Rostedt struct ftrace_profile *b = p2; 432493762fcSSteven Rostedt 433493762fcSSteven Rostedt if (a->counter < b->counter) 434493762fcSSteven Rostedt return -1; 435493762fcSSteven Rostedt if (a->counter > b->counter) 436493762fcSSteven Rostedt return 1; 437493762fcSSteven Rostedt else 438493762fcSSteven Rostedt return 0; 439493762fcSSteven Rostedt } 4400706f1c4SSteven Rostedt #endif 441493762fcSSteven Rostedt 442493762fcSSteven Rostedt static int function_stat_headers(struct seq_file *m) 443493762fcSSteven Rostedt { 4440706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 44534886c8bSSteven Rostedt seq_printf(m, " Function " 446e330b3bcSChase Douglas "Hit Time Avg s^2\n" 44734886c8bSSteven Rostedt " -------- " 448e330b3bcSChase Douglas "--- ---- --- ---\n"); 4490706f1c4SSteven Rostedt #else 450493762fcSSteven Rostedt seq_printf(m, " Function Hit\n" 451493762fcSSteven Rostedt " -------- ---\n"); 4520706f1c4SSteven Rostedt #endif 453493762fcSSteven Rostedt return 0; 454493762fcSSteven Rostedt } 455493762fcSSteven Rostedt 456493762fcSSteven Rostedt static int function_stat_show(struct seq_file *m, void *v) 457493762fcSSteven Rostedt { 458493762fcSSteven Rostedt struct ftrace_profile *rec = v; 459493762fcSSteven Rostedt char str[KSYM_SYMBOL_LEN]; 4603aaba20fSLi Zefan int ret = 0; 4610706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 46234886c8bSSteven Rostedt static struct trace_seq s; 46334886c8bSSteven Rostedt unsigned long long avg; 464e330b3bcSChase Douglas unsigned long long stddev; 4650706f1c4SSteven Rostedt #endif 4663aaba20fSLi Zefan mutex_lock(&ftrace_profile_lock); 4673aaba20fSLi Zefan 4683aaba20fSLi Zefan /* we raced with function_profile_reset() */ 4693aaba20fSLi Zefan if (unlikely(rec->counter == 0)) { 4703aaba20fSLi Zefan ret = -EBUSY; 4713aaba20fSLi Zefan goto out; 4723aaba20fSLi Zefan } 473493762fcSSteven Rostedt 474493762fcSSteven Rostedt kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); 4750706f1c4SSteven Rostedt seq_printf(m, " %-30.30s %10lu", str, rec->counter); 476493762fcSSteven Rostedt 4770706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 4780706f1c4SSteven Rostedt seq_printf(m, " "); 47934886c8bSSteven Rostedt avg = rec->time; 48034886c8bSSteven Rostedt do_div(avg, rec->counter); 48134886c8bSSteven Rostedt 482e330b3bcSChase Douglas /* Sample standard deviation (s^2) */ 483e330b3bcSChase Douglas if (rec->counter <= 1) 484e330b3bcSChase Douglas stddev = 0; 485e330b3bcSChase Douglas else { 486e330b3bcSChase Douglas stddev = rec->time_squared - rec->counter * avg * avg; 487e330b3bcSChase Douglas /* 488e330b3bcSChase Douglas * Divide only 1000 for ns^2 -> us^2 conversion. 489e330b3bcSChase Douglas * trace_print_graph_duration will divide 1000 again. 490e330b3bcSChase Douglas */ 491e330b3bcSChase Douglas do_div(stddev, (rec->counter - 1) * 1000); 492e330b3bcSChase Douglas } 493e330b3bcSChase Douglas 49434886c8bSSteven Rostedt trace_seq_init(&s); 49534886c8bSSteven Rostedt trace_print_graph_duration(rec->time, &s); 49634886c8bSSteven Rostedt trace_seq_puts(&s, " "); 49734886c8bSSteven Rostedt trace_print_graph_duration(avg, &s); 498e330b3bcSChase Douglas trace_seq_puts(&s, " "); 499e330b3bcSChase Douglas trace_print_graph_duration(stddev, &s); 5000706f1c4SSteven Rostedt trace_print_seq(m, &s); 5010706f1c4SSteven Rostedt #endif 5020706f1c4SSteven Rostedt seq_putc(m, '\n'); 5033aaba20fSLi Zefan out: 5043aaba20fSLi Zefan mutex_unlock(&ftrace_profile_lock); 5050706f1c4SSteven Rostedt 5063aaba20fSLi Zefan return ret; 507493762fcSSteven Rostedt } 508493762fcSSteven Rostedt 509cafb168aSSteven Rostedt static void ftrace_profile_reset(struct ftrace_profile_stat *stat) 510493762fcSSteven Rostedt { 511493762fcSSteven Rostedt struct ftrace_profile_page *pg; 512493762fcSSteven Rostedt 513cafb168aSSteven Rostedt pg = stat->pages = stat->start; 514493762fcSSteven Rostedt 515493762fcSSteven Rostedt while (pg) { 516493762fcSSteven Rostedt memset(pg->records, 0, PROFILE_RECORDS_SIZE); 517493762fcSSteven Rostedt pg->index = 0; 518493762fcSSteven Rostedt pg = pg->next; 519493762fcSSteven Rostedt } 520493762fcSSteven Rostedt 521cafb168aSSteven Rostedt memset(stat->hash, 0, 522493762fcSSteven Rostedt FTRACE_PROFILE_HASH_SIZE * sizeof(struct hlist_head)); 523493762fcSSteven Rostedt } 524493762fcSSteven Rostedt 525cafb168aSSteven Rostedt int ftrace_profile_pages_init(struct ftrace_profile_stat *stat) 526493762fcSSteven Rostedt { 527493762fcSSteven Rostedt struct ftrace_profile_page *pg; 528318e0a73SSteven Rostedt int functions; 529318e0a73SSteven Rostedt int pages; 530493762fcSSteven Rostedt int i; 531493762fcSSteven Rostedt 532493762fcSSteven Rostedt /* If we already allocated, do nothing */ 533cafb168aSSteven Rostedt if (stat->pages) 534493762fcSSteven Rostedt return 0; 535493762fcSSteven Rostedt 536cafb168aSSteven Rostedt stat->pages = (void *)get_zeroed_page(GFP_KERNEL); 537cafb168aSSteven Rostedt if (!stat->pages) 538493762fcSSteven Rostedt return -ENOMEM; 539493762fcSSteven Rostedt 540318e0a73SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE 541318e0a73SSteven Rostedt functions = ftrace_update_tot_cnt; 542318e0a73SSteven Rostedt #else 543318e0a73SSteven Rostedt /* 544318e0a73SSteven Rostedt * We do not know the number of functions that exist because 545318e0a73SSteven Rostedt * dynamic tracing is what counts them. With past experience 546318e0a73SSteven Rostedt * we have around 20K functions. That should be more than enough. 547318e0a73SSteven Rostedt * It is highly unlikely we will execute every function in 548318e0a73SSteven Rostedt * the kernel. 549318e0a73SSteven Rostedt */ 550318e0a73SSteven Rostedt functions = 20000; 551318e0a73SSteven Rostedt #endif 552318e0a73SSteven Rostedt 553cafb168aSSteven Rostedt pg = stat->start = stat->pages; 554493762fcSSteven Rostedt 555318e0a73SSteven Rostedt pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE); 556318e0a73SSteven Rostedt 557318e0a73SSteven Rostedt for (i = 0; i < pages; i++) { 558493762fcSSteven Rostedt pg->next = (void *)get_zeroed_page(GFP_KERNEL); 559493762fcSSteven Rostedt if (!pg->next) 560318e0a73SSteven Rostedt goto out_free; 561493762fcSSteven Rostedt pg = pg->next; 562493762fcSSteven Rostedt } 563493762fcSSteven Rostedt 564493762fcSSteven Rostedt return 0; 565318e0a73SSteven Rostedt 566318e0a73SSteven Rostedt out_free: 567318e0a73SSteven Rostedt pg = stat->start; 568318e0a73SSteven Rostedt while (pg) { 569318e0a73SSteven Rostedt unsigned long tmp = (unsigned long)pg; 570318e0a73SSteven Rostedt 571318e0a73SSteven Rostedt pg = pg->next; 572318e0a73SSteven Rostedt free_page(tmp); 573318e0a73SSteven Rostedt } 574318e0a73SSteven Rostedt 575318e0a73SSteven Rostedt free_page((unsigned long)stat->pages); 576318e0a73SSteven Rostedt stat->pages = NULL; 577318e0a73SSteven Rostedt stat->start = NULL; 578318e0a73SSteven Rostedt 579318e0a73SSteven Rostedt return -ENOMEM; 580493762fcSSteven Rostedt } 581493762fcSSteven Rostedt 582cafb168aSSteven Rostedt static int ftrace_profile_init_cpu(int cpu) 583493762fcSSteven Rostedt { 584cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 585493762fcSSteven Rostedt int size; 586493762fcSSteven Rostedt 587cafb168aSSteven Rostedt stat = &per_cpu(ftrace_profile_stats, cpu); 588cafb168aSSteven Rostedt 589cafb168aSSteven Rostedt if (stat->hash) { 590493762fcSSteven Rostedt /* If the profile is already created, simply reset it */ 591cafb168aSSteven Rostedt ftrace_profile_reset(stat); 592493762fcSSteven Rostedt return 0; 593493762fcSSteven Rostedt } 594493762fcSSteven Rostedt 595493762fcSSteven Rostedt /* 596493762fcSSteven Rostedt * We are profiling all functions, but usually only a few thousand 597493762fcSSteven Rostedt * functions are hit. We'll make a hash of 1024 items. 598493762fcSSteven Rostedt */ 599493762fcSSteven Rostedt size = FTRACE_PROFILE_HASH_SIZE; 600493762fcSSteven Rostedt 601cafb168aSSteven Rostedt stat->hash = kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL); 602493762fcSSteven Rostedt 603cafb168aSSteven Rostedt if (!stat->hash) 604493762fcSSteven Rostedt return -ENOMEM; 605493762fcSSteven Rostedt 606cafb168aSSteven Rostedt if (!ftrace_profile_bits) { 607493762fcSSteven Rostedt size--; 608493762fcSSteven Rostedt 609493762fcSSteven Rostedt for (; size; size >>= 1) 610493762fcSSteven Rostedt ftrace_profile_bits++; 611cafb168aSSteven Rostedt } 612493762fcSSteven Rostedt 613318e0a73SSteven Rostedt /* Preallocate the function profiling pages */ 614cafb168aSSteven Rostedt if (ftrace_profile_pages_init(stat) < 0) { 615cafb168aSSteven Rostedt kfree(stat->hash); 616cafb168aSSteven Rostedt stat->hash = NULL; 617493762fcSSteven Rostedt return -ENOMEM; 618493762fcSSteven Rostedt } 619493762fcSSteven Rostedt 620493762fcSSteven Rostedt return 0; 621493762fcSSteven Rostedt } 622493762fcSSteven Rostedt 623cafb168aSSteven Rostedt static int ftrace_profile_init(void) 624cafb168aSSteven Rostedt { 625cafb168aSSteven Rostedt int cpu; 626cafb168aSSteven Rostedt int ret = 0; 627cafb168aSSteven Rostedt 628cafb168aSSteven Rostedt for_each_online_cpu(cpu) { 629cafb168aSSteven Rostedt ret = ftrace_profile_init_cpu(cpu); 630cafb168aSSteven Rostedt if (ret) 631cafb168aSSteven Rostedt break; 632cafb168aSSteven Rostedt } 633cafb168aSSteven Rostedt 634cafb168aSSteven Rostedt return ret; 635cafb168aSSteven Rostedt } 636cafb168aSSteven Rostedt 637493762fcSSteven Rostedt /* interrupts must be disabled */ 638cafb168aSSteven Rostedt static struct ftrace_profile * 639cafb168aSSteven Rostedt ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip) 640493762fcSSteven Rostedt { 641493762fcSSteven Rostedt struct ftrace_profile *rec; 642493762fcSSteven Rostedt struct hlist_head *hhd; 643493762fcSSteven Rostedt struct hlist_node *n; 644493762fcSSteven Rostedt unsigned long key; 645493762fcSSteven Rostedt 646493762fcSSteven Rostedt key = hash_long(ip, ftrace_profile_bits); 647cafb168aSSteven Rostedt hhd = &stat->hash[key]; 648493762fcSSteven Rostedt 649493762fcSSteven Rostedt if (hlist_empty(hhd)) 650493762fcSSteven Rostedt return NULL; 651493762fcSSteven Rostedt 652493762fcSSteven Rostedt hlist_for_each_entry_rcu(rec, n, hhd, node) { 653493762fcSSteven Rostedt if (rec->ip == ip) 654493762fcSSteven Rostedt return rec; 655493762fcSSteven Rostedt } 656493762fcSSteven Rostedt 657493762fcSSteven Rostedt return NULL; 658493762fcSSteven Rostedt } 659493762fcSSteven Rostedt 660cafb168aSSteven Rostedt static void ftrace_add_profile(struct ftrace_profile_stat *stat, 661cafb168aSSteven Rostedt struct ftrace_profile *rec) 662493762fcSSteven Rostedt { 663493762fcSSteven Rostedt unsigned long key; 664493762fcSSteven Rostedt 665493762fcSSteven Rostedt key = hash_long(rec->ip, ftrace_profile_bits); 666cafb168aSSteven Rostedt hlist_add_head_rcu(&rec->node, &stat->hash[key]); 667493762fcSSteven Rostedt } 668493762fcSSteven Rostedt 669318e0a73SSteven Rostedt /* 670318e0a73SSteven Rostedt * The memory is already allocated, this simply finds a new record to use. 671318e0a73SSteven Rostedt */ 672493762fcSSteven Rostedt static struct ftrace_profile * 673318e0a73SSteven Rostedt ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip) 674493762fcSSteven Rostedt { 675493762fcSSteven Rostedt struct ftrace_profile *rec = NULL; 676493762fcSSteven Rostedt 677318e0a73SSteven Rostedt /* prevent recursion (from NMIs) */ 678cafb168aSSteven Rostedt if (atomic_inc_return(&stat->disabled) != 1) 679493762fcSSteven Rostedt goto out; 680493762fcSSteven Rostedt 681493762fcSSteven Rostedt /* 682318e0a73SSteven Rostedt * Try to find the function again since an NMI 683318e0a73SSteven Rostedt * could have added it 684493762fcSSteven Rostedt */ 685cafb168aSSteven Rostedt rec = ftrace_find_profiled_func(stat, ip); 686493762fcSSteven Rostedt if (rec) 687cafb168aSSteven Rostedt goto out; 688493762fcSSteven Rostedt 689cafb168aSSteven Rostedt if (stat->pages->index == PROFILES_PER_PAGE) { 690cafb168aSSteven Rostedt if (!stat->pages->next) 691cafb168aSSteven Rostedt goto out; 692cafb168aSSteven Rostedt stat->pages = stat->pages->next; 693493762fcSSteven Rostedt } 694493762fcSSteven Rostedt 695cafb168aSSteven Rostedt rec = &stat->pages->records[stat->pages->index++]; 696493762fcSSteven Rostedt rec->ip = ip; 697cafb168aSSteven Rostedt ftrace_add_profile(stat, rec); 698493762fcSSteven Rostedt 699493762fcSSteven Rostedt out: 700cafb168aSSteven Rostedt atomic_dec(&stat->disabled); 701493762fcSSteven Rostedt 702493762fcSSteven Rostedt return rec; 703493762fcSSteven Rostedt } 704493762fcSSteven Rostedt 705493762fcSSteven Rostedt static void 706493762fcSSteven Rostedt function_profile_call(unsigned long ip, unsigned long parent_ip) 707493762fcSSteven Rostedt { 708cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 709493762fcSSteven Rostedt struct ftrace_profile *rec; 710493762fcSSteven Rostedt unsigned long flags; 711493762fcSSteven Rostedt 712493762fcSSteven Rostedt if (!ftrace_profile_enabled) 713493762fcSSteven Rostedt return; 714493762fcSSteven Rostedt 715493762fcSSteven Rostedt local_irq_save(flags); 716cafb168aSSteven Rostedt 717cafb168aSSteven Rostedt stat = &__get_cpu_var(ftrace_profile_stats); 7180f6ce3deSSteven Rostedt if (!stat->hash || !ftrace_profile_enabled) 719cafb168aSSteven Rostedt goto out; 720cafb168aSSteven Rostedt 721cafb168aSSteven Rostedt rec = ftrace_find_profiled_func(stat, ip); 722493762fcSSteven Rostedt if (!rec) { 723318e0a73SSteven Rostedt rec = ftrace_profile_alloc(stat, ip); 724493762fcSSteven Rostedt if (!rec) 725493762fcSSteven Rostedt goto out; 726493762fcSSteven Rostedt } 727493762fcSSteven Rostedt 728493762fcSSteven Rostedt rec->counter++; 729493762fcSSteven Rostedt out: 730493762fcSSteven Rostedt local_irq_restore(flags); 731493762fcSSteven Rostedt } 732493762fcSSteven Rostedt 7330706f1c4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 7340706f1c4SSteven Rostedt static int profile_graph_entry(struct ftrace_graph_ent *trace) 7350706f1c4SSteven Rostedt { 7360706f1c4SSteven Rostedt function_profile_call(trace->func, 0); 7370706f1c4SSteven Rostedt return 1; 7380706f1c4SSteven Rostedt } 7390706f1c4SSteven Rostedt 7400706f1c4SSteven Rostedt static void profile_graph_return(struct ftrace_graph_ret *trace) 7410706f1c4SSteven Rostedt { 742cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 743a2a16d6aSSteven Rostedt unsigned long long calltime; 7440706f1c4SSteven Rostedt struct ftrace_profile *rec; 745cafb168aSSteven Rostedt unsigned long flags; 7460706f1c4SSteven Rostedt 7470706f1c4SSteven Rostedt local_irq_save(flags); 748cafb168aSSteven Rostedt stat = &__get_cpu_var(ftrace_profile_stats); 7490f6ce3deSSteven Rostedt if (!stat->hash || !ftrace_profile_enabled) 750cafb168aSSteven Rostedt goto out; 751cafb168aSSteven Rostedt 75237e44bc5SSteven Rostedt /* If the calltime was zero'd ignore it */ 75337e44bc5SSteven Rostedt if (!trace->calltime) 75437e44bc5SSteven Rostedt goto out; 75537e44bc5SSteven Rostedt 756a2a16d6aSSteven Rostedt calltime = trace->rettime - trace->calltime; 757a2a16d6aSSteven Rostedt 758a2a16d6aSSteven Rostedt if (!(trace_flags & TRACE_ITER_GRAPH_TIME)) { 759a2a16d6aSSteven Rostedt int index; 760a2a16d6aSSteven Rostedt 761a2a16d6aSSteven Rostedt index = trace->depth; 762a2a16d6aSSteven Rostedt 763a2a16d6aSSteven Rostedt /* Append this call time to the parent time to subtract */ 764a2a16d6aSSteven Rostedt if (index) 765a2a16d6aSSteven Rostedt current->ret_stack[index - 1].subtime += calltime; 766a2a16d6aSSteven Rostedt 767a2a16d6aSSteven Rostedt if (current->ret_stack[index].subtime < calltime) 768a2a16d6aSSteven Rostedt calltime -= current->ret_stack[index].subtime; 769a2a16d6aSSteven Rostedt else 770a2a16d6aSSteven Rostedt calltime = 0; 771a2a16d6aSSteven Rostedt } 772a2a16d6aSSteven Rostedt 773cafb168aSSteven Rostedt rec = ftrace_find_profiled_func(stat, trace->func); 774e330b3bcSChase Douglas if (rec) { 775a2a16d6aSSteven Rostedt rec->time += calltime; 776e330b3bcSChase Douglas rec->time_squared += calltime * calltime; 777e330b3bcSChase Douglas } 778a2a16d6aSSteven Rostedt 779cafb168aSSteven Rostedt out: 7800706f1c4SSteven Rostedt local_irq_restore(flags); 7810706f1c4SSteven Rostedt } 7820706f1c4SSteven Rostedt 7830706f1c4SSteven Rostedt static int register_ftrace_profiler(void) 7840706f1c4SSteven Rostedt { 7850706f1c4SSteven Rostedt return register_ftrace_graph(&profile_graph_return, 7860706f1c4SSteven Rostedt &profile_graph_entry); 7870706f1c4SSteven Rostedt } 7880706f1c4SSteven Rostedt 7890706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void) 7900706f1c4SSteven Rostedt { 7910706f1c4SSteven Rostedt unregister_ftrace_graph(); 7920706f1c4SSteven Rostedt } 7930706f1c4SSteven Rostedt #else 794bd38c0e6SPaul McQuade static struct ftrace_ops ftrace_profile_ops __read_mostly = { 795493762fcSSteven Rostedt .func = function_profile_call, 796493762fcSSteven Rostedt }; 797493762fcSSteven Rostedt 7980706f1c4SSteven Rostedt static int register_ftrace_profiler(void) 7990706f1c4SSteven Rostedt { 8000706f1c4SSteven Rostedt return register_ftrace_function(&ftrace_profile_ops); 8010706f1c4SSteven Rostedt } 8020706f1c4SSteven Rostedt 8030706f1c4SSteven Rostedt static void unregister_ftrace_profiler(void) 8040706f1c4SSteven Rostedt { 8050706f1c4SSteven Rostedt unregister_ftrace_function(&ftrace_profile_ops); 8060706f1c4SSteven Rostedt } 8070706f1c4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 8080706f1c4SSteven Rostedt 809493762fcSSteven Rostedt static ssize_t 810493762fcSSteven Rostedt ftrace_profile_write(struct file *filp, const char __user *ubuf, 811493762fcSSteven Rostedt size_t cnt, loff_t *ppos) 812493762fcSSteven Rostedt { 813493762fcSSteven Rostedt unsigned long val; 814493762fcSSteven Rostedt int ret; 815493762fcSSteven Rostedt 81622fe9b54SPeter Huewe ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 81722fe9b54SPeter Huewe if (ret) 818493762fcSSteven Rostedt return ret; 819493762fcSSteven Rostedt 820493762fcSSteven Rostedt val = !!val; 821493762fcSSteven Rostedt 822493762fcSSteven Rostedt mutex_lock(&ftrace_profile_lock); 823493762fcSSteven Rostedt if (ftrace_profile_enabled ^ val) { 824493762fcSSteven Rostedt if (val) { 825493762fcSSteven Rostedt ret = ftrace_profile_init(); 826493762fcSSteven Rostedt if (ret < 0) { 827493762fcSSteven Rostedt cnt = ret; 828493762fcSSteven Rostedt goto out; 829493762fcSSteven Rostedt } 830493762fcSSteven Rostedt 8310706f1c4SSteven Rostedt ret = register_ftrace_profiler(); 8320706f1c4SSteven Rostedt if (ret < 0) { 8330706f1c4SSteven Rostedt cnt = ret; 8340706f1c4SSteven Rostedt goto out; 8350706f1c4SSteven Rostedt } 836493762fcSSteven Rostedt ftrace_profile_enabled = 1; 837493762fcSSteven Rostedt } else { 838493762fcSSteven Rostedt ftrace_profile_enabled = 0; 8390f6ce3deSSteven Rostedt /* 8400f6ce3deSSteven Rostedt * unregister_ftrace_profiler calls stop_machine 8410f6ce3deSSteven Rostedt * so this acts like an synchronize_sched. 8420f6ce3deSSteven Rostedt */ 8430706f1c4SSteven Rostedt unregister_ftrace_profiler(); 844493762fcSSteven Rostedt } 845493762fcSSteven Rostedt } 846493762fcSSteven Rostedt out: 847493762fcSSteven Rostedt mutex_unlock(&ftrace_profile_lock); 848493762fcSSteven Rostedt 849cf8517cfSJiri Olsa *ppos += cnt; 850493762fcSSteven Rostedt 851493762fcSSteven Rostedt return cnt; 852493762fcSSteven Rostedt } 853493762fcSSteven Rostedt 854493762fcSSteven Rostedt static ssize_t 855493762fcSSteven Rostedt ftrace_profile_read(struct file *filp, char __user *ubuf, 856493762fcSSteven Rostedt size_t cnt, loff_t *ppos) 857493762fcSSteven Rostedt { 858fb9fb015SSteven Rostedt char buf[64]; /* big enough to hold a number */ 859493762fcSSteven Rostedt int r; 860493762fcSSteven Rostedt 861493762fcSSteven Rostedt r = sprintf(buf, "%u\n", ftrace_profile_enabled); 862493762fcSSteven Rostedt return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 863493762fcSSteven Rostedt } 864493762fcSSteven Rostedt 865493762fcSSteven Rostedt static const struct file_operations ftrace_profile_fops = { 866493762fcSSteven Rostedt .open = tracing_open_generic, 867493762fcSSteven Rostedt .read = ftrace_profile_read, 868493762fcSSteven Rostedt .write = ftrace_profile_write, 8696038f373SArnd Bergmann .llseek = default_llseek, 870493762fcSSteven Rostedt }; 871493762fcSSteven Rostedt 872cafb168aSSteven Rostedt /* used to initialize the real stat files */ 873cafb168aSSteven Rostedt static struct tracer_stat function_stats __initdata = { 874cafb168aSSteven Rostedt .name = "functions", 875cafb168aSSteven Rostedt .stat_start = function_stat_start, 876cafb168aSSteven Rostedt .stat_next = function_stat_next, 877cafb168aSSteven Rostedt .stat_cmp = function_stat_cmp, 878cafb168aSSteven Rostedt .stat_headers = function_stat_headers, 879cafb168aSSteven Rostedt .stat_show = function_stat_show 880cafb168aSSteven Rostedt }; 881cafb168aSSteven Rostedt 8826ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer) 883493762fcSSteven Rostedt { 884cafb168aSSteven Rostedt struct ftrace_profile_stat *stat; 885493762fcSSteven Rostedt struct dentry *entry; 886cafb168aSSteven Rostedt char *name; 887493762fcSSteven Rostedt int ret; 888cafb168aSSteven Rostedt int cpu; 889493762fcSSteven Rostedt 890cafb168aSSteven Rostedt for_each_possible_cpu(cpu) { 891cafb168aSSteven Rostedt stat = &per_cpu(ftrace_profile_stats, cpu); 892cafb168aSSteven Rostedt 893cafb168aSSteven Rostedt /* allocate enough for function name + cpu number */ 894cafb168aSSteven Rostedt name = kmalloc(32, GFP_KERNEL); 895cafb168aSSteven Rostedt if (!name) { 896cafb168aSSteven Rostedt /* 897cafb168aSSteven Rostedt * The files created are permanent, if something happens 898cafb168aSSteven Rostedt * we still do not free memory. 899cafb168aSSteven Rostedt */ 900cafb168aSSteven Rostedt WARN(1, 901cafb168aSSteven Rostedt "Could not allocate stat file for cpu %d\n", 902cafb168aSSteven Rostedt cpu); 903493762fcSSteven Rostedt return; 904493762fcSSteven Rostedt } 905cafb168aSSteven Rostedt stat->stat = function_stats; 906cafb168aSSteven Rostedt snprintf(name, 32, "function%d", cpu); 907cafb168aSSteven Rostedt stat->stat.name = name; 908cafb168aSSteven Rostedt ret = register_stat_tracer(&stat->stat); 909cafb168aSSteven Rostedt if (ret) { 910cafb168aSSteven Rostedt WARN(1, 911cafb168aSSteven Rostedt "Could not register function stat for cpu %d\n", 912cafb168aSSteven Rostedt cpu); 913cafb168aSSteven Rostedt kfree(name); 914cafb168aSSteven Rostedt return; 915cafb168aSSteven Rostedt } 916cafb168aSSteven Rostedt } 917493762fcSSteven Rostedt 918493762fcSSteven Rostedt entry = debugfs_create_file("function_profile_enabled", 0644, 919493762fcSSteven Rostedt d_tracer, NULL, &ftrace_profile_fops); 920493762fcSSteven Rostedt if (!entry) 921493762fcSSteven Rostedt pr_warning("Could not create debugfs " 922493762fcSSteven Rostedt "'function_profile_enabled' entry\n"); 923493762fcSSteven Rostedt } 924493762fcSSteven Rostedt 925493762fcSSteven Rostedt #else /* CONFIG_FUNCTION_PROFILER */ 9266ab5d668SSteven Rostedt static __init void ftrace_profile_debugfs(struct dentry *d_tracer) 927493762fcSSteven Rostedt { 928493762fcSSteven Rostedt } 929493762fcSSteven Rostedt #endif /* CONFIG_FUNCTION_PROFILER */ 930493762fcSSteven Rostedt 93173d3fd96SIngo Molnar static struct pid * const ftrace_swapper_pid = &init_struct_pid; 93273d3fd96SIngo Molnar 9333d083395SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE 93473d3fd96SIngo Molnar 93599ecdc43SSteven Rostedt #ifndef CONFIG_FTRACE_MCOUNT_RECORD 936cb7be3b2SSteven Rostedt # error Dynamic ftrace depends on MCOUNT_RECORD 93799ecdc43SSteven Rostedt #endif 93899ecdc43SSteven Rostedt 9398fc0c701SSteven Rostedt static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly; 9408fc0c701SSteven Rostedt 941b6887d79SSteven Rostedt struct ftrace_func_probe { 9428fc0c701SSteven Rostedt struct hlist_node node; 943b6887d79SSteven Rostedt struct ftrace_probe_ops *ops; 9448fc0c701SSteven Rostedt unsigned long flags; 9458fc0c701SSteven Rostedt unsigned long ip; 9468fc0c701SSteven Rostedt void *data; 9478fc0c701SSteven Rostedt struct rcu_head rcu; 9488fc0c701SSteven Rostedt }; 9498fc0c701SSteven Rostedt 950d61f82d0SSteven Rostedt enum { 951d61f82d0SSteven Rostedt FTRACE_ENABLE_CALLS = (1 << 0), 952d61f82d0SSteven Rostedt FTRACE_DISABLE_CALLS = (1 << 1), 953d61f82d0SSteven Rostedt FTRACE_UPDATE_TRACE_FUNC = (1 << 2), 95479e406d7SSteven Rostedt FTRACE_START_FUNC_RET = (1 << 3), 95579e406d7SSteven Rostedt FTRACE_STOP_FUNC_RET = (1 << 4), 956d61f82d0SSteven Rostedt }; 957b448c4e3SSteven Rostedt struct ftrace_func_entry { 958b448c4e3SSteven Rostedt struct hlist_node hlist; 959b448c4e3SSteven Rostedt unsigned long ip; 960b448c4e3SSteven Rostedt }; 961b448c4e3SSteven Rostedt 962b448c4e3SSteven Rostedt struct ftrace_hash { 963b448c4e3SSteven Rostedt unsigned long size_bits; 964b448c4e3SSteven Rostedt struct hlist_head *buckets; 965b448c4e3SSteven Rostedt unsigned long count; 96607fd5515SSteven Rostedt struct rcu_head rcu; 967b448c4e3SSteven Rostedt }; 968b448c4e3SSteven Rostedt 96933dc9b12SSteven Rostedt /* 97033dc9b12SSteven Rostedt * We make these constant because no one should touch them, 97133dc9b12SSteven Rostedt * but they are used as the default "empty hash", to avoid allocating 97233dc9b12SSteven Rostedt * it all the time. These are in a read only section such that if 97333dc9b12SSteven Rostedt * anyone does try to modify it, it will cause an exception. 97433dc9b12SSteven Rostedt */ 97533dc9b12SSteven Rostedt static const struct hlist_head empty_buckets[1]; 97633dc9b12SSteven Rostedt static const struct ftrace_hash empty_hash = { 97733dc9b12SSteven Rostedt .buckets = (struct hlist_head *)empty_buckets, 978b448c4e3SSteven Rostedt }; 97933dc9b12SSteven Rostedt #define EMPTY_HASH ((struct ftrace_hash *)&empty_hash) 9805072c59fSSteven Rostedt 9812b499381SSteven Rostedt static struct ftrace_ops global_ops = { 982f45948e8SSteven Rostedt .func = ftrace_stub, 98333dc9b12SSteven Rostedt .notrace_hash = EMPTY_HASH, 98433dc9b12SSteven Rostedt .filter_hash = EMPTY_HASH, 985f45948e8SSteven Rostedt }; 986f45948e8SSteven Rostedt 987e94142a6SLai Jiangshan static struct dyn_ftrace *ftrace_new_addrs; 9883d083395SSteven Rostedt 98941c52c0dSSteven Rostedt static DEFINE_MUTEX(ftrace_regex_lock); 9903d083395SSteven Rostedt 9913c1720f0SSteven Rostedt struct ftrace_page { 9923c1720f0SSteven Rostedt struct ftrace_page *next; 993431aa3fbSSteven Rostedt int index; 9943c1720f0SSteven Rostedt struct dyn_ftrace records[]; 995aa5e5ceaSDavid Miller }; 9963c1720f0SSteven Rostedt 9973c1720f0SSteven Rostedt #define ENTRIES_PER_PAGE \ 9983c1720f0SSteven Rostedt ((PAGE_SIZE - sizeof(struct ftrace_page)) / sizeof(struct dyn_ftrace)) 9993c1720f0SSteven Rostedt 10003c1720f0SSteven Rostedt /* estimate from running different kernels */ 10013c1720f0SSteven Rostedt #define NR_TO_INIT 10000 10023c1720f0SSteven Rostedt 10033c1720f0SSteven Rostedt static struct ftrace_page *ftrace_pages_start; 10043c1720f0SSteven Rostedt static struct ftrace_page *ftrace_pages; 10053c1720f0SSteven Rostedt 100637ad5084SSteven Rostedt static struct dyn_ftrace *ftrace_free_records; 100737ad5084SSteven Rostedt 1008b448c4e3SSteven Rostedt static struct ftrace_func_entry * 1009b448c4e3SSteven Rostedt ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip) 1010b448c4e3SSteven Rostedt { 1011b448c4e3SSteven Rostedt unsigned long key; 1012b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 1013b448c4e3SSteven Rostedt struct hlist_head *hhd; 1014b448c4e3SSteven Rostedt struct hlist_node *n; 1015b448c4e3SSteven Rostedt 1016b448c4e3SSteven Rostedt if (!hash->count) 1017b448c4e3SSteven Rostedt return NULL; 1018b448c4e3SSteven Rostedt 1019b448c4e3SSteven Rostedt if (hash->size_bits > 0) 1020b448c4e3SSteven Rostedt key = hash_long(ip, hash->size_bits); 1021b448c4e3SSteven Rostedt else 1022b448c4e3SSteven Rostedt key = 0; 1023b448c4e3SSteven Rostedt 1024b448c4e3SSteven Rostedt hhd = &hash->buckets[key]; 1025b448c4e3SSteven Rostedt 1026b448c4e3SSteven Rostedt hlist_for_each_entry_rcu(entry, n, hhd, hlist) { 1027b448c4e3SSteven Rostedt if (entry->ip == ip) 1028b448c4e3SSteven Rostedt return entry; 1029b448c4e3SSteven Rostedt } 1030b448c4e3SSteven Rostedt return NULL; 1031b448c4e3SSteven Rostedt } 1032b448c4e3SSteven Rostedt 103333dc9b12SSteven Rostedt static void __add_hash_entry(struct ftrace_hash *hash, 103433dc9b12SSteven Rostedt struct ftrace_func_entry *entry) 103533dc9b12SSteven Rostedt { 103633dc9b12SSteven Rostedt struct hlist_head *hhd; 103733dc9b12SSteven Rostedt unsigned long key; 103833dc9b12SSteven Rostedt 103933dc9b12SSteven Rostedt if (hash->size_bits) 104033dc9b12SSteven Rostedt key = hash_long(entry->ip, hash->size_bits); 104133dc9b12SSteven Rostedt else 104233dc9b12SSteven Rostedt key = 0; 104333dc9b12SSteven Rostedt 104433dc9b12SSteven Rostedt hhd = &hash->buckets[key]; 104533dc9b12SSteven Rostedt hlist_add_head(&entry->hlist, hhd); 104633dc9b12SSteven Rostedt hash->count++; 104733dc9b12SSteven Rostedt } 104833dc9b12SSteven Rostedt 1049b448c4e3SSteven Rostedt static int add_hash_entry(struct ftrace_hash *hash, unsigned long ip) 1050b448c4e3SSteven Rostedt { 1051b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 1052b448c4e3SSteven Rostedt 1053b448c4e3SSteven Rostedt entry = kmalloc(sizeof(*entry), GFP_KERNEL); 1054b448c4e3SSteven Rostedt if (!entry) 1055b448c4e3SSteven Rostedt return -ENOMEM; 1056b448c4e3SSteven Rostedt 1057b448c4e3SSteven Rostedt entry->ip = ip; 105833dc9b12SSteven Rostedt __add_hash_entry(hash, entry); 1059b448c4e3SSteven Rostedt 1060b448c4e3SSteven Rostedt return 0; 1061b448c4e3SSteven Rostedt } 1062b448c4e3SSteven Rostedt 1063b448c4e3SSteven Rostedt static void 106433dc9b12SSteven Rostedt free_hash_entry(struct ftrace_hash *hash, 106533dc9b12SSteven Rostedt struct ftrace_func_entry *entry) 106633dc9b12SSteven Rostedt { 106733dc9b12SSteven Rostedt hlist_del(&entry->hlist); 106833dc9b12SSteven Rostedt kfree(entry); 106933dc9b12SSteven Rostedt hash->count--; 107033dc9b12SSteven Rostedt } 107133dc9b12SSteven Rostedt 107233dc9b12SSteven Rostedt static void 1073b448c4e3SSteven Rostedt remove_hash_entry(struct ftrace_hash *hash, 1074b448c4e3SSteven Rostedt struct ftrace_func_entry *entry) 1075b448c4e3SSteven Rostedt { 1076b448c4e3SSteven Rostedt hlist_del(&entry->hlist); 1077b448c4e3SSteven Rostedt hash->count--; 1078b448c4e3SSteven Rostedt } 1079b448c4e3SSteven Rostedt 1080b448c4e3SSteven Rostedt static void ftrace_hash_clear(struct ftrace_hash *hash) 1081b448c4e3SSteven Rostedt { 1082b448c4e3SSteven Rostedt struct hlist_head *hhd; 1083b448c4e3SSteven Rostedt struct hlist_node *tp, *tn; 1084b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 1085b448c4e3SSteven Rostedt int size = 1 << hash->size_bits; 1086b448c4e3SSteven Rostedt int i; 1087b448c4e3SSteven Rostedt 108833dc9b12SSteven Rostedt if (!hash->count) 108933dc9b12SSteven Rostedt return; 109033dc9b12SSteven Rostedt 1091b448c4e3SSteven Rostedt for (i = 0; i < size; i++) { 1092b448c4e3SSteven Rostedt hhd = &hash->buckets[i]; 1093b448c4e3SSteven Rostedt hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) 109433dc9b12SSteven Rostedt free_hash_entry(hash, entry); 1095b448c4e3SSteven Rostedt } 1096b448c4e3SSteven Rostedt FTRACE_WARN_ON(hash->count); 1097b448c4e3SSteven Rostedt } 1098b448c4e3SSteven Rostedt 109933dc9b12SSteven Rostedt static void free_ftrace_hash(struct ftrace_hash *hash) 110033dc9b12SSteven Rostedt { 110133dc9b12SSteven Rostedt if (!hash || hash == EMPTY_HASH) 110233dc9b12SSteven Rostedt return; 110333dc9b12SSteven Rostedt ftrace_hash_clear(hash); 110433dc9b12SSteven Rostedt kfree(hash->buckets); 110533dc9b12SSteven Rostedt kfree(hash); 110633dc9b12SSteven Rostedt } 110733dc9b12SSteven Rostedt 110807fd5515SSteven Rostedt static void __free_ftrace_hash_rcu(struct rcu_head *rcu) 110907fd5515SSteven Rostedt { 111007fd5515SSteven Rostedt struct ftrace_hash *hash; 111107fd5515SSteven Rostedt 111207fd5515SSteven Rostedt hash = container_of(rcu, struct ftrace_hash, rcu); 111307fd5515SSteven Rostedt free_ftrace_hash(hash); 111407fd5515SSteven Rostedt } 111507fd5515SSteven Rostedt 111607fd5515SSteven Rostedt static void free_ftrace_hash_rcu(struct ftrace_hash *hash) 111707fd5515SSteven Rostedt { 111807fd5515SSteven Rostedt if (!hash || hash == EMPTY_HASH) 111907fd5515SSteven Rostedt return; 112007fd5515SSteven Rostedt call_rcu_sched(&hash->rcu, __free_ftrace_hash_rcu); 112107fd5515SSteven Rostedt } 112207fd5515SSteven Rostedt 112333dc9b12SSteven Rostedt static struct ftrace_hash *alloc_ftrace_hash(int size_bits) 112433dc9b12SSteven Rostedt { 112533dc9b12SSteven Rostedt struct ftrace_hash *hash; 112633dc9b12SSteven Rostedt int size; 112733dc9b12SSteven Rostedt 112833dc9b12SSteven Rostedt hash = kzalloc(sizeof(*hash), GFP_KERNEL); 112933dc9b12SSteven Rostedt if (!hash) 113033dc9b12SSteven Rostedt return NULL; 113133dc9b12SSteven Rostedt 113233dc9b12SSteven Rostedt size = 1 << size_bits; 113333dc9b12SSteven Rostedt hash->buckets = kzalloc(sizeof(*hash->buckets) * size, GFP_KERNEL); 113433dc9b12SSteven Rostedt 113533dc9b12SSteven Rostedt if (!hash->buckets) { 113633dc9b12SSteven Rostedt kfree(hash); 113733dc9b12SSteven Rostedt return NULL; 113833dc9b12SSteven Rostedt } 113933dc9b12SSteven Rostedt 114033dc9b12SSteven Rostedt hash->size_bits = size_bits; 114133dc9b12SSteven Rostedt 114233dc9b12SSteven Rostedt return hash; 114333dc9b12SSteven Rostedt } 114433dc9b12SSteven Rostedt 114533dc9b12SSteven Rostedt static struct ftrace_hash * 114633dc9b12SSteven Rostedt alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) 114733dc9b12SSteven Rostedt { 114833dc9b12SSteven Rostedt struct ftrace_func_entry *entry; 114933dc9b12SSteven Rostedt struct ftrace_hash *new_hash; 115033dc9b12SSteven Rostedt struct hlist_node *tp; 115133dc9b12SSteven Rostedt int size; 115233dc9b12SSteven Rostedt int ret; 115333dc9b12SSteven Rostedt int i; 115433dc9b12SSteven Rostedt 115533dc9b12SSteven Rostedt new_hash = alloc_ftrace_hash(size_bits); 115633dc9b12SSteven Rostedt if (!new_hash) 115733dc9b12SSteven Rostedt return NULL; 115833dc9b12SSteven Rostedt 115933dc9b12SSteven Rostedt /* Empty hash? */ 116033dc9b12SSteven Rostedt if (!hash || !hash->count) 116133dc9b12SSteven Rostedt return new_hash; 116233dc9b12SSteven Rostedt 116333dc9b12SSteven Rostedt size = 1 << hash->size_bits; 116433dc9b12SSteven Rostedt for (i = 0; i < size; i++) { 116533dc9b12SSteven Rostedt hlist_for_each_entry(entry, tp, &hash->buckets[i], hlist) { 116633dc9b12SSteven Rostedt ret = add_hash_entry(new_hash, entry->ip); 116733dc9b12SSteven Rostedt if (ret < 0) 116833dc9b12SSteven Rostedt goto free_hash; 116933dc9b12SSteven Rostedt } 117033dc9b12SSteven Rostedt } 117133dc9b12SSteven Rostedt 117233dc9b12SSteven Rostedt FTRACE_WARN_ON(new_hash->count != hash->count); 117333dc9b12SSteven Rostedt 117433dc9b12SSteven Rostedt return new_hash; 117533dc9b12SSteven Rostedt 117633dc9b12SSteven Rostedt free_hash: 117733dc9b12SSteven Rostedt free_ftrace_hash(new_hash); 117833dc9b12SSteven Rostedt return NULL; 117933dc9b12SSteven Rostedt } 118033dc9b12SSteven Rostedt 118141fb61c2SSteven Rostedt static void 118241fb61c2SSteven Rostedt ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash); 118341fb61c2SSteven Rostedt static void 118441fb61c2SSteven Rostedt ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash); 118541fb61c2SSteven Rostedt 118633dc9b12SSteven Rostedt static int 118741fb61c2SSteven Rostedt ftrace_hash_move(struct ftrace_ops *ops, int enable, 118841fb61c2SSteven Rostedt struct ftrace_hash **dst, struct ftrace_hash *src) 118933dc9b12SSteven Rostedt { 119033dc9b12SSteven Rostedt struct ftrace_func_entry *entry; 119133dc9b12SSteven Rostedt struct hlist_node *tp, *tn; 119233dc9b12SSteven Rostedt struct hlist_head *hhd; 119307fd5515SSteven Rostedt struct ftrace_hash *old_hash; 119407fd5515SSteven Rostedt struct ftrace_hash *new_hash; 119533dc9b12SSteven Rostedt unsigned long key; 119633dc9b12SSteven Rostedt int size = src->count; 119733dc9b12SSteven Rostedt int bits = 0; 119841fb61c2SSteven Rostedt int ret; 119933dc9b12SSteven Rostedt int i; 120033dc9b12SSteven Rostedt 120133dc9b12SSteven Rostedt /* 120241fb61c2SSteven Rostedt * Remove the current set, update the hash and add 120341fb61c2SSteven Rostedt * them back. 120441fb61c2SSteven Rostedt */ 120541fb61c2SSteven Rostedt ftrace_hash_rec_disable(ops, enable); 120641fb61c2SSteven Rostedt 120741fb61c2SSteven Rostedt /* 120833dc9b12SSteven Rostedt * If the new source is empty, just free dst and assign it 120933dc9b12SSteven Rostedt * the empty_hash. 121033dc9b12SSteven Rostedt */ 121133dc9b12SSteven Rostedt if (!src->count) { 121207fd5515SSteven Rostedt free_ftrace_hash_rcu(*dst); 121307fd5515SSteven Rostedt rcu_assign_pointer(*dst, EMPTY_HASH); 121433dc9b12SSteven Rostedt return 0; 121533dc9b12SSteven Rostedt } 121633dc9b12SSteven Rostedt 121733dc9b12SSteven Rostedt /* 121833dc9b12SSteven Rostedt * Make the hash size about 1/2 the # found 121933dc9b12SSteven Rostedt */ 122033dc9b12SSteven Rostedt for (size /= 2; size; size >>= 1) 122133dc9b12SSteven Rostedt bits++; 122233dc9b12SSteven Rostedt 122333dc9b12SSteven Rostedt /* Don't allocate too much */ 122433dc9b12SSteven Rostedt if (bits > FTRACE_HASH_MAX_BITS) 122533dc9b12SSteven Rostedt bits = FTRACE_HASH_MAX_BITS; 122633dc9b12SSteven Rostedt 122741fb61c2SSteven Rostedt ret = -ENOMEM; 122807fd5515SSteven Rostedt new_hash = alloc_ftrace_hash(bits); 122907fd5515SSteven Rostedt if (!new_hash) 123041fb61c2SSteven Rostedt goto out; 123133dc9b12SSteven Rostedt 123233dc9b12SSteven Rostedt size = 1 << src->size_bits; 123333dc9b12SSteven Rostedt for (i = 0; i < size; i++) { 123433dc9b12SSteven Rostedt hhd = &src->buckets[i]; 123533dc9b12SSteven Rostedt hlist_for_each_entry_safe(entry, tp, tn, hhd, hlist) { 123633dc9b12SSteven Rostedt if (bits > 0) 123733dc9b12SSteven Rostedt key = hash_long(entry->ip, bits); 123833dc9b12SSteven Rostedt else 123933dc9b12SSteven Rostedt key = 0; 124033dc9b12SSteven Rostedt remove_hash_entry(src, entry); 124107fd5515SSteven Rostedt __add_hash_entry(new_hash, entry); 124233dc9b12SSteven Rostedt } 124333dc9b12SSteven Rostedt } 124433dc9b12SSteven Rostedt 124507fd5515SSteven Rostedt old_hash = *dst; 124607fd5515SSteven Rostedt rcu_assign_pointer(*dst, new_hash); 124707fd5515SSteven Rostedt free_ftrace_hash_rcu(old_hash); 124807fd5515SSteven Rostedt 124941fb61c2SSteven Rostedt ret = 0; 125041fb61c2SSteven Rostedt out: 125141fb61c2SSteven Rostedt /* 125241fb61c2SSteven Rostedt * Enable regardless of ret: 125341fb61c2SSteven Rostedt * On success, we enable the new hash. 125441fb61c2SSteven Rostedt * On failure, we re-enable the original hash. 125541fb61c2SSteven Rostedt */ 125641fb61c2SSteven Rostedt ftrace_hash_rec_enable(ops, enable); 125741fb61c2SSteven Rostedt 125841fb61c2SSteven Rostedt return ret; 125933dc9b12SSteven Rostedt } 126033dc9b12SSteven Rostedt 1261265c831cSSteven Rostedt /* 1262b848914cSSteven Rostedt * Test the hashes for this ops to see if we want to call 1263b848914cSSteven Rostedt * the ops->func or not. 1264b848914cSSteven Rostedt * 1265b848914cSSteven Rostedt * It's a match if the ip is in the ops->filter_hash or 1266b848914cSSteven Rostedt * the filter_hash does not exist or is empty, 1267b848914cSSteven Rostedt * AND 1268b848914cSSteven Rostedt * the ip is not in the ops->notrace_hash. 1269cdbe61bfSSteven Rostedt * 1270cdbe61bfSSteven Rostedt * This needs to be called with preemption disabled as 1271cdbe61bfSSteven Rostedt * the hashes are freed with call_rcu_sched(). 1272b848914cSSteven Rostedt */ 1273b848914cSSteven Rostedt static int 1274b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) 1275b848914cSSteven Rostedt { 1276b848914cSSteven Rostedt struct ftrace_hash *filter_hash; 1277b848914cSSteven Rostedt struct ftrace_hash *notrace_hash; 1278b848914cSSteven Rostedt int ret; 1279b848914cSSteven Rostedt 1280b848914cSSteven Rostedt filter_hash = rcu_dereference_raw(ops->filter_hash); 1281b848914cSSteven Rostedt notrace_hash = rcu_dereference_raw(ops->notrace_hash); 1282b848914cSSteven Rostedt 1283b848914cSSteven Rostedt if ((!filter_hash || !filter_hash->count || 1284b848914cSSteven Rostedt ftrace_lookup_ip(filter_hash, ip)) && 1285b848914cSSteven Rostedt (!notrace_hash || !notrace_hash->count || 1286b848914cSSteven Rostedt !ftrace_lookup_ip(notrace_hash, ip))) 1287b848914cSSteven Rostedt ret = 1; 1288b848914cSSteven Rostedt else 1289b848914cSSteven Rostedt ret = 0; 1290b848914cSSteven Rostedt 1291b848914cSSteven Rostedt return ret; 1292b848914cSSteven Rostedt } 1293b848914cSSteven Rostedt 1294b848914cSSteven Rostedt /* 1295265c831cSSteven Rostedt * This is a double for. Do not use 'break' to break out of the loop, 1296265c831cSSteven Rostedt * you must use a goto. 1297265c831cSSteven Rostedt */ 1298265c831cSSteven Rostedt #define do_for_each_ftrace_rec(pg, rec) \ 1299265c831cSSteven Rostedt for (pg = ftrace_pages_start; pg; pg = pg->next) { \ 1300265c831cSSteven Rostedt int _____i; \ 1301265c831cSSteven Rostedt for (_____i = 0; _____i < pg->index; _____i++) { \ 1302265c831cSSteven Rostedt rec = &pg->records[_____i]; 1303265c831cSSteven Rostedt 1304265c831cSSteven Rostedt #define while_for_each_ftrace_rec() \ 1305265c831cSSteven Rostedt } \ 1306265c831cSSteven Rostedt } 1307ecea656dSAbhishek Sagar 1308ed926f9bSSteven Rostedt static void __ftrace_hash_rec_update(struct ftrace_ops *ops, 1309ed926f9bSSteven Rostedt int filter_hash, 1310ed926f9bSSteven Rostedt bool inc) 1311ed926f9bSSteven Rostedt { 1312ed926f9bSSteven Rostedt struct ftrace_hash *hash; 1313ed926f9bSSteven Rostedt struct ftrace_hash *other_hash; 1314ed926f9bSSteven Rostedt struct ftrace_page *pg; 1315ed926f9bSSteven Rostedt struct dyn_ftrace *rec; 1316ed926f9bSSteven Rostedt int count = 0; 1317ed926f9bSSteven Rostedt int all = 0; 1318ed926f9bSSteven Rostedt 1319ed926f9bSSteven Rostedt /* Only update if the ops has been registered */ 1320ed926f9bSSteven Rostedt if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) 1321ed926f9bSSteven Rostedt return; 1322ed926f9bSSteven Rostedt 1323ed926f9bSSteven Rostedt /* 1324ed926f9bSSteven Rostedt * In the filter_hash case: 1325ed926f9bSSteven Rostedt * If the count is zero, we update all records. 1326ed926f9bSSteven Rostedt * Otherwise we just update the items in the hash. 1327ed926f9bSSteven Rostedt * 1328ed926f9bSSteven Rostedt * In the notrace_hash case: 1329ed926f9bSSteven Rostedt * We enable the update in the hash. 1330ed926f9bSSteven Rostedt * As disabling notrace means enabling the tracing, 1331ed926f9bSSteven Rostedt * and enabling notrace means disabling, the inc variable 1332ed926f9bSSteven Rostedt * gets inversed. 1333ed926f9bSSteven Rostedt */ 1334ed926f9bSSteven Rostedt if (filter_hash) { 1335ed926f9bSSteven Rostedt hash = ops->filter_hash; 1336ed926f9bSSteven Rostedt other_hash = ops->notrace_hash; 1337b848914cSSteven Rostedt if (!hash || !hash->count) 1338ed926f9bSSteven Rostedt all = 1; 1339ed926f9bSSteven Rostedt } else { 1340ed926f9bSSteven Rostedt inc = !inc; 1341ed926f9bSSteven Rostedt hash = ops->notrace_hash; 1342ed926f9bSSteven Rostedt other_hash = ops->filter_hash; 1343ed926f9bSSteven Rostedt /* 1344ed926f9bSSteven Rostedt * If the notrace hash has no items, 1345ed926f9bSSteven Rostedt * then there's nothing to do. 1346ed926f9bSSteven Rostedt */ 1347b848914cSSteven Rostedt if (hash && !hash->count) 1348ed926f9bSSteven Rostedt return; 1349ed926f9bSSteven Rostedt } 1350ed926f9bSSteven Rostedt 1351ed926f9bSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 1352ed926f9bSSteven Rostedt int in_other_hash = 0; 1353ed926f9bSSteven Rostedt int in_hash = 0; 1354ed926f9bSSteven Rostedt int match = 0; 1355ed926f9bSSteven Rostedt 1356ed926f9bSSteven Rostedt if (all) { 1357ed926f9bSSteven Rostedt /* 1358ed926f9bSSteven Rostedt * Only the filter_hash affects all records. 1359ed926f9bSSteven Rostedt * Update if the record is not in the notrace hash. 1360ed926f9bSSteven Rostedt */ 1361b848914cSSteven Rostedt if (!other_hash || !ftrace_lookup_ip(other_hash, rec->ip)) 1362ed926f9bSSteven Rostedt match = 1; 1363ed926f9bSSteven Rostedt } else { 1364b848914cSSteven Rostedt in_hash = hash && !!ftrace_lookup_ip(hash, rec->ip); 1365b848914cSSteven Rostedt in_other_hash = other_hash && !!ftrace_lookup_ip(other_hash, rec->ip); 1366ed926f9bSSteven Rostedt 1367ed926f9bSSteven Rostedt /* 1368ed926f9bSSteven Rostedt * 1369ed926f9bSSteven Rostedt */ 1370ed926f9bSSteven Rostedt if (filter_hash && in_hash && !in_other_hash) 1371ed926f9bSSteven Rostedt match = 1; 1372ed926f9bSSteven Rostedt else if (!filter_hash && in_hash && 1373ed926f9bSSteven Rostedt (in_other_hash || !other_hash->count)) 1374ed926f9bSSteven Rostedt match = 1; 1375ed926f9bSSteven Rostedt } 1376ed926f9bSSteven Rostedt if (!match) 1377ed926f9bSSteven Rostedt continue; 1378ed926f9bSSteven Rostedt 1379ed926f9bSSteven Rostedt if (inc) { 1380ed926f9bSSteven Rostedt rec->flags++; 1381ed926f9bSSteven Rostedt if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX)) 1382ed926f9bSSteven Rostedt return; 1383ed926f9bSSteven Rostedt } else { 1384ed926f9bSSteven Rostedt if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0)) 1385ed926f9bSSteven Rostedt return; 1386ed926f9bSSteven Rostedt rec->flags--; 1387ed926f9bSSteven Rostedt } 1388ed926f9bSSteven Rostedt count++; 1389ed926f9bSSteven Rostedt /* Shortcut, if we handled all records, we are done. */ 1390ed926f9bSSteven Rostedt if (!all && count == hash->count) 1391ed926f9bSSteven Rostedt return; 1392ed926f9bSSteven Rostedt } while_for_each_ftrace_rec(); 1393ed926f9bSSteven Rostedt } 1394ed926f9bSSteven Rostedt 1395ed926f9bSSteven Rostedt static void ftrace_hash_rec_disable(struct ftrace_ops *ops, 1396ed926f9bSSteven Rostedt int filter_hash) 1397ed926f9bSSteven Rostedt { 1398ed926f9bSSteven Rostedt __ftrace_hash_rec_update(ops, filter_hash, 0); 1399ed926f9bSSteven Rostedt } 1400ed926f9bSSteven Rostedt 1401ed926f9bSSteven Rostedt static void ftrace_hash_rec_enable(struct ftrace_ops *ops, 1402ed926f9bSSteven Rostedt int filter_hash) 1403ed926f9bSSteven Rostedt { 1404ed926f9bSSteven Rostedt __ftrace_hash_rec_update(ops, filter_hash, 1); 1405ed926f9bSSteven Rostedt } 1406ed926f9bSSteven Rostedt 1407e309b41dSIngo Molnar static void ftrace_free_rec(struct dyn_ftrace *rec) 140837ad5084SSteven Rostedt { 1409ee000b7fSLai Jiangshan rec->freelist = ftrace_free_records; 141037ad5084SSteven Rostedt ftrace_free_records = rec; 141137ad5084SSteven Rostedt rec->flags |= FTRACE_FL_FREE; 141237ad5084SSteven Rostedt } 141337ad5084SSteven Rostedt 1414e309b41dSIngo Molnar static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip) 14153c1720f0SSteven Rostedt { 141637ad5084SSteven Rostedt struct dyn_ftrace *rec; 141737ad5084SSteven Rostedt 141837ad5084SSteven Rostedt /* First check for freed records */ 141937ad5084SSteven Rostedt if (ftrace_free_records) { 142037ad5084SSteven Rostedt rec = ftrace_free_records; 142137ad5084SSteven Rostedt 142237ad5084SSteven Rostedt if (unlikely(!(rec->flags & FTRACE_FL_FREE))) { 14236912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 142437ad5084SSteven Rostedt ftrace_free_records = NULL; 142537ad5084SSteven Rostedt return NULL; 142637ad5084SSteven Rostedt } 142737ad5084SSteven Rostedt 1428ee000b7fSLai Jiangshan ftrace_free_records = rec->freelist; 142937ad5084SSteven Rostedt memset(rec, 0, sizeof(*rec)); 143037ad5084SSteven Rostedt return rec; 143137ad5084SSteven Rostedt } 143237ad5084SSteven Rostedt 14333c1720f0SSteven Rostedt if (ftrace_pages->index == ENTRIES_PER_PAGE) { 143408f5ac90SSteven Rostedt if (!ftrace_pages->next) { 143508f5ac90SSteven Rostedt /* allocate another page */ 143608f5ac90SSteven Rostedt ftrace_pages->next = 143708f5ac90SSteven Rostedt (void *)get_zeroed_page(GFP_KERNEL); 14383c1720f0SSteven Rostedt if (!ftrace_pages->next) 14393c1720f0SSteven Rostedt return NULL; 144008f5ac90SSteven Rostedt } 14413c1720f0SSteven Rostedt ftrace_pages = ftrace_pages->next; 14423c1720f0SSteven Rostedt } 14433c1720f0SSteven Rostedt 14443c1720f0SSteven Rostedt return &ftrace_pages->records[ftrace_pages->index++]; 14453c1720f0SSteven Rostedt } 14463c1720f0SSteven Rostedt 144708f5ac90SSteven Rostedt static struct dyn_ftrace * 1448d61f82d0SSteven Rostedt ftrace_record_ip(unsigned long ip) 14493d083395SSteven Rostedt { 145008f5ac90SSteven Rostedt struct dyn_ftrace *rec; 14513d083395SSteven Rostedt 1452f3c7ac40SSteven Rostedt if (ftrace_disabled) 145308f5ac90SSteven Rostedt return NULL; 1454d61f82d0SSteven Rostedt 145508f5ac90SSteven Rostedt rec = ftrace_alloc_dyn_node(ip); 145608f5ac90SSteven Rostedt if (!rec) 145708f5ac90SSteven Rostedt return NULL; 14583d083395SSteven Rostedt 145908f5ac90SSteven Rostedt rec->ip = ip; 1460ee000b7fSLai Jiangshan rec->newlist = ftrace_new_addrs; 1461e94142a6SLai Jiangshan ftrace_new_addrs = rec; 14623d083395SSteven Rostedt 146308f5ac90SSteven Rostedt return rec; 14643d083395SSteven Rostedt } 14653d083395SSteven Rostedt 146605736a42SSteven Rostedt static void print_ip_ins(const char *fmt, unsigned char *p) 146705736a42SSteven Rostedt { 146805736a42SSteven Rostedt int i; 146905736a42SSteven Rostedt 147005736a42SSteven Rostedt printk(KERN_CONT "%s", fmt); 147105736a42SSteven Rostedt 147205736a42SSteven Rostedt for (i = 0; i < MCOUNT_INSN_SIZE; i++) 147305736a42SSteven Rostedt printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]); 147405736a42SSteven Rostedt } 147505736a42SSteven Rostedt 147631e88909SSteven Rostedt static void ftrace_bug(int failed, unsigned long ip) 14773c1720f0SSteven Rostedt { 1478b17e8a37SSteven Rostedt switch (failed) { 1479593eb8a2SSteven Rostedt case -EFAULT: 14806912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 148105736a42SSteven Rostedt pr_info("ftrace faulted on modifying "); 148205736a42SSteven Rostedt print_ip_sym(ip); 148305736a42SSteven Rostedt break; 1484593eb8a2SSteven Rostedt case -EINVAL: 14856912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 148605736a42SSteven Rostedt pr_info("ftrace failed to modify "); 148705736a42SSteven Rostedt print_ip_sym(ip); 148805736a42SSteven Rostedt print_ip_ins(" actual: ", (unsigned char *)ip); 148905736a42SSteven Rostedt printk(KERN_CONT "\n"); 149005736a42SSteven Rostedt break; 1491593eb8a2SSteven Rostedt case -EPERM: 14926912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 1493593eb8a2SSteven Rostedt pr_info("ftrace faulted on writing "); 1494593eb8a2SSteven Rostedt print_ip_sym(ip); 1495593eb8a2SSteven Rostedt break; 1496593eb8a2SSteven Rostedt default: 14976912896eSSteven Rostedt FTRACE_WARN_ON_ONCE(1); 1498593eb8a2SSteven Rostedt pr_info("ftrace faulted on unknown error "); 1499593eb8a2SSteven Rostedt print_ip_sym(ip); 150005736a42SSteven Rostedt } 1501b17e8a37SSteven Rostedt } 150205736a42SSteven Rostedt 15033d083395SSteven Rostedt 15042cfa1978SMasami Hiramatsu /* Return 1 if the address range is reserved for ftrace */ 15052cfa1978SMasami Hiramatsu int ftrace_text_reserved(void *start, void *end) 15062cfa1978SMasami Hiramatsu { 15072cfa1978SMasami Hiramatsu struct dyn_ftrace *rec; 15082cfa1978SMasami Hiramatsu struct ftrace_page *pg; 15092cfa1978SMasami Hiramatsu 15102cfa1978SMasami Hiramatsu do_for_each_ftrace_rec(pg, rec) { 15112cfa1978SMasami Hiramatsu if (rec->ip <= (unsigned long)end && 15122cfa1978SMasami Hiramatsu rec->ip + MCOUNT_INSN_SIZE > (unsigned long)start) 15132cfa1978SMasami Hiramatsu return 1; 15142cfa1978SMasami Hiramatsu } while_for_each_ftrace_rec(); 15152cfa1978SMasami Hiramatsu return 0; 15162cfa1978SMasami Hiramatsu } 15172cfa1978SMasami Hiramatsu 15182cfa1978SMasami Hiramatsu 15193d083395SSteven Rostedt static int 152031e88909SSteven Rostedt __ftrace_replace_code(struct dyn_ftrace *rec, int enable) 15213d083395SSteven Rostedt { 1522e7d3737eSFrederic Weisbecker unsigned long ftrace_addr; 152364fbcd16SXiao Guangrong unsigned long flag = 0UL; 1524e7d3737eSFrederic Weisbecker 1525f0001207SShaohua Li ftrace_addr = (unsigned long)FTRACE_ADDR; 15263d083395SSteven Rostedt 15273d083395SSteven Rostedt /* 1528ed926f9bSSteven Rostedt * If we are enabling tracing: 15293d083395SSteven Rostedt * 1530ed926f9bSSteven Rostedt * If the record has a ref count, then we need to enable it 1531ed926f9bSSteven Rostedt * because someone is using it. 15323d083395SSteven Rostedt * 1533ed926f9bSSteven Rostedt * Otherwise we make sure its disabled. 1534ed926f9bSSteven Rostedt * 1535ed926f9bSSteven Rostedt * If we are disabling tracing, then disable all records that 1536ed926f9bSSteven Rostedt * are enabled. 15373d083395SSteven Rostedt */ 1538ed926f9bSSteven Rostedt if (enable && (rec->flags & ~FTRACE_FL_MASK)) 153964fbcd16SXiao Guangrong flag = FTRACE_FL_ENABLED; 15403d083395SSteven Rostedt 154164fbcd16SXiao Guangrong /* If the state of this record hasn't changed, then do nothing */ 154264fbcd16SXiao Guangrong if ((rec->flags & FTRACE_FL_ENABLED) == flag) 154364fbcd16SXiao Guangrong return 0; 154464fbcd16SXiao Guangrong 154564fbcd16SXiao Guangrong if (flag) { 154664fbcd16SXiao Guangrong rec->flags |= FTRACE_FL_ENABLED; 1547e7d3737eSFrederic Weisbecker return ftrace_make_call(rec, ftrace_addr); 154864fbcd16SXiao Guangrong } 154964fbcd16SXiao Guangrong 155064fbcd16SXiao Guangrong rec->flags &= ~FTRACE_FL_ENABLED; 1551e7d3737eSFrederic Weisbecker return ftrace_make_nop(NULL, rec, ftrace_addr); 15523d083395SSteven Rostedt } 15533d083395SSteven Rostedt 15543d083395SSteven Rostedt static void ftrace_replace_code(int enable) 15553d083395SSteven Rostedt { 15563d083395SSteven Rostedt struct dyn_ftrace *rec; 15573d083395SSteven Rostedt struct ftrace_page *pg; 15586a24a244SSteven Rostedt int failed; 15593d083395SSteven Rostedt 156045a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 156145a4a237SSteven Rostedt return; 156245a4a237SSteven Rostedt 1563265c831cSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 1564d2c8c3eaSSteven Rostedt /* Skip over free records */ 1565d2c8c3eaSSteven Rostedt if (rec->flags & FTRACE_FL_FREE) 15663d083395SSteven Rostedt continue; 15673d083395SSteven Rostedt 156831e88909SSteven Rostedt failed = __ftrace_replace_code(rec, enable); 1569fa9d13cfSZhaolei if (failed) { 157031e88909SSteven Rostedt ftrace_bug(failed, rec->ip); 15714377245aSSteven Rostedt /* Stop processing */ 15724377245aSSteven Rostedt return; 15734377245aSSteven Rostedt } 1574265c831cSSteven Rostedt } while_for_each_ftrace_rec(); 15753d083395SSteven Rostedt } 15763c1720f0SSteven Rostedt 15773b47bfc1SSteven Rostedt static int 157831e88909SSteven Rostedt ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec) 15793c1720f0SSteven Rostedt { 158037ad5084SSteven Rostedt unsigned long ip; 1581492a7ea5SAbhishek Sagar int ret; 158237ad5084SSteven Rostedt 1583492a7ea5SAbhishek Sagar ip = rec->ip; 15843c1720f0SSteven Rostedt 158545a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 158645a4a237SSteven Rostedt return 0; 158745a4a237SSteven Rostedt 158825aac9dcSShaohua Li ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR); 15893d083395SSteven Rostedt if (ret) { 159031e88909SSteven Rostedt ftrace_bug(ret, ip); 15913d083395SSteven Rostedt return 0; 1592d61f82d0SSteven Rostedt } 1593d61f82d0SSteven Rostedt return 1; 15943d083395SSteven Rostedt } 15953d083395SSteven Rostedt 1596000ab691SSteven Rostedt /* 1597000ab691SSteven Rostedt * archs can override this function if they must do something 1598000ab691SSteven Rostedt * before the modifying code is performed. 1599000ab691SSteven Rostedt */ 1600000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_prepare(void) 1601000ab691SSteven Rostedt { 1602000ab691SSteven Rostedt return 0; 1603000ab691SSteven Rostedt } 1604000ab691SSteven Rostedt 1605000ab691SSteven Rostedt /* 1606000ab691SSteven Rostedt * archs can override this function if they must do something 1607000ab691SSteven Rostedt * after the modifying code is performed. 1608000ab691SSteven Rostedt */ 1609000ab691SSteven Rostedt int __weak ftrace_arch_code_modify_post_process(void) 1610000ab691SSteven Rostedt { 1611000ab691SSteven Rostedt return 0; 1612000ab691SSteven Rostedt } 1613000ab691SSteven Rostedt 16143d083395SSteven Rostedt static int __ftrace_modify_code(void *data) 16153d083395SSteven Rostedt { 16163d083395SSteven Rostedt int *command = data; 16173d083395SSteven Rostedt 16186331c28cSSteven Rostedt /* 16196331c28cSSteven Rostedt * Do not call function tracer while we update the code. 16206331c28cSSteven Rostedt * We are in stop machine, no worrying about races. 16216331c28cSSteven Rostedt */ 16226331c28cSSteven Rostedt function_trace_stop++; 16236331c28cSSteven Rostedt 1624a3583244SSteven Rostedt if (*command & FTRACE_ENABLE_CALLS) 16253d083395SSteven Rostedt ftrace_replace_code(1); 1626a3583244SSteven Rostedt else if (*command & FTRACE_DISABLE_CALLS) 16273d083395SSteven Rostedt ftrace_replace_code(0); 16283d083395SSteven Rostedt 16293d083395SSteven Rostedt if (*command & FTRACE_UPDATE_TRACE_FUNC) 16303d083395SSteven Rostedt ftrace_update_ftrace_func(ftrace_trace_function); 16313d083395SSteven Rostedt 16325a45cfe1SSteven Rostedt if (*command & FTRACE_START_FUNC_RET) 16335a45cfe1SSteven Rostedt ftrace_enable_ftrace_graph_caller(); 16345a45cfe1SSteven Rostedt else if (*command & FTRACE_STOP_FUNC_RET) 16355a45cfe1SSteven Rostedt ftrace_disable_ftrace_graph_caller(); 16365a45cfe1SSteven Rostedt 16376331c28cSSteven Rostedt #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST 16386331c28cSSteven Rostedt /* 16396331c28cSSteven Rostedt * For archs that call ftrace_test_stop_func(), we must 16406331c28cSSteven Rostedt * wait till after we update all the function callers 16416331c28cSSteven Rostedt * before we update the callback. This keeps different 16426331c28cSSteven Rostedt * ops that record different functions from corrupting 16436331c28cSSteven Rostedt * each other. 16446331c28cSSteven Rostedt */ 16456331c28cSSteven Rostedt __ftrace_trace_function = __ftrace_trace_function_delay; 16466331c28cSSteven Rostedt #endif 16476331c28cSSteven Rostedt function_trace_stop--; 16486331c28cSSteven Rostedt 16493d083395SSteven Rostedt return 0; 16503d083395SSteven Rostedt } 16513d083395SSteven Rostedt 1652e309b41dSIngo Molnar static void ftrace_run_update_code(int command) 16533d083395SSteven Rostedt { 1654000ab691SSteven Rostedt int ret; 1655000ab691SSteven Rostedt 1656000ab691SSteven Rostedt ret = ftrace_arch_code_modify_prepare(); 1657000ab691SSteven Rostedt FTRACE_WARN_ON(ret); 1658000ab691SSteven Rostedt if (ret) 1659000ab691SSteven Rostedt return; 1660000ab691SSteven Rostedt 1661784e2d76SRusty Russell stop_machine(__ftrace_modify_code, &command, NULL); 1662000ab691SSteven Rostedt 1663000ab691SSteven Rostedt ret = ftrace_arch_code_modify_post_process(); 1664000ab691SSteven Rostedt FTRACE_WARN_ON(ret); 16653d083395SSteven Rostedt } 16663d083395SSteven Rostedt 16673d083395SSteven Rostedt static ftrace_func_t saved_ftrace_func; 166860a7ecf4SSteven Rostedt static int ftrace_start_up; 1669b848914cSSteven Rostedt static int global_start_up; 1670df4fc315SSteven Rostedt 1671df4fc315SSteven Rostedt static void ftrace_startup_enable(int command) 1672df4fc315SSteven Rostedt { 1673df4fc315SSteven Rostedt if (saved_ftrace_func != ftrace_trace_function) { 1674df4fc315SSteven Rostedt saved_ftrace_func = ftrace_trace_function; 1675df4fc315SSteven Rostedt command |= FTRACE_UPDATE_TRACE_FUNC; 1676df4fc315SSteven Rostedt } 1677df4fc315SSteven Rostedt 1678df4fc315SSteven Rostedt if (!command || !ftrace_enabled) 1679df4fc315SSteven Rostedt return; 1680df4fc315SSteven Rostedt 1681df4fc315SSteven Rostedt ftrace_run_update_code(command); 1682df4fc315SSteven Rostedt } 16833d083395SSteven Rostedt 1684a1cd6173SSteven Rostedt static int ftrace_startup(struct ftrace_ops *ops, int command) 16853d083395SSteven Rostedt { 1686b848914cSSteven Rostedt bool hash_enable = true; 1687b848914cSSteven Rostedt 16884eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 1689a1cd6173SSteven Rostedt return -ENODEV; 16904eebcc81SSteven Rostedt 169160a7ecf4SSteven Rostedt ftrace_start_up++; 1692d61f82d0SSteven Rostedt command |= FTRACE_ENABLE_CALLS; 16933d083395SSteven Rostedt 1694b848914cSSteven Rostedt /* ops marked global share the filter hashes */ 1695b848914cSSteven Rostedt if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 1696b848914cSSteven Rostedt ops = &global_ops; 1697b848914cSSteven Rostedt /* Don't update hash if global is already set */ 1698b848914cSSteven Rostedt if (global_start_up) 1699b848914cSSteven Rostedt hash_enable = false; 1700b848914cSSteven Rostedt global_start_up++; 1701b848914cSSteven Rostedt } 1702b848914cSSteven Rostedt 1703ed926f9bSSteven Rostedt ops->flags |= FTRACE_OPS_FL_ENABLED; 1704b848914cSSteven Rostedt if (hash_enable) 1705ed926f9bSSteven Rostedt ftrace_hash_rec_enable(ops, 1); 1706ed926f9bSSteven Rostedt 1707df4fc315SSteven Rostedt ftrace_startup_enable(command); 1708a1cd6173SSteven Rostedt 1709a1cd6173SSteven Rostedt return 0; 17103d083395SSteven Rostedt } 17113d083395SSteven Rostedt 1712bd69c30bSSteven Rostedt static void ftrace_shutdown(struct ftrace_ops *ops, int command) 17133d083395SSteven Rostedt { 1714b848914cSSteven Rostedt bool hash_disable = true; 1715b848914cSSteven Rostedt 17164eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 17174eebcc81SSteven Rostedt return; 17184eebcc81SSteven Rostedt 171960a7ecf4SSteven Rostedt ftrace_start_up--; 17209ea1a153SFrederic Weisbecker /* 17219ea1a153SFrederic Weisbecker * Just warn in case of unbalance, no need to kill ftrace, it's not 17229ea1a153SFrederic Weisbecker * critical but the ftrace_call callers may be never nopped again after 17239ea1a153SFrederic Weisbecker * further ftrace uses. 17249ea1a153SFrederic Weisbecker */ 17259ea1a153SFrederic Weisbecker WARN_ON_ONCE(ftrace_start_up < 0); 17269ea1a153SFrederic Weisbecker 1727b848914cSSteven Rostedt if (ops->flags & FTRACE_OPS_FL_GLOBAL) { 1728b848914cSSteven Rostedt ops = &global_ops; 1729b848914cSSteven Rostedt global_start_up--; 1730b848914cSSteven Rostedt WARN_ON_ONCE(global_start_up < 0); 1731b848914cSSteven Rostedt /* Don't update hash if global still has users */ 1732b848914cSSteven Rostedt if (global_start_up) { 1733b848914cSSteven Rostedt WARN_ON_ONCE(!ftrace_start_up); 1734b848914cSSteven Rostedt hash_disable = false; 1735b848914cSSteven Rostedt } 1736b848914cSSteven Rostedt } 1737b848914cSSteven Rostedt 1738b848914cSSteven Rostedt if (hash_disable) 1739ed926f9bSSteven Rostedt ftrace_hash_rec_disable(ops, 1); 1740ed926f9bSSteven Rostedt 1741b848914cSSteven Rostedt if (ops != &global_ops || !global_start_up) 1742ed926f9bSSteven Rostedt ops->flags &= ~FTRACE_OPS_FL_ENABLED; 1743b848914cSSteven Rostedt 1744b848914cSSteven Rostedt if (!ftrace_start_up) 1745b848914cSSteven Rostedt command |= FTRACE_DISABLE_CALLS; 1746d61f82d0SSteven Rostedt 1747d61f82d0SSteven Rostedt if (saved_ftrace_func != ftrace_trace_function) { 1748d61f82d0SSteven Rostedt saved_ftrace_func = ftrace_trace_function; 1749d61f82d0SSteven Rostedt command |= FTRACE_UPDATE_TRACE_FUNC; 1750d61f82d0SSteven Rostedt } 1751d61f82d0SSteven Rostedt 1752d61f82d0SSteven Rostedt if (!command || !ftrace_enabled) 1753e6ea44e9SSteven Rostedt return; 17543d083395SSteven Rostedt 1755d61f82d0SSteven Rostedt ftrace_run_update_code(command); 17563d083395SSteven Rostedt } 17573d083395SSteven Rostedt 1758e309b41dSIngo Molnar static void ftrace_startup_sysctl(void) 1759b0fc494fSSteven Rostedt { 17604eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 17614eebcc81SSteven Rostedt return; 17624eebcc81SSteven Rostedt 1763d61f82d0SSteven Rostedt /* Force update next time */ 1764d61f82d0SSteven Rostedt saved_ftrace_func = NULL; 176560a7ecf4SSteven Rostedt /* ftrace_start_up is true if we want ftrace running */ 176660a7ecf4SSteven Rostedt if (ftrace_start_up) 176779e406d7SSteven Rostedt ftrace_run_update_code(FTRACE_ENABLE_CALLS); 1768b0fc494fSSteven Rostedt } 1769b0fc494fSSteven Rostedt 1770e309b41dSIngo Molnar static void ftrace_shutdown_sysctl(void) 1771b0fc494fSSteven Rostedt { 17724eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 17734eebcc81SSteven Rostedt return; 17744eebcc81SSteven Rostedt 177560a7ecf4SSteven Rostedt /* ftrace_start_up is true if ftrace is running */ 177660a7ecf4SSteven Rostedt if (ftrace_start_up) 177779e406d7SSteven Rostedt ftrace_run_update_code(FTRACE_DISABLE_CALLS); 1778b0fc494fSSteven Rostedt } 1779b0fc494fSSteven Rostedt 17803d083395SSteven Rostedt static cycle_t ftrace_update_time; 17813d083395SSteven Rostedt static unsigned long ftrace_update_cnt; 17823d083395SSteven Rostedt unsigned long ftrace_update_tot_cnt; 17833d083395SSteven Rostedt 1784f7bc8b61SSteven Rostedt static int ops_traces_mod(struct ftrace_ops *ops) 1785f7bc8b61SSteven Rostedt { 1786f7bc8b61SSteven Rostedt struct ftrace_hash *hash; 1787f7bc8b61SSteven Rostedt 1788f7bc8b61SSteven Rostedt hash = ops->filter_hash; 1789f7bc8b61SSteven Rostedt return !!(!hash || !hash->count); 1790f7bc8b61SSteven Rostedt } 1791f7bc8b61SSteven Rostedt 179231e88909SSteven Rostedt static int ftrace_update_code(struct module *mod) 17933d083395SSteven Rostedt { 1794e94142a6SLai Jiangshan struct dyn_ftrace *p; 1795f22f9a89SAbhishek Sagar cycle_t start, stop; 1796f7bc8b61SSteven Rostedt unsigned long ref = 0; 1797f7bc8b61SSteven Rostedt 1798f7bc8b61SSteven Rostedt /* 1799f7bc8b61SSteven Rostedt * When adding a module, we need to check if tracers are 1800f7bc8b61SSteven Rostedt * currently enabled and if they are set to trace all functions. 1801f7bc8b61SSteven Rostedt * If they are, we need to enable the module functions as well 1802f7bc8b61SSteven Rostedt * as update the reference counts for those function records. 1803f7bc8b61SSteven Rostedt */ 1804f7bc8b61SSteven Rostedt if (mod) { 1805f7bc8b61SSteven Rostedt struct ftrace_ops *ops; 1806f7bc8b61SSteven Rostedt 1807f7bc8b61SSteven Rostedt for (ops = ftrace_ops_list; 1808f7bc8b61SSteven Rostedt ops != &ftrace_list_end; ops = ops->next) { 1809f7bc8b61SSteven Rostedt if (ops->flags & FTRACE_OPS_FL_ENABLED && 1810f7bc8b61SSteven Rostedt ops_traces_mod(ops)) 1811f7bc8b61SSteven Rostedt ref++; 1812f7bc8b61SSteven Rostedt } 1813f7bc8b61SSteven Rostedt } 18143d083395SSteven Rostedt 1815750ed1a4SIngo Molnar start = ftrace_now(raw_smp_processor_id()); 18163d083395SSteven Rostedt ftrace_update_cnt = 0; 18173d083395SSteven Rostedt 1818e94142a6SLai Jiangshan while (ftrace_new_addrs) { 1819f22f9a89SAbhishek Sagar 182008f5ac90SSteven Rostedt /* If something went wrong, bail without enabling anything */ 182108f5ac90SSteven Rostedt if (unlikely(ftrace_disabled)) 182208f5ac90SSteven Rostedt return -1; 18233d083395SSteven Rostedt 1824e94142a6SLai Jiangshan p = ftrace_new_addrs; 1825ee000b7fSLai Jiangshan ftrace_new_addrs = p->newlist; 1826f7bc8b61SSteven Rostedt p->flags = ref; 1827f22f9a89SAbhishek Sagar 18285cb084bbSJiri Olsa /* 182925985edcSLucas De Marchi * Do the initial record conversion from mcount jump 18305cb084bbSJiri Olsa * to the NOP instructions. 18315cb084bbSJiri Olsa */ 18325cb084bbSJiri Olsa if (!ftrace_code_disable(mod, p)) { 18335cb084bbSJiri Olsa ftrace_free_rec(p); 1834d2c8c3eaSSteven Rostedt /* Game over */ 1835d2c8c3eaSSteven Rostedt break; 18365cb084bbSJiri Olsa } 18375cb084bbSJiri Olsa 18383d083395SSteven Rostedt ftrace_update_cnt++; 18395cb084bbSJiri Olsa 18405cb084bbSJiri Olsa /* 18415cb084bbSJiri Olsa * If the tracing is enabled, go ahead and enable the record. 18425cb084bbSJiri Olsa * 18435cb084bbSJiri Olsa * The reason not to enable the record immediatelly is the 18445cb084bbSJiri Olsa * inherent check of ftrace_make_nop/ftrace_make_call for 18455cb084bbSJiri Olsa * correct previous instructions. Making first the NOP 18465cb084bbSJiri Olsa * conversion puts the module to the correct state, thus 18475cb084bbSJiri Olsa * passing the ftrace_make_call check. 18485cb084bbSJiri Olsa */ 1849f7bc8b61SSteven Rostedt if (ftrace_start_up && ref) { 18505cb084bbSJiri Olsa int failed = __ftrace_replace_code(p, 1); 18515cb084bbSJiri Olsa if (failed) { 18525cb084bbSJiri Olsa ftrace_bug(failed, p->ip); 18530eb96701SAbhishek Sagar ftrace_free_rec(p); 18543d083395SSteven Rostedt } 18555cb084bbSJiri Olsa } 18565cb084bbSJiri Olsa } 18573d083395SSteven Rostedt 1858750ed1a4SIngo Molnar stop = ftrace_now(raw_smp_processor_id()); 18593d083395SSteven Rostedt ftrace_update_time = stop - start; 18603d083395SSteven Rostedt ftrace_update_tot_cnt += ftrace_update_cnt; 18613d083395SSteven Rostedt 186216444a8aSArnaldo Carvalho de Melo return 0; 186316444a8aSArnaldo Carvalho de Melo } 186416444a8aSArnaldo Carvalho de Melo 186568bf21aaSSteven Rostedt static int __init ftrace_dyn_table_alloc(unsigned long num_to_init) 18663c1720f0SSteven Rostedt { 18673c1720f0SSteven Rostedt struct ftrace_page *pg; 18683c1720f0SSteven Rostedt int cnt; 18693c1720f0SSteven Rostedt int i; 18703c1720f0SSteven Rostedt 18713c1720f0SSteven Rostedt /* allocate a few pages */ 18723c1720f0SSteven Rostedt ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL); 18733c1720f0SSteven Rostedt if (!ftrace_pages_start) 18743c1720f0SSteven Rostedt return -1; 18753c1720f0SSteven Rostedt 18763c1720f0SSteven Rostedt /* 18773c1720f0SSteven Rostedt * Allocate a few more pages. 18783c1720f0SSteven Rostedt * 18793c1720f0SSteven Rostedt * TODO: have some parser search vmlinux before 18803c1720f0SSteven Rostedt * final linking to find all calls to ftrace. 18813c1720f0SSteven Rostedt * Then we can: 18823c1720f0SSteven Rostedt * a) know how many pages to allocate. 18833c1720f0SSteven Rostedt * and/or 18843c1720f0SSteven Rostedt * b) set up the table then. 18853c1720f0SSteven Rostedt * 18863c1720f0SSteven Rostedt * The dynamic code is still necessary for 18873c1720f0SSteven Rostedt * modules. 18883c1720f0SSteven Rostedt */ 18893c1720f0SSteven Rostedt 18903c1720f0SSteven Rostedt pg = ftrace_pages = ftrace_pages_start; 18913c1720f0SSteven Rostedt 189268bf21aaSSteven Rostedt cnt = num_to_init / ENTRIES_PER_PAGE; 189308f5ac90SSteven Rostedt pr_info("ftrace: allocating %ld entries in %d pages\n", 18945821e1b7Swalimis num_to_init, cnt + 1); 18953c1720f0SSteven Rostedt 18963c1720f0SSteven Rostedt for (i = 0; i < cnt; i++) { 18973c1720f0SSteven Rostedt pg->next = (void *)get_zeroed_page(GFP_KERNEL); 18983c1720f0SSteven Rostedt 18993c1720f0SSteven Rostedt /* If we fail, we'll try later anyway */ 19003c1720f0SSteven Rostedt if (!pg->next) 19013c1720f0SSteven Rostedt break; 19023c1720f0SSteven Rostedt 19033c1720f0SSteven Rostedt pg = pg->next; 19043c1720f0SSteven Rostedt } 19053c1720f0SSteven Rostedt 19063c1720f0SSteven Rostedt return 0; 19073c1720f0SSteven Rostedt } 19083c1720f0SSteven Rostedt 19095072c59fSSteven Rostedt enum { 19105072c59fSSteven Rostedt FTRACE_ITER_FILTER = (1 << 0), 1911689fd8b6S[email protected] FTRACE_ITER_NOTRACE = (1 << 1), 19123499e461SSteven Rostedt FTRACE_ITER_PRINTALL = (1 << 2), 19133499e461SSteven Rostedt FTRACE_ITER_HASH = (1 << 3), 1914647bcd03SSteven Rostedt FTRACE_ITER_ENABLED = (1 << 4), 19155072c59fSSteven Rostedt }; 19165072c59fSSteven Rostedt 19175072c59fSSteven Rostedt #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ 19185072c59fSSteven Rostedt 19195072c59fSSteven Rostedt struct ftrace_iterator { 192098c4fd04SSteven Rostedt loff_t pos; 19212bccfffdSSteven Rostedt loff_t func_pos; 19225072c59fSSteven Rostedt struct ftrace_page *pg; 19234aeb6967SSteven Rostedt struct dyn_ftrace *func; 19244aeb6967SSteven Rostedt struct ftrace_func_probe *probe; 19254aeb6967SSteven Rostedt struct trace_parser parser; 19261cf41dd7SSteven Rostedt struct ftrace_hash *hash; 192733dc9b12SSteven Rostedt struct ftrace_ops *ops; 19288fc0c701SSteven Rostedt int hidx; 1929431aa3fbSSteven Rostedt int idx; 19305072c59fSSteven Rostedt unsigned flags; 19315072c59fSSteven Rostedt }; 19325072c59fSSteven Rostedt 1933e309b41dSIngo Molnar static void * 19344aeb6967SSteven Rostedt t_hash_next(struct seq_file *m, loff_t *pos) 19358fc0c701SSteven Rostedt { 19368fc0c701SSteven Rostedt struct ftrace_iterator *iter = m->private; 19374aeb6967SSteven Rostedt struct hlist_node *hnd = NULL; 19388fc0c701SSteven Rostedt struct hlist_head *hhd; 19398fc0c701SSteven Rostedt 19408fc0c701SSteven Rostedt (*pos)++; 194198c4fd04SSteven Rostedt iter->pos = *pos; 19428fc0c701SSteven Rostedt 19434aeb6967SSteven Rostedt if (iter->probe) 19444aeb6967SSteven Rostedt hnd = &iter->probe->node; 19458fc0c701SSteven Rostedt retry: 19468fc0c701SSteven Rostedt if (iter->hidx >= FTRACE_FUNC_HASHSIZE) 19478fc0c701SSteven Rostedt return NULL; 19488fc0c701SSteven Rostedt 19498fc0c701SSteven Rostedt hhd = &ftrace_func_hash[iter->hidx]; 19508fc0c701SSteven Rostedt 19518fc0c701SSteven Rostedt if (hlist_empty(hhd)) { 19528fc0c701SSteven Rostedt iter->hidx++; 19538fc0c701SSteven Rostedt hnd = NULL; 19548fc0c701SSteven Rostedt goto retry; 19558fc0c701SSteven Rostedt } 19568fc0c701SSteven Rostedt 19578fc0c701SSteven Rostedt if (!hnd) 19588fc0c701SSteven Rostedt hnd = hhd->first; 19598fc0c701SSteven Rostedt else { 19608fc0c701SSteven Rostedt hnd = hnd->next; 19618fc0c701SSteven Rostedt if (!hnd) { 19628fc0c701SSteven Rostedt iter->hidx++; 19638fc0c701SSteven Rostedt goto retry; 19648fc0c701SSteven Rostedt } 19658fc0c701SSteven Rostedt } 19668fc0c701SSteven Rostedt 19674aeb6967SSteven Rostedt if (WARN_ON_ONCE(!hnd)) 19684aeb6967SSteven Rostedt return NULL; 19694aeb6967SSteven Rostedt 19704aeb6967SSteven Rostedt iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node); 19714aeb6967SSteven Rostedt 19724aeb6967SSteven Rostedt return iter; 19738fc0c701SSteven Rostedt } 19748fc0c701SSteven Rostedt 19758fc0c701SSteven Rostedt static void *t_hash_start(struct seq_file *m, loff_t *pos) 19768fc0c701SSteven Rostedt { 19778fc0c701SSteven Rostedt struct ftrace_iterator *iter = m->private; 19788fc0c701SSteven Rostedt void *p = NULL; 1979d82d6244SLi Zefan loff_t l; 1980d82d6244SLi Zefan 19812bccfffdSSteven Rostedt if (iter->func_pos > *pos) 19822bccfffdSSteven Rostedt return NULL; 19838fc0c701SSteven Rostedt 1984d82d6244SLi Zefan iter->hidx = 0; 19852bccfffdSSteven Rostedt for (l = 0; l <= (*pos - iter->func_pos); ) { 19864aeb6967SSteven Rostedt p = t_hash_next(m, &l); 1987d82d6244SLi Zefan if (!p) 1988d82d6244SLi Zefan break; 1989d82d6244SLi Zefan } 19904aeb6967SSteven Rostedt if (!p) 19914aeb6967SSteven Rostedt return NULL; 19924aeb6967SSteven Rostedt 199398c4fd04SSteven Rostedt /* Only set this if we have an item */ 199498c4fd04SSteven Rostedt iter->flags |= FTRACE_ITER_HASH; 199598c4fd04SSteven Rostedt 19964aeb6967SSteven Rostedt return iter; 19978fc0c701SSteven Rostedt } 19988fc0c701SSteven Rostedt 19994aeb6967SSteven Rostedt static int 20004aeb6967SSteven Rostedt t_hash_show(struct seq_file *m, struct ftrace_iterator *iter) 20018fc0c701SSteven Rostedt { 2002b6887d79SSteven Rostedt struct ftrace_func_probe *rec; 20038fc0c701SSteven Rostedt 20044aeb6967SSteven Rostedt rec = iter->probe; 20054aeb6967SSteven Rostedt if (WARN_ON_ONCE(!rec)) 20064aeb6967SSteven Rostedt return -EIO; 20078fc0c701SSteven Rostedt 2008809dcf29SSteven Rostedt if (rec->ops->print) 2009809dcf29SSteven Rostedt return rec->ops->print(m, rec->ip, rec->ops, rec->data); 2010809dcf29SSteven Rostedt 2011b375a11aSSteven Rostedt seq_printf(m, "%ps:%ps", (void *)rec->ip, (void *)rec->ops->func); 20128fc0c701SSteven Rostedt 20138fc0c701SSteven Rostedt if (rec->data) 20148fc0c701SSteven Rostedt seq_printf(m, ":%p", rec->data); 20158fc0c701SSteven Rostedt seq_putc(m, '\n'); 20168fc0c701SSteven Rostedt 20178fc0c701SSteven Rostedt return 0; 20188fc0c701SSteven Rostedt } 20198fc0c701SSteven Rostedt 20208fc0c701SSteven Rostedt static void * 20215072c59fSSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos) 20225072c59fSSteven Rostedt { 20235072c59fSSteven Rostedt struct ftrace_iterator *iter = m->private; 2024f45948e8SSteven Rostedt struct ftrace_ops *ops = &global_ops; 20255072c59fSSteven Rostedt struct dyn_ftrace *rec = NULL; 20265072c59fSSteven Rostedt 202745a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 202845a4a237SSteven Rostedt return NULL; 202945a4a237SSteven Rostedt 20308fc0c701SSteven Rostedt if (iter->flags & FTRACE_ITER_HASH) 20314aeb6967SSteven Rostedt return t_hash_next(m, pos); 20328fc0c701SSteven Rostedt 20335072c59fSSteven Rostedt (*pos)++; 20341106b699SJiri Olsa iter->pos = iter->func_pos = *pos; 20355072c59fSSteven Rostedt 20360c75a3edSSteven Rostedt if (iter->flags & FTRACE_ITER_PRINTALL) 203757c072c7SSteven Rostedt return t_hash_start(m, pos); 20380c75a3edSSteven Rostedt 20395072c59fSSteven Rostedt retry: 20405072c59fSSteven Rostedt if (iter->idx >= iter->pg->index) { 20415072c59fSSteven Rostedt if (iter->pg->next) { 20425072c59fSSteven Rostedt iter->pg = iter->pg->next; 20435072c59fSSteven Rostedt iter->idx = 0; 20445072c59fSSteven Rostedt goto retry; 20455072c59fSSteven Rostedt } 20465072c59fSSteven Rostedt } else { 20475072c59fSSteven Rostedt rec = &iter->pg->records[iter->idx++]; 2048a9fdda33SSteven Rostedt if ((rec->flags & FTRACE_FL_FREE) || 2049a9fdda33SSteven Rostedt 20500183fb1cSSteven Rostedt ((iter->flags & FTRACE_ITER_FILTER) && 2051f45948e8SSteven Rostedt !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) || 20520183fb1cSSteven Rostedt 205341c52c0dSSteven Rostedt ((iter->flags & FTRACE_ITER_NOTRACE) && 2054647bcd03SSteven Rostedt !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) || 2055647bcd03SSteven Rostedt 2056647bcd03SSteven Rostedt ((iter->flags & FTRACE_ITER_ENABLED) && 2057647bcd03SSteven Rostedt !(rec->flags & ~FTRACE_FL_MASK))) { 2058647bcd03SSteven Rostedt 20595072c59fSSteven Rostedt rec = NULL; 20605072c59fSSteven Rostedt goto retry; 20615072c59fSSteven Rostedt } 20625072c59fSSteven Rostedt } 20635072c59fSSteven Rostedt 20644aeb6967SSteven Rostedt if (!rec) 206557c072c7SSteven Rostedt return t_hash_start(m, pos); 20664aeb6967SSteven Rostedt 20674aeb6967SSteven Rostedt iter->func = rec; 20684aeb6967SSteven Rostedt 20694aeb6967SSteven Rostedt return iter; 20705072c59fSSteven Rostedt } 20715072c59fSSteven Rostedt 207298c4fd04SSteven Rostedt static void reset_iter_read(struct ftrace_iterator *iter) 207398c4fd04SSteven Rostedt { 207498c4fd04SSteven Rostedt iter->pos = 0; 207598c4fd04SSteven Rostedt iter->func_pos = 0; 207698c4fd04SSteven Rostedt iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH); 20775072c59fSSteven Rostedt } 20785072c59fSSteven Rostedt 20795072c59fSSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos) 20805072c59fSSteven Rostedt { 20815072c59fSSteven Rostedt struct ftrace_iterator *iter = m->private; 2082f45948e8SSteven Rostedt struct ftrace_ops *ops = &global_ops; 20835072c59fSSteven Rostedt void *p = NULL; 2084694ce0a5SLi Zefan loff_t l; 20855072c59fSSteven Rostedt 20868fc0c701SSteven Rostedt mutex_lock(&ftrace_lock); 208745a4a237SSteven Rostedt 208845a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 208945a4a237SSteven Rostedt return NULL; 209045a4a237SSteven Rostedt 20910c75a3edSSteven Rostedt /* 209298c4fd04SSteven Rostedt * If an lseek was done, then reset and start from beginning. 209398c4fd04SSteven Rostedt */ 209498c4fd04SSteven Rostedt if (*pos < iter->pos) 209598c4fd04SSteven Rostedt reset_iter_read(iter); 209698c4fd04SSteven Rostedt 209798c4fd04SSteven Rostedt /* 20980c75a3edSSteven Rostedt * For set_ftrace_filter reading, if we have the filter 20990c75a3edSSteven Rostedt * off, we can short cut and just print out that all 21000c75a3edSSteven Rostedt * functions are enabled. 21010c75a3edSSteven Rostedt */ 2102f45948e8SSteven Rostedt if (iter->flags & FTRACE_ITER_FILTER && !ops->filter_hash->count) { 21030c75a3edSSteven Rostedt if (*pos > 0) 21048fc0c701SSteven Rostedt return t_hash_start(m, pos); 21050c75a3edSSteven Rostedt iter->flags |= FTRACE_ITER_PRINTALL; 2106df091625SChris Wright /* reset in case of seek/pread */ 2107df091625SChris Wright iter->flags &= ~FTRACE_ITER_HASH; 21080c75a3edSSteven Rostedt return iter; 21090c75a3edSSteven Rostedt } 21100c75a3edSSteven Rostedt 21118fc0c701SSteven Rostedt if (iter->flags & FTRACE_ITER_HASH) 21128fc0c701SSteven Rostedt return t_hash_start(m, pos); 21138fc0c701SSteven Rostedt 211498c4fd04SSteven Rostedt /* 211598c4fd04SSteven Rostedt * Unfortunately, we need to restart at ftrace_pages_start 211698c4fd04SSteven Rostedt * every time we let go of the ftrace_mutex. This is because 211798c4fd04SSteven Rostedt * those pointers can change without the lock. 211898c4fd04SSteven Rostedt */ 2119694ce0a5SLi Zefan iter->pg = ftrace_pages_start; 2120694ce0a5SLi Zefan iter->idx = 0; 2121694ce0a5SLi Zefan for (l = 0; l <= *pos; ) { 2122694ce0a5SLi Zefan p = t_next(m, p, &l); 2123694ce0a5SLi Zefan if (!p) 2124694ce0a5SLi Zefan break; 212550cdaf08SLiming Wang } 21265821e1b7Swalimis 21274aeb6967SSteven Rostedt if (!p) { 21284aeb6967SSteven Rostedt if (iter->flags & FTRACE_ITER_FILTER) 21298fc0c701SSteven Rostedt return t_hash_start(m, pos); 21308fc0c701SSteven Rostedt 21314aeb6967SSteven Rostedt return NULL; 21324aeb6967SSteven Rostedt } 21334aeb6967SSteven Rostedt 21344aeb6967SSteven Rostedt return iter; 21355072c59fSSteven Rostedt } 21365072c59fSSteven Rostedt 21375072c59fSSteven Rostedt static void t_stop(struct seq_file *m, void *p) 21385072c59fSSteven Rostedt { 21398fc0c701SSteven Rostedt mutex_unlock(&ftrace_lock); 21405072c59fSSteven Rostedt } 21415072c59fSSteven Rostedt 21425072c59fSSteven Rostedt static int t_show(struct seq_file *m, void *v) 21435072c59fSSteven Rostedt { 21440c75a3edSSteven Rostedt struct ftrace_iterator *iter = m->private; 21454aeb6967SSteven Rostedt struct dyn_ftrace *rec; 21465072c59fSSteven Rostedt 21478fc0c701SSteven Rostedt if (iter->flags & FTRACE_ITER_HASH) 21484aeb6967SSteven Rostedt return t_hash_show(m, iter); 21498fc0c701SSteven Rostedt 21500c75a3edSSteven Rostedt if (iter->flags & FTRACE_ITER_PRINTALL) { 21510c75a3edSSteven Rostedt seq_printf(m, "#### all functions enabled ####\n"); 21520c75a3edSSteven Rostedt return 0; 21530c75a3edSSteven Rostedt } 21540c75a3edSSteven Rostedt 21554aeb6967SSteven Rostedt rec = iter->func; 21564aeb6967SSteven Rostedt 21575072c59fSSteven Rostedt if (!rec) 21585072c59fSSteven Rostedt return 0; 21595072c59fSSteven Rostedt 2160647bcd03SSteven Rostedt seq_printf(m, "%ps", (void *)rec->ip); 2161647bcd03SSteven Rostedt if (iter->flags & FTRACE_ITER_ENABLED) 2162647bcd03SSteven Rostedt seq_printf(m, " (%ld)", 2163647bcd03SSteven Rostedt rec->flags & ~FTRACE_FL_MASK); 2164647bcd03SSteven Rostedt seq_printf(m, "\n"); 21655072c59fSSteven Rostedt 21665072c59fSSteven Rostedt return 0; 21675072c59fSSteven Rostedt } 21685072c59fSSteven Rostedt 216988e9d34cSJames Morris static const struct seq_operations show_ftrace_seq_ops = { 21705072c59fSSteven Rostedt .start = t_start, 21715072c59fSSteven Rostedt .next = t_next, 21725072c59fSSteven Rostedt .stop = t_stop, 21735072c59fSSteven Rostedt .show = t_show, 21745072c59fSSteven Rostedt }; 21755072c59fSSteven Rostedt 2176e309b41dSIngo Molnar static int 21775072c59fSSteven Rostedt ftrace_avail_open(struct inode *inode, struct file *file) 21785072c59fSSteven Rostedt { 21795072c59fSSteven Rostedt struct ftrace_iterator *iter; 21805072c59fSSteven Rostedt int ret; 21815072c59fSSteven Rostedt 21824eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 21834eebcc81SSteven Rostedt return -ENODEV; 21844eebcc81SSteven Rostedt 21855072c59fSSteven Rostedt iter = kzalloc(sizeof(*iter), GFP_KERNEL); 21865072c59fSSteven Rostedt if (!iter) 21875072c59fSSteven Rostedt return -ENOMEM; 21885072c59fSSteven Rostedt 21895072c59fSSteven Rostedt iter->pg = ftrace_pages_start; 21905072c59fSSteven Rostedt 21915072c59fSSteven Rostedt ret = seq_open(file, &show_ftrace_seq_ops); 21925072c59fSSteven Rostedt if (!ret) { 21935072c59fSSteven Rostedt struct seq_file *m = file->private_data; 21944bf39a94SIngo Molnar 21955072c59fSSteven Rostedt m->private = iter; 21964bf39a94SIngo Molnar } else { 21975072c59fSSteven Rostedt kfree(iter); 21984bf39a94SIngo Molnar } 21995072c59fSSteven Rostedt 22005072c59fSSteven Rostedt return ret; 22015072c59fSSteven Rostedt } 22025072c59fSSteven Rostedt 2203647bcd03SSteven Rostedt static int 2204647bcd03SSteven Rostedt ftrace_enabled_open(struct inode *inode, struct file *file) 2205647bcd03SSteven Rostedt { 2206647bcd03SSteven Rostedt struct ftrace_iterator *iter; 2207647bcd03SSteven Rostedt int ret; 2208647bcd03SSteven Rostedt 2209647bcd03SSteven Rostedt if (unlikely(ftrace_disabled)) 2210647bcd03SSteven Rostedt return -ENODEV; 2211647bcd03SSteven Rostedt 2212647bcd03SSteven Rostedt iter = kzalloc(sizeof(*iter), GFP_KERNEL); 2213647bcd03SSteven Rostedt if (!iter) 2214647bcd03SSteven Rostedt return -ENOMEM; 2215647bcd03SSteven Rostedt 2216647bcd03SSteven Rostedt iter->pg = ftrace_pages_start; 2217647bcd03SSteven Rostedt iter->flags = FTRACE_ITER_ENABLED; 2218647bcd03SSteven Rostedt 2219647bcd03SSteven Rostedt ret = seq_open(file, &show_ftrace_seq_ops); 2220647bcd03SSteven Rostedt if (!ret) { 2221647bcd03SSteven Rostedt struct seq_file *m = file->private_data; 2222647bcd03SSteven Rostedt 2223647bcd03SSteven Rostedt m->private = iter; 2224647bcd03SSteven Rostedt } else { 2225647bcd03SSteven Rostedt kfree(iter); 2226647bcd03SSteven Rostedt } 2227647bcd03SSteven Rostedt 2228647bcd03SSteven Rostedt return ret; 2229647bcd03SSteven Rostedt } 2230647bcd03SSteven Rostedt 22311cf41dd7SSteven Rostedt static void ftrace_filter_reset(struct ftrace_hash *hash) 22325072c59fSSteven Rostedt { 223352baf119SSteven Rostedt mutex_lock(&ftrace_lock); 22341cf41dd7SSteven Rostedt ftrace_hash_clear(hash); 223552baf119SSteven Rostedt mutex_unlock(&ftrace_lock); 22365072c59fSSteven Rostedt } 22375072c59fSSteven Rostedt 2238e309b41dSIngo Molnar static int 2239f45948e8SSteven Rostedt ftrace_regex_open(struct ftrace_ops *ops, int flag, 22401cf41dd7SSteven Rostedt struct inode *inode, struct file *file) 22415072c59fSSteven Rostedt { 22425072c59fSSteven Rostedt struct ftrace_iterator *iter; 2243f45948e8SSteven Rostedt struct ftrace_hash *hash; 22445072c59fSSteven Rostedt int ret = 0; 22455072c59fSSteven Rostedt 22464eebcc81SSteven Rostedt if (unlikely(ftrace_disabled)) 22474eebcc81SSteven Rostedt return -ENODEV; 22484eebcc81SSteven Rostedt 22495072c59fSSteven Rostedt iter = kzalloc(sizeof(*iter), GFP_KERNEL); 22505072c59fSSteven Rostedt if (!iter) 22515072c59fSSteven Rostedt return -ENOMEM; 22525072c59fSSteven Rostedt 2253689fd8b6S[email protected] if (trace_parser_get_init(&iter->parser, FTRACE_BUFF_MAX)) { 2254689fd8b6S[email protected] kfree(iter); 2255689fd8b6S[email protected] return -ENOMEM; 2256689fd8b6S[email protected] } 2257689fd8b6S[email protected] 2258f45948e8SSteven Rostedt if (flag & FTRACE_ITER_NOTRACE) 2259f45948e8SSteven Rostedt hash = ops->notrace_hash; 2260f45948e8SSteven Rostedt else 2261f45948e8SSteven Rostedt hash = ops->filter_hash; 2262f45948e8SSteven Rostedt 226333dc9b12SSteven Rostedt iter->ops = ops; 226433dc9b12SSteven Rostedt iter->flags = flag; 226533dc9b12SSteven Rostedt 226633dc9b12SSteven Rostedt if (file->f_mode & FMODE_WRITE) { 226733dc9b12SSteven Rostedt mutex_lock(&ftrace_lock); 226833dc9b12SSteven Rostedt iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); 226933dc9b12SSteven Rostedt mutex_unlock(&ftrace_lock); 227033dc9b12SSteven Rostedt 227133dc9b12SSteven Rostedt if (!iter->hash) { 227233dc9b12SSteven Rostedt trace_parser_put(&iter->parser); 227333dc9b12SSteven Rostedt kfree(iter); 227433dc9b12SSteven Rostedt return -ENOMEM; 227533dc9b12SSteven Rostedt } 227633dc9b12SSteven Rostedt } 22771cf41dd7SSteven Rostedt 227841c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 227933dc9b12SSteven Rostedt 22805072c59fSSteven Rostedt if ((file->f_mode & FMODE_WRITE) && 22818650ae32SSteven Rostedt (file->f_flags & O_TRUNC)) 228233dc9b12SSteven Rostedt ftrace_filter_reset(iter->hash); 22835072c59fSSteven Rostedt 22845072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) { 22855072c59fSSteven Rostedt iter->pg = ftrace_pages_start; 22865072c59fSSteven Rostedt 22875072c59fSSteven Rostedt ret = seq_open(file, &show_ftrace_seq_ops); 22885072c59fSSteven Rostedt if (!ret) { 22895072c59fSSteven Rostedt struct seq_file *m = file->private_data; 22905072c59fSSteven Rostedt m->private = iter; 229179fe249cSLi Zefan } else { 229233dc9b12SSteven Rostedt /* Failed */ 229333dc9b12SSteven Rostedt free_ftrace_hash(iter->hash); 229479fe249cSLi Zefan trace_parser_put(&iter->parser); 22955072c59fSSteven Rostedt kfree(iter); 229679fe249cSLi Zefan } 22975072c59fSSteven Rostedt } else 22985072c59fSSteven Rostedt file->private_data = iter; 229941c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 23005072c59fSSteven Rostedt 23015072c59fSSteven Rostedt return ret; 23025072c59fSSteven Rostedt } 23035072c59fSSteven Rostedt 230441c52c0dSSteven Rostedt static int 230541c52c0dSSteven Rostedt ftrace_filter_open(struct inode *inode, struct file *file) 230641c52c0dSSteven Rostedt { 2307f45948e8SSteven Rostedt return ftrace_regex_open(&global_ops, FTRACE_ITER_FILTER, 23081cf41dd7SSteven Rostedt inode, file); 230941c52c0dSSteven Rostedt } 231041c52c0dSSteven Rostedt 231141c52c0dSSteven Rostedt static int 231241c52c0dSSteven Rostedt ftrace_notrace_open(struct inode *inode, struct file *file) 231341c52c0dSSteven Rostedt { 2314f45948e8SSteven Rostedt return ftrace_regex_open(&global_ops, FTRACE_ITER_NOTRACE, 23151cf41dd7SSteven Rostedt inode, file); 231641c52c0dSSteven Rostedt } 231741c52c0dSSteven Rostedt 2318e309b41dSIngo Molnar static loff_t 231941c52c0dSSteven Rostedt ftrace_regex_lseek(struct file *file, loff_t offset, int origin) 23205072c59fSSteven Rostedt { 23215072c59fSSteven Rostedt loff_t ret; 23225072c59fSSteven Rostedt 23235072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) 23245072c59fSSteven Rostedt ret = seq_lseek(file, offset, origin); 23255072c59fSSteven Rostedt else 23265072c59fSSteven Rostedt file->f_pos = ret = 1; 23275072c59fSSteven Rostedt 23285072c59fSSteven Rostedt return ret; 23295072c59fSSteven Rostedt } 23305072c59fSSteven Rostedt 233164e7c440SSteven Rostedt static int ftrace_match(char *str, char *regex, int len, int type) 23329f4801e3SSteven Rostedt { 23339f4801e3SSteven Rostedt int matched = 0; 2334751e9983SLi Zefan int slen; 23359f4801e3SSteven Rostedt 23369f4801e3SSteven Rostedt switch (type) { 23379f4801e3SSteven Rostedt case MATCH_FULL: 23389f4801e3SSteven Rostedt if (strcmp(str, regex) == 0) 23399f4801e3SSteven Rostedt matched = 1; 23409f4801e3SSteven Rostedt break; 23419f4801e3SSteven Rostedt case MATCH_FRONT_ONLY: 23429f4801e3SSteven Rostedt if (strncmp(str, regex, len) == 0) 23439f4801e3SSteven Rostedt matched = 1; 23449f4801e3SSteven Rostedt break; 23459f4801e3SSteven Rostedt case MATCH_MIDDLE_ONLY: 23469f4801e3SSteven Rostedt if (strstr(str, regex)) 23479f4801e3SSteven Rostedt matched = 1; 23489f4801e3SSteven Rostedt break; 23499f4801e3SSteven Rostedt case MATCH_END_ONLY: 2350751e9983SLi Zefan slen = strlen(str); 2351751e9983SLi Zefan if (slen >= len && memcmp(str + slen - len, regex, len) == 0) 23529f4801e3SSteven Rostedt matched = 1; 23539f4801e3SSteven Rostedt break; 23549f4801e3SSteven Rostedt } 23559f4801e3SSteven Rostedt 23569f4801e3SSteven Rostedt return matched; 23579f4801e3SSteven Rostedt } 23589f4801e3SSteven Rostedt 2359b448c4e3SSteven Rostedt static int 23601cf41dd7SSteven Rostedt enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int not) 236164e7c440SSteven Rostedt { 2362b448c4e3SSteven Rostedt struct ftrace_func_entry *entry; 2363b448c4e3SSteven Rostedt int ret = 0; 2364b448c4e3SSteven Rostedt 23651cf41dd7SSteven Rostedt entry = ftrace_lookup_ip(hash, rec->ip); 2366b448c4e3SSteven Rostedt if (not) { 2367b448c4e3SSteven Rostedt /* Do nothing if it doesn't exist */ 2368b448c4e3SSteven Rostedt if (!entry) 2369b448c4e3SSteven Rostedt return 0; 2370b448c4e3SSteven Rostedt 237133dc9b12SSteven Rostedt free_hash_entry(hash, entry); 2372b448c4e3SSteven Rostedt } else { 2373b448c4e3SSteven Rostedt /* Do nothing if it exists */ 2374b448c4e3SSteven Rostedt if (entry) 2375b448c4e3SSteven Rostedt return 0; 2376b448c4e3SSteven Rostedt 2377b448c4e3SSteven Rostedt ret = add_hash_entry(hash, rec->ip); 2378b448c4e3SSteven Rostedt } 2379b448c4e3SSteven Rostedt return ret; 2380996e87beSSteven Rostedt } 2381996e87beSSteven Rostedt 238264e7c440SSteven Rostedt static int 2383b9df92d2SSteven Rostedt ftrace_match_record(struct dyn_ftrace *rec, char *mod, 2384b9df92d2SSteven Rostedt char *regex, int len, int type) 238564e7c440SSteven Rostedt { 238664e7c440SSteven Rostedt char str[KSYM_SYMBOL_LEN]; 2387b9df92d2SSteven Rostedt char *modname; 238864e7c440SSteven Rostedt 2389b9df92d2SSteven Rostedt kallsyms_lookup(rec->ip, NULL, NULL, &modname, str); 2390b9df92d2SSteven Rostedt 2391b9df92d2SSteven Rostedt if (mod) { 2392b9df92d2SSteven Rostedt /* module lookup requires matching the module */ 2393b9df92d2SSteven Rostedt if (!modname || strcmp(modname, mod)) 2394b9df92d2SSteven Rostedt return 0; 2395b9df92d2SSteven Rostedt 2396b9df92d2SSteven Rostedt /* blank search means to match all funcs in the mod */ 2397b9df92d2SSteven Rostedt if (!len) 2398b9df92d2SSteven Rostedt return 1; 2399b9df92d2SSteven Rostedt } 2400b9df92d2SSteven Rostedt 240164e7c440SSteven Rostedt return ftrace_match(str, regex, len, type); 240264e7c440SSteven Rostedt } 240364e7c440SSteven Rostedt 24041cf41dd7SSteven Rostedt static int 24051cf41dd7SSteven Rostedt match_records(struct ftrace_hash *hash, char *buff, 24061cf41dd7SSteven Rostedt int len, char *mod, int not) 24079f4801e3SSteven Rostedt { 2408b9df92d2SSteven Rostedt unsigned search_len = 0; 24099f4801e3SSteven Rostedt struct ftrace_page *pg; 24109f4801e3SSteven Rostedt struct dyn_ftrace *rec; 2411b9df92d2SSteven Rostedt int type = MATCH_FULL; 2412b9df92d2SSteven Rostedt char *search = buff; 2413311d16daSLi Zefan int found = 0; 2414b448c4e3SSteven Rostedt int ret; 24159f4801e3SSteven Rostedt 2416b9df92d2SSteven Rostedt if (len) { 24173f6fe06dSFrederic Weisbecker type = filter_parse_regex(buff, len, &search, ¬); 24189f4801e3SSteven Rostedt search_len = strlen(search); 2419b9df92d2SSteven Rostedt } 2420b9df92d2SSteven Rostedt 242152baf119SSteven Rostedt mutex_lock(&ftrace_lock); 2422b9df92d2SSteven Rostedt 2423b9df92d2SSteven Rostedt if (unlikely(ftrace_disabled)) 2424b9df92d2SSteven Rostedt goto out_unlock; 2425b9df92d2SSteven Rostedt 2426265c831cSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 24275072c59fSSteven Rostedt 2428b9df92d2SSteven Rostedt if (ftrace_match_record(rec, mod, search, search_len, type)) { 24291cf41dd7SSteven Rostedt ret = enter_record(hash, rec, not); 2430b448c4e3SSteven Rostedt if (ret < 0) { 2431b448c4e3SSteven Rostedt found = ret; 2432b448c4e3SSteven Rostedt goto out_unlock; 2433b448c4e3SSteven Rostedt } 2434311d16daSLi Zefan found = 1; 24355072c59fSSteven Rostedt } 2436265c831cSSteven Rostedt } while_for_each_ftrace_rec(); 2437b9df92d2SSteven Rostedt out_unlock: 243852baf119SSteven Rostedt mutex_unlock(&ftrace_lock); 2439311d16daSLi Zefan 2440311d16daSLi Zefan return found; 24415072c59fSSteven Rostedt } 24425072c59fSSteven Rostedt 244364e7c440SSteven Rostedt static int 24441cf41dd7SSteven Rostedt ftrace_match_records(struct ftrace_hash *hash, char *buff, int len) 244564e7c440SSteven Rostedt { 24461cf41dd7SSteven Rostedt return match_records(hash, buff, len, NULL, 0); 244764e7c440SSteven Rostedt } 244864e7c440SSteven Rostedt 24491cf41dd7SSteven Rostedt static int 24501cf41dd7SSteven Rostedt ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod) 245164e7c440SSteven Rostedt { 245264e7c440SSteven Rostedt int not = 0; 24536a24a244SSteven Rostedt 245464e7c440SSteven Rostedt /* blank or '*' mean the same */ 245564e7c440SSteven Rostedt if (strcmp(buff, "*") == 0) 245664e7c440SSteven Rostedt buff[0] = 0; 245764e7c440SSteven Rostedt 245864e7c440SSteven Rostedt /* handle the case of 'dont filter this module' */ 245964e7c440SSteven Rostedt if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) { 246064e7c440SSteven Rostedt buff[0] = 0; 246164e7c440SSteven Rostedt not = 1; 246264e7c440SSteven Rostedt } 246364e7c440SSteven Rostedt 24641cf41dd7SSteven Rostedt return match_records(hash, buff, strlen(buff), mod, not); 246564e7c440SSteven Rostedt } 246664e7c440SSteven Rostedt 2467f6180773SSteven Rostedt /* 2468f6180773SSteven Rostedt * We register the module command as a template to show others how 2469f6180773SSteven Rostedt * to register the a command as well. 2470f6180773SSteven Rostedt */ 2471f6180773SSteven Rostedt 2472f6180773SSteven Rostedt static int 247343dd61c9SSteven Rostedt ftrace_mod_callback(struct ftrace_hash *hash, 247443dd61c9SSteven Rostedt char *func, char *cmd, char *param, int enable) 2475f6180773SSteven Rostedt { 2476f6180773SSteven Rostedt char *mod; 2477b448c4e3SSteven Rostedt int ret = -EINVAL; 2478f6180773SSteven Rostedt 2479f6180773SSteven Rostedt /* 2480f6180773SSteven Rostedt * cmd == 'mod' because we only registered this func 2481f6180773SSteven Rostedt * for the 'mod' ftrace_func_command. 2482f6180773SSteven Rostedt * But if you register one func with multiple commands, 2483f6180773SSteven Rostedt * you can tell which command was used by the cmd 2484f6180773SSteven Rostedt * parameter. 2485f6180773SSteven Rostedt */ 2486f6180773SSteven Rostedt 2487f6180773SSteven Rostedt /* we must have a module name */ 2488f6180773SSteven Rostedt if (!param) 2489b448c4e3SSteven Rostedt return ret; 2490f6180773SSteven Rostedt 2491f6180773SSteven Rostedt mod = strsep(¶m, ":"); 2492f6180773SSteven Rostedt if (!strlen(mod)) 2493b448c4e3SSteven Rostedt return ret; 2494f6180773SSteven Rostedt 24951cf41dd7SSteven Rostedt ret = ftrace_match_module_records(hash, func, mod); 2496b448c4e3SSteven Rostedt if (!ret) 2497b448c4e3SSteven Rostedt ret = -EINVAL; 2498b448c4e3SSteven Rostedt if (ret < 0) 2499b448c4e3SSteven Rostedt return ret; 2500b448c4e3SSteven Rostedt 2501f6180773SSteven Rostedt return 0; 2502f6180773SSteven Rostedt } 2503f6180773SSteven Rostedt 2504f6180773SSteven Rostedt static struct ftrace_func_command ftrace_mod_cmd = { 2505f6180773SSteven Rostedt .name = "mod", 2506f6180773SSteven Rostedt .func = ftrace_mod_callback, 2507f6180773SSteven Rostedt }; 2508f6180773SSteven Rostedt 2509f6180773SSteven Rostedt static int __init ftrace_mod_cmd_init(void) 2510f6180773SSteven Rostedt { 2511f6180773SSteven Rostedt return register_ftrace_command(&ftrace_mod_cmd); 2512f6180773SSteven Rostedt } 2513f6180773SSteven Rostedt device_initcall(ftrace_mod_cmd_init); 2514f6180773SSteven Rostedt 251559df055fSSteven Rostedt static void 2516b6887d79SSteven Rostedt function_trace_probe_call(unsigned long ip, unsigned long parent_ip) 251759df055fSSteven Rostedt { 2518b6887d79SSteven Rostedt struct ftrace_func_probe *entry; 251959df055fSSteven Rostedt struct hlist_head *hhd; 252059df055fSSteven Rostedt struct hlist_node *n; 252159df055fSSteven Rostedt unsigned long key; 252259df055fSSteven Rostedt 252359df055fSSteven Rostedt key = hash_long(ip, FTRACE_HASH_BITS); 252459df055fSSteven Rostedt 252559df055fSSteven Rostedt hhd = &ftrace_func_hash[key]; 252659df055fSSteven Rostedt 252759df055fSSteven Rostedt if (hlist_empty(hhd)) 252859df055fSSteven Rostedt return; 252959df055fSSteven Rostedt 253059df055fSSteven Rostedt /* 253159df055fSSteven Rostedt * Disable preemption for these calls to prevent a RCU grace 253259df055fSSteven Rostedt * period. This syncs the hash iteration and freeing of items 253359df055fSSteven Rostedt * on the hash. rcu_read_lock is too dangerous here. 253459df055fSSteven Rostedt */ 25355168ae50SSteven Rostedt preempt_disable_notrace(); 253659df055fSSteven Rostedt hlist_for_each_entry_rcu(entry, n, hhd, node) { 253759df055fSSteven Rostedt if (entry->ip == ip) 253859df055fSSteven Rostedt entry->ops->func(ip, parent_ip, &entry->data); 253959df055fSSteven Rostedt } 25405168ae50SSteven Rostedt preempt_enable_notrace(); 254159df055fSSteven Rostedt } 254259df055fSSteven Rostedt 2543b6887d79SSteven Rostedt static struct ftrace_ops trace_probe_ops __read_mostly = 254459df055fSSteven Rostedt { 2545b6887d79SSteven Rostedt .func = function_trace_probe_call, 254659df055fSSteven Rostedt }; 254759df055fSSteven Rostedt 2548b6887d79SSteven Rostedt static int ftrace_probe_registered; 254959df055fSSteven Rostedt 2550b6887d79SSteven Rostedt static void __enable_ftrace_function_probe(void) 255159df055fSSteven Rostedt { 2552b848914cSSteven Rostedt int ret; 255359df055fSSteven Rostedt int i; 255459df055fSSteven Rostedt 2555b6887d79SSteven Rostedt if (ftrace_probe_registered) 255659df055fSSteven Rostedt return; 255759df055fSSteven Rostedt 255859df055fSSteven Rostedt for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 255959df055fSSteven Rostedt struct hlist_head *hhd = &ftrace_func_hash[i]; 256059df055fSSteven Rostedt if (hhd->first) 256159df055fSSteven Rostedt break; 256259df055fSSteven Rostedt } 256359df055fSSteven Rostedt /* Nothing registered? */ 256459df055fSSteven Rostedt if (i == FTRACE_FUNC_HASHSIZE) 256559df055fSSteven Rostedt return; 256659df055fSSteven Rostedt 2567b848914cSSteven Rostedt ret = __register_ftrace_function(&trace_probe_ops); 2568b848914cSSteven Rostedt if (!ret) 2569a1cd6173SSteven Rostedt ret = ftrace_startup(&trace_probe_ops, 0); 2570b848914cSSteven Rostedt 2571b6887d79SSteven Rostedt ftrace_probe_registered = 1; 257259df055fSSteven Rostedt } 257359df055fSSteven Rostedt 2574b6887d79SSteven Rostedt static void __disable_ftrace_function_probe(void) 257559df055fSSteven Rostedt { 2576b848914cSSteven Rostedt int ret; 257759df055fSSteven Rostedt int i; 257859df055fSSteven Rostedt 2579b6887d79SSteven Rostedt if (!ftrace_probe_registered) 258059df055fSSteven Rostedt return; 258159df055fSSteven Rostedt 258259df055fSSteven Rostedt for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 258359df055fSSteven Rostedt struct hlist_head *hhd = &ftrace_func_hash[i]; 258459df055fSSteven Rostedt if (hhd->first) 258559df055fSSteven Rostedt return; 258659df055fSSteven Rostedt } 258759df055fSSteven Rostedt 258859df055fSSteven Rostedt /* no more funcs left */ 2589b848914cSSteven Rostedt ret = __unregister_ftrace_function(&trace_probe_ops); 2590b848914cSSteven Rostedt if (!ret) 2591b848914cSSteven Rostedt ftrace_shutdown(&trace_probe_ops, 0); 2592b848914cSSteven Rostedt 2593b6887d79SSteven Rostedt ftrace_probe_registered = 0; 259459df055fSSteven Rostedt } 259559df055fSSteven Rostedt 259659df055fSSteven Rostedt 259759df055fSSteven Rostedt static void ftrace_free_entry_rcu(struct rcu_head *rhp) 259859df055fSSteven Rostedt { 2599b6887d79SSteven Rostedt struct ftrace_func_probe *entry = 2600b6887d79SSteven Rostedt container_of(rhp, struct ftrace_func_probe, rcu); 260159df055fSSteven Rostedt 260259df055fSSteven Rostedt if (entry->ops->free) 260359df055fSSteven Rostedt entry->ops->free(&entry->data); 260459df055fSSteven Rostedt kfree(entry); 260559df055fSSteven Rostedt } 260659df055fSSteven Rostedt 260759df055fSSteven Rostedt 260859df055fSSteven Rostedt int 2609b6887d79SSteven Rostedt register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 261059df055fSSteven Rostedt void *data) 261159df055fSSteven Rostedt { 2612b6887d79SSteven Rostedt struct ftrace_func_probe *entry; 261359df055fSSteven Rostedt struct ftrace_page *pg; 261459df055fSSteven Rostedt struct dyn_ftrace *rec; 261559df055fSSteven Rostedt int type, len, not; 26166a24a244SSteven Rostedt unsigned long key; 261759df055fSSteven Rostedt int count = 0; 261859df055fSSteven Rostedt char *search; 261959df055fSSteven Rostedt 26203f6fe06dSFrederic Weisbecker type = filter_parse_regex(glob, strlen(glob), &search, ¬); 262159df055fSSteven Rostedt len = strlen(search); 262259df055fSSteven Rostedt 2623b6887d79SSteven Rostedt /* we do not support '!' for function probes */ 262459df055fSSteven Rostedt if (WARN_ON(not)) 262559df055fSSteven Rostedt return -EINVAL; 262659df055fSSteven Rostedt 262759df055fSSteven Rostedt mutex_lock(&ftrace_lock); 262859df055fSSteven Rostedt 262945a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 263045a4a237SSteven Rostedt goto out_unlock; 263145a4a237SSteven Rostedt 263259df055fSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 263359df055fSSteven Rostedt 2634b9df92d2SSteven Rostedt if (!ftrace_match_record(rec, NULL, search, len, type)) 263559df055fSSteven Rostedt continue; 263659df055fSSteven Rostedt 263759df055fSSteven Rostedt entry = kmalloc(sizeof(*entry), GFP_KERNEL); 263859df055fSSteven Rostedt if (!entry) { 2639b6887d79SSteven Rostedt /* If we did not process any, then return error */ 264059df055fSSteven Rostedt if (!count) 264159df055fSSteven Rostedt count = -ENOMEM; 264259df055fSSteven Rostedt goto out_unlock; 264359df055fSSteven Rostedt } 264459df055fSSteven Rostedt 264559df055fSSteven Rostedt count++; 264659df055fSSteven Rostedt 264759df055fSSteven Rostedt entry->data = data; 264859df055fSSteven Rostedt 264959df055fSSteven Rostedt /* 265059df055fSSteven Rostedt * The caller might want to do something special 265159df055fSSteven Rostedt * for each function we find. We call the callback 265259df055fSSteven Rostedt * to give the caller an opportunity to do so. 265359df055fSSteven Rostedt */ 265459df055fSSteven Rostedt if (ops->callback) { 265559df055fSSteven Rostedt if (ops->callback(rec->ip, &entry->data) < 0) { 265659df055fSSteven Rostedt /* caller does not like this func */ 265759df055fSSteven Rostedt kfree(entry); 265859df055fSSteven Rostedt continue; 265959df055fSSteven Rostedt } 266059df055fSSteven Rostedt } 266159df055fSSteven Rostedt 266259df055fSSteven Rostedt entry->ops = ops; 266359df055fSSteven Rostedt entry->ip = rec->ip; 266459df055fSSteven Rostedt 266559df055fSSteven Rostedt key = hash_long(entry->ip, FTRACE_HASH_BITS); 266659df055fSSteven Rostedt hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]); 266759df055fSSteven Rostedt 266859df055fSSteven Rostedt } while_for_each_ftrace_rec(); 2669b6887d79SSteven Rostedt __enable_ftrace_function_probe(); 267059df055fSSteven Rostedt 267159df055fSSteven Rostedt out_unlock: 267259df055fSSteven Rostedt mutex_unlock(&ftrace_lock); 267359df055fSSteven Rostedt 267459df055fSSteven Rostedt return count; 267559df055fSSteven Rostedt } 267659df055fSSteven Rostedt 267759df055fSSteven Rostedt enum { 2678b6887d79SSteven Rostedt PROBE_TEST_FUNC = 1, 2679b6887d79SSteven Rostedt PROBE_TEST_DATA = 2 268059df055fSSteven Rostedt }; 268159df055fSSteven Rostedt 268259df055fSSteven Rostedt static void 2683b6887d79SSteven Rostedt __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 268459df055fSSteven Rostedt void *data, int flags) 268559df055fSSteven Rostedt { 2686b6887d79SSteven Rostedt struct ftrace_func_probe *entry; 268759df055fSSteven Rostedt struct hlist_node *n, *tmp; 268859df055fSSteven Rostedt char str[KSYM_SYMBOL_LEN]; 268959df055fSSteven Rostedt int type = MATCH_FULL; 269059df055fSSteven Rostedt int i, len = 0; 269159df055fSSteven Rostedt char *search; 269259df055fSSteven Rostedt 2693b36461daSAtsushi Tsuji if (glob && (strcmp(glob, "*") == 0 || !strlen(glob))) 269459df055fSSteven Rostedt glob = NULL; 2695b36461daSAtsushi Tsuji else if (glob) { 269659df055fSSteven Rostedt int not; 269759df055fSSteven Rostedt 26983f6fe06dSFrederic Weisbecker type = filter_parse_regex(glob, strlen(glob), &search, ¬); 269959df055fSSteven Rostedt len = strlen(search); 270059df055fSSteven Rostedt 2701b6887d79SSteven Rostedt /* we do not support '!' for function probes */ 270259df055fSSteven Rostedt if (WARN_ON(not)) 270359df055fSSteven Rostedt return; 270459df055fSSteven Rostedt } 270559df055fSSteven Rostedt 270659df055fSSteven Rostedt mutex_lock(&ftrace_lock); 270759df055fSSteven Rostedt for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 270859df055fSSteven Rostedt struct hlist_head *hhd = &ftrace_func_hash[i]; 270959df055fSSteven Rostedt 271059df055fSSteven Rostedt hlist_for_each_entry_safe(entry, n, tmp, hhd, node) { 271159df055fSSteven Rostedt 271259df055fSSteven Rostedt /* break up if statements for readability */ 2713b6887d79SSteven Rostedt if ((flags & PROBE_TEST_FUNC) && entry->ops != ops) 271459df055fSSteven Rostedt continue; 271559df055fSSteven Rostedt 2716b6887d79SSteven Rostedt if ((flags & PROBE_TEST_DATA) && entry->data != data) 271759df055fSSteven Rostedt continue; 271859df055fSSteven Rostedt 271959df055fSSteven Rostedt /* do this last, since it is the most expensive */ 272059df055fSSteven Rostedt if (glob) { 272159df055fSSteven Rostedt kallsyms_lookup(entry->ip, NULL, NULL, 272259df055fSSteven Rostedt NULL, str); 272359df055fSSteven Rostedt if (!ftrace_match(str, glob, len, type)) 272459df055fSSteven Rostedt continue; 272559df055fSSteven Rostedt } 272659df055fSSteven Rostedt 272759df055fSSteven Rostedt hlist_del(&entry->node); 272859df055fSSteven Rostedt call_rcu(&entry->rcu, ftrace_free_entry_rcu); 272959df055fSSteven Rostedt } 273059df055fSSteven Rostedt } 2731b6887d79SSteven Rostedt __disable_ftrace_function_probe(); 273259df055fSSteven Rostedt mutex_unlock(&ftrace_lock); 273359df055fSSteven Rostedt } 273459df055fSSteven Rostedt 273559df055fSSteven Rostedt void 2736b6887d79SSteven Rostedt unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 273759df055fSSteven Rostedt void *data) 273859df055fSSteven Rostedt { 2739b6887d79SSteven Rostedt __unregister_ftrace_function_probe(glob, ops, data, 2740b6887d79SSteven Rostedt PROBE_TEST_FUNC | PROBE_TEST_DATA); 274159df055fSSteven Rostedt } 274259df055fSSteven Rostedt 274359df055fSSteven Rostedt void 2744b6887d79SSteven Rostedt unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops) 274559df055fSSteven Rostedt { 2746b6887d79SSteven Rostedt __unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC); 274759df055fSSteven Rostedt } 274859df055fSSteven Rostedt 2749b6887d79SSteven Rostedt void unregister_ftrace_function_probe_all(char *glob) 275059df055fSSteven Rostedt { 2751b6887d79SSteven Rostedt __unregister_ftrace_function_probe(glob, NULL, NULL, 0); 275259df055fSSteven Rostedt } 275359df055fSSteven Rostedt 2754f6180773SSteven Rostedt static LIST_HEAD(ftrace_commands); 2755f6180773SSteven Rostedt static DEFINE_MUTEX(ftrace_cmd_mutex); 2756f6180773SSteven Rostedt 2757f6180773SSteven Rostedt int register_ftrace_command(struct ftrace_func_command *cmd) 2758f6180773SSteven Rostedt { 2759f6180773SSteven Rostedt struct ftrace_func_command *p; 2760f6180773SSteven Rostedt int ret = 0; 2761f6180773SSteven Rostedt 2762f6180773SSteven Rostedt mutex_lock(&ftrace_cmd_mutex); 2763f6180773SSteven Rostedt list_for_each_entry(p, &ftrace_commands, list) { 2764f6180773SSteven Rostedt if (strcmp(cmd->name, p->name) == 0) { 2765f6180773SSteven Rostedt ret = -EBUSY; 2766f6180773SSteven Rostedt goto out_unlock; 2767f6180773SSteven Rostedt } 2768f6180773SSteven Rostedt } 2769f6180773SSteven Rostedt list_add(&cmd->list, &ftrace_commands); 2770f6180773SSteven Rostedt out_unlock: 2771f6180773SSteven Rostedt mutex_unlock(&ftrace_cmd_mutex); 2772f6180773SSteven Rostedt 2773f6180773SSteven Rostedt return ret; 2774f6180773SSteven Rostedt } 2775f6180773SSteven Rostedt 2776f6180773SSteven Rostedt int unregister_ftrace_command(struct ftrace_func_command *cmd) 2777f6180773SSteven Rostedt { 2778f6180773SSteven Rostedt struct ftrace_func_command *p, *n; 2779f6180773SSteven Rostedt int ret = -ENODEV; 2780f6180773SSteven Rostedt 2781f6180773SSteven Rostedt mutex_lock(&ftrace_cmd_mutex); 2782f6180773SSteven Rostedt list_for_each_entry_safe(p, n, &ftrace_commands, list) { 2783f6180773SSteven Rostedt if (strcmp(cmd->name, p->name) == 0) { 2784f6180773SSteven Rostedt ret = 0; 2785f6180773SSteven Rostedt list_del_init(&p->list); 2786f6180773SSteven Rostedt goto out_unlock; 2787f6180773SSteven Rostedt } 2788f6180773SSteven Rostedt } 2789f6180773SSteven Rostedt out_unlock: 2790f6180773SSteven Rostedt mutex_unlock(&ftrace_cmd_mutex); 2791f6180773SSteven Rostedt 2792f6180773SSteven Rostedt return ret; 2793f6180773SSteven Rostedt } 2794f6180773SSteven Rostedt 279533dc9b12SSteven Rostedt static int ftrace_process_regex(struct ftrace_hash *hash, 279633dc9b12SSteven Rostedt char *buff, int len, int enable) 279764e7c440SSteven Rostedt { 2798f6180773SSteven Rostedt char *func, *command, *next = buff; 27996a24a244SSteven Rostedt struct ftrace_func_command *p; 28000aff1c0cSGuoWen Li int ret = -EINVAL; 280164e7c440SSteven Rostedt 280264e7c440SSteven Rostedt func = strsep(&next, ":"); 280364e7c440SSteven Rostedt 280464e7c440SSteven Rostedt if (!next) { 28051cf41dd7SSteven Rostedt ret = ftrace_match_records(hash, func, len); 2806b448c4e3SSteven Rostedt if (!ret) 2807b448c4e3SSteven Rostedt ret = -EINVAL; 2808b448c4e3SSteven Rostedt if (ret < 0) 2809311d16daSLi Zefan return ret; 2810b448c4e3SSteven Rostedt return 0; 281164e7c440SSteven Rostedt } 281264e7c440SSteven Rostedt 2813f6180773SSteven Rostedt /* command found */ 281464e7c440SSteven Rostedt 281564e7c440SSteven Rostedt command = strsep(&next, ":"); 281664e7c440SSteven Rostedt 2817f6180773SSteven Rostedt mutex_lock(&ftrace_cmd_mutex); 2818f6180773SSteven Rostedt list_for_each_entry(p, &ftrace_commands, list) { 2819f6180773SSteven Rostedt if (strcmp(p->name, command) == 0) { 282043dd61c9SSteven Rostedt ret = p->func(hash, func, command, next, enable); 2821f6180773SSteven Rostedt goto out_unlock; 282264e7c440SSteven Rostedt } 2823f6180773SSteven Rostedt } 2824f6180773SSteven Rostedt out_unlock: 2825f6180773SSteven Rostedt mutex_unlock(&ftrace_cmd_mutex); 282664e7c440SSteven Rostedt 2827f6180773SSteven Rostedt return ret; 282864e7c440SSteven Rostedt } 282964e7c440SSteven Rostedt 2830e309b41dSIngo Molnar static ssize_t 283141c52c0dSSteven Rostedt ftrace_regex_write(struct file *file, const char __user *ubuf, 283241c52c0dSSteven Rostedt size_t cnt, loff_t *ppos, int enable) 28335072c59fSSteven Rostedt { 28345072c59fSSteven Rostedt struct ftrace_iterator *iter; 2835689fd8b6S[email protected] struct trace_parser *parser; 2836689fd8b6S[email protected] ssize_t ret, read; 28375072c59fSSteven Rostedt 28384ba7978eSLi Zefan if (!cnt) 28395072c59fSSteven Rostedt return 0; 28405072c59fSSteven Rostedt 284141c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 28425072c59fSSteven Rostedt 284345a4a237SSteven Rostedt ret = -ENODEV; 284445a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 284545a4a237SSteven Rostedt goto out_unlock; 284645a4a237SSteven Rostedt 28475072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) { 28485072c59fSSteven Rostedt struct seq_file *m = file->private_data; 28495072c59fSSteven Rostedt iter = m->private; 28505072c59fSSteven Rostedt } else 28515072c59fSSteven Rostedt iter = file->private_data; 28525072c59fSSteven Rostedt 2853689fd8b6S[email protected] parser = &iter->parser; 2854689fd8b6S[email protected] read = trace_get_user(parser, ubuf, cnt, ppos); 28555072c59fSSteven Rostedt 28564ba7978eSLi Zefan if (read >= 0 && trace_parser_loaded(parser) && 2857689fd8b6S[email protected] !trace_parser_cont(parser)) { 285833dc9b12SSteven Rostedt ret = ftrace_process_regex(iter->hash, parser->buffer, 2859689fd8b6S[email protected] parser->idx, enable); 2860313254a9SLi Zefan trace_parser_clear(parser); 28615072c59fSSteven Rostedt if (ret) 2862ed146b25SLi Zefan goto out_unlock; 28635072c59fSSteven Rostedt } 28645072c59fSSteven Rostedt 28655072c59fSSteven Rostedt ret = read; 2866ed146b25SLi Zefan out_unlock: 286741c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 2868ed146b25SLi Zefan 28695072c59fSSteven Rostedt return ret; 28705072c59fSSteven Rostedt } 28715072c59fSSteven Rostedt 287241c52c0dSSteven Rostedt static ssize_t 287341c52c0dSSteven Rostedt ftrace_filter_write(struct file *file, const char __user *ubuf, 287441c52c0dSSteven Rostedt size_t cnt, loff_t *ppos) 287541c52c0dSSteven Rostedt { 287641c52c0dSSteven Rostedt return ftrace_regex_write(file, ubuf, cnt, ppos, 1); 287741c52c0dSSteven Rostedt } 287841c52c0dSSteven Rostedt 287941c52c0dSSteven Rostedt static ssize_t 288041c52c0dSSteven Rostedt ftrace_notrace_write(struct file *file, const char __user *ubuf, 288141c52c0dSSteven Rostedt size_t cnt, loff_t *ppos) 288241c52c0dSSteven Rostedt { 288341c52c0dSSteven Rostedt return ftrace_regex_write(file, ubuf, cnt, ppos, 0); 288441c52c0dSSteven Rostedt } 288541c52c0dSSteven Rostedt 288633dc9b12SSteven Rostedt static int 2887f45948e8SSteven Rostedt ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, 2888f45948e8SSteven Rostedt int reset, int enable) 288941c52c0dSSteven Rostedt { 289033dc9b12SSteven Rostedt struct ftrace_hash **orig_hash; 2891f45948e8SSteven Rostedt struct ftrace_hash *hash; 289233dc9b12SSteven Rostedt int ret; 2893f45948e8SSteven Rostedt 2894936e074bSSteven Rostedt /* All global ops uses the global ops filters */ 2895936e074bSSteven Rostedt if (ops->flags & FTRACE_OPS_FL_GLOBAL) 2896936e074bSSteven Rostedt ops = &global_ops; 2897936e074bSSteven Rostedt 289841c52c0dSSteven Rostedt if (unlikely(ftrace_disabled)) 289933dc9b12SSteven Rostedt return -ENODEV; 290041c52c0dSSteven Rostedt 2901f45948e8SSteven Rostedt if (enable) 290233dc9b12SSteven Rostedt orig_hash = &ops->filter_hash; 2903f45948e8SSteven Rostedt else 290433dc9b12SSteven Rostedt orig_hash = &ops->notrace_hash; 290533dc9b12SSteven Rostedt 290633dc9b12SSteven Rostedt hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 290733dc9b12SSteven Rostedt if (!hash) 290833dc9b12SSteven Rostedt return -ENOMEM; 2909f45948e8SSteven Rostedt 291041c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 291141c52c0dSSteven Rostedt if (reset) 29121cf41dd7SSteven Rostedt ftrace_filter_reset(hash); 291341c52c0dSSteven Rostedt if (buf) 29141cf41dd7SSteven Rostedt ftrace_match_records(hash, buf, len); 291533dc9b12SSteven Rostedt 291633dc9b12SSteven Rostedt mutex_lock(&ftrace_lock); 291741fb61c2SSteven Rostedt ret = ftrace_hash_move(ops, enable, orig_hash, hash); 2918072126f4SSteven Rostedt if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED 2919072126f4SSteven Rostedt && ftrace_enabled) 2920072126f4SSteven Rostedt ftrace_run_update_code(FTRACE_ENABLE_CALLS); 2921072126f4SSteven Rostedt 292233dc9b12SSteven Rostedt mutex_unlock(&ftrace_lock); 292333dc9b12SSteven Rostedt 292441c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 292533dc9b12SSteven Rostedt 292633dc9b12SSteven Rostedt free_ftrace_hash(hash); 292733dc9b12SSteven Rostedt return ret; 292841c52c0dSSteven Rostedt } 292941c52c0dSSteven Rostedt 293077a2b37dSSteven Rostedt /** 293177a2b37dSSteven Rostedt * ftrace_set_filter - set a function to filter on in ftrace 2932936e074bSSteven Rostedt * @ops - the ops to set the filter with 293377a2b37dSSteven Rostedt * @buf - the string that holds the function filter text. 293477a2b37dSSteven Rostedt * @len - the length of the string. 293577a2b37dSSteven Rostedt * @reset - non zero to reset all filters before applying this filter. 293677a2b37dSSteven Rostedt * 293777a2b37dSSteven Rostedt * Filters denote which functions should be enabled when tracing is enabled. 293877a2b37dSSteven Rostedt * If @buf is NULL and reset is set, all functions will be enabled for tracing. 293977a2b37dSSteven Rostedt */ 2940936e074bSSteven Rostedt void ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, 2941936e074bSSteven Rostedt int len, int reset) 294277a2b37dSSteven Rostedt { 2943936e074bSSteven Rostedt ftrace_set_regex(ops, buf, len, reset, 1); 294441c52c0dSSteven Rostedt } 2945936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_filter); 29464eebcc81SSteven Rostedt 294741c52c0dSSteven Rostedt /** 294841c52c0dSSteven Rostedt * ftrace_set_notrace - set a function to not trace in ftrace 2949936e074bSSteven Rostedt * @ops - the ops to set the notrace filter with 295041c52c0dSSteven Rostedt * @buf - the string that holds the function notrace text. 295141c52c0dSSteven Rostedt * @len - the length of the string. 295241c52c0dSSteven Rostedt * @reset - non zero to reset all filters before applying this filter. 295341c52c0dSSteven Rostedt * 295441c52c0dSSteven Rostedt * Notrace Filters denote which functions should not be enabled when tracing 295541c52c0dSSteven Rostedt * is enabled. If @buf is NULL and reset is set, all functions will be enabled 295641c52c0dSSteven Rostedt * for tracing. 295741c52c0dSSteven Rostedt */ 2958936e074bSSteven Rostedt void ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, 2959936e074bSSteven Rostedt int len, int reset) 2960936e074bSSteven Rostedt { 2961936e074bSSteven Rostedt ftrace_set_regex(ops, buf, len, reset, 0); 2962936e074bSSteven Rostedt } 2963936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_notrace); 2964936e074bSSteven Rostedt /** 2965936e074bSSteven Rostedt * ftrace_set_filter - set a function to filter on in ftrace 2966936e074bSSteven Rostedt * @ops - the ops to set the filter with 2967936e074bSSteven Rostedt * @buf - the string that holds the function filter text. 2968936e074bSSteven Rostedt * @len - the length of the string. 2969936e074bSSteven Rostedt * @reset - non zero to reset all filters before applying this filter. 2970936e074bSSteven Rostedt * 2971936e074bSSteven Rostedt * Filters denote which functions should be enabled when tracing is enabled. 2972936e074bSSteven Rostedt * If @buf is NULL and reset is set, all functions will be enabled for tracing. 2973936e074bSSteven Rostedt */ 2974936e074bSSteven Rostedt void ftrace_set_global_filter(unsigned char *buf, int len, int reset) 2975936e074bSSteven Rostedt { 2976936e074bSSteven Rostedt ftrace_set_regex(&global_ops, buf, len, reset, 1); 2977936e074bSSteven Rostedt } 2978936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_filter); 2979936e074bSSteven Rostedt 2980936e074bSSteven Rostedt /** 2981936e074bSSteven Rostedt * ftrace_set_notrace - set a function to not trace in ftrace 2982936e074bSSteven Rostedt * @ops - the ops to set the notrace filter with 2983936e074bSSteven Rostedt * @buf - the string that holds the function notrace text. 2984936e074bSSteven Rostedt * @len - the length of the string. 2985936e074bSSteven Rostedt * @reset - non zero to reset all filters before applying this filter. 2986936e074bSSteven Rostedt * 2987936e074bSSteven Rostedt * Notrace Filters denote which functions should not be enabled when tracing 2988936e074bSSteven Rostedt * is enabled. If @buf is NULL and reset is set, all functions will be enabled 2989936e074bSSteven Rostedt * for tracing. 2990936e074bSSteven Rostedt */ 2991936e074bSSteven Rostedt void ftrace_set_global_notrace(unsigned char *buf, int len, int reset) 299241c52c0dSSteven Rostedt { 2993f45948e8SSteven Rostedt ftrace_set_regex(&global_ops, buf, len, reset, 0); 299477a2b37dSSteven Rostedt } 2995936e074bSSteven Rostedt EXPORT_SYMBOL_GPL(ftrace_set_global_notrace); 299677a2b37dSSteven Rostedt 29972af15d6aSSteven Rostedt /* 29982af15d6aSSteven Rostedt * command line interface to allow users to set filters on boot up. 29992af15d6aSSteven Rostedt */ 30002af15d6aSSteven Rostedt #define FTRACE_FILTER_SIZE COMMAND_LINE_SIZE 30012af15d6aSSteven Rostedt static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata; 30022af15d6aSSteven Rostedt static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata; 30032af15d6aSSteven Rostedt 30042af15d6aSSteven Rostedt static int __init set_ftrace_notrace(char *str) 30052af15d6aSSteven Rostedt { 30062af15d6aSSteven Rostedt strncpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE); 30072af15d6aSSteven Rostedt return 1; 30082af15d6aSSteven Rostedt } 30092af15d6aSSteven Rostedt __setup("ftrace_notrace=", set_ftrace_notrace); 30102af15d6aSSteven Rostedt 30112af15d6aSSteven Rostedt static int __init set_ftrace_filter(char *str) 30122af15d6aSSteven Rostedt { 30132af15d6aSSteven Rostedt strncpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE); 30142af15d6aSSteven Rostedt return 1; 30152af15d6aSSteven Rostedt } 30162af15d6aSSteven Rostedt __setup("ftrace_filter=", set_ftrace_filter); 30172af15d6aSSteven Rostedt 3018369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER 3019f6060f46SLai Jiangshan static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata; 3020801c29fdSSteven Rostedt static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); 3021801c29fdSSteven Rostedt 3022369bc18fSStefan Assmann static int __init set_graph_function(char *str) 3023369bc18fSStefan Assmann { 302406f43d66SFrederic Weisbecker strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE); 3025369bc18fSStefan Assmann return 1; 3026369bc18fSStefan Assmann } 3027369bc18fSStefan Assmann __setup("ftrace_graph_filter=", set_graph_function); 3028369bc18fSStefan Assmann 3029369bc18fSStefan Assmann static void __init set_ftrace_early_graph(char *buf) 3030369bc18fSStefan Assmann { 3031369bc18fSStefan Assmann int ret; 3032369bc18fSStefan Assmann char *func; 3033369bc18fSStefan Assmann 3034369bc18fSStefan Assmann while (buf) { 3035369bc18fSStefan Assmann func = strsep(&buf, ","); 3036369bc18fSStefan Assmann /* we allow only one expression at a time */ 3037369bc18fSStefan Assmann ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, 3038369bc18fSStefan Assmann func); 3039369bc18fSStefan Assmann if (ret) 3040369bc18fSStefan Assmann printk(KERN_DEBUG "ftrace: function %s not " 3041369bc18fSStefan Assmann "traceable\n", func); 3042369bc18fSStefan Assmann } 3043369bc18fSStefan Assmann } 3044369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 3045369bc18fSStefan Assmann 3046f45948e8SSteven Rostedt static void __init 3047f45948e8SSteven Rostedt set_ftrace_early_filter(struct ftrace_ops *ops, char *buf, int enable) 30482af15d6aSSteven Rostedt { 30492af15d6aSSteven Rostedt char *func; 30502af15d6aSSteven Rostedt 30512af15d6aSSteven Rostedt while (buf) { 30522af15d6aSSteven Rostedt func = strsep(&buf, ","); 3053f45948e8SSteven Rostedt ftrace_set_regex(ops, func, strlen(func), 0, enable); 30542af15d6aSSteven Rostedt } 30552af15d6aSSteven Rostedt } 30562af15d6aSSteven Rostedt 30572af15d6aSSteven Rostedt static void __init set_ftrace_early_filters(void) 30582af15d6aSSteven Rostedt { 30592af15d6aSSteven Rostedt if (ftrace_filter_buf[0]) 3060f45948e8SSteven Rostedt set_ftrace_early_filter(&global_ops, ftrace_filter_buf, 1); 30612af15d6aSSteven Rostedt if (ftrace_notrace_buf[0]) 3062f45948e8SSteven Rostedt set_ftrace_early_filter(&global_ops, ftrace_notrace_buf, 0); 3063369bc18fSStefan Assmann #ifdef CONFIG_FUNCTION_GRAPH_TRACER 3064369bc18fSStefan Assmann if (ftrace_graph_buf[0]) 3065369bc18fSStefan Assmann set_ftrace_early_graph(ftrace_graph_buf); 3066369bc18fSStefan Assmann #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 30672af15d6aSSteven Rostedt } 30682af15d6aSSteven Rostedt 3069e309b41dSIngo Molnar static int 30701cf41dd7SSteven Rostedt ftrace_regex_release(struct inode *inode, struct file *file) 30715072c59fSSteven Rostedt { 30725072c59fSSteven Rostedt struct seq_file *m = (struct seq_file *)file->private_data; 30735072c59fSSteven Rostedt struct ftrace_iterator *iter; 307433dc9b12SSteven Rostedt struct ftrace_hash **orig_hash; 3075689fd8b6S[email protected] struct trace_parser *parser; 3076ed926f9bSSteven Rostedt int filter_hash; 307733dc9b12SSteven Rostedt int ret; 30785072c59fSSteven Rostedt 307941c52c0dSSteven Rostedt mutex_lock(&ftrace_regex_lock); 30805072c59fSSteven Rostedt if (file->f_mode & FMODE_READ) { 30815072c59fSSteven Rostedt iter = m->private; 30825072c59fSSteven Rostedt 30835072c59fSSteven Rostedt seq_release(inode, file); 30845072c59fSSteven Rostedt } else 30855072c59fSSteven Rostedt iter = file->private_data; 30865072c59fSSteven Rostedt 3087689fd8b6S[email protected] parser = &iter->parser; 3088689fd8b6S[email protected] if (trace_parser_loaded(parser)) { 3089689fd8b6S[email protected] parser->buffer[parser->idx] = 0; 30901cf41dd7SSteven Rostedt ftrace_match_records(iter->hash, parser->buffer, parser->idx); 30915072c59fSSteven Rostedt } 30925072c59fSSteven Rostedt 3093058e297dSSteven Rostedt trace_parser_put(parser); 3094058e297dSSteven Rostedt 3095058e297dSSteven Rostedt if (file->f_mode & FMODE_WRITE) { 3096ed926f9bSSteven Rostedt filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); 3097ed926f9bSSteven Rostedt 3098ed926f9bSSteven Rostedt if (filter_hash) 309933dc9b12SSteven Rostedt orig_hash = &iter->ops->filter_hash; 3100ed926f9bSSteven Rostedt else 3101ed926f9bSSteven Rostedt orig_hash = &iter->ops->notrace_hash; 310233dc9b12SSteven Rostedt 3103e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 310441fb61c2SSteven Rostedt ret = ftrace_hash_move(iter->ops, filter_hash, 310541fb61c2SSteven Rostedt orig_hash, iter->hash); 310641fb61c2SSteven Rostedt if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED) 3107ed926f9bSSteven Rostedt && ftrace_enabled) 31085072c59fSSteven Rostedt ftrace_run_update_code(FTRACE_ENABLE_CALLS); 310941fb61c2SSteven Rostedt 3110e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 3111058e297dSSteven Rostedt } 311233dc9b12SSteven Rostedt free_ftrace_hash(iter->hash); 311333dc9b12SSteven Rostedt kfree(iter); 3114689fd8b6S[email protected] 311541c52c0dSSteven Rostedt mutex_unlock(&ftrace_regex_lock); 31165072c59fSSteven Rostedt return 0; 31175072c59fSSteven Rostedt } 31185072c59fSSteven Rostedt 31195e2336a0SSteven Rostedt static const struct file_operations ftrace_avail_fops = { 31205072c59fSSteven Rostedt .open = ftrace_avail_open, 31215072c59fSSteven Rostedt .read = seq_read, 31225072c59fSSteven Rostedt .llseek = seq_lseek, 31233be04b47SLi Zefan .release = seq_release_private, 31245072c59fSSteven Rostedt }; 31255072c59fSSteven Rostedt 3126647bcd03SSteven Rostedt static const struct file_operations ftrace_enabled_fops = { 3127647bcd03SSteven Rostedt .open = ftrace_enabled_open, 3128647bcd03SSteven Rostedt .read = seq_read, 3129647bcd03SSteven Rostedt .llseek = seq_lseek, 3130647bcd03SSteven Rostedt .release = seq_release_private, 3131647bcd03SSteven Rostedt }; 3132647bcd03SSteven Rostedt 31335e2336a0SSteven Rostedt static const struct file_operations ftrace_filter_fops = { 31345072c59fSSteven Rostedt .open = ftrace_filter_open, 3135850a80cfSLai Jiangshan .read = seq_read, 31365072c59fSSteven Rostedt .write = ftrace_filter_write, 313798c4fd04SSteven Rostedt .llseek = ftrace_regex_lseek, 31381cf41dd7SSteven Rostedt .release = ftrace_regex_release, 31395072c59fSSteven Rostedt }; 31405072c59fSSteven Rostedt 31415e2336a0SSteven Rostedt static const struct file_operations ftrace_notrace_fops = { 314241c52c0dSSteven Rostedt .open = ftrace_notrace_open, 3143850a80cfSLai Jiangshan .read = seq_read, 314441c52c0dSSteven Rostedt .write = ftrace_notrace_write, 314541c52c0dSSteven Rostedt .llseek = ftrace_regex_lseek, 31461cf41dd7SSteven Rostedt .release = ftrace_regex_release, 314741c52c0dSSteven Rostedt }; 314841c52c0dSSteven Rostedt 3149ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 3150ea4e2bc4SSteven Rostedt 3151ea4e2bc4SSteven Rostedt static DEFINE_MUTEX(graph_lock); 3152ea4e2bc4SSteven Rostedt 3153ea4e2bc4SSteven Rostedt int ftrace_graph_count; 3154c7c6b1feSLi Zefan int ftrace_graph_filter_enabled; 3155ea4e2bc4SSteven Rostedt unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; 3156ea4e2bc4SSteven Rostedt 3157ea4e2bc4SSteven Rostedt static void * 315885951842SLi Zefan __g_next(struct seq_file *m, loff_t *pos) 3159ea4e2bc4SSteven Rostedt { 316085951842SLi Zefan if (*pos >= ftrace_graph_count) 3161ea4e2bc4SSteven Rostedt return NULL; 3162a4ec5e0cSLi Zefan return &ftrace_graph_funcs[*pos]; 316385951842SLi Zefan } 3164ea4e2bc4SSteven Rostedt 316585951842SLi Zefan static void * 316685951842SLi Zefan g_next(struct seq_file *m, void *v, loff_t *pos) 316785951842SLi Zefan { 316885951842SLi Zefan (*pos)++; 316985951842SLi Zefan return __g_next(m, pos); 3170ea4e2bc4SSteven Rostedt } 3171ea4e2bc4SSteven Rostedt 3172ea4e2bc4SSteven Rostedt static void *g_start(struct seq_file *m, loff_t *pos) 3173ea4e2bc4SSteven Rostedt { 3174ea4e2bc4SSteven Rostedt mutex_lock(&graph_lock); 3175ea4e2bc4SSteven Rostedt 3176f9349a8fSFrederic Weisbecker /* Nothing, tell g_show to print all functions are enabled */ 3177c7c6b1feSLi Zefan if (!ftrace_graph_filter_enabled && !*pos) 3178f9349a8fSFrederic Weisbecker return (void *)1; 3179f9349a8fSFrederic Weisbecker 318085951842SLi Zefan return __g_next(m, pos); 3181ea4e2bc4SSteven Rostedt } 3182ea4e2bc4SSteven Rostedt 3183ea4e2bc4SSteven Rostedt static void g_stop(struct seq_file *m, void *p) 3184ea4e2bc4SSteven Rostedt { 3185ea4e2bc4SSteven Rostedt mutex_unlock(&graph_lock); 3186ea4e2bc4SSteven Rostedt } 3187ea4e2bc4SSteven Rostedt 3188ea4e2bc4SSteven Rostedt static int g_show(struct seq_file *m, void *v) 3189ea4e2bc4SSteven Rostedt { 3190ea4e2bc4SSteven Rostedt unsigned long *ptr = v; 3191ea4e2bc4SSteven Rostedt 3192ea4e2bc4SSteven Rostedt if (!ptr) 3193ea4e2bc4SSteven Rostedt return 0; 3194ea4e2bc4SSteven Rostedt 3195f9349a8fSFrederic Weisbecker if (ptr == (unsigned long *)1) { 3196f9349a8fSFrederic Weisbecker seq_printf(m, "#### all functions enabled ####\n"); 3197f9349a8fSFrederic Weisbecker return 0; 3198f9349a8fSFrederic Weisbecker } 3199f9349a8fSFrederic Weisbecker 3200b375a11aSSteven Rostedt seq_printf(m, "%ps\n", (void *)*ptr); 3201ea4e2bc4SSteven Rostedt 3202ea4e2bc4SSteven Rostedt return 0; 3203ea4e2bc4SSteven Rostedt } 3204ea4e2bc4SSteven Rostedt 320588e9d34cSJames Morris static const struct seq_operations ftrace_graph_seq_ops = { 3206ea4e2bc4SSteven Rostedt .start = g_start, 3207ea4e2bc4SSteven Rostedt .next = g_next, 3208ea4e2bc4SSteven Rostedt .stop = g_stop, 3209ea4e2bc4SSteven Rostedt .show = g_show, 3210ea4e2bc4SSteven Rostedt }; 3211ea4e2bc4SSteven Rostedt 3212ea4e2bc4SSteven Rostedt static int 3213ea4e2bc4SSteven Rostedt ftrace_graph_open(struct inode *inode, struct file *file) 3214ea4e2bc4SSteven Rostedt { 3215ea4e2bc4SSteven Rostedt int ret = 0; 3216ea4e2bc4SSteven Rostedt 3217ea4e2bc4SSteven Rostedt if (unlikely(ftrace_disabled)) 3218ea4e2bc4SSteven Rostedt return -ENODEV; 3219ea4e2bc4SSteven Rostedt 3220ea4e2bc4SSteven Rostedt mutex_lock(&graph_lock); 3221ea4e2bc4SSteven Rostedt if ((file->f_mode & FMODE_WRITE) && 32228650ae32SSteven Rostedt (file->f_flags & O_TRUNC)) { 3223c7c6b1feSLi Zefan ftrace_graph_filter_enabled = 0; 3224ea4e2bc4SSteven Rostedt ftrace_graph_count = 0; 3225ea4e2bc4SSteven Rostedt memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs)); 3226ea4e2bc4SSteven Rostedt } 3227ea4e2bc4SSteven Rostedt mutex_unlock(&graph_lock); 3228ea4e2bc4SSteven Rostedt 3229a4ec5e0cSLi Zefan if (file->f_mode & FMODE_READ) 3230a4ec5e0cSLi Zefan ret = seq_open(file, &ftrace_graph_seq_ops); 3231a4ec5e0cSLi Zefan 3232ea4e2bc4SSteven Rostedt return ret; 3233ea4e2bc4SSteven Rostedt } 3234ea4e2bc4SSteven Rostedt 3235ea4e2bc4SSteven Rostedt static int 323687827111SLi Zefan ftrace_graph_release(struct inode *inode, struct file *file) 323787827111SLi Zefan { 323887827111SLi Zefan if (file->f_mode & FMODE_READ) 323987827111SLi Zefan seq_release(inode, file); 324087827111SLi Zefan return 0; 324187827111SLi Zefan } 324287827111SLi Zefan 324387827111SLi Zefan static int 3244f9349a8fSFrederic Weisbecker ftrace_set_func(unsigned long *array, int *idx, char *buffer) 3245ea4e2bc4SSteven Rostedt { 3246ea4e2bc4SSteven Rostedt struct dyn_ftrace *rec; 3247ea4e2bc4SSteven Rostedt struct ftrace_page *pg; 3248f9349a8fSFrederic Weisbecker int search_len; 3249c7c6b1feSLi Zefan int fail = 1; 3250f9349a8fSFrederic Weisbecker int type, not; 3251f9349a8fSFrederic Weisbecker char *search; 3252f9349a8fSFrederic Weisbecker bool exists; 3253f9349a8fSFrederic Weisbecker int i; 3254ea4e2bc4SSteven Rostedt 3255f9349a8fSFrederic Weisbecker /* decode regex */ 32563f6fe06dSFrederic Weisbecker type = filter_parse_regex(buffer, strlen(buffer), &search, ¬); 3257c7c6b1feSLi Zefan if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) 3258c7c6b1feSLi Zefan return -EBUSY; 3259f9349a8fSFrederic Weisbecker 3260f9349a8fSFrederic Weisbecker search_len = strlen(search); 3261f9349a8fSFrederic Weisbecker 326252baf119SSteven Rostedt mutex_lock(&ftrace_lock); 326345a4a237SSteven Rostedt 326445a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) { 326545a4a237SSteven Rostedt mutex_unlock(&ftrace_lock); 326645a4a237SSteven Rostedt return -ENODEV; 326745a4a237SSteven Rostedt } 326845a4a237SSteven Rostedt 3269265c831cSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 3270ea4e2bc4SSteven Rostedt 327145a4a237SSteven Rostedt if (rec->flags & FTRACE_FL_FREE) 3272ea4e2bc4SSteven Rostedt continue; 3273ea4e2bc4SSteven Rostedt 3274b9df92d2SSteven Rostedt if (ftrace_match_record(rec, NULL, search, search_len, type)) { 3275c7c6b1feSLi Zefan /* if it is in the array */ 3276f9349a8fSFrederic Weisbecker exists = false; 3277c7c6b1feSLi Zefan for (i = 0; i < *idx; i++) { 3278f9349a8fSFrederic Weisbecker if (array[i] == rec->ip) { 3279f9349a8fSFrederic Weisbecker exists = true; 3280faec2ec5SLiming Wang break; 3281faec2ec5SLiming Wang } 3282c7c6b1feSLi Zefan } 3283c7c6b1feSLi Zefan 3284c7c6b1feSLi Zefan if (!not) { 3285c7c6b1feSLi Zefan fail = 0; 3286c7c6b1feSLi Zefan if (!exists) { 3287f9349a8fSFrederic Weisbecker array[(*idx)++] = rec->ip; 3288c7c6b1feSLi Zefan if (*idx >= FTRACE_GRAPH_MAX_FUNCS) 3289c7c6b1feSLi Zefan goto out; 3290c7c6b1feSLi Zefan } 3291c7c6b1feSLi Zefan } else { 3292c7c6b1feSLi Zefan if (exists) { 3293c7c6b1feSLi Zefan array[i] = array[--(*idx)]; 3294c7c6b1feSLi Zefan array[*idx] = 0; 3295c7c6b1feSLi Zefan fail = 0; 3296c7c6b1feSLi Zefan } 3297c7c6b1feSLi Zefan } 3298f9349a8fSFrederic Weisbecker } 3299265c831cSSteven Rostedt } while_for_each_ftrace_rec(); 3300c7c6b1feSLi Zefan out: 330152baf119SSteven Rostedt mutex_unlock(&ftrace_lock); 3302ea4e2bc4SSteven Rostedt 3303c7c6b1feSLi Zefan if (fail) 3304c7c6b1feSLi Zefan return -EINVAL; 3305c7c6b1feSLi Zefan 3306c7c6b1feSLi Zefan ftrace_graph_filter_enabled = 1; 3307c7c6b1feSLi Zefan return 0; 3308ea4e2bc4SSteven Rostedt } 3309ea4e2bc4SSteven Rostedt 3310ea4e2bc4SSteven Rostedt static ssize_t 3311ea4e2bc4SSteven Rostedt ftrace_graph_write(struct file *file, const char __user *ubuf, 3312ea4e2bc4SSteven Rostedt size_t cnt, loff_t *ppos) 3313ea4e2bc4SSteven Rostedt { 3314689fd8b6S[email protected] struct trace_parser parser; 33154ba7978eSLi Zefan ssize_t read, ret; 3316ea4e2bc4SSteven Rostedt 3317c7c6b1feSLi Zefan if (!cnt) 3318ea4e2bc4SSteven Rostedt return 0; 3319ea4e2bc4SSteven Rostedt 3320ea4e2bc4SSteven Rostedt mutex_lock(&graph_lock); 3321ea4e2bc4SSteven Rostedt 3322689fd8b6S[email protected] if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) { 3323689fd8b6S[email protected] ret = -ENOMEM; 33241eb90f13SLi Zefan goto out_unlock; 3325ea4e2bc4SSteven Rostedt } 3326ea4e2bc4SSteven Rostedt 3327689fd8b6S[email protected] read = trace_get_user(&parser, ubuf, cnt, ppos); 3328689fd8b6S[email protected] 33294ba7978eSLi Zefan if (read >= 0 && trace_parser_loaded((&parser))) { 3330689fd8b6S[email protected] parser.buffer[parser.idx] = 0; 3331ea4e2bc4SSteven Rostedt 3332f9349a8fSFrederic Weisbecker /* we allow only one expression at a time */ 3333a4ec5e0cSLi Zefan ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, 3334689fd8b6S[email protected] parser.buffer); 3335ea4e2bc4SSteven Rostedt if (ret) 33361eb90f13SLi Zefan goto out_free; 3337689fd8b6S[email protected] } 3338ea4e2bc4SSteven Rostedt 3339ea4e2bc4SSteven Rostedt ret = read; 33401eb90f13SLi Zefan 33411eb90f13SLi Zefan out_free: 3342689fd8b6S[email protected] trace_parser_put(&parser); 33431eb90f13SLi Zefan out_unlock: 3344ea4e2bc4SSteven Rostedt mutex_unlock(&graph_lock); 3345ea4e2bc4SSteven Rostedt 3346ea4e2bc4SSteven Rostedt return ret; 3347ea4e2bc4SSteven Rostedt } 3348ea4e2bc4SSteven Rostedt 3349ea4e2bc4SSteven Rostedt static const struct file_operations ftrace_graph_fops = { 3350ea4e2bc4SSteven Rostedt .open = ftrace_graph_open, 3351850a80cfSLai Jiangshan .read = seq_read, 3352ea4e2bc4SSteven Rostedt .write = ftrace_graph_write, 335387827111SLi Zefan .release = ftrace_graph_release, 33546038f373SArnd Bergmann .llseek = seq_lseek, 3355ea4e2bc4SSteven Rostedt }; 3356ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 3357ea4e2bc4SSteven Rostedt 3358df4fc315SSteven Rostedt static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer) 33595072c59fSSteven Rostedt { 33605072c59fSSteven Rostedt 33615452af66SFrederic Weisbecker trace_create_file("available_filter_functions", 0444, 33625072c59fSSteven Rostedt d_tracer, NULL, &ftrace_avail_fops); 33635072c59fSSteven Rostedt 3364647bcd03SSteven Rostedt trace_create_file("enabled_functions", 0444, 3365647bcd03SSteven Rostedt d_tracer, NULL, &ftrace_enabled_fops); 3366647bcd03SSteven Rostedt 33675452af66SFrederic Weisbecker trace_create_file("set_ftrace_filter", 0644, d_tracer, 33685072c59fSSteven Rostedt NULL, &ftrace_filter_fops); 336941c52c0dSSteven Rostedt 33705452af66SFrederic Weisbecker trace_create_file("set_ftrace_notrace", 0644, d_tracer, 337141c52c0dSSteven Rostedt NULL, &ftrace_notrace_fops); 3372ad90c0e3SSteven Rostedt 3373ea4e2bc4SSteven Rostedt #ifdef CONFIG_FUNCTION_GRAPH_TRACER 33745452af66SFrederic Weisbecker trace_create_file("set_graph_function", 0444, d_tracer, 3375ea4e2bc4SSteven Rostedt NULL, 3376ea4e2bc4SSteven Rostedt &ftrace_graph_fops); 3377ea4e2bc4SSteven Rostedt #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 3378ea4e2bc4SSteven Rostedt 33795072c59fSSteven Rostedt return 0; 33805072c59fSSteven Rostedt } 33815072c59fSSteven Rostedt 33825cb084bbSJiri Olsa static int ftrace_process_locs(struct module *mod, 338331e88909SSteven Rostedt unsigned long *start, 338468bf21aaSSteven Rostedt unsigned long *end) 338568bf21aaSSteven Rostedt { 338668bf21aaSSteven Rostedt unsigned long *p; 338768bf21aaSSteven Rostedt unsigned long addr; 33884376cac6SSteven Rostedt unsigned long flags = 0; /* Shut up gcc */ 338968bf21aaSSteven Rostedt 3390e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 339168bf21aaSSteven Rostedt p = start; 339268bf21aaSSteven Rostedt while (p < end) { 339368bf21aaSSteven Rostedt addr = ftrace_call_adjust(*p++); 339420e5227eSSteven Rostedt /* 339520e5227eSSteven Rostedt * Some architecture linkers will pad between 339620e5227eSSteven Rostedt * the different mcount_loc sections of different 339720e5227eSSteven Rostedt * object files to satisfy alignments. 339820e5227eSSteven Rostedt * Skip any NULL pointers. 339920e5227eSSteven Rostedt */ 340020e5227eSSteven Rostedt if (!addr) 340120e5227eSSteven Rostedt continue; 340268bf21aaSSteven Rostedt ftrace_record_ip(addr); 340368bf21aaSSteven Rostedt } 340468bf21aaSSteven Rostedt 3405a4f18ed1SSteven Rostedt /* 34064376cac6SSteven Rostedt * We only need to disable interrupts on start up 34074376cac6SSteven Rostedt * because we are modifying code that an interrupt 34084376cac6SSteven Rostedt * may execute, and the modification is not atomic. 34094376cac6SSteven Rostedt * But for modules, nothing runs the code we modify 34104376cac6SSteven Rostedt * until we are finished with it, and there's no 34114376cac6SSteven Rostedt * reason to cause large interrupt latencies while we do it. 3412a4f18ed1SSteven Rostedt */ 34134376cac6SSteven Rostedt if (!mod) 3414a4f18ed1SSteven Rostedt local_irq_save(flags); 341531e88909SSteven Rostedt ftrace_update_code(mod); 34164376cac6SSteven Rostedt if (!mod) 3417a4f18ed1SSteven Rostedt local_irq_restore(flags); 3418e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 341968bf21aaSSteven Rostedt 342068bf21aaSSteven Rostedt return 0; 342168bf21aaSSteven Rostedt } 342268bf21aaSSteven Rostedt 342393eb677dSSteven Rostedt #ifdef CONFIG_MODULES 3424e7247a15S[email protected] void ftrace_release_mod(struct module *mod) 342593eb677dSSteven Rostedt { 342693eb677dSSteven Rostedt struct dyn_ftrace *rec; 342793eb677dSSteven Rostedt struct ftrace_page *pg; 342893eb677dSSteven Rostedt 342993eb677dSSteven Rostedt mutex_lock(&ftrace_lock); 343045a4a237SSteven Rostedt 343145a4a237SSteven Rostedt if (ftrace_disabled) 343245a4a237SSteven Rostedt goto out_unlock; 343345a4a237SSteven Rostedt 343493eb677dSSteven Rostedt do_for_each_ftrace_rec(pg, rec) { 3435e7247a15S[email protected] if (within_module_core(rec->ip, mod)) { 343693eb677dSSteven Rostedt /* 343793eb677dSSteven Rostedt * rec->ip is changed in ftrace_free_rec() 343893eb677dSSteven Rostedt * It should not between s and e if record was freed. 343993eb677dSSteven Rostedt */ 344093eb677dSSteven Rostedt FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE); 344193eb677dSSteven Rostedt ftrace_free_rec(rec); 344293eb677dSSteven Rostedt } 344393eb677dSSteven Rostedt } while_for_each_ftrace_rec(); 344445a4a237SSteven Rostedt out_unlock: 344593eb677dSSteven Rostedt mutex_unlock(&ftrace_lock); 344693eb677dSSteven Rostedt } 344793eb677dSSteven Rostedt 344893eb677dSSteven Rostedt static void ftrace_init_module(struct module *mod, 344931e88909SSteven Rostedt unsigned long *start, unsigned long *end) 345090d595feSSteven Rostedt { 345100fd61aeSSteven Rostedt if (ftrace_disabled || start == end) 3452fed1939cSSteven Rostedt return; 34535cb084bbSJiri Olsa ftrace_process_locs(mod, start, end); 345490d595feSSteven Rostedt } 345590d595feSSteven Rostedt 345693eb677dSSteven Rostedt static int ftrace_module_notify(struct notifier_block *self, 345793eb677dSSteven Rostedt unsigned long val, void *data) 345893eb677dSSteven Rostedt { 345993eb677dSSteven Rostedt struct module *mod = data; 346093eb677dSSteven Rostedt 346193eb677dSSteven Rostedt switch (val) { 346293eb677dSSteven Rostedt case MODULE_STATE_COMING: 346393eb677dSSteven Rostedt ftrace_init_module(mod, mod->ftrace_callsites, 346493eb677dSSteven Rostedt mod->ftrace_callsites + 346593eb677dSSteven Rostedt mod->num_ftrace_callsites); 346693eb677dSSteven Rostedt break; 346793eb677dSSteven Rostedt case MODULE_STATE_GOING: 3468e7247a15S[email protected] ftrace_release_mod(mod); 346993eb677dSSteven Rostedt break; 347093eb677dSSteven Rostedt } 347193eb677dSSteven Rostedt 347293eb677dSSteven Rostedt return 0; 347393eb677dSSteven Rostedt } 347493eb677dSSteven Rostedt #else 347593eb677dSSteven Rostedt static int ftrace_module_notify(struct notifier_block *self, 347693eb677dSSteven Rostedt unsigned long val, void *data) 347793eb677dSSteven Rostedt { 347893eb677dSSteven Rostedt return 0; 347993eb677dSSteven Rostedt } 348093eb677dSSteven Rostedt #endif /* CONFIG_MODULES */ 348193eb677dSSteven Rostedt 348293eb677dSSteven Rostedt struct notifier_block ftrace_module_nb = { 348393eb677dSSteven Rostedt .notifier_call = ftrace_module_notify, 348493eb677dSSteven Rostedt .priority = 0, 348593eb677dSSteven Rostedt }; 348693eb677dSSteven Rostedt 348768bf21aaSSteven Rostedt extern unsigned long __start_mcount_loc[]; 348868bf21aaSSteven Rostedt extern unsigned long __stop_mcount_loc[]; 348968bf21aaSSteven Rostedt 349068bf21aaSSteven Rostedt void __init ftrace_init(void) 349168bf21aaSSteven Rostedt { 349268bf21aaSSteven Rostedt unsigned long count, addr, flags; 349368bf21aaSSteven Rostedt int ret; 349468bf21aaSSteven Rostedt 349568bf21aaSSteven Rostedt /* Keep the ftrace pointer to the stub */ 349668bf21aaSSteven Rostedt addr = (unsigned long)ftrace_stub; 349768bf21aaSSteven Rostedt 349868bf21aaSSteven Rostedt local_irq_save(flags); 349968bf21aaSSteven Rostedt ftrace_dyn_arch_init(&addr); 350068bf21aaSSteven Rostedt local_irq_restore(flags); 350168bf21aaSSteven Rostedt 350268bf21aaSSteven Rostedt /* ftrace_dyn_arch_init places the return code in addr */ 350368bf21aaSSteven Rostedt if (addr) 350468bf21aaSSteven Rostedt goto failed; 350568bf21aaSSteven Rostedt 350668bf21aaSSteven Rostedt count = __stop_mcount_loc - __start_mcount_loc; 350768bf21aaSSteven Rostedt 350868bf21aaSSteven Rostedt ret = ftrace_dyn_table_alloc(count); 350968bf21aaSSteven Rostedt if (ret) 351068bf21aaSSteven Rostedt goto failed; 351168bf21aaSSteven Rostedt 351268bf21aaSSteven Rostedt last_ftrace_enabled = ftrace_enabled = 1; 351368bf21aaSSteven Rostedt 35145cb084bbSJiri Olsa ret = ftrace_process_locs(NULL, 351531e88909SSteven Rostedt __start_mcount_loc, 351668bf21aaSSteven Rostedt __stop_mcount_loc); 351768bf21aaSSteven Rostedt 351893eb677dSSteven Rostedt ret = register_module_notifier(&ftrace_module_nb); 351924ed0c4bSMing Lei if (ret) 352093eb677dSSteven Rostedt pr_warning("Failed to register trace ftrace module notifier\n"); 352193eb677dSSteven Rostedt 35222af15d6aSSteven Rostedt set_ftrace_early_filters(); 35232af15d6aSSteven Rostedt 352468bf21aaSSteven Rostedt return; 352568bf21aaSSteven Rostedt failed: 352668bf21aaSSteven Rostedt ftrace_disabled = 1; 352768bf21aaSSteven Rostedt } 352868bf21aaSSteven Rostedt 35293d083395SSteven Rostedt #else 35300b6e4d56SFrederic Weisbecker 35312b499381SSteven Rostedt static struct ftrace_ops global_ops = { 3532bd69c30bSSteven Rostedt .func = ftrace_stub, 3533bd69c30bSSteven Rostedt }; 3534bd69c30bSSteven Rostedt 35350b6e4d56SFrederic Weisbecker static int __init ftrace_nodyn_init(void) 35360b6e4d56SFrederic Weisbecker { 35370b6e4d56SFrederic Weisbecker ftrace_enabled = 1; 35380b6e4d56SFrederic Weisbecker return 0; 35390b6e4d56SFrederic Weisbecker } 35400b6e4d56SFrederic Weisbecker device_initcall(ftrace_nodyn_init); 35410b6e4d56SFrederic Weisbecker 3542df4fc315SSteven Rostedt static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; } 3543df4fc315SSteven Rostedt static inline void ftrace_startup_enable(int command) { } 35445a45cfe1SSteven Rostedt /* Keep as macros so we do not need to define the commands */ 35453b6cfdb1SSteven Rostedt # define ftrace_startup(ops, command) \ 35463b6cfdb1SSteven Rostedt ({ \ 35473b6cfdb1SSteven Rostedt (ops)->flags |= FTRACE_OPS_FL_ENABLED; \ 35483b6cfdb1SSteven Rostedt 0; \ 35493b6cfdb1SSteven Rostedt }) 3550bd69c30bSSteven Rostedt # define ftrace_shutdown(ops, command) do { } while (0) 3551b0fc494fSSteven Rostedt # define ftrace_startup_sysctl() do { } while (0) 3552b0fc494fSSteven Rostedt # define ftrace_shutdown_sysctl() do { } while (0) 3553b848914cSSteven Rostedt 3554b848914cSSteven Rostedt static inline int 3555b848914cSSteven Rostedt ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) 3556b848914cSSteven Rostedt { 3557b848914cSSteven Rostedt return 1; 3558b848914cSSteven Rostedt } 3559b848914cSSteven Rostedt 35603d083395SSteven Rostedt #endif /* CONFIG_DYNAMIC_FTRACE */ 35613d083395SSteven Rostedt 3562b848914cSSteven Rostedt static void 3563b848914cSSteven Rostedt ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip) 3564b848914cSSteven Rostedt { 3565cdbe61bfSSteven Rostedt struct ftrace_ops *op; 3566b848914cSSteven Rostedt 3567b1cff0adSSteven Rostedt if (unlikely(trace_recursion_test(TRACE_INTERNAL_BIT))) 3568b1cff0adSSteven Rostedt return; 3569b1cff0adSSteven Rostedt 3570b1cff0adSSteven Rostedt trace_recursion_set(TRACE_INTERNAL_BIT); 3571cdbe61bfSSteven Rostedt /* 3572cdbe61bfSSteven Rostedt * Some of the ops may be dynamically allocated, 3573cdbe61bfSSteven Rostedt * they must be freed after a synchronize_sched(). 3574cdbe61bfSSteven Rostedt */ 3575cdbe61bfSSteven Rostedt preempt_disable_notrace(); 3576cdbe61bfSSteven Rostedt op = rcu_dereference_raw(ftrace_ops_list); 3577b848914cSSteven Rostedt while (op != &ftrace_list_end) { 3578b848914cSSteven Rostedt if (ftrace_ops_test(op, ip)) 3579b848914cSSteven Rostedt op->func(ip, parent_ip); 3580b848914cSSteven Rostedt op = rcu_dereference_raw(op->next); 3581b848914cSSteven Rostedt }; 3582cdbe61bfSSteven Rostedt preempt_enable_notrace(); 3583b1cff0adSSteven Rostedt trace_recursion_clear(TRACE_INTERNAL_BIT); 3584b848914cSSteven Rostedt } 3585b848914cSSteven Rostedt 3586e32d8956SSteven Rostedt static void clear_ftrace_swapper(void) 3587e32d8956SSteven Rostedt { 3588e32d8956SSteven Rostedt struct task_struct *p; 3589e32d8956SSteven Rostedt int cpu; 3590e32d8956SSteven Rostedt 3591e32d8956SSteven Rostedt get_online_cpus(); 3592e32d8956SSteven Rostedt for_each_online_cpu(cpu) { 3593e32d8956SSteven Rostedt p = idle_task(cpu); 3594e32d8956SSteven Rostedt clear_tsk_trace_trace(p); 3595e32d8956SSteven Rostedt } 3596e32d8956SSteven Rostedt put_online_cpus(); 3597e32d8956SSteven Rostedt } 3598e32d8956SSteven Rostedt 3599e32d8956SSteven Rostedt static void set_ftrace_swapper(void) 3600e32d8956SSteven Rostedt { 3601e32d8956SSteven Rostedt struct task_struct *p; 3602e32d8956SSteven Rostedt int cpu; 3603e32d8956SSteven Rostedt 3604e32d8956SSteven Rostedt get_online_cpus(); 3605e32d8956SSteven Rostedt for_each_online_cpu(cpu) { 3606e32d8956SSteven Rostedt p = idle_task(cpu); 3607e32d8956SSteven Rostedt set_tsk_trace_trace(p); 3608e32d8956SSteven Rostedt } 3609e32d8956SSteven Rostedt put_online_cpus(); 3610e32d8956SSteven Rostedt } 3611e32d8956SSteven Rostedt 3612e32d8956SSteven Rostedt static void clear_ftrace_pid(struct pid *pid) 3613978f3a45SSteven Rostedt { 3614978f3a45SSteven Rostedt struct task_struct *p; 3615978f3a45SSteven Rostedt 3616229c4ef8SOleg Nesterov rcu_read_lock(); 3617e32d8956SSteven Rostedt do_each_pid_task(pid, PIDTYPE_PID, p) { 3618978f3a45SSteven Rostedt clear_tsk_trace_trace(p); 3619e32d8956SSteven Rostedt } while_each_pid_task(pid, PIDTYPE_PID, p); 3620229c4ef8SOleg Nesterov rcu_read_unlock(); 3621229c4ef8SOleg Nesterov 3622e32d8956SSteven Rostedt put_pid(pid); 3623978f3a45SSteven Rostedt } 3624978f3a45SSteven Rostedt 3625e32d8956SSteven Rostedt static void set_ftrace_pid(struct pid *pid) 3626978f3a45SSteven Rostedt { 3627978f3a45SSteven Rostedt struct task_struct *p; 3628978f3a45SSteven Rostedt 3629229c4ef8SOleg Nesterov rcu_read_lock(); 3630978f3a45SSteven Rostedt do_each_pid_task(pid, PIDTYPE_PID, p) { 3631978f3a45SSteven Rostedt set_tsk_trace_trace(p); 3632978f3a45SSteven Rostedt } while_each_pid_task(pid, PIDTYPE_PID, p); 3633229c4ef8SOleg Nesterov rcu_read_unlock(); 3634978f3a45SSteven Rostedt } 3635978f3a45SSteven Rostedt 3636756d17eeS[email protected] static void clear_ftrace_pid_task(struct pid *pid) 3637e32d8956SSteven Rostedt { 3638756d17eeS[email protected] if (pid == ftrace_swapper_pid) 3639e32d8956SSteven Rostedt clear_ftrace_swapper(); 3640e32d8956SSteven Rostedt else 3641756d17eeS[email protected] clear_ftrace_pid(pid); 3642e32d8956SSteven Rostedt } 3643e32d8956SSteven Rostedt 3644e32d8956SSteven Rostedt static void set_ftrace_pid_task(struct pid *pid) 3645e32d8956SSteven Rostedt { 3646e32d8956SSteven Rostedt if (pid == ftrace_swapper_pid) 3647e32d8956SSteven Rostedt set_ftrace_swapper(); 3648e32d8956SSteven Rostedt else 3649e32d8956SSteven Rostedt set_ftrace_pid(pid); 3650e32d8956SSteven Rostedt } 3651e32d8956SSteven Rostedt 3652756d17eeS[email protected] static int ftrace_pid_add(int p) 3653756d17eeS[email protected] { 3654756d17eeS[email protected] struct pid *pid; 3655756d17eeS[email protected] struct ftrace_pid *fpid; 3656756d17eeS[email protected] int ret = -EINVAL; 3657756d17eeS[email protected] 3658756d17eeS[email protected] mutex_lock(&ftrace_lock); 3659756d17eeS[email protected] 3660756d17eeS[email protected] if (!p) 3661756d17eeS[email protected] pid = ftrace_swapper_pid; 3662756d17eeS[email protected] else 3663756d17eeS[email protected] pid = find_get_pid(p); 3664756d17eeS[email protected] 3665756d17eeS[email protected] if (!pid) 3666756d17eeS[email protected] goto out; 3667756d17eeS[email protected] 3668756d17eeS[email protected] ret = 0; 3669756d17eeS[email protected] 3670756d17eeS[email protected] list_for_each_entry(fpid, &ftrace_pids, list) 3671756d17eeS[email protected] if (fpid->pid == pid) 3672756d17eeS[email protected] goto out_put; 3673756d17eeS[email protected] 3674756d17eeS[email protected] ret = -ENOMEM; 3675756d17eeS[email protected] 3676756d17eeS[email protected] fpid = kmalloc(sizeof(*fpid), GFP_KERNEL); 3677756d17eeS[email protected] if (!fpid) 3678756d17eeS[email protected] goto out_put; 3679756d17eeS[email protected] 3680756d17eeS[email protected] list_add(&fpid->list, &ftrace_pids); 3681756d17eeS[email protected] fpid->pid = pid; 3682756d17eeS[email protected] 3683756d17eeS[email protected] set_ftrace_pid_task(pid); 3684756d17eeS[email protected] 3685756d17eeS[email protected] ftrace_update_pid_func(); 3686756d17eeS[email protected] ftrace_startup_enable(0); 3687756d17eeS[email protected] 3688756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3689756d17eeS[email protected] return 0; 3690756d17eeS[email protected] 3691756d17eeS[email protected] out_put: 3692756d17eeS[email protected] if (pid != ftrace_swapper_pid) 3693756d17eeS[email protected] put_pid(pid); 3694756d17eeS[email protected] 3695756d17eeS[email protected] out: 3696756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3697756d17eeS[email protected] return ret; 3698756d17eeS[email protected] } 3699756d17eeS[email protected] 3700756d17eeS[email protected] static void ftrace_pid_reset(void) 3701756d17eeS[email protected] { 3702756d17eeS[email protected] struct ftrace_pid *fpid, *safe; 3703756d17eeS[email protected] 3704756d17eeS[email protected] mutex_lock(&ftrace_lock); 3705756d17eeS[email protected] list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) { 3706756d17eeS[email protected] struct pid *pid = fpid->pid; 3707756d17eeS[email protected] 3708756d17eeS[email protected] clear_ftrace_pid_task(pid); 3709756d17eeS[email protected] 3710756d17eeS[email protected] list_del(&fpid->list); 3711756d17eeS[email protected] kfree(fpid); 3712756d17eeS[email protected] } 3713756d17eeS[email protected] 3714756d17eeS[email protected] ftrace_update_pid_func(); 3715756d17eeS[email protected] ftrace_startup_enable(0); 3716756d17eeS[email protected] 3717756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3718756d17eeS[email protected] } 3719756d17eeS[email protected] 3720756d17eeS[email protected] static void *fpid_start(struct seq_file *m, loff_t *pos) 3721756d17eeS[email protected] { 3722756d17eeS[email protected] mutex_lock(&ftrace_lock); 3723756d17eeS[email protected] 3724756d17eeS[email protected] if (list_empty(&ftrace_pids) && (!*pos)) 3725756d17eeS[email protected] return (void *) 1; 3726756d17eeS[email protected] 3727756d17eeS[email protected] return seq_list_start(&ftrace_pids, *pos); 3728756d17eeS[email protected] } 3729756d17eeS[email protected] 3730756d17eeS[email protected] static void *fpid_next(struct seq_file *m, void *v, loff_t *pos) 3731756d17eeS[email protected] { 3732756d17eeS[email protected] if (v == (void *)1) 3733756d17eeS[email protected] return NULL; 3734756d17eeS[email protected] 3735756d17eeS[email protected] return seq_list_next(v, &ftrace_pids, pos); 3736756d17eeS[email protected] } 3737756d17eeS[email protected] 3738756d17eeS[email protected] static void fpid_stop(struct seq_file *m, void *p) 3739756d17eeS[email protected] { 3740756d17eeS[email protected] mutex_unlock(&ftrace_lock); 3741756d17eeS[email protected] } 3742756d17eeS[email protected] 3743756d17eeS[email protected] static int fpid_show(struct seq_file *m, void *v) 3744756d17eeS[email protected] { 3745756d17eeS[email protected] const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list); 3746756d17eeS[email protected] 3747756d17eeS[email protected] if (v == (void *)1) { 3748756d17eeS[email protected] seq_printf(m, "no pid\n"); 3749756d17eeS[email protected] return 0; 3750756d17eeS[email protected] } 3751756d17eeS[email protected] 3752756d17eeS[email protected] if (fpid->pid == ftrace_swapper_pid) 3753756d17eeS[email protected] seq_printf(m, "swapper tasks\n"); 3754756d17eeS[email protected] else 3755756d17eeS[email protected] seq_printf(m, "%u\n", pid_vnr(fpid->pid)); 3756756d17eeS[email protected] 3757756d17eeS[email protected] return 0; 3758756d17eeS[email protected] } 3759756d17eeS[email protected] 3760756d17eeS[email protected] static const struct seq_operations ftrace_pid_sops = { 3761756d17eeS[email protected] .start = fpid_start, 3762756d17eeS[email protected] .next = fpid_next, 3763756d17eeS[email protected] .stop = fpid_stop, 3764756d17eeS[email protected] .show = fpid_show, 3765756d17eeS[email protected] }; 3766756d17eeS[email protected] 3767756d17eeS[email protected] static int 3768756d17eeS[email protected] ftrace_pid_open(struct inode *inode, struct file *file) 3769756d17eeS[email protected] { 3770756d17eeS[email protected] int ret = 0; 3771756d17eeS[email protected] 3772756d17eeS[email protected] if ((file->f_mode & FMODE_WRITE) && 3773756d17eeS[email protected] (file->f_flags & O_TRUNC)) 3774756d17eeS[email protected] ftrace_pid_reset(); 3775756d17eeS[email protected] 3776756d17eeS[email protected] if (file->f_mode & FMODE_READ) 3777756d17eeS[email protected] ret = seq_open(file, &ftrace_pid_sops); 3778756d17eeS[email protected] 3779756d17eeS[email protected] return ret; 3780756d17eeS[email protected] } 3781756d17eeS[email protected] 3782df4fc315SSteven Rostedt static ssize_t 3783df4fc315SSteven Rostedt ftrace_pid_write(struct file *filp, const char __user *ubuf, 3784df4fc315SSteven Rostedt size_t cnt, loff_t *ppos) 3785df4fc315SSteven Rostedt { 3786457dc928SIngo Molnar char buf[64], *tmp; 3787df4fc315SSteven Rostedt long val; 3788df4fc315SSteven Rostedt int ret; 3789df4fc315SSteven Rostedt 3790df4fc315SSteven Rostedt if (cnt >= sizeof(buf)) 3791df4fc315SSteven Rostedt return -EINVAL; 3792df4fc315SSteven Rostedt 3793df4fc315SSteven Rostedt if (copy_from_user(&buf, ubuf, cnt)) 3794df4fc315SSteven Rostedt return -EFAULT; 3795df4fc315SSteven Rostedt 3796df4fc315SSteven Rostedt buf[cnt] = 0; 3797df4fc315SSteven Rostedt 3798756d17eeS[email protected] /* 3799756d17eeS[email protected] * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid" 3800756d17eeS[email protected] * to clean the filter quietly. 3801756d17eeS[email protected] */ 3802457dc928SIngo Molnar tmp = strstrip(buf); 3803457dc928SIngo Molnar if (strlen(tmp) == 0) 3804756d17eeS[email protected] return 1; 3805756d17eeS[email protected] 3806457dc928SIngo Molnar ret = strict_strtol(tmp, 10, &val); 3807df4fc315SSteven Rostedt if (ret < 0) 3808df4fc315SSteven Rostedt return ret; 3809df4fc315SSteven Rostedt 3810756d17eeS[email protected] ret = ftrace_pid_add(val); 3811978f3a45SSteven Rostedt 3812756d17eeS[email protected] return ret ? ret : cnt; 3813e32d8956SSteven Rostedt } 3814978f3a45SSteven Rostedt 3815756d17eeS[email protected] static int 3816756d17eeS[email protected] ftrace_pid_release(struct inode *inode, struct file *file) 3817756d17eeS[email protected] { 3818756d17eeS[email protected] if (file->f_mode & FMODE_READ) 3819756d17eeS[email protected] seq_release(inode, file); 3820978f3a45SSteven Rostedt 3821756d17eeS[email protected] return 0; 3822df4fc315SSteven Rostedt } 3823df4fc315SSteven Rostedt 38245e2336a0SSteven Rostedt static const struct file_operations ftrace_pid_fops = { 3825756d17eeS[email protected] .open = ftrace_pid_open, 3826df4fc315SSteven Rostedt .write = ftrace_pid_write, 3827756d17eeS[email protected] .read = seq_read, 3828756d17eeS[email protected] .llseek = seq_lseek, 3829756d17eeS[email protected] .release = ftrace_pid_release, 3830df4fc315SSteven Rostedt }; 3831df4fc315SSteven Rostedt 3832df4fc315SSteven Rostedt static __init int ftrace_init_debugfs(void) 3833df4fc315SSteven Rostedt { 3834df4fc315SSteven Rostedt struct dentry *d_tracer; 3835df4fc315SSteven Rostedt 3836df4fc315SSteven Rostedt d_tracer = tracing_init_dentry(); 3837df4fc315SSteven Rostedt if (!d_tracer) 3838df4fc315SSteven Rostedt return 0; 3839df4fc315SSteven Rostedt 3840df4fc315SSteven Rostedt ftrace_init_dyn_debugfs(d_tracer); 3841df4fc315SSteven Rostedt 38425452af66SFrederic Weisbecker trace_create_file("set_ftrace_pid", 0644, d_tracer, 3843df4fc315SSteven Rostedt NULL, &ftrace_pid_fops); 3844493762fcSSteven Rostedt 3845493762fcSSteven Rostedt ftrace_profile_debugfs(d_tracer); 3846493762fcSSteven Rostedt 3847df4fc315SSteven Rostedt return 0; 3848df4fc315SSteven Rostedt } 3849df4fc315SSteven Rostedt fs_initcall(ftrace_init_debugfs); 3850df4fc315SSteven Rostedt 38513d083395SSteven Rostedt /** 385281adbdc0SSteven Rostedt * ftrace_kill - kill ftrace 3853a2bb6a3dSSteven Rostedt * 3854a2bb6a3dSSteven Rostedt * This function should be used by panic code. It stops ftrace 3855a2bb6a3dSSteven Rostedt * but in a not so nice way. If you need to simply kill ftrace 3856a2bb6a3dSSteven Rostedt * from a non-atomic section, use ftrace_kill. 3857a2bb6a3dSSteven Rostedt */ 385881adbdc0SSteven Rostedt void ftrace_kill(void) 3859a2bb6a3dSSteven Rostedt { 3860a2bb6a3dSSteven Rostedt ftrace_disabled = 1; 3861a2bb6a3dSSteven Rostedt ftrace_enabled = 0; 3862a2bb6a3dSSteven Rostedt clear_ftrace_function(); 3863a2bb6a3dSSteven Rostedt } 3864a2bb6a3dSSteven Rostedt 3865a2bb6a3dSSteven Rostedt /** 3866*e0a413f6SSteven Rostedt * Test if ftrace is dead or not. 3867*e0a413f6SSteven Rostedt */ 3868*e0a413f6SSteven Rostedt int ftrace_is_dead(void) 3869*e0a413f6SSteven Rostedt { 3870*e0a413f6SSteven Rostedt return ftrace_disabled; 3871*e0a413f6SSteven Rostedt } 3872*e0a413f6SSteven Rostedt 3873*e0a413f6SSteven Rostedt /** 38743d083395SSteven Rostedt * register_ftrace_function - register a function for profiling 38753d083395SSteven Rostedt * @ops - ops structure that holds the function for profiling. 38763d083395SSteven Rostedt * 38773d083395SSteven Rostedt * Register a function to be called by all functions in the 38783d083395SSteven Rostedt * kernel. 38793d083395SSteven Rostedt * 38803d083395SSteven Rostedt * Note: @ops->func and all the functions it calls must be labeled 38813d083395SSteven Rostedt * with "notrace", otherwise it will go into a 38823d083395SSteven Rostedt * recursive loop. 38833d083395SSteven Rostedt */ 38843d083395SSteven Rostedt int register_ftrace_function(struct ftrace_ops *ops) 38853d083395SSteven Rostedt { 388645a4a237SSteven Rostedt int ret = -1; 38874eebcc81SSteven Rostedt 3888e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 3889e7d3737eSFrederic Weisbecker 389045a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 389145a4a237SSteven Rostedt goto out_unlock; 389245a4a237SSteven Rostedt 3893b0fc494fSSteven Rostedt ret = __register_ftrace_function(ops); 3894b848914cSSteven Rostedt if (!ret) 3895a1cd6173SSteven Rostedt ret = ftrace_startup(ops, 0); 3896b848914cSSteven Rostedt 3897b0fc494fSSteven Rostedt 389845a4a237SSteven Rostedt out_unlock: 3899e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 3900b0fc494fSSteven Rostedt return ret; 39013d083395SSteven Rostedt } 3902cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(register_ftrace_function); 39033d083395SSteven Rostedt 39043d083395SSteven Rostedt /** 390532632920SUwe Kleine-Koenig * unregister_ftrace_function - unregister a function for profiling. 39063d083395SSteven Rostedt * @ops - ops structure that holds the function to unregister 39073d083395SSteven Rostedt * 39083d083395SSteven Rostedt * Unregister a function that was added to be called by ftrace profiling. 39093d083395SSteven Rostedt */ 39103d083395SSteven Rostedt int unregister_ftrace_function(struct ftrace_ops *ops) 39113d083395SSteven Rostedt { 39123d083395SSteven Rostedt int ret; 39133d083395SSteven Rostedt 3914e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 39153d083395SSteven Rostedt ret = __unregister_ftrace_function(ops); 3916b848914cSSteven Rostedt if (!ret) 3917b848914cSSteven Rostedt ftrace_shutdown(ops, 0); 3918e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 3919b0fc494fSSteven Rostedt 3920b0fc494fSSteven Rostedt return ret; 3921b0fc494fSSteven Rostedt } 3922cdbe61bfSSteven Rostedt EXPORT_SYMBOL_GPL(unregister_ftrace_function); 3923b0fc494fSSteven Rostedt 3924e309b41dSIngo Molnar int 3925b0fc494fSSteven Rostedt ftrace_enable_sysctl(struct ctl_table *table, int write, 39268d65af78SAlexey Dobriyan void __user *buffer, size_t *lenp, 3927b0fc494fSSteven Rostedt loff_t *ppos) 3928b0fc494fSSteven Rostedt { 392945a4a237SSteven Rostedt int ret = -ENODEV; 39304eebcc81SSteven Rostedt 3931e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 3932b0fc494fSSteven Rostedt 393345a4a237SSteven Rostedt if (unlikely(ftrace_disabled)) 393445a4a237SSteven Rostedt goto out; 393545a4a237SSteven Rostedt 39368d65af78SAlexey Dobriyan ret = proc_dointvec(table, write, buffer, lenp, ppos); 3937b0fc494fSSteven Rostedt 3938a32c7765SLi Zefan if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) 3939b0fc494fSSteven Rostedt goto out; 3940b0fc494fSSteven Rostedt 3941a32c7765SLi Zefan last_ftrace_enabled = !!ftrace_enabled; 3942b0fc494fSSteven Rostedt 3943b0fc494fSSteven Rostedt if (ftrace_enabled) { 3944b0fc494fSSteven Rostedt 3945b0fc494fSSteven Rostedt ftrace_startup_sysctl(); 3946b0fc494fSSteven Rostedt 3947b0fc494fSSteven Rostedt /* we are starting ftrace again */ 3948b848914cSSteven Rostedt if (ftrace_ops_list != &ftrace_list_end) { 3949b848914cSSteven Rostedt if (ftrace_ops_list->next == &ftrace_list_end) 3950b848914cSSteven Rostedt ftrace_trace_function = ftrace_ops_list->func; 3951b0fc494fSSteven Rostedt else 3952b848914cSSteven Rostedt ftrace_trace_function = ftrace_ops_list_func; 3953b0fc494fSSteven Rostedt } 3954b0fc494fSSteven Rostedt 3955b0fc494fSSteven Rostedt } else { 3956b0fc494fSSteven Rostedt /* stopping ftrace calls (just send to ftrace_stub) */ 3957b0fc494fSSteven Rostedt ftrace_trace_function = ftrace_stub; 3958b0fc494fSSteven Rostedt 3959b0fc494fSSteven Rostedt ftrace_shutdown_sysctl(); 3960b0fc494fSSteven Rostedt } 3961b0fc494fSSteven Rostedt 3962b0fc494fSSteven Rostedt out: 3963e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 39643d083395SSteven Rostedt return ret; 396516444a8aSArnaldo Carvalho de Melo } 3966f17845e5SIngo Molnar 3967fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER 3968e7d3737eSFrederic Weisbecker 3969597af815SSteven Rostedt static int ftrace_graph_active; 39704a2b8ddaSFrederic Weisbecker static struct notifier_block ftrace_suspend_notifier; 3971f201ae23SFrederic Weisbecker 3972e49dc19cSSteven Rostedt int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) 3973e49dc19cSSteven Rostedt { 3974e49dc19cSSteven Rostedt return 0; 3975e49dc19cSSteven Rostedt } 3976e49dc19cSSteven Rostedt 3977287b6e68SFrederic Weisbecker /* The callbacks that hook a function */ 3978287b6e68SFrederic Weisbecker trace_func_graph_ret_t ftrace_graph_return = 3979287b6e68SFrederic Weisbecker (trace_func_graph_ret_t)ftrace_stub; 3980e49dc19cSSteven Rostedt trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub; 3981f201ae23SFrederic Weisbecker 3982f201ae23SFrederic Weisbecker /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */ 3983f201ae23SFrederic Weisbecker static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) 3984f201ae23SFrederic Weisbecker { 3985f201ae23SFrederic Weisbecker int i; 3986f201ae23SFrederic Weisbecker int ret = 0; 3987f201ae23SFrederic Weisbecker unsigned long flags; 3988f201ae23SFrederic Weisbecker int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE; 3989f201ae23SFrederic Weisbecker struct task_struct *g, *t; 3990f201ae23SFrederic Weisbecker 3991f201ae23SFrederic Weisbecker for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) { 3992f201ae23SFrederic Weisbecker ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH 3993f201ae23SFrederic Weisbecker * sizeof(struct ftrace_ret_stack), 3994f201ae23SFrederic Weisbecker GFP_KERNEL); 3995f201ae23SFrederic Weisbecker if (!ret_stack_list[i]) { 3996f201ae23SFrederic Weisbecker start = 0; 3997f201ae23SFrederic Weisbecker end = i; 3998f201ae23SFrederic Weisbecker ret = -ENOMEM; 3999f201ae23SFrederic Weisbecker goto free; 4000f201ae23SFrederic Weisbecker } 4001f201ae23SFrederic Weisbecker } 4002f201ae23SFrederic Weisbecker 4003f201ae23SFrederic Weisbecker read_lock_irqsave(&tasklist_lock, flags); 4004f201ae23SFrederic Weisbecker do_each_thread(g, t) { 4005f201ae23SFrederic Weisbecker if (start == end) { 4006f201ae23SFrederic Weisbecker ret = -EAGAIN; 4007f201ae23SFrederic Weisbecker goto unlock; 4008f201ae23SFrederic Weisbecker } 4009f201ae23SFrederic Weisbecker 4010f201ae23SFrederic Weisbecker if (t->ret_stack == NULL) { 4011380c4b14SFrederic Weisbecker atomic_set(&t->tracing_graph_pause, 0); 4012f201ae23SFrederic Weisbecker atomic_set(&t->trace_overrun, 0); 401326c01624SSteven Rostedt t->curr_ret_stack = -1; 401426c01624SSteven Rostedt /* Make sure the tasks see the -1 first: */ 401526c01624SSteven Rostedt smp_wmb(); 401626c01624SSteven Rostedt t->ret_stack = ret_stack_list[start++]; 4017f201ae23SFrederic Weisbecker } 4018f201ae23SFrederic Weisbecker } while_each_thread(g, t); 4019f201ae23SFrederic Weisbecker 4020f201ae23SFrederic Weisbecker unlock: 4021f201ae23SFrederic Weisbecker read_unlock_irqrestore(&tasklist_lock, flags); 4022f201ae23SFrederic Weisbecker free: 4023f201ae23SFrederic Weisbecker for (i = start; i < end; i++) 4024f201ae23SFrederic Weisbecker kfree(ret_stack_list[i]); 4025f201ae23SFrederic Weisbecker return ret; 4026f201ae23SFrederic Weisbecker } 4027f201ae23SFrederic Weisbecker 40288aef2d28SSteven Rostedt static void 402938516ab5SSteven Rostedt ftrace_graph_probe_sched_switch(void *ignore, 403038516ab5SSteven Rostedt struct task_struct *prev, struct task_struct *next) 40318aef2d28SSteven Rostedt { 40328aef2d28SSteven Rostedt unsigned long long timestamp; 40338aef2d28SSteven Rostedt int index; 40348aef2d28SSteven Rostedt 4035be6f164aSSteven Rostedt /* 4036be6f164aSSteven Rostedt * Does the user want to count the time a function was asleep. 4037be6f164aSSteven Rostedt * If so, do not update the time stamps. 4038be6f164aSSteven Rostedt */ 4039be6f164aSSteven Rostedt if (trace_flags & TRACE_ITER_SLEEP_TIME) 4040be6f164aSSteven Rostedt return; 4041be6f164aSSteven Rostedt 40428aef2d28SSteven Rostedt timestamp = trace_clock_local(); 40438aef2d28SSteven Rostedt 40448aef2d28SSteven Rostedt prev->ftrace_timestamp = timestamp; 40458aef2d28SSteven Rostedt 40468aef2d28SSteven Rostedt /* only process tasks that we timestamped */ 40478aef2d28SSteven Rostedt if (!next->ftrace_timestamp) 40488aef2d28SSteven Rostedt return; 40498aef2d28SSteven Rostedt 40508aef2d28SSteven Rostedt /* 40518aef2d28SSteven Rostedt * Update all the counters in next to make up for the 40528aef2d28SSteven Rostedt * time next was sleeping. 40538aef2d28SSteven Rostedt */ 40548aef2d28SSteven Rostedt timestamp -= next->ftrace_timestamp; 40558aef2d28SSteven Rostedt 40568aef2d28SSteven Rostedt for (index = next->curr_ret_stack; index >= 0; index--) 40578aef2d28SSteven Rostedt next->ret_stack[index].calltime += timestamp; 40588aef2d28SSteven Rostedt } 40598aef2d28SSteven Rostedt 4060f201ae23SFrederic Weisbecker /* Allocate a return stack for each task */ 4061fb52607aSFrederic Weisbecker static int start_graph_tracing(void) 4062f201ae23SFrederic Weisbecker { 4063f201ae23SFrederic Weisbecker struct ftrace_ret_stack **ret_stack_list; 40645b058bcdSFrederic Weisbecker int ret, cpu; 4065f201ae23SFrederic Weisbecker 4066f201ae23SFrederic Weisbecker ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE * 4067f201ae23SFrederic Weisbecker sizeof(struct ftrace_ret_stack *), 4068f201ae23SFrederic Weisbecker GFP_KERNEL); 4069f201ae23SFrederic Weisbecker 4070f201ae23SFrederic Weisbecker if (!ret_stack_list) 4071f201ae23SFrederic Weisbecker return -ENOMEM; 4072f201ae23SFrederic Weisbecker 40735b058bcdSFrederic Weisbecker /* The cpu_boot init_task->ret_stack will never be freed */ 4074179c498aSSteven Rostedt for_each_online_cpu(cpu) { 4075179c498aSSteven Rostedt if (!idle_task(cpu)->ret_stack) 4076868baf07SSteven Rostedt ftrace_graph_init_idle_task(idle_task(cpu), cpu); 4077179c498aSSteven Rostedt } 40785b058bcdSFrederic Weisbecker 4079f201ae23SFrederic Weisbecker do { 4080f201ae23SFrederic Weisbecker ret = alloc_retstack_tasklist(ret_stack_list); 4081f201ae23SFrederic Weisbecker } while (ret == -EAGAIN); 4082f201ae23SFrederic Weisbecker 40838aef2d28SSteven Rostedt if (!ret) { 408438516ab5SSteven Rostedt ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); 40858aef2d28SSteven Rostedt if (ret) 40868aef2d28SSteven Rostedt pr_info("ftrace_graph: Couldn't activate tracepoint" 40878aef2d28SSteven Rostedt " probe to kernel_sched_switch\n"); 40888aef2d28SSteven Rostedt } 40898aef2d28SSteven Rostedt 4090f201ae23SFrederic Weisbecker kfree(ret_stack_list); 4091f201ae23SFrederic Weisbecker return ret; 4092f201ae23SFrederic Weisbecker } 4093f201ae23SFrederic Weisbecker 40944a2b8ddaSFrederic Weisbecker /* 40954a2b8ddaSFrederic Weisbecker * Hibernation protection. 40964a2b8ddaSFrederic Weisbecker * The state of the current task is too much unstable during 40974a2b8ddaSFrederic Weisbecker * suspend/restore to disk. We want to protect against that. 40984a2b8ddaSFrederic Weisbecker */ 40994a2b8ddaSFrederic Weisbecker static int 41004a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state, 41014a2b8ddaSFrederic Weisbecker void *unused) 41024a2b8ddaSFrederic Weisbecker { 41034a2b8ddaSFrederic Weisbecker switch (state) { 41044a2b8ddaSFrederic Weisbecker case PM_HIBERNATION_PREPARE: 41054a2b8ddaSFrederic Weisbecker pause_graph_tracing(); 41064a2b8ddaSFrederic Weisbecker break; 41074a2b8ddaSFrederic Weisbecker 41084a2b8ddaSFrederic Weisbecker case PM_POST_HIBERNATION: 41094a2b8ddaSFrederic Weisbecker unpause_graph_tracing(); 41104a2b8ddaSFrederic Weisbecker break; 41114a2b8ddaSFrederic Weisbecker } 41124a2b8ddaSFrederic Weisbecker return NOTIFY_DONE; 41134a2b8ddaSFrederic Weisbecker } 41144a2b8ddaSFrederic Weisbecker 4115287b6e68SFrederic Weisbecker int register_ftrace_graph(trace_func_graph_ret_t retfunc, 4116287b6e68SFrederic Weisbecker trace_func_graph_ent_t entryfunc) 411715e6cb36SFrederic Weisbecker { 4118e7d3737eSFrederic Weisbecker int ret = 0; 4119e7d3737eSFrederic Weisbecker 4120e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 4121e7d3737eSFrederic Weisbecker 412205ce5818SSteven Rostedt /* we currently allow only one tracer registered at a time */ 4123597af815SSteven Rostedt if (ftrace_graph_active) { 412405ce5818SSteven Rostedt ret = -EBUSY; 412505ce5818SSteven Rostedt goto out; 412605ce5818SSteven Rostedt } 412705ce5818SSteven Rostedt 41284a2b8ddaSFrederic Weisbecker ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call; 41294a2b8ddaSFrederic Weisbecker register_pm_notifier(&ftrace_suspend_notifier); 41304a2b8ddaSFrederic Weisbecker 4131597af815SSteven Rostedt ftrace_graph_active++; 4132fb52607aSFrederic Weisbecker ret = start_graph_tracing(); 4133f201ae23SFrederic Weisbecker if (ret) { 4134597af815SSteven Rostedt ftrace_graph_active--; 4135f201ae23SFrederic Weisbecker goto out; 4136f201ae23SFrederic Weisbecker } 4137e53a6319SSteven Rostedt 4138287b6e68SFrederic Weisbecker ftrace_graph_return = retfunc; 4139287b6e68SFrederic Weisbecker ftrace_graph_entry = entryfunc; 4140e53a6319SSteven Rostedt 4141a1cd6173SSteven Rostedt ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET); 4142e7d3737eSFrederic Weisbecker 4143e7d3737eSFrederic Weisbecker out: 4144e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 4145e7d3737eSFrederic Weisbecker return ret; 414615e6cb36SFrederic Weisbecker } 414715e6cb36SFrederic Weisbecker 4148fb52607aSFrederic Weisbecker void unregister_ftrace_graph(void) 414915e6cb36SFrederic Weisbecker { 4150e6ea44e9SSteven Rostedt mutex_lock(&ftrace_lock); 4151e7d3737eSFrederic Weisbecker 4152597af815SSteven Rostedt if (unlikely(!ftrace_graph_active)) 41532aad1b76SSteven Rostedt goto out; 41542aad1b76SSteven Rostedt 4155597af815SSteven Rostedt ftrace_graph_active--; 4156287b6e68SFrederic Weisbecker ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; 4157e49dc19cSSteven Rostedt ftrace_graph_entry = ftrace_graph_entry_stub; 4158bd69c30bSSteven Rostedt ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET); 41594a2b8ddaSFrederic Weisbecker unregister_pm_notifier(&ftrace_suspend_notifier); 416038516ab5SSteven Rostedt unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); 4161e7d3737eSFrederic Weisbecker 41622aad1b76SSteven Rostedt out: 4163e6ea44e9SSteven Rostedt mutex_unlock(&ftrace_lock); 416415e6cb36SFrederic Weisbecker } 4165f201ae23SFrederic Weisbecker 4166868baf07SSteven Rostedt static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); 4167868baf07SSteven Rostedt 4168868baf07SSteven Rostedt static void 4169868baf07SSteven Rostedt graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) 4170868baf07SSteven Rostedt { 4171868baf07SSteven Rostedt atomic_set(&t->tracing_graph_pause, 0); 4172868baf07SSteven Rostedt atomic_set(&t->trace_overrun, 0); 4173868baf07SSteven Rostedt t->ftrace_timestamp = 0; 417425985edcSLucas De Marchi /* make curr_ret_stack visible before we add the ret_stack */ 4175868baf07SSteven Rostedt smp_wmb(); 4176868baf07SSteven Rostedt t->ret_stack = ret_stack; 4177868baf07SSteven Rostedt } 4178868baf07SSteven Rostedt 4179868baf07SSteven Rostedt /* 4180868baf07SSteven Rostedt * Allocate a return stack for the idle task. May be the first 4181868baf07SSteven Rostedt * time through, or it may be done by CPU hotplug online. 4182868baf07SSteven Rostedt */ 4183868baf07SSteven Rostedt void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) 4184868baf07SSteven Rostedt { 4185868baf07SSteven Rostedt t->curr_ret_stack = -1; 4186868baf07SSteven Rostedt /* 4187868baf07SSteven Rostedt * The idle task has no parent, it either has its own 4188868baf07SSteven Rostedt * stack or no stack at all. 4189868baf07SSteven Rostedt */ 4190868baf07SSteven Rostedt if (t->ret_stack) 4191868baf07SSteven Rostedt WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu)); 4192868baf07SSteven Rostedt 4193868baf07SSteven Rostedt if (ftrace_graph_active) { 4194868baf07SSteven Rostedt struct ftrace_ret_stack *ret_stack; 4195868baf07SSteven Rostedt 4196868baf07SSteven Rostedt ret_stack = per_cpu(idle_ret_stack, cpu); 4197868baf07SSteven Rostedt if (!ret_stack) { 4198868baf07SSteven Rostedt ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH 4199868baf07SSteven Rostedt * sizeof(struct ftrace_ret_stack), 4200868baf07SSteven Rostedt GFP_KERNEL); 4201868baf07SSteven Rostedt if (!ret_stack) 4202868baf07SSteven Rostedt return; 4203868baf07SSteven Rostedt per_cpu(idle_ret_stack, cpu) = ret_stack; 4204868baf07SSteven Rostedt } 4205868baf07SSteven Rostedt graph_init_task(t, ret_stack); 4206868baf07SSteven Rostedt } 4207868baf07SSteven Rostedt } 4208868baf07SSteven Rostedt 4209f201ae23SFrederic Weisbecker /* Allocate a return stack for newly created task */ 4210fb52607aSFrederic Weisbecker void ftrace_graph_init_task(struct task_struct *t) 4211f201ae23SFrederic Weisbecker { 421284047e36SSteven Rostedt /* Make sure we do not use the parent ret_stack */ 421384047e36SSteven Rostedt t->ret_stack = NULL; 4214ea14eb71SSteven Rostedt t->curr_ret_stack = -1; 421584047e36SSteven Rostedt 4216597af815SSteven Rostedt if (ftrace_graph_active) { 421782310a32SSteven Rostedt struct ftrace_ret_stack *ret_stack; 421882310a32SSteven Rostedt 421982310a32SSteven Rostedt ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH 4220f201ae23SFrederic Weisbecker * sizeof(struct ftrace_ret_stack), 4221f201ae23SFrederic Weisbecker GFP_KERNEL); 422282310a32SSteven Rostedt if (!ret_stack) 4223f201ae23SFrederic Weisbecker return; 4224868baf07SSteven Rostedt graph_init_task(t, ret_stack); 422584047e36SSteven Rostedt } 4226f201ae23SFrederic Weisbecker } 4227f201ae23SFrederic Weisbecker 4228fb52607aSFrederic Weisbecker void ftrace_graph_exit_task(struct task_struct *t) 4229f201ae23SFrederic Weisbecker { 4230eae849caSFrederic Weisbecker struct ftrace_ret_stack *ret_stack = t->ret_stack; 4231eae849caSFrederic Weisbecker 4232f201ae23SFrederic Weisbecker t->ret_stack = NULL; 4233eae849caSFrederic Weisbecker /* NULL must become visible to IRQs before we free it: */ 4234eae849caSFrederic Weisbecker barrier(); 4235eae849caSFrederic Weisbecker 4236eae849caSFrederic Weisbecker kfree(ret_stack); 4237f201ae23SFrederic Weisbecker } 423814a866c5SSteven Rostedt 423914a866c5SSteven Rostedt void ftrace_graph_stop(void) 424014a866c5SSteven Rostedt { 424114a866c5SSteven Rostedt ftrace_stop(); 424214a866c5SSteven Rostedt } 424315e6cb36SFrederic Weisbecker #endif 4244