1*4882a593Smuzhiyun====================== 2*4882a593SmuzhiyunFunction Tracer Design 3*4882a593Smuzhiyun====================== 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun:Author: Mike Frysinger 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun.. caution:: 8*4882a593Smuzhiyun This document is out of date. Some of the description below doesn't 9*4882a593Smuzhiyun match current implementation now. 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunIntroduction 12*4882a593Smuzhiyun------------ 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunHere we will cover the architecture pieces that the common function tracing 15*4882a593Smuzhiyuncode relies on for proper functioning. Things are broken down into increasing 16*4882a593Smuzhiyuncomplexity so that you can start simple and at least get basic functionality. 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunNote that this focuses on architecture implementation details only. If you 19*4882a593Smuzhiyunwant more explanation of a feature in terms of common code, review the common 20*4882a593Smuzhiyunftrace.txt file. 21*4882a593Smuzhiyun 22*4882a593SmuzhiyunIdeally, everyone who wishes to retain performance while supporting tracing in 23*4882a593Smuzhiyuntheir kernel should make it all the way to dynamic ftrace support. 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun 26*4882a593SmuzhiyunPrerequisites 27*4882a593Smuzhiyun------------- 28*4882a593Smuzhiyun 29*4882a593SmuzhiyunFtrace relies on these features being implemented: 30*4882a593Smuzhiyun - STACKTRACE_SUPPORT - implement save_stack_trace() 31*4882a593Smuzhiyun - TRACE_IRQFLAGS_SUPPORT - implement include/asm/irqflags.h 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun 34*4882a593SmuzhiyunHAVE_FUNCTION_TRACER 35*4882a593Smuzhiyun-------------------- 36*4882a593Smuzhiyun 37*4882a593SmuzhiyunYou will need to implement the mcount and the ftrace_stub functions. 38*4882a593Smuzhiyun 39*4882a593SmuzhiyunThe exact mcount symbol name will depend on your toolchain. Some call it 40*4882a593Smuzhiyun"mcount", "_mcount", or even "__mcount". You can probably figure it out by 41*4882a593Smuzhiyunrunning something like:: 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun $ echo 'main(){}' | gcc -x c -S -o - - -pg | grep mcount 44*4882a593Smuzhiyun call mcount 45*4882a593Smuzhiyun 46*4882a593SmuzhiyunWe'll make the assumption below that the symbol is "mcount" just to keep things 47*4882a593Smuzhiyunnice and simple in the examples. 48*4882a593Smuzhiyun 49*4882a593SmuzhiyunKeep in mind that the ABI that is in effect inside of the mcount function is 50*4882a593Smuzhiyun*highly* architecture/toolchain specific. We cannot help you in this regard, 51*4882a593Smuzhiyunsorry. Dig up some old documentation and/or find someone more familiar than 52*4882a593Smuzhiyunyou to bang ideas off of. Typically, register usage (argument/scratch/etc...) 53*4882a593Smuzhiyunis a major issue at this point, especially in relation to the location of the 54*4882a593Smuzhiyunmcount call (before/after function prologue). You might also want to look at 55*4882a593Smuzhiyunhow glibc has implemented the mcount function for your architecture. It might 56*4882a593Smuzhiyunbe (semi-)relevant. 57*4882a593Smuzhiyun 58*4882a593SmuzhiyunThe mcount function should check the function pointer ftrace_trace_function 59*4882a593Smuzhiyunto see if it is set to ftrace_stub. If it is, there is nothing for you to do, 60*4882a593Smuzhiyunso return immediately. If it isn't, then call that function in the same way 61*4882a593Smuzhiyunthe mcount function normally calls __mcount_internal -- the first argument is 62*4882a593Smuzhiyunthe "frompc" while the second argument is the "selfpc" (adjusted to remove the 63*4882a593Smuzhiyunsize of the mcount call that is embedded in the function). 64*4882a593Smuzhiyun 65*4882a593SmuzhiyunFor example, if the function foo() calls bar(), when the bar() function calls 66*4882a593Smuzhiyunmcount(), the arguments mcount() will pass to the tracer are: 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun - "frompc" - the address bar() will use to return to foo() 69*4882a593Smuzhiyun - "selfpc" - the address bar() (with mcount() size adjustment) 70*4882a593Smuzhiyun 71*4882a593SmuzhiyunAlso keep in mind that this mcount function will be called *a lot*, so 72*4882a593Smuzhiyunoptimizing for the default case of no tracer will help the smooth running of 73*4882a593Smuzhiyunyour system when tracing is disabled. So the start of the mcount function is 74*4882a593Smuzhiyuntypically the bare minimum with checking things before returning. That also 75*4882a593Smuzhiyunmeans the code flow should usually be kept linear (i.e. no branching in the nop 76*4882a593Smuzhiyuncase). This is of course an optimization and not a hard requirement. 77*4882a593Smuzhiyun 78*4882a593SmuzhiyunHere is some pseudo code that should help (these functions should actually be 79*4882a593Smuzhiyunimplemented in assembly):: 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun void ftrace_stub(void) 82*4882a593Smuzhiyun { 83*4882a593Smuzhiyun return; 84*4882a593Smuzhiyun } 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun void mcount(void) 87*4882a593Smuzhiyun { 88*4882a593Smuzhiyun /* save any bare state needed in order to do initial checking */ 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun extern void (*ftrace_trace_function)(unsigned long, unsigned long); 91*4882a593Smuzhiyun if (ftrace_trace_function != ftrace_stub) 92*4882a593Smuzhiyun goto do_trace; 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun /* restore any bare state */ 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun return; 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun do_trace: 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun /* save all state needed by the ABI (see paragraph above) */ 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun unsigned long frompc = ...; 103*4882a593Smuzhiyun unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE; 104*4882a593Smuzhiyun ftrace_trace_function(frompc, selfpc); 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun /* restore all state needed by the ABI */ 107*4882a593Smuzhiyun } 108*4882a593Smuzhiyun 109*4882a593SmuzhiyunDon't forget to export mcount for modules ! 110*4882a593Smuzhiyun:: 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun extern void mcount(void); 113*4882a593Smuzhiyun EXPORT_SYMBOL(mcount); 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun 116*4882a593SmuzhiyunHAVE_FUNCTION_GRAPH_TRACER 117*4882a593Smuzhiyun-------------------------- 118*4882a593Smuzhiyun 119*4882a593SmuzhiyunDeep breath ... time to do some real work. Here you will need to update the 120*4882a593Smuzhiyunmcount function to check ftrace graph function pointers, as well as implement 121*4882a593Smuzhiyunsome functions to save (hijack) and restore the return address. 122*4882a593Smuzhiyun 123*4882a593SmuzhiyunThe mcount function should check the function pointers ftrace_graph_return 124*4882a593Smuzhiyun(compare to ftrace_stub) and ftrace_graph_entry (compare to 125*4882a593Smuzhiyunftrace_graph_entry_stub). If either of those is not set to the relevant stub 126*4882a593Smuzhiyunfunction, call the arch-specific function ftrace_graph_caller which in turn 127*4882a593Smuzhiyuncalls the arch-specific function prepare_ftrace_return. Neither of these 128*4882a593Smuzhiyunfunction names is strictly required, but you should use them anyway to stay 129*4882a593Smuzhiyunconsistent across the architecture ports -- easier to compare & contrast 130*4882a593Smuzhiyunthings. 131*4882a593Smuzhiyun 132*4882a593SmuzhiyunThe arguments to prepare_ftrace_return are slightly different than what are 133*4882a593Smuzhiyunpassed to ftrace_trace_function. The second argument "selfpc" is the same, 134*4882a593Smuzhiyunbut the first argument should be a pointer to the "frompc". Typically this is 135*4882a593Smuzhiyunlocated on the stack. This allows the function to hijack the return address 136*4882a593Smuzhiyuntemporarily to have it point to the arch-specific function return_to_handler. 137*4882a593SmuzhiyunThat function will simply call the common ftrace_return_to_handler function and 138*4882a593Smuzhiyunthat will return the original return address with which you can return to the 139*4882a593Smuzhiyunoriginal call site. 140*4882a593Smuzhiyun 141*4882a593SmuzhiyunHere is the updated mcount pseudo code:: 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun void mcount(void) 144*4882a593Smuzhiyun { 145*4882a593Smuzhiyun ... 146*4882a593Smuzhiyun if (ftrace_trace_function != ftrace_stub) 147*4882a593Smuzhiyun goto do_trace; 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun +#ifdef CONFIG_FUNCTION_GRAPH_TRACER 150*4882a593Smuzhiyun + extern void (*ftrace_graph_return)(...); 151*4882a593Smuzhiyun + extern void (*ftrace_graph_entry)(...); 152*4882a593Smuzhiyun + if (ftrace_graph_return != ftrace_stub || 153*4882a593Smuzhiyun + ftrace_graph_entry != ftrace_graph_entry_stub) 154*4882a593Smuzhiyun + ftrace_graph_caller(); 155*4882a593Smuzhiyun +#endif 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun /* restore any bare state */ 158*4882a593Smuzhiyun ... 159*4882a593Smuzhiyun 160*4882a593SmuzhiyunHere is the pseudo code for the new ftrace_graph_caller assembly function:: 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun #ifdef CONFIG_FUNCTION_GRAPH_TRACER 163*4882a593Smuzhiyun void ftrace_graph_caller(void) 164*4882a593Smuzhiyun { 165*4882a593Smuzhiyun /* save all state needed by the ABI */ 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun unsigned long *frompc = &...; 168*4882a593Smuzhiyun unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE; 169*4882a593Smuzhiyun /* passing frame pointer up is optional -- see below */ 170*4882a593Smuzhiyun prepare_ftrace_return(frompc, selfpc, frame_pointer); 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun /* restore all state needed by the ABI */ 173*4882a593Smuzhiyun } 174*4882a593Smuzhiyun #endif 175*4882a593Smuzhiyun 176*4882a593SmuzhiyunFor information on how to implement prepare_ftrace_return(), simply look at the 177*4882a593Smuzhiyunx86 version (the frame pointer passing is optional; see the next section for 178*4882a593Smuzhiyunmore information). The only architecture-specific piece in it is the setup of 179*4882a593Smuzhiyunthe fault recovery table (the asm(...) code). The rest should be the same 180*4882a593Smuzhiyunacross architectures. 181*4882a593Smuzhiyun 182*4882a593SmuzhiyunHere is the pseudo code for the new return_to_handler assembly function. Note 183*4882a593Smuzhiyunthat the ABI that applies here is different from what applies to the mcount 184*4882a593Smuzhiyuncode. Since you are returning from a function (after the epilogue), you might 185*4882a593Smuzhiyunbe able to skimp on things saved/restored (usually just registers used to pass 186*4882a593Smuzhiyunreturn values). 187*4882a593Smuzhiyun:: 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun #ifdef CONFIG_FUNCTION_GRAPH_TRACER 190*4882a593Smuzhiyun void return_to_handler(void) 191*4882a593Smuzhiyun { 192*4882a593Smuzhiyun /* save all state needed by the ABI (see paragraph above) */ 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun void (*original_return_point)(void) = ftrace_return_to_handler(); 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun /* restore all state needed by the ABI */ 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun /* this is usually either a return or a jump */ 199*4882a593Smuzhiyun original_return_point(); 200*4882a593Smuzhiyun } 201*4882a593Smuzhiyun #endif 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun 204*4882a593SmuzhiyunHAVE_FUNCTION_GRAPH_FP_TEST 205*4882a593Smuzhiyun--------------------------- 206*4882a593Smuzhiyun 207*4882a593SmuzhiyunAn arch may pass in a unique value (frame pointer) to both the entering and 208*4882a593Smuzhiyunexiting of a function. On exit, the value is compared and if it does not 209*4882a593Smuzhiyunmatch, then it will panic the kernel. This is largely a sanity check for bad 210*4882a593Smuzhiyuncode generation with gcc. If gcc for your port sanely updates the frame 211*4882a593Smuzhiyunpointer under different optimization levels, then ignore this option. 212*4882a593Smuzhiyun 213*4882a593SmuzhiyunHowever, adding support for it isn't terribly difficult. In your assembly code 214*4882a593Smuzhiyunthat calls prepare_ftrace_return(), pass the frame pointer as the 3rd argument. 215*4882a593SmuzhiyunThen in the C version of that function, do what the x86 port does and pass it 216*4882a593Smuzhiyunalong to ftrace_push_return_trace() instead of a stub value of 0. 217*4882a593Smuzhiyun 218*4882a593SmuzhiyunSimilarly, when you call ftrace_return_to_handler(), pass it the frame pointer. 219*4882a593Smuzhiyun 220*4882a593SmuzhiyunHAVE_FUNCTION_GRAPH_RET_ADDR_PTR 221*4882a593Smuzhiyun-------------------------------- 222*4882a593Smuzhiyun 223*4882a593SmuzhiyunAn arch may pass in a pointer to the return address on the stack. This 224*4882a593Smuzhiyunprevents potential stack unwinding issues where the unwinder gets out of 225*4882a593Smuzhiyunsync with ret_stack and the wrong addresses are reported by 226*4882a593Smuzhiyunftrace_graph_ret_addr(). 227*4882a593Smuzhiyun 228*4882a593SmuzhiyunAdding support for it is easy: just define the macro in asm/ftrace.h and 229*4882a593Smuzhiyunpass the return address pointer as the 'retp' argument to 230*4882a593Smuzhiyunftrace_push_return_trace(). 231*4882a593Smuzhiyun 232*4882a593SmuzhiyunHAVE_SYSCALL_TRACEPOINTS 233*4882a593Smuzhiyun------------------------ 234*4882a593Smuzhiyun 235*4882a593SmuzhiyunYou need very few things to get the syscalls tracing in an arch. 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun - Support HAVE_ARCH_TRACEHOOK (see arch/Kconfig). 238*4882a593Smuzhiyun - Have a NR_syscalls variable in <asm/unistd.h> that provides the number 239*4882a593Smuzhiyun of syscalls supported by the arch. 240*4882a593Smuzhiyun - Support the TIF_SYSCALL_TRACEPOINT thread flags. 241*4882a593Smuzhiyun - Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace 242*4882a593Smuzhiyun in the ptrace syscalls tracing path. 243*4882a593Smuzhiyun - If the system call table on this arch is more complicated than a simple array 244*4882a593Smuzhiyun of addresses of the system calls, implement an arch_syscall_addr to return 245*4882a593Smuzhiyun the address of a given system call. 246*4882a593Smuzhiyun - If the symbol names of the system calls do not match the function names on 247*4882a593Smuzhiyun this arch, define ARCH_HAS_SYSCALL_MATCH_SYM_NAME in asm/ftrace.h and 248*4882a593Smuzhiyun implement arch_syscall_match_sym_name with the appropriate logic to return 249*4882a593Smuzhiyun true if the function name corresponds with the symbol name. 250*4882a593Smuzhiyun - Tag this arch as HAVE_SYSCALL_TRACEPOINTS. 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun 253*4882a593SmuzhiyunHAVE_FTRACE_MCOUNT_RECORD 254*4882a593Smuzhiyun------------------------- 255*4882a593Smuzhiyun 256*4882a593SmuzhiyunSee scripts/recordmcount.pl for more info. Just fill in the arch-specific 257*4882a593Smuzhiyundetails for how to locate the addresses of mcount call sites via objdump. 258*4882a593SmuzhiyunThis option doesn't make much sense without also implementing dynamic ftrace. 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun 261*4882a593SmuzhiyunHAVE_DYNAMIC_FTRACE 262*4882a593Smuzhiyun------------------- 263*4882a593Smuzhiyun 264*4882a593SmuzhiyunYou will first need HAVE_FTRACE_MCOUNT_RECORD and HAVE_FUNCTION_TRACER, so 265*4882a593Smuzhiyunscroll your reader back up if you got over eager. 266*4882a593Smuzhiyun 267*4882a593SmuzhiyunOnce those are out of the way, you will need to implement: 268*4882a593Smuzhiyun - asm/ftrace.h: 269*4882a593Smuzhiyun - MCOUNT_ADDR 270*4882a593Smuzhiyun - ftrace_call_adjust() 271*4882a593Smuzhiyun - struct dyn_arch_ftrace{} 272*4882a593Smuzhiyun - asm code: 273*4882a593Smuzhiyun - mcount() (new stub) 274*4882a593Smuzhiyun - ftrace_caller() 275*4882a593Smuzhiyun - ftrace_call() 276*4882a593Smuzhiyun - ftrace_stub() 277*4882a593Smuzhiyun - C code: 278*4882a593Smuzhiyun - ftrace_dyn_arch_init() 279*4882a593Smuzhiyun - ftrace_make_nop() 280*4882a593Smuzhiyun - ftrace_make_call() 281*4882a593Smuzhiyun - ftrace_update_ftrace_func() 282*4882a593Smuzhiyun 283*4882a593SmuzhiyunFirst you will need to fill out some arch details in your asm/ftrace.h. 284*4882a593Smuzhiyun 285*4882a593SmuzhiyunDefine MCOUNT_ADDR as the address of your mcount symbol similar to:: 286*4882a593Smuzhiyun 287*4882a593Smuzhiyun #define MCOUNT_ADDR ((unsigned long)mcount) 288*4882a593Smuzhiyun 289*4882a593SmuzhiyunSince no one else will have a decl for that function, you will need to:: 290*4882a593Smuzhiyun 291*4882a593Smuzhiyun extern void mcount(void); 292*4882a593Smuzhiyun 293*4882a593SmuzhiyunYou will also need the helper function ftrace_call_adjust(). Most people 294*4882a593Smuzhiyunwill be able to stub it out like so:: 295*4882a593Smuzhiyun 296*4882a593Smuzhiyun static inline unsigned long ftrace_call_adjust(unsigned long addr) 297*4882a593Smuzhiyun { 298*4882a593Smuzhiyun return addr; 299*4882a593Smuzhiyun } 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun<details to be filled> 302*4882a593Smuzhiyun 303*4882a593SmuzhiyunLastly you will need the custom dyn_arch_ftrace structure. If you need 304*4882a593Smuzhiyunsome extra state when runtime patching arbitrary call sites, this is the 305*4882a593Smuzhiyunplace. For now though, create an empty struct:: 306*4882a593Smuzhiyun 307*4882a593Smuzhiyun struct dyn_arch_ftrace { 308*4882a593Smuzhiyun /* No extra data needed */ 309*4882a593Smuzhiyun }; 310*4882a593Smuzhiyun 311*4882a593SmuzhiyunWith the header out of the way, we can fill out the assembly code. While we 312*4882a593Smuzhiyundid already create a mcount() function earlier, dynamic ftrace only wants a 313*4882a593Smuzhiyunstub function. This is because the mcount() will only be used during boot 314*4882a593Smuzhiyunand then all references to it will be patched out never to return. Instead, 315*4882a593Smuzhiyunthe guts of the old mcount() will be used to create a new ftrace_caller() 316*4882a593Smuzhiyunfunction. Because the two are hard to merge, it will most likely be a lot 317*4882a593Smuzhiyuneasier to have two separate definitions split up by #ifdefs. Same goes for 318*4882a593Smuzhiyunthe ftrace_stub() as that will now be inlined in ftrace_caller(). 319*4882a593Smuzhiyun 320*4882a593SmuzhiyunBefore we get confused anymore, let's check out some pseudo code so you can 321*4882a593Smuzhiyunimplement your own stuff in assembly:: 322*4882a593Smuzhiyun 323*4882a593Smuzhiyun void mcount(void) 324*4882a593Smuzhiyun { 325*4882a593Smuzhiyun return; 326*4882a593Smuzhiyun } 327*4882a593Smuzhiyun 328*4882a593Smuzhiyun void ftrace_caller(void) 329*4882a593Smuzhiyun { 330*4882a593Smuzhiyun /* save all state needed by the ABI (see paragraph above) */ 331*4882a593Smuzhiyun 332*4882a593Smuzhiyun unsigned long frompc = ...; 333*4882a593Smuzhiyun unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE; 334*4882a593Smuzhiyun 335*4882a593Smuzhiyun ftrace_call: 336*4882a593Smuzhiyun ftrace_stub(frompc, selfpc); 337*4882a593Smuzhiyun 338*4882a593Smuzhiyun /* restore all state needed by the ABI */ 339*4882a593Smuzhiyun 340*4882a593Smuzhiyun ftrace_stub: 341*4882a593Smuzhiyun return; 342*4882a593Smuzhiyun } 343*4882a593Smuzhiyun 344*4882a593SmuzhiyunThis might look a little odd at first, but keep in mind that we will be runtime 345*4882a593Smuzhiyunpatching multiple things. First, only functions that we actually want to trace 346*4882a593Smuzhiyunwill be patched to call ftrace_caller(). Second, since we only have one tracer 347*4882a593Smuzhiyunactive at a time, we will patch the ftrace_caller() function itself to call the 348*4882a593Smuzhiyunspecific tracer in question. That is the point of the ftrace_call label. 349*4882a593Smuzhiyun 350*4882a593SmuzhiyunWith that in mind, let's move on to the C code that will actually be doing the 351*4882a593Smuzhiyunruntime patching. You'll need a little knowledge of your arch's opcodes in 352*4882a593Smuzhiyunorder to make it through the next section. 353*4882a593Smuzhiyun 354*4882a593SmuzhiyunEvery arch has an init callback function. If you need to do something early on 355*4882a593Smuzhiyunto initialize some state, this is the time to do that. Otherwise, this simple 356*4882a593Smuzhiyunfunction below should be sufficient for most people:: 357*4882a593Smuzhiyun 358*4882a593Smuzhiyun int __init ftrace_dyn_arch_init(void) 359*4882a593Smuzhiyun { 360*4882a593Smuzhiyun return 0; 361*4882a593Smuzhiyun } 362*4882a593Smuzhiyun 363*4882a593SmuzhiyunThere are two functions that are used to do runtime patching of arbitrary 364*4882a593Smuzhiyunfunctions. The first is used to turn the mcount call site into a nop (which 365*4882a593Smuzhiyunis what helps us retain runtime performance when not tracing). The second is 366*4882a593Smuzhiyunused to turn the mcount call site into a call to an arbitrary location (but 367*4882a593Smuzhiyuntypically that is ftracer_caller()). See the general function definition in 368*4882a593Smuzhiyunlinux/ftrace.h for the functions:: 369*4882a593Smuzhiyun 370*4882a593Smuzhiyun ftrace_make_nop() 371*4882a593Smuzhiyun ftrace_make_call() 372*4882a593Smuzhiyun 373*4882a593SmuzhiyunThe rec->ip value is the address of the mcount call site that was collected 374*4882a593Smuzhiyunby the scripts/recordmcount.pl during build time. 375*4882a593Smuzhiyun 376*4882a593SmuzhiyunThe last function is used to do runtime patching of the active tracer. This 377*4882a593Smuzhiyunwill be modifying the assembly code at the location of the ftrace_call symbol 378*4882a593Smuzhiyuninside of the ftrace_caller() function. So you should have sufficient padding 379*4882a593Smuzhiyunat that location to support the new function calls you'll be inserting. Some 380*4882a593Smuzhiyunpeople will be using a "call" type instruction while others will be using a 381*4882a593Smuzhiyun"branch" type instruction. Specifically, the function is:: 382*4882a593Smuzhiyun 383*4882a593Smuzhiyun ftrace_update_ftrace_func() 384*4882a593Smuzhiyun 385*4882a593Smuzhiyun 386*4882a593SmuzhiyunHAVE_DYNAMIC_FTRACE + HAVE_FUNCTION_GRAPH_TRACER 387*4882a593Smuzhiyun------------------------------------------------ 388*4882a593Smuzhiyun 389*4882a593SmuzhiyunThe function grapher needs a few tweaks in order to work with dynamic ftrace. 390*4882a593SmuzhiyunBasically, you will need to: 391*4882a593Smuzhiyun 392*4882a593Smuzhiyun - update: 393*4882a593Smuzhiyun - ftrace_caller() 394*4882a593Smuzhiyun - ftrace_graph_call() 395*4882a593Smuzhiyun - ftrace_graph_caller() 396*4882a593Smuzhiyun - implement: 397*4882a593Smuzhiyun - ftrace_enable_ftrace_graph_caller() 398*4882a593Smuzhiyun - ftrace_disable_ftrace_graph_caller() 399*4882a593Smuzhiyun 400*4882a593Smuzhiyun<details to be filled> 401*4882a593Smuzhiyun 402*4882a593SmuzhiyunQuick notes: 403*4882a593Smuzhiyun 404*4882a593Smuzhiyun - add a nop stub after the ftrace_call location named ftrace_graph_call; 405*4882a593Smuzhiyun stub needs to be large enough to support a call to ftrace_graph_caller() 406*4882a593Smuzhiyun - update ftrace_graph_caller() to work with being called by the new 407*4882a593Smuzhiyun ftrace_caller() since some semantics may have changed 408*4882a593Smuzhiyun - ftrace_enable_ftrace_graph_caller() will runtime patch the 409*4882a593Smuzhiyun ftrace_graph_call location with a call to ftrace_graph_caller() 410*4882a593Smuzhiyun - ftrace_disable_ftrace_graph_caller() will runtime patch the 411*4882a593Smuzhiyun ftrace_graph_call location with nops 412