2 * linux/arch/x86_64/mcount_64.S
4 * Copyright (C) 2014 Steven Rostedt, Red Hat Inc
7 #include <linux/linkage.h>
8 #include <asm/ptrace.h>
9 #include <asm/ftrace.h>
13 .section .entry.text, "ax"
16 #ifdef CONFIG_FUNCTION_TRACER
18 #ifdef CC_USING_FENTRY
19 # define function_hook __fentry__
21 # define function_hook mcount
25 * gcc -pg option adds a call to 'mcount' in most functions.
26 * When -mfentry is used, the call is to 'fentry' and not 'mcount'
27 * and is done before the function's stack frame is set up.
28 * They both require a set of regs to be saved before calling
29 * any C code and restored before returning back to the function.
31 * On boot up, all these calls are converted into nops. When tracing
32 * is enabled, the call can jump to either ftrace_caller or
33 * ftrace_regs_caller. Callbacks (tracing functions) that require
34 * ftrace_regs_caller (like kprobes) need to have pt_regs passed to
35 * it. For this reason, the size of the pt_regs structure will be
36 * allocated on the stack and the required mcount registers will
37 * be saved in the locations that pt_regs has them in.
40 /* skip is set if the stack was already partially adjusted */
41 .macro save_mcount_regs skip=0
43 * We add enough stack to save all regs.
45 subq $(SS+8-\skip), %rsp
53 /* Move RIP to its proper location */
58 .macro restore_mcount_regs skip=0
66 addq $(SS+8-\skip), %rsp
69 /* skip is set if stack has been adjusted */
70 .macro ftrace_caller_setup trace_label skip=0
71 save_mcount_regs \skip
73 /* Save this location */
75 /* Load the ftrace_ops into the 3rd parameter */
76 movq function_trace_op(%rip), %rdx
78 /* Load ip into the first parameter */
80 subq $MCOUNT_INSN_SIZE, %rdi
81 /* Load the parent_ip into the second parameter */
82 #ifdef CC_USING_FENTRY
83 movq SS+16(%rsp), %rsi
89 #ifdef CONFIG_DYNAMIC_FTRACE
95 #ifdef CONFIG_FRAME_POINTER
97 * Stack traces will stop at the ftrace trampoline if the frame pointer
98 * is not set up properly. If fentry is used, we need to save a frame
99 * pointer for the parent as well as the function traced, because the
100 * fentry is called before the stack frame is set up, where as mcount
101 * is called afterward.
103 .macro create_frame parent rip
104 #ifdef CC_USING_FENTRY
115 #ifdef CC_USING_FENTRY
122 .macro create_frame parent rip
126 #endif /* CONFIG_FRAME_POINTER */
129 ftrace_caller_setup ftrace_caller_op_ptr
130 /* regs go into 4th parameter (but make it NULL) */
133 create_frame %rsi, %rdi
143 * The copied trampoline must call ftrace_return as it
144 * still may need to call the function graph tracer.
146 GLOBAL(ftrace_caller_end)
148 GLOBAL(ftrace_return)
150 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
151 GLOBAL(ftrace_graph_call)
159 ENTRY(ftrace_regs_caller)
160 /* Save the current flags before compare (in SS location)*/
163 /* skip=8 to skip flags saved in SS */
164 ftrace_caller_setup ftrace_regs_caller_op_ptr 8
166 /* Save the rest of pt_regs */
175 /* Copy saved flags */
177 movq %rcx, EFLAGS(%rsp)
178 /* Kernel segments */
179 movq $__KERNEL_DS, %rcx
181 movq $__KERNEL_CS, %rcx
183 /* Stack - skipping return address */
184 leaq SS+16(%rsp), %rcx
187 /* regs go into 4th parameter */
190 create_frame %rsi, %rdi
192 GLOBAL(ftrace_regs_call)
197 /* Copy flags back to SS, to restore them */
198 movq EFLAGS(%rsp), %rax
201 /* Handlers can change the RIP */
203 movq %rax, SS+8(%rsp)
205 /* restore the rest of pt_regs */
214 /* skip=8 to skip flags saved in SS */
215 restore_mcount_regs 8
221 * As this jmp to ftrace_return can be a short jump
222 * it must not be copied into the trampoline.
223 * The trampoline will add the code to jump
226 GLOBAL(ftrace_regs_caller_end)
233 END(ftrace_regs_caller)
236 #else /* ! CONFIG_DYNAMIC_FTRACE */
239 cmpq $ftrace_stub, ftrace_trace_function
243 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
244 cmpq $ftrace_stub, ftrace_graph_return
245 jnz ftrace_graph_caller
247 cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
248 jnz ftrace_graph_caller
255 ftrace_caller_setup ftrace_caller_op_ptr
257 call *ftrace_trace_function
263 #endif /* CONFIG_DYNAMIC_FTRACE */
264 #endif /* CONFIG_FUNCTION_TRACER */
266 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
267 ENTRY(ftrace_graph_caller)
270 #ifdef CC_USING_FENTRY
271 leaq SS+16(%rsp), %rdi
272 movq $0, %rdx /* No framepointers needed */
278 subq $MCOUNT_INSN_SIZE, %rsi
280 call prepare_ftrace_return
285 END(ftrace_graph_caller)
287 GLOBAL(return_to_handler)
290 /* Save the return values */
295 call ftrace_return_to_handler