ftrace: Use of __fentry__
Steven Rostedt
maintainerIngo,
Please pull the latest tip/perf/core tree, which can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
tip/perf/core
Head SHA1: d57c5d51a30152f3175d2344cb6395f08bf8ee0c
Steven Rostedt (4):
ftrace: Make recordmcount.c handle __fentry__
ftrace: Add -mfentry to Makefile on function tracer
ftrace: Do not test frame pointers if -mfentry is used ftrace/x86: Add support for -mfentry to x86_64
----
Makefile | 6 +++++- arch/x86/Kconfig | 1 + arch/x86/include/asm/ftrace.h | 7 ++++++- arch/x86/kernel/entry_64.S | 32 +++++++++++++++++++++++++++----- arch/x86/kernel/x8664_ksyms_64.c | 6 +++++- kernel/trace/Kconfig | 5 +++++ kernel/trace/trace_functions_graph.c | 5 ++++- scripts/recordmcount.h | 4 +++- 8 files changed, 56 insertions(+), 10 deletions(-)
Steven Rostedt
maintainerPATCH 1/4 ftrace: Make recordmcount.c handle __fentry__
With gcc 4.6.0 the -mfentry feature places the function profiling call at the start of the function. When this is used, the call is to __fentry__ and not mcount.
Change recordmcount.c to record both callers to __fentry__ and mcount.
--- scripts/recordmcount.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
scripts/recordmcount.h +3 -1
@@ -261,11 +261,13 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0, &sym0[Elf_r_sym (relp)];char const *symname = &str0[w (symp->st_name)];char const *mcount = gpfx =='_' ?"_mcount" :"mcount" ; +char const *fentry ="__fentry__" ;if (symname[0 ] =='.' ) ++symname;/* ppc64 hack */ if (strcmp (mcount, symname) ==0 || - (altmcount &&strcmp (altmcount, symname) ==0 )) + (altmcount &&strcmp (altmcount, symname) ==0 ) || + (strcmp (fentry, symname) ==0 )) mcountsym =Elf_r_sym (relp);return mcountsym;
Signature · 1 line
1.7.10.4
Re: [PATCH 1/4] ftrace: Make recordmcount.c handle __fentry__
I did a quick read of the patches and they all look good to me.
-Andi
Signature · 1 line
[email protected] -- Speaking for myself only.
Steven Rostedt
maintainerPATCH 2/4 ftrace: Add -mfentry to Makefile on function tracer
In reply to Steven RostedtThanks to Andi Kleen, gcc 4.6.0 now supports -mfentry for x86 (and hopefully soon for other archs). What this does is to have the function profiler start at the beginning of the function instead of after the stack is set up. As plain -pg (mcount) is called after the stack is set up, and in some cases can have issues with the function graph tracer. It also requires frame pointers to be enabled.
The -mfentry now calls __fentry__ at the beginning of the function. This allows for compiling without frame pointers and even has the ability to access parameters if needed.
If the architecture and the compiler both support -mfentry then use that instead.
--- Makefile | 6 +++++- kernel/trace/Kconfig | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-)
Makefile +5 -1
@@ -609,7 +609,11 @@ KBUILD_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly) endif ifdef CONFIG_FUNCTION_TRACER -KBUILD_CFLAGS += -pg +ifdef CONFIG_HAVE_FENTRY +CC_USING_FENTRY := $(call cc-option, -mfentry -DCC_USING_FENTRY) +endif +KBUILD_CFLAGS += -pg $(CC_USING_FENTRY) +KBUILD_AFLAGS += $(CC_USING_FENTRY) ifdef CONFIG_DYNAMIC_FTRACE ifdef CONFIG_HAVE_C_RECORDMCOUNT BUILD_C_RECORDMCOUNT := y
kernel/trace/Kconfig +5 -0
@@ -49,6 +49,11 @@ config HAVE_SYSCALL_TRACEPOINTS help See Documentation/trace/ftrace-design.txt +config HAVE_FENTRY + bool + help + Arch supports the gcc options -pg with -mfentry + config HAVE_C_RECORDMCOUNT bool help
Signature · 1 line
1.7.10.4
Steven Rostedt
maintainerPATCH 3/4 ftrace: Do not test frame pointers if -mfentry is used
In reply to Steven RostedtThe function graph has a test to check if the frame pointer is corrupted, which can happen with various options of gcc with mcount. But this is not an issue with -mfentry as -mfentry does not need nor use frame pointers for function graph tracing.
--- kernel/trace/trace_functions_graph.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/trace/trace_functions_graph.c +4 -1
@@ -143,7 +143,7 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,return ; } -#ifdef CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST +#if defined(CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST ) && !defined(CC_USING_FENTRY )/* * The arch may choose to record the frame pointer used * and check it here to make sure that it is what we expect it
@@ -154,6 +154,9 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,* * Currently, x86_32 with optimize for size (-Os) makes the latest * gcc do the above. +* +* Note, -mfentry does not use frame pointers, and this test +* is not needed if CC_USING_FENTRY is set. */ if (unlikely (current->ret_stack[index].fp != frame_pointer)) {ftrace_graph_stop ();
Signature · 1 line
1.7.10.4
Steven Rostedt
maintainerPATCH 4/4 ftrace/x86: Add support for -mfentry to x86_64
In reply to Steven RostedtIf the kernel is compiled with gcc 4.6.0 which supports -mfentry, then use that instead of mcount.
With mcount, frame pointers are forced with the -pg option and we get something like:
<can_vma_merge_before>:
55 push %rbp
48 89 e5 mov %rsp,%rbp
53 push %rbx
41 51 push %r9
e8 fe 6a 39 00 callq ffffffff81483d00 <mcount>
31 c0 xor %eax,%eax
48 89 fb mov %rdi,%rbx
48 89 d7 mov %rdx,%rdi
48 33 73 30 xor 0x30(%rbx),%rsi
48 f7 c6 ff ff ff f7 test $0xfffffffff7ffffff,%rsiWith -mfentry, frame pointers are no longer forced and the call looks like this:
<can_vma_merge_before>:
e8 33 af 37 00 callq ffffffff81461b40 <__fentry__>
53 push %rbx
48 89 fb mov %rdi,%rbx
31 c0 xor %eax,%eax
48 89 d7 mov %rdx,%rdi
41 51 push %r9
48 33 73 30 xor 0x30(%rbx),%rsi
48 f7 c6 ff ff ff f7 test $0xfffffffff7ffffff,%rsiThis adds the ftrace hook at the beginning of the function before a frame is set up, and allows the function callbacks to be able to access parameters. As kprobes now can use function tracing (at least on x86) this speeds up the kprobe hooks that are at the beginning of the function.
--- arch/x86/Kconfig | 1 + arch/x86/include/asm/ftrace.h | 7 ++++++- arch/x86/kernel/entry_64.S | 32 +++++++++++++++++++++++++++----- arch/x86/kernel/x8664_ksyms_64.c | 6 +++++- 4 files changed, 39 insertions(+), 7 deletions(-)
arch/x86/Kconfig +1 -0
@@ -36,6 +36,7 @@ config X86 select HAVE_KRETPROBES select HAVE_OPTPROBES select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_FENTRY if X86_64 select HAVE_C_RECORDMCOUNT select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACER
arch/x86/include/asm/ftrace.h +6 -1
@@ -35,7 +35,11 @@#endif #ifdef CONFIG_FUNCTION_TRACER -#define MCOUNT_ADDR ((long)(mcount)) +#ifdef CC_USING_FENTRY +# define MCOUNT_ADDR ((long)(__fentry__)) +#else +# define MCOUNT_ADDR ((long)(mcount)) +#endif #define MCOUNT_INSN_SIZE 5/* sizeof mcount call */ #ifdef CONFIG_DYNAMIC_FTRACE
@@ -46,6 +50,7 @@#ifndef __ASSEMBLY__extern void mcount (void );extern atomic_t modifying_ftrace_code; +extern void __fentry__ (void );static inline unsigned long ftrace_call_adjust (unsigned long addr) {
arch/x86/kernel/entry_64.S +27 -5
@@ -68,10 +68,18 @@ .section .entry.text, "ax" #ifdef CONFIG_FUNCTION_TRACER + +#ifdef CC_USING_FENTRY +# define function_hook __fentry__ +#else +# define function_hook mcount +#endif + #ifdef CONFIG_DYNAMIC_FTRACE -ENTRY(mcount) + +ENTRY(function_hook) retq -END(mcount) +END(function_hook) /* skip is set if stack has been adjusted */ .macro ftrace_caller_setup skip=0
@@ -84,7 +92,11 @@ END(mcount) movq RIP(%rsp), %rdi subq $MCOUNT_INSN_SIZE, %rdi /* Load the parent_ip into the second parameter */ +#ifdef CC_USING_FENTRY + movq SS+16(%rsp), %rsi +#else movq 8(%rbp), %rsi +#endif .endm ENTRY(ftrace_caller)
@@ -177,7 +189,8 @@ END(ftrace_regs_caller) #else /* ! CONFIG_DYNAMIC_FTRACE */ -ENTRY(mcount) + +ENTRY(function_hook) cmpl $0, function_trace_stop jne ftrace_stub
@@ -199,7 +212,11 @@ trace: MCOUNT_SAVE_FRAME movq RIP(%rsp), %rdi +#ifdef CC_USING_FENTRY + movq SS+16(%rsp), %rsi +#else movq 8(%rbp), %rsi +#endif subq $MCOUNT_INSN_SIZE, %rdi call *ftrace_trace_function
@@ -207,7 +224,7 @@ trace: MCOUNT_RESTORE_FRAME jmp ftrace_stub -END(mcount) +END(function_hook) #endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_TRACER */
@@ -215,9 +232,14 @@ END(mcount) ENTRY(ftrace_graph_caller) MCOUNT_SAVE_FRAME +#ifdef CC_USING_FENTRY + leaq SS+16(%rsp), %rdi + movq $0, %rdx /* No framepointers needed */ +#else leaq 8(%rbp), %rdi - movq RIP(%rsp), %rsi movq (%rbp), %rdx +#endif + movq RIP(%rsp), %rsi subq $MCOUNT_INSN_SIZE, %rsi call prepare_ftrace_return
arch/x86/kernel/x8664_ksyms_64.c +5 -1
@@ -13,9 +13,13 @@#include <asm/ftrace.h> #ifdef CONFIG_FUNCTION_TRACER -/* mcount is defined in assembly */ +/* mcount and __fentry__ are defined in assembly */ +#ifdef CC_USING_FENTRY +EXPORT_SYMBOL (__fentry__); +#else EXPORT_SYMBOL (mcount);#endif +#endif EXPORT_SYMBOL (__get_user_1);EXPORT_SYMBOL (__get_user_2);
Signature · 1 line
1.7.10.4