aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/stacktrace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-06 16:20:10 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-06 16:20:10 -0400
commitc6799ade4ae04b53a5f677e5289116155ff01574 (patch)
tree3601b5e2387e39d62c207e4268c6cc5c68f2a364 /arch/arm/kernel/stacktrace.c
parentb7405e16435f710edfae6ba32bef4ca20d3de145 (diff)
parent5cd47155155a32e5b944ac9fc3f3dc578e429aa0 (diff)
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (82 commits) [ARM] Add comments marking in-use ptrace numbers [ARM] Move syscall saving out of the way of utrace [ARM] 4360/1: S3C24XX: regs-udc.h remove unused macro [ARM] 4358/1: S3C24XX: mach-qt2410.c: remove linux/mmc/protocol.h header [ARM] mm 10: allow memory type to be specified with ioremap [ARM] mm 9: add additional device memory types [ARM] mm 8: define mem_types table L1 bit 4 to be for ARMv6 [ARM] iop: add missing parens in macro [ARM] mm 7: remove duplicated __ioremap() prototypes ARM: OMAP: fix OMAP1 mpuio suspend/resume oops ARM: OMAP: MPUIO wake updates ARM: OMAP: speed up gpio irq handling ARM: OMAP: plat-omap changes for 2430 SDP ARM: OMAP: gpio object shrinkage, cleanup ARM: OMAP: /sys/kernel/debug/omap_gpio ARM: OMAP: Implement workaround for GPIO wakeup bug in OMAP2420 silicon ARM: OMAP: Enable 24xx GPIO autoidling [ARM] 4318/2: DSM-G600 Board Support [ARM] 4227/1: minor head.S fixups [ARM] 4328/1: Move i.MX UART regs to driver ...
Diffstat (limited to 'arch/arm/kernel/stacktrace.c')
-rw-r--r--arch/arm/kernel/stacktrace.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
new file mode 100644
index 000000000000..77ef35efaa8d
--- /dev/null
+++ b/arch/arm/kernel/stacktrace.c
@@ -0,0 +1,73 @@
1#include <linux/sched.h>
2#include <linux/stacktrace.h>
3
4#include "stacktrace.h"
5
6int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
7 int (*fn)(struct stackframe *, void *), void *data)
8{
9 struct stackframe *frame;
10
11 do {
12 /*
13 * Check current frame pointer is within bounds
14 */
15 if ((fp - 12) < low || fp + 4 >= high)
16 break;
17
18 frame = (struct stackframe *)(fp - 12);
19
20 if (fn(frame, data))
21 break;
22
23 /*
24 * Update the low bound - the next frame must always
25 * be at a higher address than the current frame.
26 */
27 low = fp + 4;
28 fp = frame->fp;
29 } while (fp);
30
31 return 0;
32}
33
34#ifdef CONFIG_STACKTRACE
35struct stack_trace_data {
36 struct stack_trace *trace;
37 unsigned int skip;
38};
39
40static int save_trace(struct stackframe *frame, void *d)
41{
42 struct stack_trace_data *data = d;
43 struct stack_trace *trace = data->trace;
44
45 if (data->skip) {
46 data->skip--;
47 return 0;
48 }
49
50 trace->entries[trace->nr_entries++] = frame->lr;
51
52 return trace->nr_entries >= trace->max_entries;
53}
54
55void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
56{
57 struct stack_trace_data data;
58 unsigned long fp, base;
59
60 data.trace = trace;
61 data.skip = trace->skip;
62
63 if (task) {
64 base = (unsigned long)task_stack_page(task);
65 fp = 0; /* FIXME */
66 } else {
67 base = (unsigned long)task_stack_page(current);
68 asm("mov %0, fp" : "=r" (fp));
69 }
70
71 walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
72}
73#endif