diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-11-23 14:01:59 -0500 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-12-07 08:52:36 -0500 |
commit | 2f0260371f428fd78ffc2287a5c5768ea8eeab97 (patch) | |
tree | 7e9da0354fa88da8d4113267b04fba3ba337d3ec /arch/avr32/kernel | |
parent | 58bd2bfebd02ff7fe84bbb36188e908223b2c7b7 (diff) |
[AVR32] Implement stacktrace support
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32/kernel')
-rw-r--r-- | arch/avr32/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/avr32/kernel/stacktrace.c | 53 |
2 files changed, 54 insertions, 0 deletions
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile index 989fcd1fef7e..2d6d48f35f69 100644 --- a/arch/avr32/kernel/Makefile +++ b/arch/avr32/kernel/Makefile | |||
@@ -11,3 +11,4 @@ obj-y += signal.o sys_avr32.o process.o time.o | |||
11 | obj-y += init_task.o switch_to.o cpu.o | 11 | obj-y += init_task.o switch_to.o cpu.o |
12 | obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o | 12 | obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o |
13 | obj-$(CONFIG_KPROBES) += kprobes.o | 13 | obj-$(CONFIG_KPROBES) += kprobes.o |
14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
diff --git a/arch/avr32/kernel/stacktrace.c b/arch/avr32/kernel/stacktrace.c new file mode 100644 index 000000000000..9a68190bbffd --- /dev/null +++ b/arch/avr32/kernel/stacktrace.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Stack trace management functions | ||
3 | * | ||
4 | * Copyright (C) 2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/stacktrace.h> | ||
12 | #include <linux/thread_info.h> | ||
13 | |||
14 | register unsigned long current_frame_pointer asm("r7"); | ||
15 | |||
16 | struct stackframe { | ||
17 | unsigned long lr; | ||
18 | unsigned long fp; | ||
19 | }; | ||
20 | |||
21 | /* | ||
22 | * Save stack-backtrace addresses into a stack_trace buffer. | ||
23 | */ | ||
24 | void save_stack_trace(struct stack_trace *trace) | ||
25 | { | ||
26 | unsigned long low, high; | ||
27 | unsigned long fp; | ||
28 | struct stackframe *frame; | ||
29 | int skip = trace->skip; | ||
30 | |||
31 | low = (unsigned long)task_stack_page(current); | ||
32 | high = low + THREAD_SIZE; | ||
33 | fp = current_frame_pointer; | ||
34 | |||
35 | while (fp >= low && fp <= (high - 8)) { | ||
36 | frame = (struct stackframe *)fp; | ||
37 | |||
38 | if (skip) { | ||
39 | skip--; | ||
40 | } else { | ||
41 | trace->entries[trace->nr_entries++] = frame->lr; | ||
42 | if (trace->nr_entries >= trace->max_entries) | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * The next frame must be at a higher address than the | ||
48 | * current frame. | ||
49 | */ | ||
50 | low = fp + 8; | ||
51 | fp = frame->fp; | ||
52 | } | ||
53 | } | ||