0a9cfdb271dd2c2c92f0cb8f31930f84d73c6127
[kernel.git] / arch / mips / kernel / mcount.S
1 /*
2  * MIPS specific _mcount support
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive for
6  * more details.
7  *
8  * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
9  * Author: Wu Zhangjin <wuzj@lemote.com>
10  */
11
12 #include <asm/regdef.h>
13 #include <asm/stackframe.h>
14 #include <asm/ftrace.h>
15
16         .text
17         .set noreorder
18         .set noat
19
20         .macro MCOUNT_SAVE_REGS
21         PTR_SUBU        sp, PT_SIZE
22         PTR_S   ra, PT_R31(sp)
23         PTR_S   AT, PT_R1(sp)
24         PTR_S   a0, PT_R4(sp)
25         PTR_S   a1, PT_R5(sp)
26         PTR_S   a2, PT_R6(sp)
27         PTR_S   a3, PT_R7(sp)
28 #ifdef CONFIG_64BIT
29         PTR_S   a4, PT_R8(sp)
30         PTR_S   a5, PT_R9(sp)
31         PTR_S   a6, PT_R10(sp)
32         PTR_S   a7, PT_R11(sp)
33 #endif
34         .endm
35
36         .macro MCOUNT_RESTORE_REGS
37         PTR_L   ra, PT_R31(sp)
38         PTR_L   AT, PT_R1(sp)
39         PTR_L   a0, PT_R4(sp)
40         PTR_L   a1, PT_R5(sp)
41         PTR_L   a2, PT_R6(sp)
42         PTR_L   a3, PT_R7(sp)
43 #ifdef CONFIG_64BIT
44         PTR_L   a4, PT_R8(sp)
45         PTR_L   a5, PT_R9(sp)
46         PTR_L   a6, PT_R10(sp)
47         PTR_L   a7, PT_R11(sp)
48 #endif
49 #ifdef CONFIG_64BIT
50         PTR_ADDIU       sp, PT_SIZE
51 #else
52         PTR_ADDIU       sp, (PT_SIZE + 8)
53 #endif
54 .endm
55
56         .macro RETURN_BACK
57         jr ra
58          move ra, AT
59         .endm
60
61 #ifdef CONFIG_DYNAMIC_FTRACE
62
63 NESTED(ftrace_caller, PT_SIZE, ra)
64         .globl _mcount
65 _mcount:
66         b       ftrace_stub
67          nop
68         lw      t1, function_trace_stop
69         bnez    t1, ftrace_stub
70          nop
71
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
76
77         move    a0, ra          /* arg1: next ip, selfaddr */
78         .globl ftrace_call
79 ftrace_call:
80         nop     /* a placeholder for the call to a real tracing function */
81          move   a1, AT          /* arg2: the caller's next ip, parent */
82
83 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
84         .globl ftrace_graph_call
85 ftrace_graph_call:
86         nop
87          nop
88 #endif
89
90         MCOUNT_RESTORE_REGS
91         .globl ftrace_stub
92 ftrace_stub:
93         RETURN_BACK
94         END(ftrace_caller)
95
96 #else   /* ! CONFIG_DYNAMIC_FTRACE */
97
98 NESTED(_mcount, PT_SIZE, ra)
99         lw      t1, function_trace_stop
100         bnez    t1, ftrace_stub
101          nop
102         PTR_LA  t1, ftrace_stub
103         PTR_L   t2, ftrace_trace_function /* Prepare t2 for (1) */
104         bne     t1, t2, static_trace
105          nop
106
107 #ifdef  CONFIG_FUNCTION_GRAPH_TRACER
108         PTR_L   t3, ftrace_graph_return
109         bne     t1, t3, ftrace_graph_caller
110          nop
111         PTR_LA  t1, ftrace_graph_entry_stub
112         PTR_L   t3, ftrace_graph_entry
113         bne     t1, t3, ftrace_graph_caller
114          nop
115 #endif
116         b       ftrace_stub
117          nop
118
119 static_trace:
120         MCOUNT_SAVE_REGS
121
122         move    a0, ra          /* arg1: next ip, selfaddr */
123         jalr    t2              /* (1) call *ftrace_trace_function */
124          move   a1, AT          /* arg2: the caller's next ip, parent */
125
126         MCOUNT_RESTORE_REGS
127         .globl ftrace_stub
128 ftrace_stub:
129         RETURN_BACK
130         END(_mcount)
131
132 #endif  /* ! CONFIG_DYNAMIC_FTRACE */
133
134 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
135
136 NESTED(ftrace_graph_caller, PT_SIZE, ra)
137 #ifdef CONFIG_DYNAMIC_FTRACE
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
142 #else
143         MCOUNT_SAVE_REGS
144         move    a1, ra          /* arg2: next ip, selfaddr */
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
153         PTR_LA  a0, PT_R1(sp)   /* arg1: &AT -> a0 */
154 #endif
155         jal     prepare_ftrace_return
156 #ifdef CONFIG_FRAME_POINTER
157          move   a2, fp          /* arg3: frame pointer */
158 #else
159 #ifdef CONFIG_64BIT
160          PTR_LA a2, PT_SIZE(sp)
161 #else
162          PTR_LA a2, (PT_SIZE+8)(sp)
163 #endif
164 #endif
165
166         MCOUNT_RESTORE_REGS
167         RETURN_BACK
168         END(ftrace_graph_caller)
169
170         .align  2
171         .globl  return_to_handler
172 return_to_handler:
173         PTR_SUBU        sp, PT_SIZE
174         PTR_S   v0, PT_R2(sp)
175
176         jal     ftrace_return_to_handler
177          PTR_S  v1, PT_R3(sp)
178
179         /* restore the real parent address: v0 -> ra */
180         move    ra, v0
181
182         PTR_L   v0, PT_R2(sp)
183         PTR_L   v1, PT_R3(sp)
184         jr      ra
185          PTR_ADDIU      sp, PT_SIZE
186 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
187
188         .set at
189         .set reorder