Root/
1 | function tracer guts |
2 | ==================== |
3 | By Mike Frysinger |
4 | |
5 | Introduction |
6 | ------------ |
7 | |
8 | Here we will cover the architecture pieces that the common function tracing |
9 | code relies on for proper functioning. Things are broken down into increasing |
10 | complexity so that you can start simple and at least get basic functionality. |
11 | |
12 | Note that this focuses on architecture implementation details only. If you |
13 | want more explanation of a feature in terms of common code, review the common |
14 | ftrace.txt file. |
15 | |
16 | |
17 | Prerequisites |
18 | ------------- |
19 | |
20 | Ftrace relies on these features being implemented: |
21 | STACKTRACE_SUPPORT - implement save_stack_trace() |
22 | TRACE_IRQFLAGS_SUPPORT - implement include/asm/irqflags.h |
23 | |
24 | |
25 | HAVE_FUNCTION_TRACER |
26 | -------------------- |
27 | |
28 | You will need to implement the mcount and the ftrace_stub functions. |
29 | |
30 | The exact mcount symbol name will depend on your toolchain. Some call it |
31 | "mcount", "_mcount", or even "__mcount". You can probably figure it out by |
32 | running something like: |
33 | $ echo 'main(){}' | gcc -x c -S -o - - -pg | grep mcount |
34 | call mcount |
35 | We'll make the assumption below that the symbol is "mcount" just to keep things |
36 | nice and simple in the examples. |
37 | |
38 | Keep in mind that the ABI that is in effect inside of the mcount function is |
39 | *highly* architecture/toolchain specific. We cannot help you in this regard, |
40 | sorry. Dig up some old documentation and/or find someone more familiar than |
41 | you to bang ideas off of. Typically, register usage (argument/scratch/etc...) |
42 | is a major issue at this point, especially in relation to the location of the |
43 | mcount call (before/after function prologue). You might also want to look at |
44 | how glibc has implemented the mcount function for your architecture. It might |
45 | be (semi-)relevant. |
46 | |
47 | The mcount function should check the function pointer ftrace_trace_function |
48 | to see if it is set to ftrace_stub. If it is, there is nothing for you to do, |
49 | so return immediately. If it isn't, then call that function in the same way |
50 | the mcount function normally calls __mcount_internal -- the first argument is |
51 | the "frompc" while the second argument is the "selfpc" (adjusted to remove the |
52 | size of the mcount call that is embedded in the function). |
53 | |
54 | For example, if the function foo() calls bar(), when the bar() function calls |
55 | mcount(), the arguments mcount() will pass to the tracer are: |
56 | "frompc" - the address bar() will use to return to foo() |
57 | "selfpc" - the address bar() (with mcount() size adjustment) |
58 | |
59 | Also keep in mind that this mcount function will be called *a lot*, so |
60 | optimizing for the default case of no tracer will help the smooth running of |
61 | your system when tracing is disabled. So the start of the mcount function is |
62 | typically the bare minimum with checking things before returning. That also |
63 | means the code flow should usually be kept linear (i.e. no branching in the nop |
64 | case). This is of course an optimization and not a hard requirement. |
65 | |
66 | Here is some pseudo code that should help (these functions should actually be |
67 | implemented in assembly): |
68 | |
69 | void ftrace_stub(void) |
70 | { |
71 | return; |
72 | } |
73 | |
74 | void mcount(void) |
75 | { |
76 | /* save any bare state needed in order to do initial checking */ |
77 | |
78 | extern void (*ftrace_trace_function)(unsigned long, unsigned long); |
79 | if (ftrace_trace_function != ftrace_stub) |
80 | goto do_trace; |
81 | |
82 | /* restore any bare state */ |
83 | |
84 | return; |
85 | |
86 | do_trace: |
87 | |
88 | /* save all state needed by the ABI (see paragraph above) */ |
89 | |
90 | unsigned long frompc = ...; |
91 | unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE; |
92 | ftrace_trace_function(frompc, selfpc); |
93 | |
94 | /* restore all state needed by the ABI */ |
95 | } |
96 | |
97 | Don't forget to export mcount for modules ! |
98 | extern void mcount(void); |
99 | EXPORT_SYMBOL(mcount); |
100 | |
101 | |
102 | HAVE_FUNCTION_TRACE_MCOUNT_TEST |
103 | ------------------------------- |
104 | |
105 | This is an optional optimization for the normal case when tracing is turned off |
106 | in the system. If you do not enable this Kconfig option, the common ftrace |
107 | code will take care of doing the checking for you. |
108 | |
109 | To support this feature, you only need to check the function_trace_stop |
110 | variable in the mcount function. If it is non-zero, there is no tracing to be |
111 | done at all, so you can return. |
112 | |
113 | This additional pseudo code would simply be: |
114 | void mcount(void) |
115 | { |
116 | /* save any bare state needed in order to do initial checking */ |
117 | |
118 | + if (function_trace_stop) |
119 | + return; |
120 | |
121 | extern void (*ftrace_trace_function)(unsigned long, unsigned long); |
122 | if (ftrace_trace_function != ftrace_stub) |
123 | ... |
124 | |
125 | |
126 | HAVE_FUNCTION_GRAPH_TRACER |
127 | -------------------------- |
128 | |
129 | Deep breath ... time to do some real work. Here you will need to update the |
130 | mcount function to check ftrace graph function pointers, as well as implement |
131 | some functions to save (hijack) and restore the return address. |
132 | |
133 | The mcount function should check the function pointers ftrace_graph_return |
134 | (compare to ftrace_stub) and ftrace_graph_entry (compare to |
135 | ftrace_graph_entry_stub). If either of those is not set to the relevant stub |
136 | function, call the arch-specific function ftrace_graph_caller which in turn |
137 | calls the arch-specific function prepare_ftrace_return. Neither of these |
138 | function names is strictly required, but you should use them anyway to stay |
139 | consistent across the architecture ports -- easier to compare & contrast |
140 | things. |
141 | |
142 | The arguments to prepare_ftrace_return are slightly different than what are |
143 | passed to ftrace_trace_function. The second argument "selfpc" is the same, |
144 | but the first argument should be a pointer to the "frompc". Typically this is |
145 | located on the stack. This allows the function to hijack the return address |
146 | temporarily to have it point to the arch-specific function return_to_handler. |
147 | That function will simply call the common ftrace_return_to_handler function and |
148 | that will return the original return address with which you can return to the |
149 | original call site. |
150 | |
151 | Here is the updated mcount pseudo code: |
152 | void mcount(void) |
153 | { |
154 | ... |
155 | if (ftrace_trace_function != ftrace_stub) |
156 | goto do_trace; |
157 | |
158 | +#ifdef CONFIG_FUNCTION_GRAPH_TRACER |
159 | + extern void (*ftrace_graph_return)(...); |
160 | + extern void (*ftrace_graph_entry)(...); |
161 | + if (ftrace_graph_return != ftrace_stub || |
162 | + ftrace_graph_entry != ftrace_graph_entry_stub) |
163 | + ftrace_graph_caller(); |
164 | +#endif |
165 | |
166 | /* restore any bare state */ |
167 | ... |
168 | |
169 | Here is the pseudo code for the new ftrace_graph_caller assembly function: |
170 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
171 | void ftrace_graph_caller(void) |
172 | { |
173 | /* save all state needed by the ABI */ |
174 | |
175 | unsigned long *frompc = &...; |
176 | unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE; |
177 | /* passing frame pointer up is optional -- see below */ |
178 | prepare_ftrace_return(frompc, selfpc, frame_pointer); |
179 | |
180 | /* restore all state needed by the ABI */ |
181 | } |
182 | #endif |
183 | |
184 | For information on how to implement prepare_ftrace_return(), simply look at the |
185 | x86 version (the frame pointer passing is optional; see the next section for |
186 | more information). The only architecture-specific piece in it is the setup of |
187 | the fault recovery table (the asm(...) code). The rest should be the same |
188 | across architectures. |
189 | |
190 | Here is the pseudo code for the new return_to_handler assembly function. Note |
191 | that the ABI that applies here is different from what applies to the mcount |
192 | code. Since you are returning from a function (after the epilogue), you might |
193 | be able to skimp on things saved/restored (usually just registers used to pass |
194 | return values). |
195 | |
196 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
197 | void return_to_handler(void) |
198 | { |
199 | /* save all state needed by the ABI (see paragraph above) */ |
200 | |
201 | void (*original_return_point)(void) = ftrace_return_to_handler(); |
202 | |
203 | /* restore all state needed by the ABI */ |
204 | |
205 | /* this is usually either a return or a jump */ |
206 | original_return_point(); |
207 | } |
208 | #endif |
209 | |
210 | |
211 | HAVE_FUNCTION_GRAPH_FP_TEST |
212 | --------------------------- |
213 | |
214 | An arch may pass in a unique value (frame pointer) to both the entering and |
215 | exiting of a function. On exit, the value is compared and if it does not |
216 | match, then it will panic the kernel. This is largely a sanity check for bad |
217 | code generation with gcc. If gcc for your port sanely updates the frame |
218 | pointer under different opitmization levels, then ignore this option. |
219 | |
220 | However, adding support for it isn't terribly difficult. In your assembly code |
221 | that calls prepare_ftrace_return(), pass the frame pointer as the 3rd argument. |
222 | Then in the C version of that function, do what the x86 port does and pass it |
223 | along to ftrace_push_return_trace() instead of a stub value of 0. |
224 | |
225 | Similarly, when you call ftrace_return_to_handler(), pass it the frame pointer. |
226 | |
227 | |
228 | HAVE_FTRACE_NMI_ENTER |
229 | --------------------- |
230 | |
231 | If you can't trace NMI functions, then skip this option. |
232 | |
233 | <details to be filled> |
234 | |
235 | |
236 | HAVE_SYSCALL_TRACEPOINTS |
237 | --------------------- |
238 | |
239 | You need very few things to get the syscalls tracing in an arch. |
240 | |
241 | - Support HAVE_ARCH_TRACEHOOK (see arch/Kconfig). |
242 | - Have a NR_syscalls variable in <asm/unistd.h> that provides the number |
243 | of syscalls supported by the arch. |
244 | - Support the TIF_SYSCALL_TRACEPOINT thread flags. |
245 | - Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace |
246 | in the ptrace syscalls tracing path. |
247 | - Tag this arch as HAVE_SYSCALL_TRACEPOINTS. |
248 | |
249 | |
250 | HAVE_FTRACE_MCOUNT_RECORD |
251 | ------------------------- |
252 | |
253 | See scripts/recordmcount.pl for more info. |
254 | |
255 | <details to be filled> |
256 | |
257 | |
258 | HAVE_DYNAMIC_FTRACE |
259 | --------------------- |
260 | |
261 | <details to be filled> |
262 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9