1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright (C) 2017 Steven Rostedt, VMware Inc.
6 #include <linux/linkage.h>
7 #include <asm/page_types.h>
8 #include <asm/segment.h>
9 #include <asm/export.h>
10 #include <asm/ftrace.h>
11 #include <asm/nospec-branch.h>
13 # define function_hook __fentry__
14 EXPORT_SYMBOL(__fentry__)
16 #ifdef CONFIG_FRAME_POINTER
17 # define MCOUNT_FRAME 1 /* using frame = true */
19 # define MCOUNT_FRAME 0 /* using frame = false */
28 #ifdef CONFIG_FRAME_POINTER
30 * Frame pointers are of ip followed by bp.
31 * Since fentry is an immediate jump, we are left with
32 * parent-ip, function-ip. We need to add a frame with
33 * parent-ip followed by ebp.
35 pushl 4(%esp) /* parent ip */
38 pushl 2*4(%esp) /* function ip */
40 /* For mcount, the function ip is directly above */
47 pushl $0 /* Pass NULL as regs pointer */
49 #ifdef CONFIG_FRAME_POINTER
50 /* Load parent ebp into edx */
53 /* There's no frame pointer, load the appropriate stack addr instead */
57 movl (MCOUNT_FRAME+4)*4(%esp), %eax /* load the rip */
58 /* Get the parent ip */
59 movl 4(%edx), %edx /* edx has ebp */
61 movl function_trace_op, %ecx
62 subl $MCOUNT_INSN_SIZE, %eax
68 addl $4, %esp /* skip NULL pointer */
72 #ifdef CONFIG_FRAME_POINTER
74 addl $4,%esp /* skip function ip */
75 popl %ebp /* this is the orig bp */
76 addl $4, %esp /* skip parent ip */
79 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
80 .globl ftrace_graph_call
85 /* This is weak to keep gas from relaxing the jumps */
90 ENTRY(ftrace_regs_caller)
92 * i386 does not save SS and ESP when coming from kernel.
93 * Instead, to get sp, ®s->sp is used (see ptrace.h).
94 * Unfortunately, that means eflags must be at the same location
95 * as the current return ip is. We move the return ip into the
96 * regs->ip location, and move flags into the return ip location.
99 pushl 4(%esp) /* Save the return ip */
100 pushl $0 /* Load 0 into orig_ax */
107 /* Get flags and place them into the return ip slot */
119 movl 12*4(%esp), %eax /* Load ip (1st parameter) */
120 subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */
121 movl 15*4(%esp), %edx /* Load parent ip (2nd parameter) */
122 movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
123 pushl %esp /* Save pt_regs as 4th parameter */
125 GLOBAL(ftrace_regs_call)
128 addl $4, %esp /* Skip pt_regs */
134 /* Move return ip back to its original location */
135 movl 12*4(%esp), %eax
136 movl %eax, 14*4(%esp)
150 /* use lea to not affect flags */
151 lea 3*4(%esp), %esp /* Skip orig_ax, ip and cs */
155 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
156 ENTRY(ftrace_graph_caller)
161 /* Even with frame pointers, fentry doesn't have one here */
164 subl $MCOUNT_INSN_SIZE, %eax
165 call prepare_ftrace_return
170 END(ftrace_graph_caller)
172 .globl return_to_handler
177 call ftrace_return_to_handler