diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/ftrace.c | 24 | ||||
-rw-r--r-- | arch/mips/kernel/mcount.S | 14 |
2 files changed, 31 insertions, 7 deletions
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index e363fc69aabd..68b067040d8b 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c | |||
@@ -148,6 +148,7 @@ int ftrace_disable_ftrace_graph_caller(void) | |||
148 | 148 | ||
149 | #endif /* !CONFIG_DYNAMIC_FTRACE */ | 149 | #endif /* !CONFIG_DYNAMIC_FTRACE */ |
150 | 150 | ||
151 | #ifndef KBUILD_MCOUNT_RA_ADDRESS | ||
151 | #define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ | 152 | #define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ |
152 | #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ | 153 | #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ |
153 | #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ | 154 | #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ |
@@ -201,6 +202,8 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, | |||
201 | return 0; | 202 | return 0; |
202 | } | 203 | } |
203 | 204 | ||
205 | #endif | ||
206 | |||
204 | /* | 207 | /* |
205 | * Hook the return address and push it in the stack of return addrs | 208 | * Hook the return address and push it in the stack of return addrs |
206 | * in current thread info. | 209 | * in current thread info. |
@@ -218,19 +221,26 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, | |||
218 | return; | 221 | return; |
219 | 222 | ||
220 | /* "parent" is the stack address saved the return address of the caller | 223 | /* "parent" is the stack address saved the return address of the caller |
221 | * of _mcount, for a leaf function not save the return address in the | 224 | * of _mcount. |
222 | * stack address, so, we "emulate" one in _mcount's stack space, and | 225 | * |
223 | * hijack it directly, but for a non-leaf function, it will save the | 226 | * if the gcc < 4.5, a leaf function does not save the return address |
224 | * return address to the its stack space, so, we can not hijack the | 227 | * in the stack address, so, we "emulate" one in _mcount's stack space, |
225 | * "parent" directly, but need to find the real stack address, | 228 | * and hijack it directly, but for a non-leaf function, it save the |
229 | * return address to the its own stack space, we can not hijack it | ||
230 | * directly, but need to find the real stack address, | ||
226 | * ftrace_get_parent_addr() does it! | 231 | * ftrace_get_parent_addr() does it! |
232 | * | ||
233 | * if gcc>= 4.5, with the new -mmcount-ra-address option, for a | ||
234 | * non-leaf function, the location of the return address will be saved | ||
235 | * to $12 for us, and for a leaf function, only put a zero into $12. we | ||
236 | * do it in ftrace_graph_caller of mcount.S. | ||
227 | */ | 237 | */ |
228 | 238 | ||
229 | /* old = *parent; */ | 239 | /* old = *parent; */ |
230 | safe_load_stack(old, parent, faulted); | 240 | safe_load_stack(old, parent, faulted); |
231 | if (unlikely(faulted)) | 241 | if (unlikely(faulted)) |
232 | goto out; | 242 | goto out; |
233 | 243 | #ifndef KBUILD_MCOUNT_RA_ADDRESS | |
234 | parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, | 244 | parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, |
235 | (unsigned long)parent, | 245 | (unsigned long)parent, |
236 | fp); | 246 | fp); |
@@ -238,7 +248,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, | |||
238 | * ra, stop function graph tracer and return */ | 248 | * ra, stop function graph tracer and return */ |
239 | if (parent == 0) | 249 | if (parent == 0) |
240 | goto out; | 250 | goto out; |
241 | 251 | #endif | |
242 | /* *parent = return_hooker; */ | 252 | /* *parent = return_hooker; */ |
243 | safe_store_stack(return_hooker, parent, faulted); | 253 | safe_store_stack(return_hooker, parent, faulted); |
244 | if (unlikely(faulted)) | 254 | if (unlikely(faulted)) |
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 522e91c688fc..0a9cfdb271dd 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S | |||
@@ -70,6 +70,9 @@ _mcount: | |||
70 | nop | 70 | nop |
71 | 71 | ||
72 | MCOUNT_SAVE_REGS | 72 | MCOUNT_SAVE_REGS |
73 | #ifdef KBUILD_MCOUNT_RA_ADDRESS | ||
74 | PTR_S t0, PT_R12(sp) /* t0 saved the location of the return address(at) by -mmcount-ra-address */ | ||
75 | #endif | ||
73 | 76 | ||
74 | move a0, ra /* arg1: next ip, selfaddr */ | 77 | move a0, ra /* arg1: next ip, selfaddr */ |
75 | .globl ftrace_call | 78 | .globl ftrace_call |
@@ -133,11 +136,22 @@ ftrace_stub: | |||
133 | NESTED(ftrace_graph_caller, PT_SIZE, ra) | 136 | NESTED(ftrace_graph_caller, PT_SIZE, ra) |
134 | #ifdef CONFIG_DYNAMIC_FTRACE | 137 | #ifdef CONFIG_DYNAMIC_FTRACE |
135 | PTR_L a1, PT_R31(sp) /* load the original ra from the stack */ | 138 | PTR_L a1, PT_R31(sp) /* load the original ra from the stack */ |
139 | #ifdef KBUILD_MCOUNT_RA_ADDRESS | ||
140 | PTR_L t0, PT_R12(sp) /* load the original t0 from the stack */ | ||
141 | #endif | ||
136 | #else | 142 | #else |
137 | MCOUNT_SAVE_REGS | 143 | MCOUNT_SAVE_REGS |
138 | move a1, ra /* arg2: next ip, selfaddr */ | 144 | move a1, ra /* arg2: next ip, selfaddr */ |
139 | #endif | 145 | #endif |
146 | |||
147 | #ifdef KBUILD_MCOUNT_RA_ADDRESS | ||
148 | bnez t0, 1f /* non-leaf func: t0 saved the location of the return address */ | ||
149 | nop | ||
150 | PTR_LA t0, PT_R1(sp) /* leaf func: get the location of at(old ra) from our own stack */ | ||
151 | 1: move a0, t0 /* arg1: the location of the return address */ | ||
152 | #else | ||
140 | PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */ | 153 | PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */ |
154 | #endif | ||
141 | jal prepare_ftrace_return | 155 | jal prepare_ftrace_return |
142 | #ifdef CONFIG_FRAME_POINTER | 156 | #ifdef CONFIG_FRAME_POINTER |
143 | move a2, fp /* arg3: frame pointer */ | 157 | move a2, fp /* arg3: frame pointer */ |