tracing: Only allow trace_array_printk() to be used by instances
[linux-block.git] / arch / x86 / kernel / ftrace_64.S
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
e18eead3 2/*
e18eead3
SR
3 * Copyright (C) 2014 Steven Rostedt, Red Hat Inc
4 */
5
6#include <linux/linkage.h>
7#include <asm/ptrace.h>
8#include <asm/ftrace.h>
784d5699 9#include <asm/export.h>
9351803b 10#include <asm/nospec-branch.h>
e2ac83d7 11#include <asm/unwind_hints.h>
ea1ed38d 12#include <asm/frame.h>
e18eead3
SR
13
14 .code64
b9f6976b 15 .section .text, "ax"
e18eead3 16
0687c36e 17#ifdef CONFIG_FRAME_POINTER
0687c36e
SRRH
18/* Save parent and function stack frames (rip and rbp) */
19# define MCOUNT_FRAME_SIZE (8+16*2)
0687c36e
SRRH
20#else
21/* No need to save a stack frame */
e2ac83d7 22# define MCOUNT_FRAME_SIZE 0
0687c36e
SRRH
23#endif /* CONFIG_FRAME_POINTER */
24
85f6f029 25/* Size of stack used to save mcount regs in save_mcount_regs */
dc2745b6 26#define MCOUNT_REG_SIZE (FRAME_SIZE + MCOUNT_FRAME_SIZE)
85f6f029 27
05df710e
SRRH
28/*
29 * gcc -pg option adds a call to 'mcount' in most functions.
30 * When -mfentry is used, the call is to 'fentry' and not 'mcount'
31 * and is done before the function's stack frame is set up.
32 * They both require a set of regs to be saved before calling
33 * any C code and restored before returning back to the function.
34 *
35 * On boot up, all these calls are converted into nops. When tracing
36 * is enabled, the call can jump to either ftrace_caller or
37 * ftrace_regs_caller. Callbacks (tracing functions) that require
38 * ftrace_regs_caller (like kprobes) need to have pt_regs passed to
39 * it. For this reason, the size of the pt_regs structure will be
40 * allocated on the stack and the required mcount registers will
41 * be saved in the locations that pt_regs has them in.
42 */
43
f1ab00af
SRRH
44/*
45 * @added: the amount of stack added before calling this
46 *
47 * After this is called, the following registers contain:
48 *
49 * %rdi - holds the address that called the trampoline
50 * %rsi - holds the parent function (traced function's return address)
51 * %rdx - holds the original %rbp
52 */
527aa75b 53.macro save_mcount_regs added=0
0687c36e 54
e2ac83d7
JP
55#ifdef CONFIG_FRAME_POINTER
56 /* Save the original rbp */
0687c36e
SRRH
57 pushq %rbp
58
0687c36e
SRRH
59 /*
60 * Stack traces will stop at the ftrace trampoline if the frame pointer
61 * is not set up properly. If fentry is used, we need to save a frame
62 * pointer for the parent as well as the function traced, because the
63 * fentry is called before the stack frame is set up, where as mcount
64 * is called afterward.
65 */
562e14f7 66
0687c36e
SRRH
67 /* Save the parent pointer (skip orig rbp and our return address) */
68 pushq \added+8*2(%rsp)
69 pushq %rbp
70 movq %rsp, %rbp
71 /* Save the return address (now skip orig rbp, rbp and parent) */
72 pushq \added+8*3(%rsp)
0687c36e
SRRH
73 pushq %rbp
74 movq %rsp, %rbp
75#endif /* CONFIG_FRAME_POINTER */
76
77 /*
78 * We add enough stack to save all regs.
79 */
dc2745b6 80 subq $(FRAME_SIZE), %rsp
4bcdf152
SRRH
81 movq %rax, RAX(%rsp)
82 movq %rcx, RCX(%rsp)
83 movq %rdx, RDX(%rsp)
84 movq %rsi, RSI(%rsp)
85 movq %rdi, RDI(%rsp)
86 movq %r8, R8(%rsp)
87 movq %r9, R9(%rsp)
562955fe 88 movq $0, ORIG_RAX(%rsp)
0687c36e
SRRH
89 /*
90 * Save the original RBP. Even though the mcount ABI does not
91 * require this, it helps out callers.
92 */
e2ac83d7 93#ifdef CONFIG_FRAME_POINTER
0687c36e 94 movq MCOUNT_REG_SIZE-8(%rsp), %rdx
e2ac83d7
JP
95#else
96 movq %rbp, %rdx
97#endif
0687c36e
SRRH
98 movq %rdx, RBP(%rsp)
99
f1ab00af 100 /* Copy the parent address into %rsi (second parameter) */
f1ab00af 101 movq MCOUNT_REG_SIZE+8+\added(%rsp), %rsi
f1ab00af 102
4bcdf152 103 /* Move RIP to its proper location */
85f6f029 104 movq MCOUNT_REG_SIZE+\added(%rsp), %rdi
094dfc54 105 movq %rdi, RIP(%rsp)
f1ab00af
SRRH
106
107 /*
108 * Now %rdi (the first parameter) has the return address of
109 * where ftrace_call returns. But the callbacks expect the
6a06bdbf 110 * address of the call itself.
f1ab00af
SRRH
111 */
112 subq $MCOUNT_INSN_SIZE, %rdi
4bcdf152
SRRH
113 .endm
114
562955fe
SRV
115.macro restore_mcount_regs save=0
116
117 /* ftrace_regs_caller or frame pointers require this */
118 movq RBP(%rsp), %rbp
119
4bcdf152
SRRH
120 movq R9(%rsp), %r9
121 movq R8(%rsp), %r8
122 movq RDI(%rsp), %rdi
123 movq RSI(%rsp), %rsi
124 movq RDX(%rsp), %rdx
125 movq RCX(%rsp), %rcx
126 movq RAX(%rsp), %rax
0687c36e 127
562955fe 128 addq $MCOUNT_REG_SIZE-\save, %rsp
0687c36e 129
4bcdf152
SRRH
130 .endm
131
76c2f13c
SRRH
132#ifdef CONFIG_DYNAMIC_FTRACE
133
0f42c1ad 134SYM_FUNC_START(__fentry__)
76c2f13c 135 retq
0f42c1ad
BP
136SYM_FUNC_END(__fentry__)
137EXPORT_SYMBOL(__fentry__)
76c2f13c 138
6dcc5627 139SYM_FUNC_START(ftrace_caller)
f1ab00af
SRRH
140 /* save_mcount_regs fills in first two parameters */
141 save_mcount_regs
142
26ba4e57 143SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL)
f1ab00af
SRRH
144 /* Load the ftrace_ops into the 3rd parameter */
145 movq function_trace_op(%rip), %rdx
146
e18eead3
SR
147 /* regs go into 4th parameter (but make it NULL) */
148 movq $0, %rcx
149
26ba4e57 150SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
e18eead3
SR
151 call ftrace_stub
152
05df710e 153 restore_mcount_regs
f3bea491
SRRH
154
155 /*
f1b92bb6
BP
156 * The code up to this label is copied into trampolines so
157 * think twice before adding any new code or changing the
158 * layout here.
f3bea491 159 */
0298739b 160SYM_INNER_LABEL(ftrace_caller_end, SYM_L_GLOBAL)
e18eead3 161
0298739b
PZ
162 jmp ftrace_epilogue
163SYM_FUNC_END(ftrace_caller);
164
165SYM_FUNC_START(ftrace_epilogue)
e18eead3 166#ifdef CONFIG_FUNCTION_GRAPH_TRACER
26ba4e57 167SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
e18eead3
SR
168 jmp ftrace_stub
169#endif
170
d2a68c4e
SRV
171/*
172 * This is weak to keep gas from relaxing the jumps.
173 * It is also used to copy the retq for trampolines.
174 */
13fbe784 175SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK)
e18eead3 176 retq
0298739b 177SYM_FUNC_END(ftrace_epilogue)
e18eead3 178
6dcc5627 179SYM_FUNC_START(ftrace_regs_caller)
527aa75b 180 /* Save the current flags before any operations that can change them */
e18eead3
SR
181 pushfq
182
527aa75b 183 /* added 8 bytes to save flags */
f1ab00af
SRRH
184 save_mcount_regs 8
185 /* save_mcount_regs fills in first two parameters */
186
26ba4e57 187SYM_INNER_LABEL(ftrace_regs_caller_op_ptr, SYM_L_GLOBAL)
f1ab00af
SRRH
188 /* Load the ftrace_ops into the 3rd parameter */
189 movq function_trace_op(%rip), %rdx
e18eead3
SR
190
191 /* Save the rest of pt_regs */
192 movq %r15, R15(%rsp)
193 movq %r14, R14(%rsp)
194 movq %r13, R13(%rsp)
195 movq %r12, R12(%rsp)
196 movq %r11, R11(%rsp)
197 movq %r10, R10(%rsp)
e18eead3
SR
198 movq %rbx, RBX(%rsp)
199 /* Copy saved flags */
85f6f029 200 movq MCOUNT_REG_SIZE(%rsp), %rcx
e18eead3
SR
201 movq %rcx, EFLAGS(%rsp)
202 /* Kernel segments */
203 movq $__KERNEL_DS, %rcx
204 movq %rcx, SS(%rsp)
205 movq $__KERNEL_CS, %rcx
206 movq %rcx, CS(%rsp)
527aa75b 207 /* Stack - skipping return address and flags */
85f6f029 208 leaq MCOUNT_REG_SIZE+8*2(%rsp), %rcx
e18eead3
SR
209 movq %rcx, RSP(%rsp)
210
ea1ed38d
PZ
211 ENCODE_FRAME_POINTER
212
e18eead3
SR
213 /* regs go into 4th parameter */
214 leaq (%rsp), %rcx
215
26ba4e57 216SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)
e18eead3
SR
217 call ftrace_stub
218
219 /* Copy flags back to SS, to restore them */
220 movq EFLAGS(%rsp), %rax
85f6f029 221 movq %rax, MCOUNT_REG_SIZE(%rsp)
e18eead3
SR
222
223 /* Handlers can change the RIP */
224 movq RIP(%rsp), %rax
85f6f029 225 movq %rax, MCOUNT_REG_SIZE+8(%rsp)
e18eead3
SR
226
227 /* restore the rest of pt_regs */
228 movq R15(%rsp), %r15
229 movq R14(%rsp), %r14
230 movq R13(%rsp), %r13
231 movq R12(%rsp), %r12
232 movq R10(%rsp), %r10
e18eead3
SR
233 movq RBX(%rsp), %rbx
234
562955fe
SRV
235 movq ORIG_RAX(%rsp), %rax
236 movq %rax, MCOUNT_REG_SIZE-8(%rsp)
237
0298739b
PZ
238 /*
239 * If ORIG_RAX is anything but zero, make this a call to that.
240 * See arch_ftrace_set_direct_caller().
241 */
562955fe 242 movq ORIG_RAX(%rsp), %rax
9f2dfd61
PZ
243 testq %rax, %rax
244 jz 1f
562955fe
SRV
245
246 /* Swap the flags with orig_rax */
247 movq MCOUNT_REG_SIZE(%rsp), %rdi
248 movq %rdi, MCOUNT_REG_SIZE-8(%rsp)
249 movq %rax, MCOUNT_REG_SIZE(%rsp)
250
251 restore_mcount_regs 8
0298739b
PZ
252 /* Restore flags */
253 popfq
562955fe 254
0298739b
PZ
255SYM_INNER_LABEL(ftrace_regs_caller_ret, SYM_L_GLOBAL);
256 UNWIND_HINT_RET_OFFSET
257 jmp ftrace_epilogue
562955fe
SRV
258
2591: restore_mcount_regs
e18eead3
SR
260 /* Restore flags */
261 popfq
262
f3bea491 263 /*
f1b92bb6 264 * As this jmp to ftrace_epilogue can be a short jump
f3bea491
SRRH
265 * it must not be copied into the trampoline.
266 * The trampoline will add the code to jump
267 * to the return.
268 */
26ba4e57 269SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL)
f1b92bb6 270 jmp ftrace_epilogue
fdc841b5 271
6dcc5627 272SYM_FUNC_END(ftrace_regs_caller)
e18eead3
SR
273
274
275#else /* ! CONFIG_DYNAMIC_FTRACE */
276
0f42c1ad 277SYM_FUNC_START(__fentry__)
e18eead3
SR
278 cmpq $ftrace_stub, ftrace_trace_function
279 jnz trace
280
62a207d7 281fgraph_trace:
e18eead3
SR
282#ifdef CONFIG_FUNCTION_GRAPH_TRACER
283 cmpq $ftrace_stub, ftrace_graph_return
284 jnz ftrace_graph_caller
285
286 cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
287 jnz ftrace_graph_caller
288#endif
289
26ba4e57 290SYM_INNER_LABEL(ftrace_stub, SYM_L_GLOBAL)
e18eead3
SR
291 retq
292
293trace:
f1ab00af
SRRH
294 /* save_mcount_regs fills in first two parameters */
295 save_mcount_regs
e18eead3 296
112677d6
NK
297 /*
298 * When DYNAMIC_FTRACE is not defined, ARCH_SUPPORTS_FTRACE_OPS is not
299 * set (see include/asm/ftrace.h and include/linux/ftrace.h). Only the
300 * ip and parent ip are used and the list function is called when
301 * function tracing is enabled.
302 */
9351803b 303 movq ftrace_trace_function, %r8
34fdce69 304 CALL_NOSPEC r8
05df710e 305 restore_mcount_regs
e18eead3 306
62a207d7 307 jmp fgraph_trace
0f42c1ad
BP
308SYM_FUNC_END(__fentry__)
309EXPORT_SYMBOL(__fentry__)
e18eead3 310#endif /* CONFIG_DYNAMIC_FTRACE */
e18eead3
SR
311
312#ifdef CONFIG_FUNCTION_GRAPH_TRACER
6dcc5627 313SYM_FUNC_START(ftrace_graph_caller)
6a06bdbf 314 /* Saves rbp into %rdx and fills first parameter */
05df710e 315 save_mcount_regs
e18eead3 316
6a06bdbf 317 leaq MCOUNT_REG_SIZE+8(%rsp), %rsi
e18eead3 318 movq $0, %rdx /* No framepointers needed */
e18eead3
SR
319 call prepare_ftrace_return
320
05df710e 321 restore_mcount_regs
e18eead3
SR
322
323 retq
6dcc5627 324SYM_FUNC_END(ftrace_graph_caller)
e18eead3 325
bc7b11c0 326SYM_CODE_START(return_to_handler)
e2ac83d7 327 UNWIND_HINT_EMPTY
e18eead3
SR
328 subq $24, %rsp
329
330 /* Save the return values */
331 movq %rax, (%rsp)
332 movq %rdx, 8(%rsp)
333 movq %rbp, %rdi
334
335 call ftrace_return_to_handler
336
337 movq %rax, %rdi
338 movq 8(%rsp), %rdx
339 movq (%rsp), %rax
340 addq $24, %rsp
34fdce69 341 JMP_NOSPEC rdi
bc7b11c0 342SYM_CODE_END(return_to_handler)
e18eead3 343#endif