Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) 2017 Steven Rostedt, VMware Inc. |
| 4 | */ |
| 5 | |
| 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> |
David Woodhouse | 9351803 | 2018-01-11 21:46:29 +0000 | [diff] [blame] | 11 | #include <asm/nospec-branch.h> |
Peter Zijlstra | ea1ed38 | 2019-05-07 23:25:50 +0200 | [diff] [blame] | 12 | #include <asm/frame.h> |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 13 | #include <asm/asm-offsets.h> |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 14 | |
Steven Rostedt (VMware) | 562e14f | 2019-05-09 15:32:05 -0400 | [diff] [blame] | 15 | #ifdef CONFIG_FRAME_POINTER |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 16 | # define MCOUNT_FRAME 1 /* using frame = true */ |
| 17 | #else |
| 18 | # define MCOUNT_FRAME 0 /* using frame = false */ |
| 19 | #endif |
| 20 | |
Borislav Petkov | 0f42c1a | 2019-10-21 17:18:23 +0200 | [diff] [blame] | 21 | SYM_FUNC_START(__fentry__) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 22 | ret |
Borislav Petkov | 0f42c1a | 2019-10-21 17:18:23 +0200 | [diff] [blame] | 23 | SYM_FUNC_END(__fentry__) |
| 24 | EXPORT_SYMBOL(__fentry__) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 25 | |
Jiri Slaby | 5e63306 | 2019-10-11 13:51:06 +0200 | [diff] [blame] | 26 | SYM_CODE_START(ftrace_caller) |
Steven Rostedt (VMware) | e6928e5 | 2017-03-23 10:33:50 -0400 | [diff] [blame] | 27 | |
Steven Rostedt (VMware) | 562e14f | 2019-05-09 15:32:05 -0400 | [diff] [blame] | 28 | #ifdef CONFIG_FRAME_POINTER |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 29 | /* |
| 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. |
| 34 | */ |
| 35 | pushl 4(%esp) /* parent ip */ |
Steven Rostedt (VMware) | e6928e5 | 2017-03-23 10:33:50 -0400 | [diff] [blame] | 36 | pushl %ebp |
| 37 | movl %esp, %ebp |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 38 | pushl 2*4(%esp) /* function ip */ |
Steven Rostedt (VMware) | 562e14f | 2019-05-09 15:32:05 -0400 | [diff] [blame] | 39 | |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 40 | /* For mcount, the function ip is directly above */ |
| 41 | pushl %ebp |
| 42 | movl %esp, %ebp |
| 43 | #endif |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 44 | pushl %eax |
| 45 | pushl %ecx |
| 46 | pushl %edx |
| 47 | pushl $0 /* Pass NULL as regs pointer */ |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 48 | |
Steven Rostedt (VMware) | 562e14f | 2019-05-09 15:32:05 -0400 | [diff] [blame] | 49 | #ifdef CONFIG_FRAME_POINTER |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 50 | /* Load parent ebp into edx */ |
Steven Rostedt (VMware) | e6928e5 | 2017-03-23 10:33:50 -0400 | [diff] [blame] | 51 | movl 4*4(%esp), %edx |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 52 | #else |
| 53 | /* There's no frame pointer, load the appropriate stack addr instead */ |
| 54 | lea 4*4(%esp), %edx |
| 55 | #endif |
| 56 | |
| 57 | movl (MCOUNT_FRAME+4)*4(%esp), %eax /* load the rip */ |
Steven Rostedt (VMware) | e6928e5 | 2017-03-23 10:33:50 -0400 | [diff] [blame] | 58 | /* Get the parent ip */ |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 59 | movl 4(%edx), %edx /* edx has ebp */ |
| 60 | |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 61 | movl function_trace_op, %ecx |
| 62 | subl $MCOUNT_INSN_SIZE, %eax |
| 63 | |
| 64 | .globl ftrace_call |
| 65 | ftrace_call: |
| 66 | call ftrace_stub |
| 67 | |
| 68 | addl $4, %esp /* skip NULL pointer */ |
| 69 | popl %edx |
| 70 | popl %ecx |
| 71 | popl %eax |
Steven Rostedt (VMware) | 562e14f | 2019-05-09 15:32:05 -0400 | [diff] [blame] | 72 | #ifdef CONFIG_FRAME_POINTER |
Steven Rostedt (VMware) | e6928e5 | 2017-03-23 10:33:50 -0400 | [diff] [blame] | 73 | popl %ebp |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 74 | addl $4,%esp /* skip function ip */ |
| 75 | popl %ebp /* this is the orig bp */ |
| 76 | addl $4, %esp /* skip parent ip */ |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 77 | #endif |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 78 | .Lftrace_ret: |
| 79 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 80 | .globl ftrace_graph_call |
| 81 | ftrace_graph_call: |
| 82 | jmp ftrace_stub |
| 83 | #endif |
| 84 | |
| 85 | /* This is weak to keep gas from relaxing the jumps */ |
Jiri Slaby | 13fbe78 | 2019-10-11 13:51:08 +0200 | [diff] [blame] | 86 | SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 87 | ret |
Jiri Slaby | 5e63306 | 2019-10-11 13:51:06 +0200 | [diff] [blame] | 88 | SYM_CODE_END(ftrace_caller) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 89 | |
Jiri Slaby | 78762b0 | 2019-10-11 13:51:05 +0200 | [diff] [blame] | 90 | SYM_CODE_START(ftrace_regs_caller) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 91 | /* |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 92 | * We're here from an mcount/fentry CALL, and the stack frame looks like: |
| 93 | * |
| 94 | * <previous context> |
| 95 | * RET-IP |
| 96 | * |
| 97 | * The purpose of this function is to call out in an emulated INT3 |
| 98 | * environment with a stack frame like: |
| 99 | * |
| 100 | * <previous context> |
| 101 | * gap / RET-IP |
| 102 | * gap |
| 103 | * gap |
| 104 | * gap |
| 105 | * pt_regs |
| 106 | * |
| 107 | * We do _NOT_ restore: ss, flags, cs, gs, fs, es, ds |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 108 | */ |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 109 | subl $3*4, %esp # RET-IP + 3 gaps |
| 110 | pushl %ss # ss |
| 111 | pushl %esp # points at ss |
| 112 | addl $5*4, (%esp) # make it point at <previous context> |
| 113 | pushfl # flags |
| 114 | pushl $__KERNEL_CS # cs |
| 115 | pushl 7*4(%esp) # ip <- RET-IP |
| 116 | pushl $0 # orig_eax |
| 117 | |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 118 | pushl %gs |
| 119 | pushl %fs |
| 120 | pushl %es |
| 121 | pushl %ds |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 122 | |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 123 | pushl %eax |
| 124 | pushl %ebp |
| 125 | pushl %edi |
| 126 | pushl %esi |
| 127 | pushl %edx |
| 128 | pushl %ecx |
| 129 | pushl %ebx |
| 130 | |
Peter Zijlstra | ea1ed38 | 2019-05-07 23:25:50 +0200 | [diff] [blame] | 131 | ENCODE_FRAME_POINTER |
| 132 | |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 133 | movl PT_EIP(%esp), %eax # 1st argument: IP |
| 134 | subl $MCOUNT_INSN_SIZE, %eax |
| 135 | movl 21*4(%esp), %edx # 2nd argument: parent ip |
| 136 | movl function_trace_op, %ecx # 3rd argument: ftrace_pos |
| 137 | pushl %esp # 4th argument: pt_regs |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 138 | |
Jiri Slaby | 26ba4e5 | 2019-10-11 13:50:57 +0200 | [diff] [blame] | 139 | SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 140 | call ftrace_stub |
| 141 | |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 142 | addl $4, %esp # skip 4th argument |
Steven Rostedt (VMware) | ff04b44 | 2017-03-23 10:33:51 -0400 | [diff] [blame] | 143 | |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 144 | /* place IP below the new SP */ |
| 145 | movl PT_OLDESP(%esp), %eax |
| 146 | movl PT_EIP(%esp), %ecx |
| 147 | movl %ecx, -4(%eax) |
Steven Rostedt (VMware) | ff04b44 | 2017-03-23 10:33:51 -0400 | [diff] [blame] | 148 | |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 149 | /* place EAX below that */ |
| 150 | movl PT_EAX(%esp), %ecx |
| 151 | movl %ecx, -8(%eax) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 152 | |
| 153 | popl %ebx |
| 154 | popl %ecx |
| 155 | popl %edx |
| 156 | popl %esi |
| 157 | popl %edi |
| 158 | popl %ebp |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 159 | |
Peter Zijlstra | 3c88c69 | 2019-05-07 23:25:54 +0200 | [diff] [blame] | 160 | lea -8(%eax), %esp |
| 161 | popl %eax |
Steven Rostedt (VMware) | ff04b44 | 2017-03-23 10:33:51 -0400 | [diff] [blame] | 162 | |
| 163 | jmp .Lftrace_ret |
Jiri Slaby | 78762b0 | 2019-10-11 13:51:05 +0200 | [diff] [blame] | 164 | SYM_CODE_END(ftrace_regs_caller) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 165 | |
| 166 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
Jiri Slaby | 5e63306 | 2019-10-11 13:51:06 +0200 | [diff] [blame] | 167 | SYM_CODE_START(ftrace_graph_caller) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 168 | pushl %eax |
| 169 | pushl %ecx |
| 170 | pushl %edx |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 171 | movl 3*4(%esp), %eax |
| 172 | /* Even with frame pointers, fentry doesn't have one here */ |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 173 | lea 4*4(%esp), %edx |
| 174 | movl $0, %ecx |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 175 | subl $MCOUNT_INSN_SIZE, %eax |
| 176 | call prepare_ftrace_return |
| 177 | popl %edx |
| 178 | popl %ecx |
| 179 | popl %eax |
| 180 | ret |
Jiri Slaby | 5e63306 | 2019-10-11 13:51:06 +0200 | [diff] [blame] | 181 | SYM_CODE_END(ftrace_graph_caller) |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 182 | |
| 183 | .globl return_to_handler |
| 184 | return_to_handler: |
| 185 | pushl %eax |
| 186 | pushl %edx |
Steven Rostedt (VMware) | 644e0e8 | 2017-03-23 10:33:52 -0400 | [diff] [blame] | 187 | movl $0, %eax |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 188 | call ftrace_return_to_handler |
| 189 | movl %eax, %ecx |
| 190 | popl %edx |
| 191 | popl %eax |
Peter Zijlstra | 34fdce6 | 2020-04-22 17:16:40 +0200 | [diff] [blame] | 192 | JMP_NOSPEC ecx |
Steven Rostedt (VMware) | 3d82c59 | 2017-03-23 10:33:49 -0400 | [diff] [blame] | 193 | #endif |