aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/oprofile/backtrace.c
diff options
context:
space:
mode:
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 @@
20#include <asm/ptrace.h> 20#include <asm/ptrace.h>
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22#include <asm/sections.h> 22#include <asm/sections.h>
23#include <asm/stacktrace.h>
24
25static void backtrace_warning_symbol(void *data, char *msg,
26 unsigned long symbol)
27{
28 /* Ignore warnings */
29}
30
31static void backtrace_warning(void *data, char *msg)
32{
33 /* Ignore warnings */
34}
35
36static int backtrace_stack(void *data, char *name)
37{
38 /* Yes, we want all stacks */
39 return 0;
40}
41
42static void backtrace_address(void *data, unsigned long addr, int reliable)
43{
44 unsigned int *depth = data;
45
46 if ((*depth)--)
47 oprofile_add_trace(addr);
48}
49
50static struct stacktrace_ops backtrace_ops = {
51 .warning = backtrace_warning,
52 .warning_symbol = backtrace_warning_symbol,
53 .stack = backtrace_stack,
54 .address = backtrace_address,
55};
23 56
24/* Limit to stop backtracing too far. */ 57/* Limit to stop backtracing too far. */
25static int backtrace_limit = 20; 58static int backtrace_limit = 20;
@@ -74,23 +107,6 @@ static int valid_kernel_stack(unsigned long *stackaddr, struct pt_regs *regs)
74 return ((unsigned long)stackaddr > stack) && ((unsigned long)stackaddr < stack_base); 107 return ((unsigned long)stackaddr > stack) && ((unsigned long)stackaddr < stack_base);
75} 108}
76 109
77static unsigned long *
78kernel_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
79{
80 unsigned long addr;
81
82 /*
83 * If not a valid kernel address, keep going till we find one
84 * or the SP stops being a valid address.
85 */
86 do {
87 addr = *stackaddr++;
88 oprofile_add_trace(addr);
89 } while (valid_kernel_stack(stackaddr, regs));
90
91 return stackaddr;
92}
93
94void sh_backtrace(struct pt_regs * const regs, unsigned int depth) 110void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
95{ 111{
96 unsigned long *stackaddr; 112 unsigned long *stackaddr;
@@ -103,9 +119,9 @@ void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
103 119
104 stackaddr = (unsigned long *)regs->regs[15]; 120 stackaddr = (unsigned long *)regs->regs[15];
105 if (!user_mode(regs)) { 121 if (!user_mode(regs)) {
106 while (depth-- && valid_kernel_stack(stackaddr, regs)) 122 if (depth)
107 stackaddr = kernel_backtrace(stackaddr, regs); 123 dump_trace(NULL, regs, stackaddr,
108 124 &backtrace_ops, &depth);
109 return; 125 return;
110 } 126 }
111 127