aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Makefile7
-rw-r--r--arch/mips/kernel/ftrace.c24
-rw-r--r--arch/mips/kernel/mcount.S14
3 files changed, 38 insertions, 7 deletions
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 3725ee923d05..d2c39fdcdfeb 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -51,6 +51,13 @@ endif
51ifndef CONFIG_FUNCTION_TRACER 51ifndef CONFIG_FUNCTION_TRACER
52cflags-y := -ffunction-sections 52cflags-y := -ffunction-sections
53endif 53endif
54ifdef CONFIG_FUNCTION_GRAPH_TRACER
55 ifndef KBUILD_MCOUNT_RA_ADDRESS
56 ifeq ($(call cc-option-yn,-mmcount-ra-address), y)
57 cflags-y += -mmcount-ra-address -DKBUILD_MCOUNT_RA_ADDRESS
58 endif
59 endif
60endif
54cflags-y += $(call cc-option, -mno-check-zero-division) 61cflags-y += $(call cc-option, -mno-check-zero-division)
55 62
56ifdef CONFIG_32BIT 63ifdef CONFIG_32BIT
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:
133NESTED(ftrace_graph_caller, PT_SIZE, ra) 136NESTED(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 */
1511: 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 */