asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24;
+static int call_trace = 1;
ATOMIC_NOTIFIER_HEAD(i386die_chain);
int register_die_notifier(struct notifier_block *nb)
return ebp;
}
-static asmlinkage void show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
+static asmlinkage int show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
{
+ int n = 0;
int printed = 0; /* nr of entries already printed on current line */
while (unwind(info) == 0 && UNW_PC(info)) {
+ ++n;
printed = print_addr_and_symbol(UNW_PC(info), log_lvl, printed);
if (arch_unw_user_mode(info))
break;
}
if (printed)
printk("\n");
+ return n;
}
static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, char *log_lvl)
{
unsigned long ebp;
- struct unwind_frame_info info;
if (!task)
task = current;
- if (regs) {
- if (unwind_init_frame_info(&info, task, regs) == 0) {
- show_trace_unwind(&info, log_lvl);
- return;
+ if (call_trace >= 0) {
+ int unw_ret = 0;
+ struct unwind_frame_info info;
+
+ if (regs) {
+ if (unwind_init_frame_info(&info, task, regs) == 0)
+ unw_ret = show_trace_unwind(&info, log_lvl);
+ } else if (task == current)
+ unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
+ else {
+ if (unwind_init_blocked(&info, task) == 0)
+ unw_ret = show_trace_unwind(&info, log_lvl);
}
- } else if (task == current) {
- if (unwind_init_running(&info, show_trace_unwind, log_lvl) == 0)
- return;
- } else {
- if (unwind_init_blocked(&info, task) == 0) {
- show_trace_unwind(&info, log_lvl);
- return;
+ if (unw_ret > 0) {
+ if (call_trace > 0)
+ return;
+ printk("%sLegacy call trace:\n", log_lvl);
}
}
return 1;
}
__setup("kstack=", kstack_setup);
+
+static int __init call_trace_setup(char *s)
+{
+ if (strcmp(s, "old") == 0)
+ call_trace = -1;
+ else if (strcmp(s, "both") == 0)
+ call_trace = 0;
+ else if (strcmp(s, "new") == 0)
+ call_trace = 1;
+ return 1;
+}
+__setup("call_trace=", call_trace_setup);
}
static int kstack_depth_to_print = 10;
+static int call_trace = 1;
#ifdef CONFIG_KALLSYMS
#include <linux/kallsyms.h>
return NULL;
}
-static void show_trace_unwind(struct unwind_frame_info *info, void *context)
+static int show_trace_unwind(struct unwind_frame_info *info, void *context)
{
- int i = 11;
+ int i = 11, n = 0;
while (unwind(info) == 0 && UNW_PC(info)) {
+ ++n;
if (i > 50) {
printk("\n ");
i = 7;
break;
}
printk("\n");
+ return n;
}
/*
{
const unsigned cpu = safe_smp_processor_id();
unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
- int i;
+ int i = 11;
unsigned used = 0;
- struct unwind_frame_info info;
printk("\nCall Trace:");
if (!tsk)
tsk = current;
- if (regs) {
- if (unwind_init_frame_info(&info, tsk, regs) == 0) {
- show_trace_unwind(&info, NULL);
- return;
+ if (call_trace >= 0) {
+ int unw_ret = 0;
+ struct unwind_frame_info info;
+
+ if (regs) {
+ if (unwind_init_frame_info(&info, tsk, regs) == 0)
+ unw_ret = show_trace_unwind(&info, NULL);
+ } else if (tsk == current)
+ unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
+ else {
+ if (unwind_init_blocked(&info, tsk) == 0)
+ unw_ret = show_trace_unwind(&info, NULL);
}
- } else if (tsk == current) {
- if (unwind_init_running(&info, show_trace_unwind, NULL) == 0)
- return;
- } else {
- if (unwind_init_blocked(&info, tsk) == 0) {
- show_trace_unwind(&info, NULL);
- return;
+ if (unw_ret > 0) {
+ if (call_trace > 0)
+ return;
+ printk("Legacy call trace:");
+ i = 18;
}
}
} \
} while (0)
- for(i = 11; ; ) {
+ for(; ; ) {
const char *id;
unsigned long *estack_end;
estack_end = in_exception_stack(cpu, (unsigned long)stack,
}
__setup("kstack=", kstack_setup);
+static int __init call_trace_setup(char *s)
+{
+ if (strcmp(s, "old") == 0)
+ call_trace = -1;
+ else if (strcmp(s, "both") == 0)
+ call_trace = 0;
+ else if (strcmp(s, "new") == 0)
+ call_trace = 1;
+ return 1;
+}
+__setup("call_trace=", call_trace_setup);
info->regs.xes = __USER_DS;
}
-extern asmlinkage void arch_unwind_init_running(struct unwind_frame_info *,
- asmlinkage void (*callback)(struct unwind_frame_info *,
- void *arg),
- void *arg);
+extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
+ asmlinkage int (*callback)(struct unwind_frame_info *,
+ void *arg),
+ void *arg);
static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
{
info->regs.ss = __KERNEL_DS;
}
-extern void arch_unwind_init_running(struct unwind_frame_info *,
- void (*callback)(struct unwind_frame_info *,
- void *arg),
- void *arg);
+extern int arch_unwind_init_running(struct unwind_frame_info *,
+ int (*callback)(struct unwind_frame_info *,
+ void *arg),
+ void *arg);
static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
{
* Prepare to unwind the currently running thread.
*/
extern int unwind_init_running(struct unwind_frame_info *,
- asmlinkage void (*callback)(struct unwind_frame_info *,
- void *arg),
+ asmlinkage int (*callback)(struct unwind_frame_info *,
+ void *arg),
void *arg);
/*
}
static inline int unwind_init_running(struct unwind_frame_info *info,
- asmlinkage void (*cb)(struct unwind_frame_info *,
- void *arg),
+ asmlinkage int (*cb)(struct unwind_frame_info *,
+ void *arg),
void *arg)
{
return -ENOSYS;
* Prepare to unwind the currently running thread.
*/
int unwind_init_running(struct unwind_frame_info *info,
- asmlinkage void (*callback)(struct unwind_frame_info *,
- void *arg),
+ asmlinkage int (*callback)(struct unwind_frame_info *,
+ void *arg),
void *arg)
{
info->task = current;
- arch_unwind_init_running(info, callback, arg);
- return 0;
+ return arch_unwind_init_running(info, callback, arg);
}
EXPORT_SYMBOL(unwind_init_running);