| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 1 | 		function tracer guts | 
 | 2 | 		==================== | 
| Mike Frysinger | 0368897 | 2010-01-22 08:12:47 -0500 | [diff] [blame] | 3 | 		By Mike Frysinger | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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() | 
| Randy Dunlap | 7e25f44 | 2009-12-18 15:17:12 -0800 | [diff] [blame] | 57 | 	"selfpc" - the address bar() (with mcount() size adjustment) | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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 | 
| Randy Dunlap | 7e25f44 | 2009-12-18 15:17:12 -0800 | [diff] [blame] | 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. | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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 | 
| Randy Dunlap | 7e25f44 | 2009-12-18 15:17:12 -0800 | [diff] [blame] | 135 | ftrace_graph_entry_stub).  If either of those is not set to the relevant stub | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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 | 
| Randy Dunlap | 7e25f44 | 2009-12-18 15:17:12 -0800 | [diff] [blame] | 138 | function names is strictly required, but you should use them anyway to stay | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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 | 
| Randy Dunlap | 7e25f44 | 2009-12-18 15:17:12 -0800 | [diff] [blame] | 148 | that will return the original return address with which you can return to the | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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; | 
| Mike Frysinger | 0368897 | 2010-01-22 08:12:47 -0500 | [diff] [blame] | 177 | 	/* passing frame pointer up is optional -- see below */ | 
 | 178 | 	prepare_ftrace_return(frompc, selfpc, frame_pointer); | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 179 |  | 
 | 180 | 	/* restore all state needed by the ABI */ | 
 | 181 | } | 
 | 182 | #endif | 
 | 183 |  | 
| Mike Frysinger | 0368897 | 2010-01-22 08:12:47 -0500 | [diff] [blame] | 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 | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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 |  | 
| Mike Frysinger | 0368897 | 2010-01-22 08:12:47 -0500 | [diff] [blame] | 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 |  | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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 |  | 
| Frederic Weisbecker | 459c6d1 | 2009-09-19 07:14:15 +0200 | [diff] [blame] | 236 | HAVE_SYSCALL_TRACEPOINTS | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 237 | --------------------- | 
 | 238 |  | 
| Frederic Weisbecker | 459c6d1 | 2009-09-19 07:14:15 +0200 | [diff] [blame] | 239 | You need very few things to get the syscalls tracing in an arch. | 
 | 240 |  | 
| Mike Frysinger | e7b8e67 | 2010-01-26 04:40:03 -0500 | [diff] [blame] | 241 | - Support HAVE_ARCH_TRACEHOOK (see arch/Kconfig). | 
| Frederic Weisbecker | 459c6d1 | 2009-09-19 07:14:15 +0200 | [diff] [blame] | 242 | - Have a NR_syscalls variable in <asm/unistd.h> that provides the number | 
 | 243 |   of syscalls supported by the arch. | 
| Mike Frysinger | e7b8e67 | 2010-01-26 04:40:03 -0500 | [diff] [blame] | 244 | - Support the TIF_SYSCALL_TRACEPOINT thread flags. | 
| Frederic Weisbecker | 459c6d1 | 2009-09-19 07:14:15 +0200 | [diff] [blame] | 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. | 
| Mike Frysinger | 555f386 | 2009-09-14 20:10:15 -0400 | [diff] [blame] | 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> |