ftrace/x86: Add support for -mfentry to x86_64
authorSteven Rostedt <srostedt@redhat.com>
Wed, 9 Feb 2011 18:32:18 +0000 (13:32 -0500)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 23 Aug 2012 15:26:36 +0000 (11:26 -0400)
If 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,%rsi

With -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,%rsi

This 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.

Link: http://lkml.kernel.org/r/20120807194100.130477900@goodmis.org
Acked-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Andi Kleen <andi@firstfloor.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
arch/x86/Kconfig
arch/x86/include/asm/ftrace.h
arch/x86/kernel/entry_64.S
arch/x86/kernel/x8664_ksyms_64.c

index a2d19ee750ca90122090345ee6d9c04681990213..28dd891a0a160a9c2f988f6698cecc1334174b58 100644 (file)
@@ -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
index a6cae0c1720cdcd66f27724c0b8fd6a52a013c82..9a25b522d37799adf0b7a00d898ba30cb70b08b7 100644 (file)
 #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)
 {
index b7a81dcb7366d4d70abaa460069c1cf1d4916ca9..ed767b747fe5e731c38e92fd872cd71a137adc55 100644 (file)
        .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
index 6020f6f5927cbc1035b7f86b1f19f1422ded0acf..1330dd10295031544d08788320524fb917b889bc 100644 (file)
 #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);