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> 13e5a81b62SSteven Rostedt #include <linux/init.h> 14e5a81b62SSteven Rostedt #include <linux/fs.h> 15e5a81b62SSteven Rostedt #include "trace.h" 16e5a81b62SSteven Rostedt 17e5a81b62SSteven Rostedt #define STACK_TRACE_ENTRIES 500 18e5a81b62SSteven Rostedt 191b6cced6SSteven Rostedt static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = 201b6cced6SSteven Rostedt { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; 211b6cced6SSteven Rostedt static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; 221b6cced6SSteven Rostedt 23e5a81b62SSteven Rostedt static struct stack_trace max_stack_trace = { 24e5a81b62SSteven Rostedt .max_entries = STACK_TRACE_ENTRIES, 25e5a81b62SSteven Rostedt .entries = stack_dump_trace, 26e5a81b62SSteven Rostedt }; 27e5a81b62SSteven Rostedt 28e5a81b62SSteven Rostedt static unsigned long max_stack_size; 29e5a81b62SSteven Rostedt static raw_spinlock_t max_stack_lock = 30e5a81b62SSteven Rostedt (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; 31e5a81b62SSteven Rostedt 32e5a81b62SSteven Rostedt static int stack_trace_disabled __read_mostly; 33e5a81b62SSteven Rostedt static DEFINE_PER_CPU(int, trace_active); 34e5a81b62SSteven Rostedt 35e5a81b62SSteven Rostedt static inline void check_stack(void) 36e5a81b62SSteven Rostedt { 371b6cced6SSteven Rostedt unsigned long this_size, flags; 381b6cced6SSteven Rostedt unsigned long *p, *top, *start; 391b6cced6SSteven Rostedt int i; 40e5a81b62SSteven Rostedt 41e5a81b62SSteven Rostedt this_size = ((unsigned long)&this_size) & (THREAD_SIZE-1); 42e5a81b62SSteven Rostedt this_size = THREAD_SIZE - this_size; 43e5a81b62SSteven Rostedt 44e5a81b62SSteven Rostedt if (this_size <= max_stack_size) 45e5a81b62SSteven Rostedt return; 46e5a81b62SSteven Rostedt 4781520a1bSSteven Rostedt /* we do not handle interrupt stacks yet */ 4881520a1bSSteven Rostedt if (!object_is_on_stack(&this_size)) 4981520a1bSSteven Rostedt return; 5081520a1bSSteven Rostedt 51e5a81b62SSteven Rostedt raw_local_irq_save(flags); 52e5a81b62SSteven Rostedt __raw_spin_lock(&max_stack_lock); 53e5a81b62SSteven Rostedt 54e5a81b62SSteven Rostedt /* a race could have already updated it */ 55e5a81b62SSteven Rostedt if (this_size <= max_stack_size) 56e5a81b62SSteven Rostedt goto out; 57e5a81b62SSteven Rostedt 58e5a81b62SSteven Rostedt max_stack_size = this_size; 59e5a81b62SSteven Rostedt 60e5a81b62SSteven Rostedt max_stack_trace.nr_entries = 0; 611b6cced6SSteven Rostedt max_stack_trace.skip = 3; 62e5a81b62SSteven Rostedt 63e5a81b62SSteven Rostedt save_stack_trace(&max_stack_trace); 64e5a81b62SSteven Rostedt 651b6cced6SSteven Rostedt /* 661b6cced6SSteven Rostedt * Now find where in the stack these are. 671b6cced6SSteven Rostedt */ 681b6cced6SSteven Rostedt i = 0; 691b6cced6SSteven Rostedt start = &this_size; 701b6cced6SSteven Rostedt top = (unsigned long *) 711b6cced6SSteven Rostedt (((unsigned long)start & ~(THREAD_SIZE-1)) + THREAD_SIZE); 721b6cced6SSteven Rostedt 731b6cced6SSteven Rostedt /* 741b6cced6SSteven Rostedt * Loop through all the entries. One of the entries may 751b6cced6SSteven Rostedt * for some reason be missed on the stack, so we may 761b6cced6SSteven Rostedt * have to account for them. If they are all there, this 771b6cced6SSteven Rostedt * loop will only happen once. This code only takes place 781b6cced6SSteven Rostedt * on a new max, so it is far from a fast path. 791b6cced6SSteven Rostedt */ 801b6cced6SSteven Rostedt while (i < max_stack_trace.nr_entries) { 811b6cced6SSteven Rostedt 821b6cced6SSteven Rostedt stack_dump_index[i] = this_size; 831b6cced6SSteven Rostedt p = start; 841b6cced6SSteven Rostedt 851b6cced6SSteven Rostedt for (; p < top && i < max_stack_trace.nr_entries; p++) { 861b6cced6SSteven Rostedt if (*p == stack_dump_trace[i]) { 871b6cced6SSteven Rostedt this_size = stack_dump_index[i++] = 881b6cced6SSteven Rostedt (top - p) * sizeof(unsigned long); 891b6cced6SSteven Rostedt /* Start the search from here */ 901b6cced6SSteven Rostedt start = p + 1; 911b6cced6SSteven Rostedt } 921b6cced6SSteven Rostedt } 931b6cced6SSteven Rostedt 941b6cced6SSteven Rostedt i++; 951b6cced6SSteven Rostedt } 961b6cced6SSteven Rostedt 97e5a81b62SSteven Rostedt out: 98e5a81b62SSteven Rostedt __raw_spin_unlock(&max_stack_lock); 99e5a81b62SSteven Rostedt raw_local_irq_restore(flags); 100e5a81b62SSteven Rostedt } 101e5a81b62SSteven Rostedt 102e5a81b62SSteven Rostedt static void 103e5a81b62SSteven Rostedt stack_trace_call(unsigned long ip, unsigned long parent_ip) 104e5a81b62SSteven Rostedt { 105e5a81b62SSteven Rostedt int cpu, resched; 106e5a81b62SSteven Rostedt 107e5a81b62SSteven Rostedt if (unlikely(!ftrace_enabled || stack_trace_disabled)) 108e5a81b62SSteven Rostedt return; 109e5a81b62SSteven Rostedt 110e5a81b62SSteven Rostedt resched = need_resched(); 111e5a81b62SSteven Rostedt preempt_disable_notrace(); 112e5a81b62SSteven Rostedt 113e5a81b62SSteven Rostedt cpu = raw_smp_processor_id(); 114e5a81b62SSteven Rostedt /* no atomic needed, we only modify this variable by this cpu */ 115e5a81b62SSteven Rostedt if (per_cpu(trace_active, cpu)++ != 0) 116e5a81b62SSteven Rostedt goto out; 117e5a81b62SSteven Rostedt 118e5a81b62SSteven Rostedt check_stack(); 119e5a81b62SSteven Rostedt 120e5a81b62SSteven Rostedt out: 121e5a81b62SSteven Rostedt per_cpu(trace_active, cpu)--; 122e5a81b62SSteven Rostedt /* prevent recursion in schedule */ 123e5a81b62SSteven Rostedt if (resched) 124e5a81b62SSteven Rostedt preempt_enable_no_resched_notrace(); 125e5a81b62SSteven Rostedt else 126e5a81b62SSteven Rostedt preempt_enable_notrace(); 127e5a81b62SSteven Rostedt } 128e5a81b62SSteven Rostedt 129e5a81b62SSteven Rostedt static struct ftrace_ops trace_ops __read_mostly = 130e5a81b62SSteven Rostedt { 131e5a81b62SSteven Rostedt .func = stack_trace_call, 132e5a81b62SSteven Rostedt }; 133e5a81b62SSteven Rostedt 134e5a81b62SSteven Rostedt static ssize_t 135e5a81b62SSteven Rostedt stack_max_size_read(struct file *filp, char __user *ubuf, 136e5a81b62SSteven Rostedt size_t count, loff_t *ppos) 137e5a81b62SSteven Rostedt { 138e5a81b62SSteven Rostedt unsigned long *ptr = filp->private_data; 139e5a81b62SSteven Rostedt char buf[64]; 140e5a81b62SSteven Rostedt int r; 141e5a81b62SSteven Rostedt 142e5a81b62SSteven Rostedt r = snprintf(buf, sizeof(buf), "%ld\n", *ptr); 143e5a81b62SSteven Rostedt if (r > sizeof(buf)) 144e5a81b62SSteven Rostedt r = sizeof(buf); 145e5a81b62SSteven Rostedt return simple_read_from_buffer(ubuf, count, ppos, buf, r); 146e5a81b62SSteven Rostedt } 147e5a81b62SSteven Rostedt 148e5a81b62SSteven Rostedt static ssize_t 149e5a81b62SSteven Rostedt stack_max_size_write(struct file *filp, const char __user *ubuf, 150e5a81b62SSteven Rostedt size_t count, loff_t *ppos) 151e5a81b62SSteven Rostedt { 152e5a81b62SSteven Rostedt long *ptr = filp->private_data; 153e5a81b62SSteven Rostedt unsigned long val, flags; 154e5a81b62SSteven Rostedt char buf[64]; 155e5a81b62SSteven Rostedt int ret; 156e5a81b62SSteven Rostedt 157e5a81b62SSteven Rostedt if (count >= sizeof(buf)) 158e5a81b62SSteven Rostedt return -EINVAL; 159e5a81b62SSteven Rostedt 160e5a81b62SSteven Rostedt if (copy_from_user(&buf, ubuf, count)) 161e5a81b62SSteven Rostedt return -EFAULT; 162e5a81b62SSteven Rostedt 163e5a81b62SSteven Rostedt buf[count] = 0; 164e5a81b62SSteven Rostedt 165e5a81b62SSteven Rostedt ret = strict_strtoul(buf, 10, &val); 166e5a81b62SSteven Rostedt if (ret < 0) 167e5a81b62SSteven Rostedt return ret; 168e5a81b62SSteven Rostedt 169e5a81b62SSteven Rostedt raw_local_irq_save(flags); 170e5a81b62SSteven Rostedt __raw_spin_lock(&max_stack_lock); 171e5a81b62SSteven Rostedt *ptr = val; 172e5a81b62SSteven Rostedt __raw_spin_unlock(&max_stack_lock); 173e5a81b62SSteven Rostedt raw_local_irq_restore(flags); 174e5a81b62SSteven Rostedt 175e5a81b62SSteven Rostedt return count; 176e5a81b62SSteven Rostedt } 177e5a81b62SSteven Rostedt 178e5a81b62SSteven Rostedt static struct file_operations stack_max_size_fops = { 179e5a81b62SSteven Rostedt .open = tracing_open_generic, 180e5a81b62SSteven Rostedt .read = stack_max_size_read, 181e5a81b62SSteven Rostedt .write = stack_max_size_write, 182e5a81b62SSteven Rostedt }; 183e5a81b62SSteven Rostedt 184e5a81b62SSteven Rostedt static void * 185e5a81b62SSteven Rostedt t_next(struct seq_file *m, void *v, loff_t *pos) 186e5a81b62SSteven Rostedt { 187*522a110bSLiming Wang long i; 188e5a81b62SSteven Rostedt 189e5a81b62SSteven Rostedt (*pos)++; 190e5a81b62SSteven Rostedt 191*522a110bSLiming Wang if (v == SEQ_START_TOKEN) 192*522a110bSLiming Wang i = 0; 193*522a110bSLiming Wang else { 194*522a110bSLiming Wang i = *(long *)v; 1951b6cced6SSteven Rostedt i++; 196*522a110bSLiming Wang } 1971b6cced6SSteven Rostedt 1981b6cced6SSteven Rostedt if (i >= max_stack_trace.nr_entries || 1991b6cced6SSteven Rostedt stack_dump_trace[i] == ULONG_MAX) 200e5a81b62SSteven Rostedt return NULL; 201e5a81b62SSteven Rostedt 2021b6cced6SSteven Rostedt m->private = (void *)i; 203e5a81b62SSteven Rostedt 2041b6cced6SSteven Rostedt return &m->private; 205e5a81b62SSteven Rostedt } 206e5a81b62SSteven Rostedt 207e5a81b62SSteven Rostedt static void *t_start(struct seq_file *m, loff_t *pos) 208e5a81b62SSteven Rostedt { 209*522a110bSLiming Wang void *t = SEQ_START_TOKEN; 210e5a81b62SSteven Rostedt loff_t l = 0; 211e5a81b62SSteven Rostedt 212e5a81b62SSteven Rostedt local_irq_disable(); 213e5a81b62SSteven Rostedt __raw_spin_lock(&max_stack_lock); 214e5a81b62SSteven Rostedt 215*522a110bSLiming Wang if (*pos == 0) 216*522a110bSLiming Wang return SEQ_START_TOKEN; 217*522a110bSLiming Wang 218e5a81b62SSteven Rostedt for (; t && l < *pos; t = t_next(m, t, &l)) 219e5a81b62SSteven Rostedt ; 220e5a81b62SSteven Rostedt 221e5a81b62SSteven Rostedt return t; 222e5a81b62SSteven Rostedt } 223e5a81b62SSteven Rostedt 224e5a81b62SSteven Rostedt static void t_stop(struct seq_file *m, void *p) 225e5a81b62SSteven Rostedt { 226e5a81b62SSteven Rostedt __raw_spin_unlock(&max_stack_lock); 227e5a81b62SSteven Rostedt local_irq_enable(); 228e5a81b62SSteven Rostedt } 229e5a81b62SSteven Rostedt 2301b6cced6SSteven Rostedt static int trace_lookup_stack(struct seq_file *m, long i) 231e5a81b62SSteven Rostedt { 2321b6cced6SSteven Rostedt unsigned long addr = stack_dump_trace[i]; 233e5a81b62SSteven Rostedt #ifdef CONFIG_KALLSYMS 234e5a81b62SSteven Rostedt char str[KSYM_SYMBOL_LEN]; 235e5a81b62SSteven Rostedt 236e5a81b62SSteven Rostedt sprint_symbol(str, addr); 237e5a81b62SSteven Rostedt 2381b6cced6SSteven Rostedt return seq_printf(m, "%s\n", str); 239e5a81b62SSteven Rostedt #else 240e5a81b62SSteven Rostedt return seq_printf(m, "%p\n", (void*)addr); 241e5a81b62SSteven Rostedt #endif 242e5a81b62SSteven Rostedt } 243e5a81b62SSteven Rostedt 244e5a81b62SSteven Rostedt static int t_show(struct seq_file *m, void *v) 245e5a81b62SSteven Rostedt { 246*522a110bSLiming Wang long i; 2471b6cced6SSteven Rostedt int size; 248e5a81b62SSteven Rostedt 249*522a110bSLiming Wang if (v == SEQ_START_TOKEN) { 2501b6cced6SSteven Rostedt seq_printf(m, " Depth Size Location" 2511b6cced6SSteven Rostedt " (%d entries)\n" 2521b6cced6SSteven Rostedt " ----- ---- --------\n", 2531b6cced6SSteven Rostedt max_stack_trace.nr_entries); 2541b6cced6SSteven Rostedt return 0; 2551b6cced6SSteven Rostedt } 2561b6cced6SSteven Rostedt 257*522a110bSLiming Wang i = *(long *)v; 258*522a110bSLiming Wang 2591b6cced6SSteven Rostedt if (i >= max_stack_trace.nr_entries || 2601b6cced6SSteven Rostedt stack_dump_trace[i] == ULONG_MAX) 261e5a81b62SSteven Rostedt return 0; 262e5a81b62SSteven Rostedt 2631b6cced6SSteven Rostedt if (i+1 == max_stack_trace.nr_entries || 2641b6cced6SSteven Rostedt stack_dump_trace[i+1] == ULONG_MAX) 2651b6cced6SSteven Rostedt size = stack_dump_index[i]; 2661b6cced6SSteven Rostedt else 2671b6cced6SSteven Rostedt size = stack_dump_index[i] - stack_dump_index[i+1]; 2681b6cced6SSteven Rostedt 2691b6cced6SSteven Rostedt seq_printf(m, "%3ld) %8d %5d ", i, stack_dump_index[i], size); 2701b6cced6SSteven Rostedt 2711b6cced6SSteven Rostedt trace_lookup_stack(m, i); 272e5a81b62SSteven Rostedt 273e5a81b62SSteven Rostedt return 0; 274e5a81b62SSteven Rostedt } 275e5a81b62SSteven Rostedt 276e5a81b62SSteven Rostedt static struct seq_operations stack_trace_seq_ops = { 277e5a81b62SSteven Rostedt .start = t_start, 278e5a81b62SSteven Rostedt .next = t_next, 279e5a81b62SSteven Rostedt .stop = t_stop, 280e5a81b62SSteven Rostedt .show = t_show, 281e5a81b62SSteven Rostedt }; 282e5a81b62SSteven Rostedt 283e5a81b62SSteven Rostedt static int stack_trace_open(struct inode *inode, struct file *file) 284e5a81b62SSteven Rostedt { 285e5a81b62SSteven Rostedt int ret; 286e5a81b62SSteven Rostedt 287e5a81b62SSteven Rostedt ret = seq_open(file, &stack_trace_seq_ops); 288e5a81b62SSteven Rostedt 289e5a81b62SSteven Rostedt return ret; 290e5a81b62SSteven Rostedt } 291e5a81b62SSteven Rostedt 292e5a81b62SSteven Rostedt static struct file_operations stack_trace_fops = { 293e5a81b62SSteven Rostedt .open = stack_trace_open, 294e5a81b62SSteven Rostedt .read = seq_read, 295e5a81b62SSteven Rostedt .llseek = seq_lseek, 296e5a81b62SSteven Rostedt }; 297e5a81b62SSteven Rostedt 298e5a81b62SSteven Rostedt static __init int stack_trace_init(void) 299e5a81b62SSteven Rostedt { 300e5a81b62SSteven Rostedt struct dentry *d_tracer; 301e5a81b62SSteven Rostedt struct dentry *entry; 302e5a81b62SSteven Rostedt 303e5a81b62SSteven Rostedt d_tracer = tracing_init_dentry(); 304e5a81b62SSteven Rostedt 305e5a81b62SSteven Rostedt entry = debugfs_create_file("stack_max_size", 0644, d_tracer, 306e5a81b62SSteven Rostedt &max_stack_size, &stack_max_size_fops); 307e5a81b62SSteven Rostedt if (!entry) 308e5a81b62SSteven Rostedt pr_warning("Could not create debugfs 'stack_max_size' entry\n"); 309e5a81b62SSteven Rostedt 310e5a81b62SSteven Rostedt entry = debugfs_create_file("stack_trace", 0444, d_tracer, 311e5a81b62SSteven Rostedt NULL, &stack_trace_fops); 312e5a81b62SSteven Rostedt if (!entry) 313e5a81b62SSteven Rostedt pr_warning("Could not create debugfs 'stack_trace' entry\n"); 314e5a81b62SSteven Rostedt 315e5a81b62SSteven Rostedt register_ftrace_function(&trace_ops); 316e5a81b62SSteven Rostedt 317e5a81b62SSteven Rostedt return 0; 318e5a81b62SSteven Rostedt } 319e5a81b62SSteven Rostedt 320e5a81b62SSteven Rostedt device_initcall(stack_trace_init); 321