summaryrefslogtreecommitdiffstats
path: root/arch/sh/oprofile/backtrace.c
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-08-07 17:11:19 +0200
committerPaul Mundt <lethal@linux-sh.org>2009-08-13 04:50:08 +0200
commit4e14dfc722b8e9e07a355f97aa60a3d9f0739071 (patch)
tree0d5b9f6ecb99a050e2ddb839aead6a1d235c26cb /arch/sh/oprofile/backtrace.c
parentsh: use printk_once (diff)
downloadlinux-4e14dfc722b8e9e07a355f97aa60a3d9f0739071.tar.xz
linux-4e14dfc722b8e9e07a355f97aa60a3d9f0739071.zip
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 <matt@console-pimps.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/oprofile/backtrace.c')
-rw-r--r--arch/sh/oprofile/backtrace.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/arch/sh/oprofile/backtrace.c b/arch/sh/oprofile/backtrace.c
index 9499a2914f89..62e4e4d0273e 100644
--- a/arch/sh/oprofile/backtrace.c
+++ b/arch/sh/oprofile/backtrace.c
@@ -20,6 +20,39 @@
#include <asm/ptrace.h>
#include <asm/uaccess.h>
#include <asm/sections.h>
+#include <asm/stacktrace.h>
+
+static void backtrace_warning_symbol(void *data, char *msg,
+ unsigned long symbol)
+{
+ /* Ignore warnings */
+}
+
+static void backtrace_warning(void *data, char *msg)
+{
+ /* Ignore warnings */
+}
+
+static int backtrace_stack(void *data, char *name)
+{
+ /* Yes, we want all stacks */
+ return 0;
+}
+
+static void backtrace_address(void *data, unsigned long addr, int reliable)
+{
+ unsigned int *depth = data;
+
+ if ((*depth)--)
+ oprofile_add_trace(addr);
+}
+
+static struct stacktrace_ops backtrace_ops = {
+ .warning = backtrace_warning,
+ .warning_symbol = backtrace_warning_symbol,
+ .stack = backtrace_stack,
+ .address = backtrace_address,
+};
/* Limit to stop backtracing too far. */
static int backtrace_limit = 20;
@@ -74,23 +107,6 @@ static int valid_kernel_stack(unsigned long *stackaddr, struct pt_regs *regs)
return ((unsigned long)stackaddr > stack) && ((unsigned long)stackaddr < stack_base);
}
-static unsigned long *
-kernel_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
-{
- unsigned long addr;
-
- /*
- * If not a valid kernel address, keep going till we find one
- * or the SP stops being a valid address.
- */
- do {
- addr = *stackaddr++;
- oprofile_add_trace(addr);
- } while (valid_kernel_stack(stackaddr, regs));
-
- return stackaddr;
-}
-
void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
{
unsigned long *stackaddr;
@@ -103,9 +119,9 @@ void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
stackaddr = (unsigned long *)regs->regs[15];
if (!user_mode(regs)) {
- while (depth-- && valid_kernel_stack(stackaddr, regs))
- stackaddr = kernel_backtrace(stackaddr, regs);
-
+ if (depth)
+ dump_trace(NULL, regs, stackaddr,
+ &backtrace_ops, &depth);
return;
}