diff options
Diffstat (limited to 'arch/x86_64/kernel/traps.c')
-rw-r--r-- | arch/x86_64/kernel/traps.c | 51 |
1 files changed, 35 insertions, 16 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index eb1534ff1f5f..bd0891f4c2c7 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
@@ -107,6 +107,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) | |||
107 | } | 107 | } |
108 | 108 | ||
109 | static int kstack_depth_to_print = 10; | 109 | static int kstack_depth_to_print = 10; |
110 | static int call_trace = 1; | ||
110 | 111 | ||
111 | #ifdef CONFIG_KALLSYMS | 112 | #ifdef CONFIG_KALLSYMS |
112 | #include <linux/kallsyms.h> | 113 | #include <linux/kallsyms.h> |
@@ -190,11 +191,12 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, | |||
190 | return NULL; | 191 | return NULL; |
191 | } | 192 | } |
192 | 193 | ||
193 | static void show_trace_unwind(struct unwind_frame_info *info, void *context) | 194 | static int show_trace_unwind(struct unwind_frame_info *info, void *context) |
194 | { | 195 | { |
195 | int i = 11; | 196 | int i = 11, n = 0; |
196 | 197 | ||
197 | while (unwind(info) == 0 && UNW_PC(info)) { | 198 | while (unwind(info) == 0 && UNW_PC(info)) { |
199 | ++n; | ||
198 | if (i > 50) { | 200 | if (i > 50) { |
199 | printk("\n "); | 201 | printk("\n "); |
200 | i = 7; | 202 | i = 7; |
@@ -205,6 +207,7 @@ static void show_trace_unwind(struct unwind_frame_info *info, void *context) | |||
205 | break; | 207 | break; |
206 | } | 208 | } |
207 | printk("\n"); | 209 | printk("\n"); |
210 | return n; | ||
208 | } | 211 | } |
209 | 212 | ||
210 | /* | 213 | /* |
@@ -218,27 +221,32 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s | |||
218 | { | 221 | { |
219 | const unsigned cpu = safe_smp_processor_id(); | 222 | const unsigned cpu = safe_smp_processor_id(); |
220 | unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; | 223 | unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; |
221 | int i; | 224 | int i = 11; |
222 | unsigned used = 0; | 225 | unsigned used = 0; |
223 | struct unwind_frame_info info; | ||
224 | 226 | ||
225 | printk("\nCall Trace:"); | 227 | printk("\nCall Trace:"); |
226 | 228 | ||
227 | if (!tsk) | 229 | if (!tsk) |
228 | tsk = current; | 230 | tsk = current; |
229 | 231 | ||
230 | if (regs) { | 232 | if (call_trace >= 0) { |
231 | if (unwind_init_frame_info(&info, tsk, regs) == 0) { | 233 | int unw_ret = 0; |
232 | show_trace_unwind(&info, NULL); | 234 | struct unwind_frame_info info; |
233 | return; | 235 | |
236 | if (regs) { | ||
237 | if (unwind_init_frame_info(&info, tsk, regs) == 0) | ||
238 | unw_ret = show_trace_unwind(&info, NULL); | ||
239 | } else if (tsk == current) | ||
240 | unw_ret = unwind_init_running(&info, show_trace_unwind, NULL); | ||
241 | else { | ||
242 | if (unwind_init_blocked(&info, tsk) == 0) | ||
243 | unw_ret = show_trace_unwind(&info, NULL); | ||
234 | } | 244 | } |
235 | } else if (tsk == current) { | 245 | if (unw_ret > 0) { |
236 | if (unwind_init_running(&info, show_trace_unwind, NULL) == 0) | 246 | if (call_trace > 0) |
237 | return; | 247 | return; |
238 | } else { | 248 | printk("Legacy call trace:"); |
239 | if (unwind_init_blocked(&info, tsk) == 0) { | 249 | i = 18; |
240 | show_trace_unwind(&info, NULL); | ||
241 | return; | ||
242 | } | 250 | } |
243 | } | 251 | } |
244 | 252 | ||
@@ -264,7 +272,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s | |||
264 | } \ | 272 | } \ |
265 | } while (0) | 273 | } while (0) |
266 | 274 | ||
267 | for(i = 11; ; ) { | 275 | for(; ; ) { |
268 | const char *id; | 276 | const char *id; |
269 | unsigned long *estack_end; | 277 | unsigned long *estack_end; |
270 | estack_end = in_exception_stack(cpu, (unsigned long)stack, | 278 | estack_end = in_exception_stack(cpu, (unsigned long)stack, |
@@ -1052,3 +1060,14 @@ static int __init kstack_setup(char *s) | |||
1052 | } | 1060 | } |
1053 | __setup("kstack=", kstack_setup); | 1061 | __setup("kstack=", kstack_setup); |
1054 | 1062 | ||
1063 | static int __init call_trace_setup(char *s) | ||
1064 | { | ||
1065 | if (strcmp(s, "old") == 0) | ||
1066 | call_trace = -1; | ||
1067 | else if (strcmp(s, "both") == 0) | ||
1068 | call_trace = 0; | ||
1069 | else if (strcmp(s, "new") == 0) | ||
1070 | call_trace = 1; | ||
1071 | return 1; | ||
1072 | } | ||
1073 | __setup("call_trace=", call_trace_setup); | ||