From 4e14dfc722b8e9e07a355f97aa60a3d9f0739071 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 7 Aug 2009 16:11:19 +0100 Subject: sh: Use the generalized stacktrace ops Copy the stacktrace ops code from x86 and provide a central function for use by functions that need to dump a callstack. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/kernel/stacktrace.c | 87 +++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 26 deletions(-) (limited to 'arch/sh/kernel/stacktrace.c') diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c index 1a2a5eb76e41..6c24a400b05e 100644 --- a/arch/sh/kernel/stacktrace.c +++ b/arch/sh/kernel/stacktrace.c @@ -14,46 +14,81 @@ #include #include #include +#include + +static void save_stack_warning(void *data, char *msg) +{ +} + +static void +save_stack_warning_symbol(void *data, char *msg, unsigned long symbol) +{ +} + +static int save_stack_stack(void *data, char *name) +{ + return 0; +} /* * Save stack-backtrace addresses into a stack_trace buffer. */ +static void save_stack_address(void *data, unsigned long addr, int reliable) +{ + struct stack_trace *trace = data; + + if (trace->skip > 0) { + trace->skip--; + return; + } + + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = addr; +} + +static const struct stacktrace_ops save_stack_ops = { + .warning = save_stack_warning, + .warning_symbol = save_stack_warning_symbol, + .stack = save_stack_stack, + .address = save_stack_address, +}; + void save_stack_trace(struct stack_trace *trace) { unsigned long *sp = (unsigned long *)current_stack_pointer; - while (!kstack_end(sp)) { - unsigned long addr = *sp++; - - if (__kernel_text_address(addr)) { - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = addr; - if (trace->nr_entries >= trace->max_entries) - break; - } - } + dump_trace(current, NULL, sp, &save_stack_ops, trace); } EXPORT_SYMBOL_GPL(save_stack_trace); +static void +save_stack_address_nosched(void *data, unsigned long addr, int reliable) +{ + struct stack_trace *trace = (struct stack_trace *)data; + + if (in_sched_functions(addr)) + return; + + if (trace->skip > 0) { + trace->skip--; + return; + } + + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = addr; +} + +static const struct stacktrace_ops save_stack_ops_nosched = { + .warning = save_stack_warning, + .warning_symbol = save_stack_warning_symbol, + .stack = save_stack_stack, + .address = save_stack_address_nosched, +}; + void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { unsigned long *sp = (unsigned long *)tsk->thread.sp; - while (!kstack_end(sp)) { - unsigned long addr = *sp++; - - if (__kernel_text_address(addr)) { - if (in_sched_functions(addr)) - break; - if (trace->skip > 0) - trace->skip--; - else - trace->entries[trace->nr_entries++] = addr; - if (trace->nr_entries >= trace->max_entries) - break; - } - } + dump_trace(current, NULL, sp, &save_stack_ops_nosched, trace); } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); -- cgit v1.2.3 From 0eff9f66de79a0707a9c3a2f8528ccfd62100f0b Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 11 Aug 2009 22:43:20 +0100 Subject: sh: Use the new stack unwinder API Instead of implementing our own stack unwinder via dump_trace() we should use the new stack unwinder API because it is more modular. This change allows us to decouple the interface for generating stacktraces from the implementation of a stack unwinder. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/kernel/stacktrace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/sh/kernel/stacktrace.c') diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c index 6c24a400b05e..45b1adde3abe 100644 --- a/arch/sh/kernel/stacktrace.c +++ b/arch/sh/kernel/stacktrace.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ void save_stack_trace(struct stack_trace *trace) { unsigned long *sp = (unsigned long *)current_stack_pointer; - dump_trace(current, NULL, sp, &save_stack_ops, trace); + unwind_stack(current, NULL, sp, &save_stack_ops, trace); } EXPORT_SYMBOL_GPL(save_stack_trace); @@ -89,6 +90,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { unsigned long *sp = (unsigned long *)tsk->thread.sp; - dump_trace(current, NULL, sp, &save_stack_ops_nosched, trace); + unwind_stack(current, NULL, sp, &save_stack_ops_nosched, trace); } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); -- cgit v1.2.3 From 48e4d4604b7da52d6a56ddc821a460b183b7353d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 15 Aug 2009 01:05:46 +0900 Subject: sh: stacktrace: Add reliability checks in address saving ops. This adopts the reliability checks from the x86 stacktrace code so known bad addresses are not recorded in the stack trace buffer. Signed-off-by: Paul Mundt --- arch/sh/kernel/stacktrace.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/sh/kernel/stacktrace.c') diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c index 45b1adde3abe..a0f497bcbb4f 100644 --- a/arch/sh/kernel/stacktrace.c +++ b/arch/sh/kernel/stacktrace.c @@ -38,6 +38,9 @@ static void save_stack_address(void *data, unsigned long addr, int reliable) { struct stack_trace *trace = data; + if (!reliable) + return; + if (trace->skip > 0) { trace->skip--; return; @@ -67,6 +70,9 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable) { struct stack_trace *trace = (struct stack_trace *)data; + if (!reliable) + return; + if (in_sched_functions(addr)) return; -- cgit v1.2.3 From 606b4c992f3b28f906100f1b6eb49059909d8da7 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 15 Aug 2009 01:11:37 +0900 Subject: sh: stacktrace: Properly terminate the trace entry buffer. This inserts a ULONG_MAX entry at the end of the valid entries in the stack trace buffer so the default code doesn't need to scan to the end of available slots. This also makes the trace buffer termination behaviour consistent with the other architectures. Signed-off-by: Paul Mundt --- arch/sh/kernel/stacktrace.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/sh/kernel/stacktrace.c') diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c index a0f497bcbb4f..c2e45c48409c 100644 --- a/arch/sh/kernel/stacktrace.c +++ b/arch/sh/kernel/stacktrace.c @@ -62,6 +62,8 @@ void save_stack_trace(struct stack_trace *trace) unsigned long *sp = (unsigned long *)current_stack_pointer; unwind_stack(current, NULL, sp, &save_stack_ops, trace); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; } EXPORT_SYMBOL_GPL(save_stack_trace); @@ -97,5 +99,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) unsigned long *sp = (unsigned long *)tsk->thread.sp; unwind_stack(current, NULL, sp, &save_stack_ops_nosched, trace); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; } EXPORT_SYMBOL_GPL(save_stack_trace_tsk); -- cgit v1.2.3