diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-06-08 18:44:45 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-06-13 07:20:14 -0400 |
commit | c7b412f41d9c95d084e049fe83248ebb41a2d8f5 (patch) | |
tree | b5e1eefd75ed64ced934c2b24a49bc894f3010ef /arch/blackfin/kernel | |
parent | 5203fa82f3907a9c3357f84aa1cdfb57e55cc175 (diff) |
Blackfin: add preliminary support for STACKTRACE
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/stacktrace.c | 53 |
2 files changed, 54 insertions, 0 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index fd4d4328a0f2..a66dda4f4b1f 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_MODULES) += module.o | |||
23 | obj-$(CONFIG_KGDB) += kgdb.o | 23 | obj-$(CONFIG_KGDB) += kgdb.o |
24 | obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o | 24 | obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o |
25 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 25 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
26 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
26 | 27 | ||
27 | # the kgdb test puts code into L2 and without linker | 28 | # the kgdb test puts code into L2 and without linker |
28 | # relaxation, we need to force long calls to/from it | 29 | # relaxation, we need to force long calls to/from it |
diff --git a/arch/blackfin/kernel/stacktrace.c b/arch/blackfin/kernel/stacktrace.c new file mode 100644 index 000000000000..30301e1eace5 --- /dev/null +++ b/arch/blackfin/kernel/stacktrace.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Blackfin stacktrace code (mostly copied from avr32) | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/sched.h> | ||
9 | #include <linux/stacktrace.h> | ||
10 | #include <linux/thread_info.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | register unsigned long current_frame_pointer asm("FP"); | ||
14 | |||
15 | struct stackframe { | ||
16 | unsigned long fp; | ||
17 | unsigned long rets; | ||
18 | }; | ||
19 | |||
20 | /* | ||
21 | * Save stack-backtrace addresses into a stack_trace buffer. | ||
22 | */ | ||
23 | void save_stack_trace(struct stack_trace *trace) | ||
24 | { | ||
25 | unsigned long low, high; | ||
26 | unsigned long fp; | ||
27 | struct stackframe *frame; | ||
28 | int skip = trace->skip; | ||
29 | |||
30 | low = (unsigned long)task_stack_page(current); | ||
31 | high = low + THREAD_SIZE; | ||
32 | fp = current_frame_pointer; | ||
33 | |||
34 | while (fp >= low && fp <= (high - sizeof(*frame))) { | ||
35 | frame = (struct stackframe *)fp; | ||
36 | |||
37 | if (skip) { | ||
38 | skip--; | ||
39 | } else { | ||
40 | trace->entries[trace->nr_entries++] = frame->rets; | ||
41 | if (trace->nr_entries >= trace->max_entries) | ||
42 | break; | ||
43 | } | ||
44 | |||
45 | /* | ||
46 | * The next frame must be at a higher address than the | ||
47 | * current frame. | ||
48 | */ | ||
49 | low = fp + sizeof(*frame); | ||
50 | fp = frame->fp; | ||
51 | } | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||