1e5a81b62SSteven Rostedt /* 2e5a81b62SSteven Rostedt * Copyright (C) 2008 Steven Rostedt <[email protected]> 3e5a81b62SSteven Rostedt * 4e5a81b62SSteven Rostedt */ 5e5a81b62SSteven Rostedt #include <linux/stacktrace.h> 6e5a81b62SSteven Rostedt #include <linux/kallsyms.h> 7e5a81b62SSteven Rostedt #include <linux/seq_file.h> 8e5a81b62SSteven Rostedt #include <linux/spinlock.h> 9e5a81b62SSteven Rostedt #include <linux/uaccess.h> 10e5a81b62SSteven Rostedt #include <linux/debugfs.h> 11e5a81b62SSteven Rostedt #include <linux/ftrace.h> 12e5a81b62SSteven Rostedt #include <linux/module.h> 13f38f1d2aSSteven Rostedt #include <linux/sysctl.h> 14e5a81b62SSteven Rostedt #include <linux/init.h> 15e5a81b62SSteven Rostedt #include <linux/fs.h> 16762e1207SSteven Rostedt 17762e1207SSteven Rostedt #include <asm/setup.h> 18762e1207SSteven Rostedt 19e5a81b62SSteven Rostedt #include "trace.h" 20e5a81b62SSteven Rostedt 21e5a81b62SSteven Rostedt #define STACK_TRACE_ENTRIES 500 22e5a81b62SSteven Rostedt 231b6cced6SSteven Rostedt static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = 241b6cced6SSteven Rostedt { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; 251b6cced6SSteven Rostedt static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; 261b6cced6SSteven Rostedt 27e5a81b62SSteven Rostedt static struct stack_trace max_stack_trace = { 28e5a81b62SSteven Rostedt .max_entries = STACK_TRACE_ENTRIES, 29e5a81b62SSteven Rostedt .entries = stack_dump_trace, 30e5a81b62SSteven Rostedt }; 31e5a81b62SSteven Rostedt 32e5a81b62SSteven Rostedt static unsigned long max_stack_size; 33445c8951SThomas Gleixner static arch_spinlock_t max_stack_lock = 34edc35bd7SThomas Gleixner (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; 35e5a81b62SSteven Rostedt 36e5a81b62SSteven Rostedt static int stack_trace_disabled __read_mostly; 37e5a81b62SSteven Rostedt static DEFINE_PER_CPU(int, trace_active); 38f38f1d2aSSteven Rostedt static DEFINE_MUTEX(stack_sysctl_mutex); 39f38f1d2aSSteven Rostedt 40f38f1d2aSSteven Rostedt int stack_tracer_enabled; 41f38f1d2aSSteven Rostedt static int last_stack_tracer_enabled; 42e5a81b62SSteven Rostedt 43e5a81b62SSteven Rostedt static inline void check_stack(void) 44e5a81b62SSteven Rostedt { 451b6cced6SSteven Rostedt unsigned long this_size, flags; 461b6cced6SSteven Rostedt unsigned long *p, *top, *start; 471b6cced6SSteven Rostedt int i; 48e5a81b62SSteven Rostedt 49e5a81b62SSteven Rostedt this_size = ((unsigned long)&this_size) & (THREAD_SIZE-1); 50e5a81b62SSteven Rostedt this_size = THREAD_SIZE - this_size; 51e5a81b62SSteven Rostedt 52e5a81b62SSteven Rostedt if (this_size <= max_stack_size) 53e5a81b62SSteven Rostedt return; 54e5a81b62SSteven Rostedt 5581520a1bSSteven Rostedt /* we do not handle interrupt stacks yet */ 5681520a1bSSteven Rostedt if (!object_is_on_stack(&this_size)) 5781520a1bSSteven Rostedt return; 5881520a1bSSteven Rostedt 59a5e25883SSteven Rostedt local_irq_save(flags); 600199c4e6SThomas Gleixner arch_spin_lock(&max_stack_lock); 61e5a81b62SSteven Rostedt 62e5a81b62SSteven Rostedt /* a race could have already updated it */ 63e5a81b62SSteven Rostedt if (this_size <= max_stack_size) 64e5a81b62SSteven Rostedt goto out; 65e5a81b62SSteven Rostedt 66e5a81b62SSteven Rostedt max_stack_size = this_size; 67e5a81b62SSteven Rostedt 68e5a81b62SSteven Rostedt max_stack_trace.nr_entries = 0; 691b6cced6SSteven Rostedt max_stack_trace.skip = 3; 70e5a81b62SSteven Rostedt 71e5a81b62SSteven Rostedt save_stack_trace(&max_stack_trace); 72e5a81b62SSteven Rostedt 731b6cced6SSteven Rostedt /* 741b6cced6SSteven Rostedt * Now find where in the stack these are. 751b6cced6SSteven Rostedt */ 761b6cced6SSteven Rostedt i = 0; 771b6cced6SSteven Rostedt start = &this_size; 781b6cced6SSteven Rostedt top = (unsigned long *) 791b6cced6SSteven Rostedt (((unsigned long)start & ~(THREAD_SIZE-1)) + THREAD_SIZE); 801b6cced6SSteven Rostedt 811b6cced6SSteven Rostedt /* 821b6cced6SSteven Rostedt * Loop through all the entries. One of the entries may 831b6cced6SSteven Rostedt * for some reason be missed on the stack, so we may 841b6cced6SSteven Rostedt * have to account for them. If they are all there, this 851b6cced6SSteven Rostedt * loop will only happen once. This code only takes place 861b6cced6SSteven Rostedt * on a new max, so it is far from a fast path. 871b6cced6SSteven Rostedt */ 881b6cced6SSteven Rostedt while (i < max_stack_trace.nr_entries) { 890a37119dSSteven Rostedt int found = 0; 901b6cced6SSteven Rostedt 911b6cced6SSteven Rostedt stack_dump_index[i] = this_size; 921b6cced6SSteven Rostedt p = start; 931b6cced6SSteven Rostedt 941b6cced6SSteven Rostedt for (; p < top && i < max_stack_trace.nr_entries; p++) { 951b6cced6SSteven Rostedt if (*p == stack_dump_trace[i]) { 961b6cced6SSteven Rostedt this_size = stack_dump_index[i++] = 971b6cced6SSteven Rostedt (top - p) * sizeof(unsigned long); 980a37119dSSteven Rostedt found = 1; 991b6cced6SSteven Rostedt /* Start the search from here */ 1001b6cced6SSteven Rostedt start = p + 1; 1011b6cced6SSteven Rostedt } 1021b6cced6SSteven Rostedt } 1031b6cced6SSteven Rostedt 1040a37119dSSteven Rostedt if (!found) 1051b6cced6SSteven Rostedt i++; 1061b6cced6SSteven Rostedt } 1071b6cced6SSteven Rostedt 108e5a81b62SSteven Rostedt out: 1090199c4e6SThomas Gleixner arch_spin_unlock(&max_stack_lock); 110a5e25883SSteven Rostedt local_irq_restore(flags); 111e5a81b62SSteven Rostedt } 112e5a81b62SSteven Rostedt 113e5a81b62SSteven Rostedt static void 114*a1e2e31dSSteven Rostedt stack_trace_call(unsigned long ip, unsigned long parent_ip, 115*a1e2e31dSSteven Rostedt struct ftrace_ops *op, struct pt_regs *pt_regs) 116e5a81b62SSteven Rostedt { 1175168ae50SSteven Rostedt int cpu; 118e5a81b62SSteven Rostedt 119e5a81b62SSteven Rostedt if (unlikely(!ftrace_enabled || stack_trace_disabled)) 120e5a81b62SSteven Rostedt return; 121e5a81b62SSteven Rostedt 1225168ae50SSteven Rostedt preempt_disable_notrace(); 123e5a81b62SSteven Rostedt 124e5a81b62SSteven Rostedt cpu = raw_smp_processor_id(); 125e5a81b62SSteven Rostedt /* no atomic needed, we only modify this variable by this cpu */ 126e5a81b62SSteven Rostedt if (per_cpu(trace_active, cpu)++ != 0) 127e5a81b62SSteven Rostedt goto out; 128e5a81b62SSteven Rostedt 129e5a81b62SSteven Rostedt check_stack(); 130e5a81b62SSteven Rostedt 131e5a81b62SSteven Rostedt out: 132e5a81b62SSteven Rostedt per_cpu(trace_active, cpu)--; 133e5a81b62SSteven Rostedt /* prevent recursion in schedule */ 1345168ae50SSteven Rostedt preempt_enable_notrace(); 135e5a81b62SSteven Rostedt } 136e5a81b62SSteven Rostedt 137e5a81b62SSteven Rostedt static struct ftrace_ops trace_ops __read_mostly = 138e5a81b62SSteven Rostedt { 139e5a81b62SSteven Rostedt .func = stack_trace_call, 140e5a81b62SSteven Rostedt }; 141e5a81b62SSteven Rostedt 142e5a81b62SSteven Rostedt static ssize_t 143e5a81b62SSteven Rostedt stack_max_size_read(struct file *filp, char __user *ubuf, 144e5a81b62SSteven Rostedt size_t count, loff_t *ppos) 145e5a81b62SSteven Rostedt { 146e5a81b62SSteven Rostedt unsigned long *ptr = filp->private_data; 147e5a81b62SSteven Rostedt char buf[64]; 148e5a81b62SSteven Rostedt int r; 149e5a81b62SSteven Rostedt 150e5a81b62SSteven Rostedt r = snprintf(buf, sizeof(buf), "%ld\n", *ptr); 151e5a81b62SSteven Rostedt if (r > sizeof(buf)) 152e5a81b62SSteven Rostedt r = sizeof(buf); 153e5a81b62SSteven Rostedt return simple_read_from_buffer(ubuf, count, ppos, buf, r); 154e5a81b62SSteven Rostedt } 155e5a81b62SSteven Rostedt 156e5a81b62SSteven Rostedt static ssize_t 157e5a81b62SSteven Rostedt stack_max_size_write(struct file *filp, const char __user *ubuf, 158e5a81b62SSteven Rostedt size_t count, loff_t *ppos) 159e5a81b62SSteven Rostedt { 160e5a81b62SSteven Rostedt long *ptr = filp->private_data; 161e5a81b62SSteven Rostedt unsigned long val, flags; 162e5a81b62SSteven Rostedt int ret; 1634f48f8b7SLai Jiangshan int cpu; 164e5a81b62SSteven Rostedt 16522fe9b54SPeter Huewe ret = kstrtoul_from_user(ubuf, count, 10, &val); 16622fe9b54SPeter Huewe if (ret) 167e5a81b62SSteven Rostedt return ret; 168e5a81b62SSteven Rostedt 169a5e25883SSteven Rostedt local_irq_save(flags); 1704f48f8b7SLai Jiangshan 1714f48f8b7SLai Jiangshan /* 1724f48f8b7SLai Jiangshan * In case we trace inside arch_spin_lock() or after (NMI), 1734f48f8b7SLai Jiangshan * we will cause circular lock, so we also need to increase 1744f48f8b7SLai Jiangshan * the percpu trace_active here. 1754f48f8b7SLai Jiangshan */ 1764f48f8b7SLai Jiangshan cpu = smp_processor_id(); 1774f48f8b7SLai Jiangshan per_cpu(trace_active, cpu)++; 1784f48f8b7SLai Jiangshan 1790199c4e6SThomas Gleixner arch_spin_lock(&max_stack_lock); 180e5a81b62SSteven Rostedt *ptr = val; 1810199c4e6SThomas Gleixner arch_spin_unlock(&max_stack_lock); 1824f48f8b7SLai Jiangshan 1834f48f8b7SLai Jiangshan per_cpu(trace_active, cpu)--; 184a5e25883SSteven Rostedt local_irq_restore(flags); 185e5a81b62SSteven Rostedt 186e5a81b62SSteven Rostedt return count; 187e5a81b62SSteven Rostedt } 188e5a81b62SSteven Rostedt 189f38f1d2aSSteven Rostedt static const struct file_operations stack_max_size_fops = { 190e5a81b62SSteven Rostedt .open = tracing_open_generic, 191e5a81b62SSteven Rostedt .read = stack_max_size_read, 192e5a81b62SSteven Rostedt .write = stack_max_size_write, 1936038f373SArnd Bergmann .llseek = default_llseek, 194e5a81b62SSteven Rostedt }; 195e5a81b62SSteven Rostedt 196e5a81b62SSteven Rostedt static void * 1972fc5f0cfSLi Zefan __next(struct seq_file *m, loff_t *pos) 198e5a81b62SSteven Rostedt { 1992fc5f0cfSLi Zefan long n = *pos - 1; 200e5a81b62SSteven Rostedt 2012fc5f0cfSLi Zefan if (n >= max_stack_trace.nr_entries || stack_dump_trace[n] == ULONG_MAX) 202e5a81b62SSteven Rostedt return NULL; 203e5a81b62SSteven Rostedt 2042fc5f0cfSLi Zefan m->private = (void *)n; 2051b6cced6SSteven Rostedt return &m->private; 206e5a81b62SSteven Rostedt } 207e5a81b62SSteven Rostedt 2082fc5f0cfSLi Zefan static void * 2092fc5f0cfSLi Zefan t_next(struct seq_file *m, void *v, loff_t *pos) 2102fc5f0cfSLi Zefan { 2112fc5f0cfSLi Zefan (*pos)++; 2122fc5f0cfSLi Zefan return __next(m, pos); 2132fc5f0cfSLi Zefan } 2142fc5f0cfSLi Zefan 215e5a81b62SSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos) 216e5a81b62SSteven Rostedt { 2174f48f8b7SLai Jiangshan int cpu; 2184f48f8b7SLai Jiangshan 219e5a81b62SSteven Rostedt local_irq_disable(); 2204f48f8b7SLai Jiangshan 2214f48f8b7SLai Jiangshan cpu = smp_processor_id(); 2224f48f8b7SLai Jiangshan per_cpu(trace_active, cpu)++; 2234f48f8b7SLai Jiangshan 2240199c4e6SThomas Gleixner arch_spin_lock(&max_stack_lock); 225e5a81b62SSteven Rostedt 226522a110bSLiming Wang if (*pos == 0) 227522a110bSLiming Wang return SEQ_START_TOKEN; 228522a110bSLiming Wang 2292fc5f0cfSLi Zefan return __next(m, pos); 230e5a81b62SSteven Rostedt } 231e5a81b62SSteven Rostedt 232e5a81b62SSteven Rostedt static void t_stop(struct seq_file *m, void *p) 233e5a81b62SSteven Rostedt { 2344f48f8b7SLai Jiangshan int cpu; 2354f48f8b7SLai Jiangshan 2360199c4e6SThomas Gleixner arch_spin_unlock(&max_stack_lock); 2374f48f8b7SLai Jiangshan 2384f48f8b7SLai Jiangshan cpu = smp_processor_id(); 2394f48f8b7SLai Jiangshan per_cpu(trace_active, cpu)--; 2404f48f8b7SLai Jiangshan 241e5a81b62SSteven Rostedt local_irq_enable(); 242e5a81b62SSteven Rostedt } 243e5a81b62SSteven Rostedt 2441b6cced6SSteven Rostedt static int trace_lookup_stack(struct seq_file *m, long i) 245e5a81b62SSteven Rostedt { 2461b6cced6SSteven Rostedt unsigned long addr = stack_dump_trace[i]; 247e5a81b62SSteven Rostedt 248151772dbSAnton Blanchard return seq_printf(m, "%pS\n", (void *)addr); 249e5a81b62SSteven Rostedt } 250e5a81b62SSteven Rostedt 251e447e1dfSSteven Rostedt static void print_disabled(struct seq_file *m) 252e447e1dfSSteven Rostedt { 253e447e1dfSSteven Rostedt seq_puts(m, "#\n" 254e447e1dfSSteven Rostedt "# Stack tracer disabled\n" 255e447e1dfSSteven Rostedt "#\n" 256e447e1dfSSteven Rostedt "# To enable the stack tracer, either add 'stacktrace' to the\n" 257e447e1dfSSteven Rostedt "# kernel command line\n" 258e447e1dfSSteven Rostedt "# or 'echo 1 > /proc/sys/kernel/stack_tracer_enabled'\n" 259e447e1dfSSteven Rostedt "#\n"); 260e447e1dfSSteven Rostedt } 261e447e1dfSSteven Rostedt 262e5a81b62SSteven Rostedt static int t_show(struct seq_file *m, void *v) 263e5a81b62SSteven Rostedt { 264522a110bSLiming Wang long i; 2651b6cced6SSteven Rostedt int size; 266e5a81b62SSteven Rostedt 267522a110bSLiming Wang if (v == SEQ_START_TOKEN) { 2681b6cced6SSteven Rostedt seq_printf(m, " Depth Size Location" 2691b6cced6SSteven Rostedt " (%d entries)\n" 2701b6cced6SSteven Rostedt " ----- ---- --------\n", 271083a63b4Swalimis max_stack_trace.nr_entries - 1); 272e447e1dfSSteven Rostedt 273e447e1dfSSteven Rostedt if (!stack_tracer_enabled && !max_stack_size) 274e447e1dfSSteven Rostedt print_disabled(m); 275e447e1dfSSteven Rostedt 2761b6cced6SSteven Rostedt return 0; 2771b6cced6SSteven Rostedt } 2781b6cced6SSteven Rostedt 279522a110bSLiming Wang i = *(long *)v; 280522a110bSLiming Wang 2811b6cced6SSteven Rostedt if (i >= max_stack_trace.nr_entries || 2821b6cced6SSteven Rostedt stack_dump_trace[i] == ULONG_MAX) 283e5a81b62SSteven Rostedt return 0; 284e5a81b62SSteven Rostedt 2851b6cced6SSteven Rostedt if (i+1 == max_stack_trace.nr_entries || 2861b6cced6SSteven Rostedt stack_dump_trace[i+1] == ULONG_MAX) 2871b6cced6SSteven Rostedt size = stack_dump_index[i]; 2881b6cced6SSteven Rostedt else 2891b6cced6SSteven Rostedt size = stack_dump_index[i] - stack_dump_index[i+1]; 2901b6cced6SSteven Rostedt 2911b6cced6SSteven Rostedt seq_printf(m, "%3ld) %8d %5d ", i, stack_dump_index[i], size); 2921b6cced6SSteven Rostedt 2931b6cced6SSteven Rostedt trace_lookup_stack(m, i); 294e5a81b62SSteven Rostedt 295e5a81b62SSteven Rostedt return 0; 296e5a81b62SSteven Rostedt } 297e5a81b62SSteven Rostedt 298f38f1d2aSSteven Rostedt static const struct seq_operations stack_trace_seq_ops = { 299e5a81b62SSteven Rostedt .start = t_start, 300e5a81b62SSteven Rostedt .next = t_next, 301e5a81b62SSteven Rostedt .stop = t_stop, 302e5a81b62SSteven Rostedt .show = t_show, 303e5a81b62SSteven Rostedt }; 304e5a81b62SSteven Rostedt 305e5a81b62SSteven Rostedt static int stack_trace_open(struct inode *inode, struct file *file) 306e5a81b62SSteven Rostedt { 307d8cc1ab7SLi Zefan return seq_open(file, &stack_trace_seq_ops); 308e5a81b62SSteven Rostedt } 309e5a81b62SSteven Rostedt 310f38f1d2aSSteven Rostedt static const struct file_operations stack_trace_fops = { 311e5a81b62SSteven Rostedt .open = stack_trace_open, 312e5a81b62SSteven Rostedt .read = seq_read, 313e5a81b62SSteven Rostedt .llseek = seq_lseek, 314d8cc1ab7SLi Zefan .release = seq_release, 315e5a81b62SSteven Rostedt }; 316e5a81b62SSteven Rostedt 317d2d45c7aSSteven Rostedt static int 318d2d45c7aSSteven Rostedt stack_trace_filter_open(struct inode *inode, struct file *file) 319d2d45c7aSSteven Rostedt { 320d2d45c7aSSteven Rostedt return ftrace_regex_open(&trace_ops, FTRACE_ITER_FILTER, 321d2d45c7aSSteven Rostedt inode, file); 322d2d45c7aSSteven Rostedt } 323d2d45c7aSSteven Rostedt 324d2d45c7aSSteven Rostedt static const struct file_operations stack_trace_filter_fops = { 325d2d45c7aSSteven Rostedt .open = stack_trace_filter_open, 326d2d45c7aSSteven Rostedt .read = seq_read, 327d2d45c7aSSteven Rostedt .write = ftrace_filter_write, 328d2d45c7aSSteven Rostedt .llseek = ftrace_regex_lseek, 329d2d45c7aSSteven Rostedt .release = ftrace_regex_release, 330d2d45c7aSSteven Rostedt }; 331d2d45c7aSSteven Rostedt 332f38f1d2aSSteven Rostedt int 333f38f1d2aSSteven Rostedt stack_trace_sysctl(struct ctl_table *table, int write, 3348d65af78SAlexey Dobriyan void __user *buffer, size_t *lenp, 335f38f1d2aSSteven Rostedt loff_t *ppos) 336f38f1d2aSSteven Rostedt { 337f38f1d2aSSteven Rostedt int ret; 338f38f1d2aSSteven Rostedt 339f38f1d2aSSteven Rostedt mutex_lock(&stack_sysctl_mutex); 340f38f1d2aSSteven Rostedt 3418d65af78SAlexey Dobriyan ret = proc_dointvec(table, write, buffer, lenp, ppos); 342f38f1d2aSSteven Rostedt 343f38f1d2aSSteven Rostedt if (ret || !write || 344a32c7765SLi Zefan (last_stack_tracer_enabled == !!stack_tracer_enabled)) 345f38f1d2aSSteven Rostedt goto out; 346f38f1d2aSSteven Rostedt 347a32c7765SLi Zefan last_stack_tracer_enabled = !!stack_tracer_enabled; 348f38f1d2aSSteven Rostedt 349f38f1d2aSSteven Rostedt if (stack_tracer_enabled) 350f38f1d2aSSteven Rostedt register_ftrace_function(&trace_ops); 351f38f1d2aSSteven Rostedt else 352f38f1d2aSSteven Rostedt unregister_ftrace_function(&trace_ops); 353f38f1d2aSSteven Rostedt 354f38f1d2aSSteven Rostedt out: 355f38f1d2aSSteven Rostedt mutex_unlock(&stack_sysctl_mutex); 356f38f1d2aSSteven Rostedt return ret; 357f38f1d2aSSteven Rostedt } 358f38f1d2aSSteven Rostedt 359762e1207SSteven Rostedt static char stack_trace_filter_buf[COMMAND_LINE_SIZE+1] __initdata; 360762e1207SSteven Rostedt 361f38f1d2aSSteven Rostedt static __init int enable_stacktrace(char *str) 362f38f1d2aSSteven Rostedt { 363762e1207SSteven Rostedt if (strncmp(str, "_filter=", 8) == 0) 364762e1207SSteven Rostedt strncpy(stack_trace_filter_buf, str+8, COMMAND_LINE_SIZE); 365762e1207SSteven Rostedt 366e05a43b7SSteven Rostedt stack_tracer_enabled = 1; 367e05a43b7SSteven Rostedt last_stack_tracer_enabled = 1; 368f38f1d2aSSteven Rostedt return 1; 369f38f1d2aSSteven Rostedt } 370f38f1d2aSSteven Rostedt __setup("stacktrace", enable_stacktrace); 371f38f1d2aSSteven Rostedt 372e5a81b62SSteven Rostedt static __init int stack_trace_init(void) 373e5a81b62SSteven Rostedt { 374e5a81b62SSteven Rostedt struct dentry *d_tracer; 375e5a81b62SSteven Rostedt 376e5a81b62SSteven Rostedt d_tracer = tracing_init_dentry(); 377e5a81b62SSteven Rostedt 3785452af66SFrederic Weisbecker trace_create_file("stack_max_size", 0644, d_tracer, 379e5a81b62SSteven Rostedt &max_stack_size, &stack_max_size_fops); 380e5a81b62SSteven Rostedt 3815452af66SFrederic Weisbecker trace_create_file("stack_trace", 0444, d_tracer, 382e5a81b62SSteven Rostedt NULL, &stack_trace_fops); 383e5a81b62SSteven Rostedt 384d2d45c7aSSteven Rostedt trace_create_file("stack_trace_filter", 0444, d_tracer, 385d2d45c7aSSteven Rostedt NULL, &stack_trace_filter_fops); 386d2d45c7aSSteven Rostedt 387762e1207SSteven Rostedt if (stack_trace_filter_buf[0]) 388762e1207SSteven Rostedt ftrace_set_early_filter(&trace_ops, stack_trace_filter_buf, 1); 389762e1207SSteven Rostedt 390e05a43b7SSteven Rostedt if (stack_tracer_enabled) 391e5a81b62SSteven Rostedt register_ftrace_function(&trace_ops); 392e5a81b62SSteven Rostedt 393e5a81b62SSteven Rostedt return 0; 394e5a81b62SSteven Rostedt } 395e5a81b62SSteven Rostedt 396e5a81b62SSteven Rostedt device_initcall(stack_trace_init); 397