Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ftrace/x86: Remove mcount support

There's two methods of enabling function tracing in Linux on x86. One is
with just "gcc -pg" and the other is "gcc -pg -mfentry". The former will use
calls to a special function "mcount" after the frame is set up in all C
functions. The latter will add calls to a special function called "fentry"
as the very first instruction of all C functions.

At compile time, there is a check to see if gcc supports, -mfentry, and if
it does, it will use that, because it is more versatile and less error prone
for function tracing.

Starting with v4.19, the minimum gcc supported to build the Linux kernel,
was raised to version 4.6. That also happens to be the first gcc version to
support -mfentry. Since on x86, using gcc versions from 4.6 and beyond will
unconditionally enable the -mfentry, it will no longer use mcount as the
method for inserting calls into the C functions of the kernel. This means
that there is no point in continuing to maintain mcount in x86.

Remove support for using mcount. This makes the code less complex, and will
also allow it to be simplified in the future.

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Jiri Kosina <jkosina@suse.cz>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

+9 -66
+3 -5
arch/x86/include/asm/ftrace.h
··· 3 3 #define _ASM_X86_FTRACE_H 4 4 5 5 #ifdef CONFIG_FUNCTION_TRACER 6 - #ifdef CC_USING_FENTRY 7 - # define MCOUNT_ADDR ((unsigned long)(__fentry__)) 8 - #else 9 - # define MCOUNT_ADDR ((unsigned long)(mcount)) 10 - # define HAVE_FUNCTION_GRAPH_FP_TEST 6 + #ifndef CC_USING_FENTRY 7 + # error Compiler does not support fentry? 11 8 #endif 9 + # define MCOUNT_ADDR ((unsigned long)(__fentry__)) 12 10 #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ 13 11 14 12 #ifdef CONFIG_DYNAMIC_FTRACE
-3
arch/x86/include/asm/livepatch.h
··· 26 26 27 27 static inline int klp_check_compiler_support(void) 28 28 { 29 - #ifndef CC_USING_FENTRY 30 - return 1; 31 - #endif 32 29 return 0; 33 30 } 34 31
+5 -31
arch/x86/kernel/ftrace_32.S
··· 10 10 #include <asm/ftrace.h> 11 11 #include <asm/nospec-branch.h> 12 12 13 - #ifdef CC_USING_FENTRY 14 13 # define function_hook __fentry__ 15 14 EXPORT_SYMBOL(__fentry__) 16 - #else 17 - # define function_hook mcount 18 - EXPORT_SYMBOL(mcount) 19 - #endif 20 15 21 - /* mcount uses a frame pointer even if CONFIG_FRAME_POINTER is not set */ 22 - #if !defined(CC_USING_FENTRY) || defined(CONFIG_FRAME_POINTER) 23 - # define USING_FRAME_POINTER 24 - #endif 25 - 26 - #ifdef USING_FRAME_POINTER 16 + #ifdef CONFIG_FRAME_POINTER 27 17 # define MCOUNT_FRAME 1 /* using frame = true */ 28 18 #else 29 19 # define MCOUNT_FRAME 0 /* using frame = false */ ··· 25 35 26 36 ENTRY(ftrace_caller) 27 37 28 - #ifdef USING_FRAME_POINTER 29 - # ifdef CC_USING_FENTRY 38 + #ifdef CONFIG_FRAME_POINTER 30 39 /* 31 40 * Frame pointers are of ip followed by bp. 32 41 * Since fentry is an immediate jump, we are left with ··· 36 47 pushl %ebp 37 48 movl %esp, %ebp 38 49 pushl 2*4(%esp) /* function ip */ 39 - # endif 50 + 40 51 /* For mcount, the function ip is directly above */ 41 52 pushl %ebp 42 53 movl %esp, %ebp ··· 46 57 pushl %edx 47 58 pushl $0 /* Pass NULL as regs pointer */ 48 59 49 - #ifdef USING_FRAME_POINTER 60 + #ifdef CONFIG_FRAME_POINTER 50 61 /* Load parent ebp into edx */ 51 62 movl 4*4(%esp), %edx 52 63 #else ··· 69 80 popl %edx 70 81 popl %ecx 71 82 popl %eax 72 - #ifdef USING_FRAME_POINTER 83 + #ifdef CONFIG_FRAME_POINTER 73 84 popl %ebp 74 - # ifdef CC_USING_FENTRY 75 85 addl $4,%esp /* skip function ip */ 76 86 popl %ebp /* this is the orig bp */ 77 87 addl $4, %esp /* skip parent ip */ 78 - # endif 79 88 #endif 80 89 .Lftrace_ret: 81 90 #ifdef CONFIG_FUNCTION_GRAPH_TRACER ··· 118 131 119 132 movl 12*4(%esp), %eax /* Load ip (1st parameter) */ 120 133 subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ 121 - #ifdef CC_USING_FENTRY 122 134 movl 15*4(%esp), %edx /* Load parent ip (2nd parameter) */ 123 - #else 124 - movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ 125 - #endif 126 135 movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ 127 136 pushl %esp /* Save pt_regs as 4th parameter */ 128 137 ··· 159 176 pushl %edx 160 177 movl 3*4(%esp), %eax 161 178 /* Even with frame pointers, fentry doesn't have one here */ 162 - #ifdef CC_USING_FENTRY 163 179 lea 4*4(%esp), %edx 164 180 movl $0, %ecx 165 - #else 166 - lea 0x4(%ebp), %edx 167 - movl (%ebp), %ecx 168 - #endif 169 181 subl $MCOUNT_INSN_SIZE, %eax 170 182 call prepare_ftrace_return 171 183 popl %edx ··· 173 195 return_to_handler: 174 196 pushl %eax 175 197 pushl %edx 176 - #ifdef CC_USING_FENTRY 177 198 movl $0, %eax 178 - #else 179 - movl %ebp, %eax 180 - #endif 181 199 call ftrace_return_to_handler 182 200 movl %eax, %ecx 183 201 popl %edx
+1 -27
arch/x86/kernel/ftrace_64.S
··· 13 13 .code64 14 14 .section .entry.text, "ax" 15 15 16 - #ifdef CC_USING_FENTRY 17 16 # define function_hook __fentry__ 18 17 EXPORT_SYMBOL(__fentry__) 19 - #else 20 - # define function_hook mcount 21 - EXPORT_SYMBOL(mcount) 22 - #endif 23 18 24 19 #ifdef CONFIG_FRAME_POINTER 25 - # ifdef CC_USING_FENTRY 26 20 /* Save parent and function stack frames (rip and rbp) */ 27 21 # define MCOUNT_FRAME_SIZE (8+16*2) 28 - # else 29 - /* Save just function stack frame (rip and rbp) */ 30 - # define MCOUNT_FRAME_SIZE (8+16) 31 - # endif 32 22 #else 33 23 /* No need to save a stack frame */ 34 24 # define MCOUNT_FRAME_SIZE 0 ··· 65 75 * fentry is called before the stack frame is set up, where as mcount 66 76 * is called afterward. 67 77 */ 68 - #ifdef CC_USING_FENTRY 78 + 69 79 /* Save the parent pointer (skip orig rbp and our return address) */ 70 80 pushq \added+8*2(%rsp) 71 81 pushq %rbp 72 82 movq %rsp, %rbp 73 83 /* Save the return address (now skip orig rbp, rbp and parent) */ 74 84 pushq \added+8*3(%rsp) 75 - #else 76 - /* Can't assume that rip is before this (unless added was zero) */ 77 - pushq \added+8(%rsp) 78 - #endif 79 85 pushq %rbp 80 86 movq %rsp, %rbp 81 87 #endif /* CONFIG_FRAME_POINTER */ ··· 99 113 movq %rdx, RBP(%rsp) 100 114 101 115 /* Copy the parent address into %rsi (second parameter) */ 102 - #ifdef CC_USING_FENTRY 103 116 movq MCOUNT_REG_SIZE+8+\added(%rsp), %rsi 104 - #else 105 - /* %rdx contains original %rbp */ 106 - movq 8(%rdx), %rsi 107 - #endif 108 117 109 118 /* Move RIP to its proper location */ 110 119 movq MCOUNT_REG_SIZE+\added(%rsp), %rdi ··· 284 303 /* Saves rbp into %rdx and fills first parameter */ 285 304 save_mcount_regs 286 305 287 - #ifdef CC_USING_FENTRY 288 306 leaq MCOUNT_REG_SIZE+8(%rsp), %rsi 289 307 movq $0, %rdx /* No framepointers needed */ 290 - #else 291 - /* Save address of the return address of traced function */ 292 - leaq 8(%rdx), %rsi 293 - /* ftrace does sanity checks against frame pointers */ 294 - movq (%rdx), %rdx 295 - #endif 296 308 call prepare_ftrace_return 297 309 298 310 restore_mcount_regs