mcount_64.S 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. * linux/arch/x86_64/mcount_64.S
  3. *
  4. * Copyright (C) 2014 Steven Rostedt, Red Hat Inc
  5. */
  6. #include <linux/linkage.h>
  7. #include <asm/ptrace.h>
  8. #include <asm/ftrace.h>
  9. #include <asm/export.h>
  10. .code64
  11. .section .entry.text, "ax"
  12. #ifdef CONFIG_FUNCTION_TRACER
  13. #ifdef CC_USING_FENTRY
  14. # define function_hook __fentry__
  15. EXPORT_SYMBOL(__fentry__)
  16. #else
  17. # define function_hook mcount
  18. EXPORT_SYMBOL(mcount)
  19. #endif
  20. /* All cases save the original rbp (8 bytes) */
  21. #ifdef CONFIG_FRAME_POINTER
  22. # ifdef CC_USING_FENTRY
  23. /* Save parent and function stack frames (rip and rbp) */
  24. # define MCOUNT_FRAME_SIZE (8+16*2)
  25. # else
  26. /* Save just function stack frame (rip and rbp) */
  27. # define MCOUNT_FRAME_SIZE (8+16)
  28. # endif
  29. #else
  30. /* No need to save a stack frame */
  31. # define MCOUNT_FRAME_SIZE 8
  32. #endif /* CONFIG_FRAME_POINTER */
  33. /* Size of stack used to save mcount regs in save_mcount_regs */
  34. #define MCOUNT_REG_SIZE (SS+8 + MCOUNT_FRAME_SIZE)
  35. /*
  36. * gcc -pg option adds a call to 'mcount' in most functions.
  37. * When -mfentry is used, the call is to 'fentry' and not 'mcount'
  38. * and is done before the function's stack frame is set up.
  39. * They both require a set of regs to be saved before calling
  40. * any C code and restored before returning back to the function.
  41. *
  42. * On boot up, all these calls are converted into nops. When tracing
  43. * is enabled, the call can jump to either ftrace_caller or
  44. * ftrace_regs_caller. Callbacks (tracing functions) that require
  45. * ftrace_regs_caller (like kprobes) need to have pt_regs passed to
  46. * it. For this reason, the size of the pt_regs structure will be
  47. * allocated on the stack and the required mcount registers will
  48. * be saved in the locations that pt_regs has them in.
  49. */
  50. /*
  51. * @added: the amount of stack added before calling this
  52. *
  53. * After this is called, the following registers contain:
  54. *
  55. * %rdi - holds the address that called the trampoline
  56. * %rsi - holds the parent function (traced function's return address)
  57. * %rdx - holds the original %rbp
  58. */
  59. .macro save_mcount_regs added=0
  60. /* Always save the original rbp */
  61. pushq %rbp
  62. #ifdef CONFIG_FRAME_POINTER
  63. /*
  64. * Stack traces will stop at the ftrace trampoline if the frame pointer
  65. * is not set up properly. If fentry is used, we need to save a frame
  66. * pointer for the parent as well as the function traced, because the
  67. * fentry is called before the stack frame is set up, where as mcount
  68. * is called afterward.
  69. */
  70. #ifdef CC_USING_FENTRY
  71. /* Save the parent pointer (skip orig rbp and our return address) */
  72. pushq \added+8*2(%rsp)
  73. pushq %rbp
  74. movq %rsp, %rbp
  75. /* Save the return address (now skip orig rbp, rbp and parent) */
  76. pushq \added+8*3(%rsp)
  77. #else
  78. /* Can't assume that rip is before this (unless added was zero) */
  79. pushq \added+8(%rsp)
  80. #endif
  81. pushq %rbp
  82. movq %rsp, %rbp
  83. #endif /* CONFIG_FRAME_POINTER */
  84. /*
  85. * We add enough stack to save all regs.
  86. */
  87. subq $(MCOUNT_REG_SIZE - MCOUNT_FRAME_SIZE), %rsp
  88. movq %rax, RAX(%rsp)
  89. movq %rcx, RCX(%rsp)
  90. movq %rdx, RDX(%rsp)
  91. movq %rsi, RSI(%rsp)
  92. movq %rdi, RDI(%rsp)
  93. movq %r8, R8(%rsp)
  94. movq %r9, R9(%rsp)
  95. /*
  96. * Save the original RBP. Even though the mcount ABI does not
  97. * require this, it helps out callers.
  98. */
  99. movq MCOUNT_REG_SIZE-8(%rsp), %rdx
  100. movq %rdx, RBP(%rsp)
  101. /* Copy the parent address into %rsi (second parameter) */
  102. #ifdef CC_USING_FENTRY
  103. movq MCOUNT_REG_SIZE+8+\added(%rsp), %rsi
  104. #else
  105. /* %rdx contains original %rbp */
  106. movq 8(%rdx), %rsi
  107. #endif
  108. /* Move RIP to its proper location */
  109. movq MCOUNT_REG_SIZE+\added(%rsp), %rdi
  110. movq %rdi, RIP(%rsp)
  111. /*
  112. * Now %rdi (the first parameter) has the return address of
  113. * where ftrace_call returns. But the callbacks expect the
  114. * address of the call itself.
  115. */
  116. subq $MCOUNT_INSN_SIZE, %rdi
  117. .endm
  118. .macro restore_mcount_regs
  119. movq R9(%rsp), %r9
  120. movq R8(%rsp), %r8
  121. movq RDI(%rsp), %rdi
  122. movq RSI(%rsp), %rsi
  123. movq RDX(%rsp), %rdx
  124. movq RCX(%rsp), %rcx
  125. movq RAX(%rsp), %rax
  126. /* ftrace_regs_caller can modify %rbp */
  127. movq RBP(%rsp), %rbp
  128. addq $MCOUNT_REG_SIZE, %rsp
  129. .endm
  130. #ifdef CONFIG_DYNAMIC_FTRACE
  131. ENTRY(function_hook)
  132. retq
  133. END(function_hook)
  134. ENTRY(ftrace_caller)
  135. /* save_mcount_regs fills in first two parameters */
  136. save_mcount_regs
  137. GLOBAL(ftrace_caller_op_ptr)
  138. /* Load the ftrace_ops into the 3rd parameter */
  139. movq function_trace_op(%rip), %rdx
  140. /* regs go into 4th parameter (but make it NULL) */
  141. movq $0, %rcx
  142. GLOBAL(ftrace_call)
  143. call ftrace_stub
  144. restore_mcount_regs
  145. /*
  146. * The copied trampoline must call ftrace_epilogue as it
  147. * still may need to call the function graph tracer.
  148. *
  149. * The code up to this label is copied into trampolines so
  150. * think twice before adding any new code or changing the
  151. * layout here.
  152. */
  153. GLOBAL(ftrace_epilogue)
  154. #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  155. GLOBAL(ftrace_graph_call)
  156. jmp ftrace_stub
  157. #endif
  158. /* This is weak to keep gas from relaxing the jumps */
  159. WEAK(ftrace_stub)
  160. retq
  161. END(ftrace_caller)
  162. ENTRY(ftrace_regs_caller)
  163. /* Save the current flags before any operations that can change them */
  164. pushfq
  165. /* added 8 bytes to save flags */
  166. save_mcount_regs 8
  167. /* save_mcount_regs fills in first two parameters */
  168. GLOBAL(ftrace_regs_caller_op_ptr)
  169. /* Load the ftrace_ops into the 3rd parameter */
  170. movq function_trace_op(%rip), %rdx
  171. /* Save the rest of pt_regs */
  172. movq %r15, R15(%rsp)
  173. movq %r14, R14(%rsp)
  174. movq %r13, R13(%rsp)
  175. movq %r12, R12(%rsp)
  176. movq %r11, R11(%rsp)
  177. movq %r10, R10(%rsp)
  178. movq %rbx, RBX(%rsp)
  179. /* Copy saved flags */
  180. movq MCOUNT_REG_SIZE(%rsp), %rcx
  181. movq %rcx, EFLAGS(%rsp)
  182. /* Kernel segments */
  183. movq $__KERNEL_DS, %rcx
  184. movq %rcx, SS(%rsp)
  185. movq $__KERNEL_CS, %rcx
  186. movq %rcx, CS(%rsp)
  187. /* Stack - skipping return address and flags */
  188. leaq MCOUNT_REG_SIZE+8*2(%rsp), %rcx
  189. movq %rcx, RSP(%rsp)
  190. /* regs go into 4th parameter */
  191. leaq (%rsp), %rcx
  192. GLOBAL(ftrace_regs_call)
  193. call ftrace_stub
  194. /* Copy flags back to SS, to restore them */
  195. movq EFLAGS(%rsp), %rax
  196. movq %rax, MCOUNT_REG_SIZE(%rsp)
  197. /* Handlers can change the RIP */
  198. movq RIP(%rsp), %rax
  199. movq %rax, MCOUNT_REG_SIZE+8(%rsp)
  200. /* restore the rest of pt_regs */
  201. movq R15(%rsp), %r15
  202. movq R14(%rsp), %r14
  203. movq R13(%rsp), %r13
  204. movq R12(%rsp), %r12
  205. movq R10(%rsp), %r10
  206. movq RBX(%rsp), %rbx
  207. restore_mcount_regs
  208. /* Restore flags */
  209. popfq
  210. /*
  211. * As this jmp to ftrace_epilogue can be a short jump
  212. * it must not be copied into the trampoline.
  213. * The trampoline will add the code to jump
  214. * to the return.
  215. */
  216. GLOBAL(ftrace_regs_caller_end)
  217. jmp ftrace_epilogue
  218. END(ftrace_regs_caller)
  219. #else /* ! CONFIG_DYNAMIC_FTRACE */
  220. ENTRY(function_hook)
  221. cmpq $ftrace_stub, ftrace_trace_function
  222. jnz trace
  223. fgraph_trace:
  224. #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  225. cmpq $ftrace_stub, ftrace_graph_return
  226. jnz ftrace_graph_caller
  227. cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
  228. jnz ftrace_graph_caller
  229. #endif
  230. GLOBAL(ftrace_stub)
  231. retq
  232. trace:
  233. /* save_mcount_regs fills in first two parameters */
  234. save_mcount_regs
  235. /*
  236. * When DYNAMIC_FTRACE is not defined, ARCH_SUPPORTS_FTRACE_OPS is not
  237. * set (see include/asm/ftrace.h and include/linux/ftrace.h). Only the
  238. * ip and parent ip are used and the list function is called when
  239. * function tracing is enabled.
  240. */
  241. call *ftrace_trace_function
  242. restore_mcount_regs
  243. jmp fgraph_trace
  244. END(function_hook)
  245. #endif /* CONFIG_DYNAMIC_FTRACE */
  246. #endif /* CONFIG_FUNCTION_TRACER */
  247. #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  248. ENTRY(ftrace_graph_caller)
  249. /* Saves rbp into %rdx and fills first parameter */
  250. save_mcount_regs
  251. #ifdef CC_USING_FENTRY
  252. leaq MCOUNT_REG_SIZE+8(%rsp), %rsi
  253. movq $0, %rdx /* No framepointers needed */
  254. #else
  255. /* Save address of the return address of traced function */
  256. leaq 8(%rdx), %rsi
  257. /* ftrace does sanity checks against frame pointers */
  258. movq (%rdx), %rdx
  259. #endif
  260. call prepare_ftrace_return
  261. restore_mcount_regs
  262. retq
  263. END(ftrace_graph_caller)
  264. GLOBAL(return_to_handler)
  265. subq $24, %rsp
  266. /* Save the return values */
  267. movq %rax, (%rsp)
  268. movq %rdx, 8(%rsp)
  269. movq %rbp, %rdi
  270. call ftrace_return_to_handler
  271. movq %rax, %rdi
  272. movq 8(%rsp), %rdx
  273. movq (%rsp), %rax
  274. addq $24, %rsp
  275. jmp *%rdi
  276. #endif