diff options
author | Yi Li <yi.li@analog.com> | 2010-01-25 23:02:44 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-03-09 00:30:50 -0500 |
commit | 7136d9c5e874813ccbd1d438924c413b7305944c (patch) | |
tree | ace35ccc968c92a21839a33f1a749f3e3812bc38 | |
parent | 652afdc3403cbccb93c7e6db582a1204a9e5e90a (diff) |
Blackfin: add CALLER_ADDR ftrace macros
Since GCC doesn't support __builtin_frame_address(n) where n!=0, add our
own function to walk the stack frame pointers.
Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r-- | arch/blackfin/include/asm/ftrace.h | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h index 90c9b400ba6d..4cfe2d9ba7e8 100644 --- a/arch/blackfin/include/asm/ftrace.h +++ b/arch/blackfin/include/asm/ftrace.h | |||
@@ -10,4 +10,57 @@ | |||
10 | 10 | ||
11 | #define MCOUNT_INSN_SIZE 6 /* sizeof "[++sp] = rets; call __mcount;" */ | 11 | #define MCOUNT_INSN_SIZE 6 /* sizeof "[++sp] = rets; call __mcount;" */ |
12 | 12 | ||
13 | #ifndef __ASSEMBLY__ | ||
14 | |||
15 | #ifdef CONFIG_FRAME_POINTER | ||
16 | #include <linux/mm.h> | ||
17 | |||
18 | extern inline void *return_address(unsigned int level) | ||
19 | { | ||
20 | unsigned long *endstack, *fp, *ret_addr; | ||
21 | unsigned int current_level = 0; | ||
22 | |||
23 | if (level == 0) | ||
24 | return __builtin_return_address(0); | ||
25 | |||
26 | fp = (unsigned long *)__builtin_frame_address(0); | ||
27 | endstack = (unsigned long *)PAGE_ALIGN((unsigned long)&level); | ||
28 | |||
29 | while (((unsigned long)fp & 0x3) == 0 && fp && | ||
30 | (fp + 1) < endstack && current_level < level) { | ||
31 | fp = (unsigned long *)*fp; | ||
32 | current_level++; | ||
33 | } | ||
34 | |||
35 | if (((unsigned long)fp & 0x3) == 0 && fp && | ||
36 | (fp + 1) < endstack) | ||
37 | ret_addr = (unsigned long *)*(fp + 1); | ||
38 | else | ||
39 | ret_addr = NULL; | ||
40 | |||
41 | return ret_addr; | ||
42 | } | ||
43 | |||
44 | #else | ||
45 | |||
46 | extern inline void *return_address(unsigned int level) | ||
47 | { | ||
48 | return NULL; | ||
49 | } | ||
50 | |||
51 | #endif /* CONFIG_FRAME_POINTER */ | ||
52 | |||
53 | #define HAVE_ARCH_CALLER_ADDR | ||
54 | |||
55 | /* inline function or macro may lead to unexpected result */ | ||
56 | #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) | ||
57 | #define CALLER_ADDR1 ((unsigned long)return_address(1)) | ||
58 | #define CALLER_ADDR2 ((unsigned long)return_address(2)) | ||
59 | #define CALLER_ADDR3 ((unsigned long)return_address(3)) | ||
60 | #define CALLER_ADDR4 ((unsigned long)return_address(4)) | ||
61 | #define CALLER_ADDR5 ((unsigned long)return_address(5)) | ||
62 | #define CALLER_ADDR6 ((unsigned long)return_address(6)) | ||
63 | |||
64 | #endif /* __ASSEMBLY__ */ | ||
65 | |||
13 | #endif | 66 | #endif |