diff options
Diffstat (limited to 'arch/mips/kernel/ftrace.c')
-rw-r--r-- | arch/mips/kernel/ftrace.c | 24 |
1 files changed, 17 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)) |