History

[PATCH] i386/x86-64: fall back to old-style call trace if no unwinding

If no unwinding is possible at all for a certain exception instance, fall back to the old style call trace instead of not showing any trace at all. Also, allow setting the stack trace mode at the command line.

Jan Beulich committed 20 years ago

Commit c33bd9a1 parent fe7cacc6 files · +83 −45Browse files

Unified · Split

6 files
  1. arch/i386/kernel/traps.c +33 −13
  2. arch/x86_64/kernel/traps.c +35 −16
  3. include/asm-i386/unwind.h +4 −4
  4. include/asm-x86_64/unwind.h +4 −4
  5. include/linux/unwind.h +4 −4
  6. kernel/unwind.c +3 −4
arch/i386/kernel/traps.c+33−13
@@ -93,6 +93,7 @@ asmlinkage void spurious_interrupt_bug(void); · 92 unmodified lines
9393 asmlinkage void machine_check(void);
9494
9595 static int kstack_depth_to_print = 24;
96+static int call_trace = 1;
9697 ATOMIC_NOTIFIER_HEAD(i386die_chain);
9798
9899 int register_die_notifier(struct notifier_block *nb)
@@ -171,40 +172,47 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, · 72 unmodified lines
171172 return ebp;
172173 }
173174
174−static asmlinkage void show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
175+static asmlinkage int show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
175176 {
177+ int n = 0;
176178 int printed = 0; /* nr of entries already printed on current line */
177179
178180 while (unwind(info) == 0 && UNW_PC(info)) {
181+ ++n;
179182 printed = print_addr_and_symbol(UNW_PC(info), log_lvl, printed);
180183 if (arch_unw_user_mode(info))
181184 break;
182185 }
183186 if (printed)
184187 printk("\n");
188+ return n;
185189 }
186190
187191 static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
188192 unsigned long *stack, char *log_lvl)
189193 {
190194 unsigned long ebp;
191− struct unwind_frame_info info;
192195
193196 if (!task)
194197 task = current;
195198
196− if (regs) {
197− if (unwind_init_frame_info(&info, task, regs) == 0) {
198− show_trace_unwind(&info, log_lvl);
199− return;
199+ if (call_trace >= 0) {
200+ int unw_ret = 0;
201+ struct unwind_frame_info info;
202+
203+ if (regs) {
204+ if (unwind_init_frame_info(&info, task, regs) == 0)
205+ unw_ret = show_trace_unwind(&info, log_lvl);
206+ } else if (task == current)
207+ unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
208+ else {
209+ if (unwind_init_blocked(&info, task) == 0)
210+ unw_ret = show_trace_unwind(&info, log_lvl);
200211 }
201− } else if (task == current) {
202− if (unwind_init_running(&info, show_trace_unwind, log_lvl) == 0)
203− return;
204− } else {
205− if (unwind_init_blocked(&info, task) == 0) {
206− show_trace_unwind(&info, log_lvl);
207− return;
212+ if (unw_ret > 0) {
213+ if (call_trace > 0)
214+ return;
215+ printk("%sLegacy call trace:\n", log_lvl);
208216 }
209217 }
210218
@@ -1245,3 +1253,15 @@ static int __init kstack_setup(char *s) · 1034 unmodified lines
12451253 return 1;
12461254 }
12471255 __setup("kstack=", kstack_setup);
1256+
1257+static int __init call_trace_setup(char *s)
1258+{
1259+ if (strcmp(s, "old") == 0)
1260+ call_trace = -1;
1261+ else if (strcmp(s, "both") == 0)
1262+ call_trace = 0;
1263+ else if (strcmp(s, "new") == 0)
1264+ call_trace = 1;
1265+ return 1;
1266+}
1267+__setup("call_trace=", call_trace_setup);
arch/x86_64/kernel/traps.c+35−16
@@ -107,6 +107,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) · 106 unmodified lines
107107 }
108108
109109 static int kstack_depth_to_print = 10;
110+static int call_trace = 1;
110111
111112 #ifdef CONFIG_KALLSYMS
112113 #include <linux/kallsyms.h>
@@ -190,11 +191,12 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, · 77 unmodified lines
190191 return NULL;
191192 }
192193
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)
194195 {
195− int i = 11;
196+ int i = 11, n = 0;
196197
197198 while (unwind(info) == 0 && UNW_PC(info)) {
199+ ++n;
198200 if (i > 50) {
199201 printk("\n ");
200202 i = 7;
@@ -205,6 +207,7 @@ static void show_trace_unwind(struct unwind_frame_info *info, void *context) · 4 unmodified lines
205207 break;
206208 }
207209 printk("\n");
210+ return n;
208211 }
209212
210213 /*
@@ -218,27 +221,32 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s · 7 unmodified lines
218221 {
219222 const unsigned cpu = safe_smp_processor_id();
220223 unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
221− int i;
224+ int i = 11;
222225 unsigned used = 0;
223− struct unwind_frame_info info;
224226
225227 printk("\nCall Trace:");
226228
227229 if (!tsk)
228230 tsk = current;
229231
230− if (regs) {
231− if (unwind_init_frame_info(&info, tsk, regs) == 0) {
232− show_trace_unwind(&info, NULL);
233− return;
232+ if (call_trace >= 0) {
233+ int unw_ret = 0;
234+ struct unwind_frame_info info;
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);
234244 }
235− } else if (tsk == current) {
236− if (unwind_init_running(&info, show_trace_unwind, NULL) == 0)
237− return;
238− } else {
239− if (unwind_init_blocked(&info, tsk) == 0) {
240− show_trace_unwind(&info, NULL);
241− return;
245+ if (unw_ret > 0) {
246+ if (call_trace > 0)
247+ return;
248+ printk("Legacy call trace:");
249+ i = 18;
242250 }
243251 }
244252
@@ -264,7 +272,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s · 19 unmodified lines
264272 } \
265273 } while (0)
266274
267− for(i = 11; ; ) {
275+ for(; ; ) {
268276 const char *id;
269277 unsigned long *estack_end;
270278 estack_end = in_exception_stack(cpu, (unsigned long)stack,
@@ -1052,3 +1060,14 @@ static int __init kstack_setup(char *s) · 781 unmodified lines
10521060 }
10531061 __setup("kstack=", kstack_setup);
10541062
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);
include/asm-i386/unwind.h+4−4
@@ -66,10 +66,10 @@ static inline void arch_unw_init_blocked(struct unwind_frame_info *info) · 65 unmodified lines
6666 info->regs.xes = __USER_DS;
6767 }
6868
69−extern asmlinkage void arch_unwind_init_running(struct unwind_frame_info *,
70− asmlinkage void (*callback)(struct unwind_frame_info *,
71− void *arg),
72− void *arg);
69+extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
70+ asmlinkage int (*callback)(struct unwind_frame_info *,
71+ void *arg),
72+ void *arg);
7373
7474 static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
7575 {
include/asm-x86_64/unwind.h+4−4
@@ -75,10 +75,10 @@ static inline void arch_unw_init_blocked(struct unwind_frame_info *info) · 74 unmodified lines
7575 info->regs.ss = __KERNEL_DS;
7676 }
7777
78−extern void arch_unwind_init_running(struct unwind_frame_info *,
79− void (*callback)(struct unwind_frame_info *,
80− void *arg),
81− void *arg);
78+extern int arch_unwind_init_running(struct unwind_frame_info *,
79+ int (*callback)(struct unwind_frame_info *,
80+ void *arg),
81+ void *arg);
8282
8383 static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
8484 {
include/linux/unwind.h+4−4
@@ -49,8 +49,8 @@ extern int unwind_init_blocked(struct unwind_frame_info *, · 48 unmodified lines
4949 * Prepare to unwind the currently running thread.
5050 */
5151 extern int unwind_init_running(struct unwind_frame_info *,
52− asmlinkage void (*callback)(struct unwind_frame_info *,
53− void *arg),
52+ asmlinkage int (*callback)(struct unwind_frame_info *,
53+ void *arg),
5454 void *arg);
5555
5656 /*
@@ -97,8 +97,8 @@ static inline int unwind_init_blocked(struct unwind_frame_info *info, · 40 unmodified lines
9797 }
9898
9999 static inline int unwind_init_running(struct unwind_frame_info *info,
100− asmlinkage void (*cb)(struct unwind_frame_info *,
101− void *arg),
100+ asmlinkage int (*cb)(struct unwind_frame_info *,
101+ void *arg),
102102 void *arg)
103103 {
104104 return -ENOSYS;
kernel/unwind.c+3−4
@@ -885,14 +885,13 @@ EXPORT_SYMBOL(unwind_init_blocked); · 884 unmodified lines
885885 * Prepare to unwind the currently running thread.
886886 */
887887 int unwind_init_running(struct unwind_frame_info *info,
888− asmlinkage void (*callback)(struct unwind_frame_info *,
889− void *arg),
888+ asmlinkage int (*callback)(struct unwind_frame_info *,
889+ void *arg),
890890 void *arg)
891891 {
892892 info->task = current;
893− arch_unwind_init_running(info, callback, arg);
894893
895− return 0;
894+ return arch_unwind_init_running(info, callback, arg);
896895 }
897896 EXPORT_SYMBOL(unwind_init_running);
898897