aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_stack.c')
-rw-r--r--kernel/trace/trace_stack.c92
1 files changed, 49 insertions, 43 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 8abf1ba18085..dda9e6742950 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -16,24 +16,22 @@
16 16
17#include "trace.h" 17#include "trace.h"
18 18
19#define STACK_TRACE_ENTRIES 500
20
21static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = 19static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] =
22 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; 20 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX };
23static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; 21unsigned stack_trace_index[STACK_TRACE_ENTRIES];
24 22
25/* 23/*
26 * Reserve one entry for the passed in ip. This will allow 24 * Reserve one entry for the passed in ip. This will allow
27 * us to remove most or all of the stack size overhead 25 * us to remove most or all of the stack size overhead
28 * added by the stack tracer itself. 26 * added by the stack tracer itself.
29 */ 27 */
30static struct stack_trace max_stack_trace = { 28struct stack_trace stack_trace_max = {
31 .max_entries = STACK_TRACE_ENTRIES - 1, 29 .max_entries = STACK_TRACE_ENTRIES - 1,
32 .entries = &stack_dump_trace[0], 30 .entries = &stack_dump_trace[0],
33}; 31};
34 32
35static unsigned long max_stack_size; 33unsigned long stack_trace_max_size;
36static arch_spinlock_t max_stack_lock = 34arch_spinlock_t stack_trace_max_lock =
37 (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; 35 (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
38 36
39static DEFINE_PER_CPU(int, trace_active); 37static DEFINE_PER_CPU(int, trace_active);
@@ -42,30 +40,38 @@ static DEFINE_MUTEX(stack_sysctl_mutex);
42int stack_tracer_enabled; 40int stack_tracer_enabled;
43static int last_stack_tracer_enabled; 41static int last_stack_tracer_enabled;
44 42
45static inline void print_max_stack(void) 43void stack_trace_print(void)
46{ 44{
47 long i; 45 long i;
48 int size; 46 int size;
49 47
50 pr_emerg(" Depth Size Location (%d entries)\n" 48 pr_emerg(" Depth Size Location (%d entries)\n"
51 " ----- ---- --------\n", 49 " ----- ---- --------\n",
52 max_stack_trace.nr_entries); 50 stack_trace_max.nr_entries);
53 51
54 for (i = 0; i < max_stack_trace.nr_entries; i++) { 52 for (i = 0; i < stack_trace_max.nr_entries; i++) {
55 if (stack_dump_trace[i] == ULONG_MAX) 53 if (stack_dump_trace[i] == ULONG_MAX)
56 break; 54 break;
57 if (i+1 == max_stack_trace.nr_entries || 55 if (i+1 == stack_trace_max.nr_entries ||
58 stack_dump_trace[i+1] == ULONG_MAX) 56 stack_dump_trace[i+1] == ULONG_MAX)
59 size = stack_dump_index[i]; 57 size = stack_trace_index[i];
60 else 58 else
61 size = stack_dump_index[i] - stack_dump_index[i+1]; 59 size = stack_trace_index[i] - stack_trace_index[i+1];
62 60
63 pr_emerg("%3ld) %8d %5d %pS\n", i, stack_dump_index[i], 61 pr_emerg("%3ld) %8d %5d %pS\n", i, stack_trace_index[i],
64 size, (void *)stack_dump_trace[i]); 62 size, (void *)stack_dump_trace[i]);
65 } 63 }
66} 64}
67 65
68static inline void 66/*
67 * When arch-specific code overides this function, the following
68 * data should be filled up, assuming stack_trace_max_lock is held to
69 * prevent concurrent updates.
70 * stack_trace_index[]
71 * stack_trace_max
72 * stack_trace_max_size
73 */
74void __weak
69check_stack(unsigned long ip, unsigned long *stack) 75check_stack(unsigned long ip, unsigned long *stack)
70{ 76{
71 unsigned long this_size, flags; unsigned long *p, *top, *start; 77 unsigned long this_size, flags; unsigned long *p, *top, *start;
@@ -78,7 +84,7 @@ check_stack(unsigned long ip, unsigned long *stack)
78 /* Remove the frame of the tracer */ 84 /* Remove the frame of the tracer */
79 this_size -= frame_size; 85 this_size -= frame_size;
80 86
81 if (this_size <= max_stack_size) 87 if (this_size <= stack_trace_max_size)
82 return; 88 return;
83 89
84 /* we do not handle interrupt stacks yet */ 90 /* we do not handle interrupt stacks yet */
@@ -90,7 +96,7 @@ check_stack(unsigned long ip, unsigned long *stack)
90 return; 96 return;
91 97
92 local_irq_save(flags); 98 local_irq_save(flags);
93 arch_spin_lock(&max_stack_lock); 99 arch_spin_lock(&stack_trace_max_lock);
94 100
95 /* 101 /*
96 * RCU may not be watching, make it see us. 102 * RCU may not be watching, make it see us.
@@ -103,18 +109,18 @@ check_stack(unsigned long ip, unsigned long *stack)
103 this_size -= tracer_frame; 109 this_size -= tracer_frame;
104 110
105 /* a race could have already updated it */ 111 /* a race could have already updated it */
106 if (this_size <= max_stack_size) 112 if (this_size <= stack_trace_max_size)
107 goto out; 113 goto out;
108 114
109 max_stack_size = this_size; 115 stack_trace_max_size = this_size;
110 116
111 max_stack_trace.nr_entries = 0; 117 stack_trace_max.nr_entries = 0;
112 max_stack_trace.skip = 3; 118 stack_trace_max.skip = 3;
113 119
114 save_stack_trace(&max_stack_trace); 120 save_stack_trace(&stack_trace_max);
115 121
116 /* Skip over the overhead of the stack tracer itself */ 122 /* Skip over the overhead of the stack tracer itself */
117 for (i = 0; i < max_stack_trace.nr_entries; i++) { 123 for (i = 0; i < stack_trace_max.nr_entries; i++) {
118 if (stack_dump_trace[i] == ip) 124 if (stack_dump_trace[i] == ip)
119 break; 125 break;
120 } 126 }
@@ -134,18 +140,18 @@ check_stack(unsigned long ip, unsigned long *stack)
134 * loop will only happen once. This code only takes place 140 * loop will only happen once. This code only takes place
135 * on a new max, so it is far from a fast path. 141 * on a new max, so it is far from a fast path.
136 */ 142 */
137 while (i < max_stack_trace.nr_entries) { 143 while (i < stack_trace_max.nr_entries) {
138 int found = 0; 144 int found = 0;
139 145
140 stack_dump_index[x] = this_size; 146 stack_trace_index[x] = this_size;
141 p = start; 147 p = start;
142 148
143 for (; p < top && i < max_stack_trace.nr_entries; p++) { 149 for (; p < top && i < stack_trace_max.nr_entries; p++) {
144 if (stack_dump_trace[i] == ULONG_MAX) 150 if (stack_dump_trace[i] == ULONG_MAX)
145 break; 151 break;
146 if (*p == stack_dump_trace[i]) { 152 if (*p == stack_dump_trace[i]) {
147 stack_dump_trace[x] = stack_dump_trace[i++]; 153 stack_dump_trace[x] = stack_dump_trace[i++];
148 this_size = stack_dump_index[x++] = 154 this_size = stack_trace_index[x++] =
149 (top - p) * sizeof(unsigned long); 155 (top - p) * sizeof(unsigned long);
150 found = 1; 156 found = 1;
151 /* Start the search from here */ 157 /* Start the search from here */
@@ -160,7 +166,7 @@ check_stack(unsigned long ip, unsigned long *stack)
160 if (unlikely(!tracer_frame)) { 166 if (unlikely(!tracer_frame)) {
161 tracer_frame = (p - stack) * 167 tracer_frame = (p - stack) *
162 sizeof(unsigned long); 168 sizeof(unsigned long);
163 max_stack_size -= tracer_frame; 169 stack_trace_max_size -= tracer_frame;
164 } 170 }
165 } 171 }
166 } 172 }
@@ -169,18 +175,18 @@ check_stack(unsigned long ip, unsigned long *stack)
169 i++; 175 i++;
170 } 176 }
171 177
172 max_stack_trace.nr_entries = x; 178 stack_trace_max.nr_entries = x;
173 for (; x < i; x++) 179 for (; x < i; x++)
174 stack_dump_trace[x] = ULONG_MAX; 180 stack_dump_trace[x] = ULONG_MAX;
175 181
176 if (task_stack_end_corrupted(current)) { 182 if (task_stack_end_corrupted(current)) {
177 print_max_stack(); 183 stack_trace_print();
178 BUG(); 184 BUG();
179 } 185 }
180 186
181 out: 187 out:
182 rcu_irq_exit(); 188 rcu_irq_exit();
183 arch_spin_unlock(&max_stack_lock); 189 arch_spin_unlock(&stack_trace_max_lock);
184 local_irq_restore(flags); 190 local_irq_restore(flags);
185} 191}
186 192
@@ -251,9 +257,9 @@ stack_max_size_write(struct file *filp, const char __user *ubuf,
251 cpu = smp_processor_id(); 257 cpu = smp_processor_id();
252 per_cpu(trace_active, cpu)++; 258 per_cpu(trace_active, cpu)++;
253 259
254 arch_spin_lock(&max_stack_lock); 260 arch_spin_lock(&stack_trace_max_lock);
255 *ptr = val; 261 *ptr = val;
256 arch_spin_unlock(&max_stack_lock); 262 arch_spin_unlock(&stack_trace_max_lock);
257 263
258 per_cpu(trace_active, cpu)--; 264 per_cpu(trace_active, cpu)--;
259 local_irq_restore(flags); 265 local_irq_restore(flags);
@@ -273,7 +279,7 @@ __next(struct seq_file *m, loff_t *pos)
273{ 279{
274 long n = *pos - 1; 280 long n = *pos - 1;
275 281
276 if (n > max_stack_trace.nr_entries || stack_dump_trace[n] == ULONG_MAX) 282 if (n > stack_trace_max.nr_entries || stack_dump_trace[n] == ULONG_MAX)
277 return NULL; 283 return NULL;
278 284
279 m->private = (void *)n; 285 m->private = (void *)n;
@@ -296,7 +302,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
296 cpu = smp_processor_id(); 302 cpu = smp_processor_id();
297 per_cpu(trace_active, cpu)++; 303 per_cpu(trace_active, cpu)++;
298 304
299 arch_spin_lock(&max_stack_lock); 305 arch_spin_lock(&stack_trace_max_lock);
300 306
301 if (*pos == 0) 307 if (*pos == 0)
302 return SEQ_START_TOKEN; 308 return SEQ_START_TOKEN;
@@ -308,7 +314,7 @@ static void t_stop(struct seq_file *m, void *p)
308{ 314{
309 int cpu; 315 int cpu;
310 316
311 arch_spin_unlock(&max_stack_lock); 317 arch_spin_unlock(&stack_trace_max_lock);
312 318
313 cpu = smp_processor_id(); 319 cpu = smp_processor_id();
314 per_cpu(trace_active, cpu)--; 320 per_cpu(trace_active, cpu)--;
@@ -343,9 +349,9 @@ static int t_show(struct seq_file *m, void *v)
343 seq_printf(m, " Depth Size Location" 349 seq_printf(m, " Depth Size Location"
344 " (%d entries)\n" 350 " (%d entries)\n"
345 " ----- ---- --------\n", 351 " ----- ---- --------\n",
346 max_stack_trace.nr_entries); 352 stack_trace_max.nr_entries);
347 353
348 if (!stack_tracer_enabled && !max_stack_size) 354 if (!stack_tracer_enabled && !stack_trace_max_size)
349 print_disabled(m); 355 print_disabled(m);
350 356
351 return 0; 357 return 0;
@@ -353,17 +359,17 @@ static int t_show(struct seq_file *m, void *v)
353 359
354 i = *(long *)v; 360 i = *(long *)v;
355 361
356 if (i >= max_stack_trace.nr_entries || 362 if (i >= stack_trace_max.nr_entries ||
357 stack_dump_trace[i] == ULONG_MAX) 363 stack_dump_trace[i] == ULONG_MAX)
358 return 0; 364 return 0;
359 365
360 if (i+1 == max_stack_trace.nr_entries || 366 if (i+1 == stack_trace_max.nr_entries ||
361 stack_dump_trace[i+1] == ULONG_MAX) 367 stack_dump_trace[i+1] == ULONG_MAX)
362 size = stack_dump_index[i]; 368 size = stack_trace_index[i];
363 else 369 else
364 size = stack_dump_index[i] - stack_dump_index[i+1]; 370 size = stack_trace_index[i] - stack_trace_index[i+1];
365 371
366 seq_printf(m, "%3ld) %8d %5d ", i, stack_dump_index[i], size); 372 seq_printf(m, "%3ld) %8d %5d ", i, stack_trace_index[i], size);
367 373
368 trace_lookup_stack(m, i); 374 trace_lookup_stack(m, i);
369 375
@@ -453,7 +459,7 @@ static __init int stack_trace_init(void)
453 return 0; 459 return 0;
454 460
455 trace_create_file("stack_max_size", 0644, d_tracer, 461 trace_create_file("stack_max_size", 0644, d_tracer,
456 &max_stack_size, &stack_max_size_fops); 462 &stack_trace_max_size, &stack_max_size_fops);
457 463
458 trace_create_file("stack_trace", 0444, d_tracer, 464 trace_create_file("stack_trace", 0444, d_tracer,
459 NULL, &stack_trace_fops); 465 NULL, &stack_trace_fops);