Skip to content

Commit 644e0e8

Browse files
rostedtKAGA-KOKO
authored andcommitted
x86/ftrace: Add -mfentry support to x86_32 with DYNAMIC_FTRACE set
x86_64 has had fentry support for some time. I did not add support to x86_32 as I was unsure if it will be used much in the future. It is still very much used, and there's issues with function graph tracing with gcc playing around with the mcount frames, causing function graph to panic. The fentry code does not have this issue, and is able to cope as there is no frame to mess up. Note, this only adds support for fentry when DYNAMIC_FTRACE is set. There's really no reason to not have that set, because the performance of the machine drops significantly when it's not enabled. Keep !DYNAMIC_FTRACE around to test it off, as there's still some archs that have FTRACE but not DYNAMIC_FTRACE. Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org> Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> Reviewed-by: Ingo Molnar <mingo@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: http://lkml.kernel.org/r/20170323143446.052202377@goodmis.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent ff04b44 commit 644e0e8

File tree

2 files changed

+73
-11
lines changed

2 files changed

+73
-11
lines changed

arch/x86/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ config X86
127127
select HAVE_EBPF_JIT if X86_64
128128
select HAVE_EFFICIENT_UNALIGNED_ACCESS
129129
select HAVE_EXIT_THREAD
130-
select HAVE_FENTRY if X86_64
130+
select HAVE_FENTRY if X86_64 || DYNAMIC_FTRACE
131131
select HAVE_FTRACE_MCOUNT_RECORD
132132
select HAVE_FUNCTION_GRAPH_TRACER
133133
select HAVE_FUNCTION_TRACER

arch/x86/kernel/ftrace_32.S

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,68 @@
99
#include <asm/ftrace.h>
1010

1111
#ifdef CONFIG_FUNCTION_TRACER
12+
13+
#ifdef CC_USING_FENTRY
14+
# define function_hook __fentry__
15+
EXPORT_SYMBOL(__fentry__)
16+
#else
17+
# define function_hook mcount
18+
EXPORT_SYMBOL(mcount)
19+
#endif
20+
1221
#ifdef CONFIG_DYNAMIC_FTRACE
1322

14-
ENTRY(mcount)
23+
/* mcount uses a frame pointer even if CONFIG_FRAME_POINTER is not set */
24+
#if !defined(CC_USING_FENTRY) || defined(CONFIG_FRAME_POINTER)
25+
# define USING_FRAME_POINTER
26+
#endif
27+
28+
#ifdef USING_FRAME_POINTER
29+
# define MCOUNT_FRAME 1 /* using frame = true */
30+
#else
31+
# define MCOUNT_FRAME 0 /* using frame = false */
32+
#endif
33+
34+
ENTRY(function_hook)
1535
ret
16-
END(mcount)
36+
END(function_hook)
1737

1838
ENTRY(ftrace_caller)
1939

40+
#ifdef USING_FRAME_POINTER
41+
# ifdef CC_USING_FENTRY
42+
/*
43+
* Frame pointers are of ip followed by bp.
44+
* Since fentry is an immediate jump, we are left with
45+
* parent-ip, function-ip. We need to add a frame with
46+
* parent-ip followed by ebp.
47+
*/
48+
pushl 4(%esp) /* parent ip */
2049
pushl %ebp
2150
movl %esp, %ebp
22-
51+
pushl 2*4(%esp) /* function ip */
52+
# endif
53+
/* For mcount, the function ip is directly above */
54+
pushl %ebp
55+
movl %esp, %ebp
56+
#endif
2357
pushl %eax
2458
pushl %ecx
2559
pushl %edx
2660
pushl $0 /* Pass NULL as regs pointer */
27-
movl 5*4(%esp), %eax
28-
/* Copy original ebp into %edx */
61+
62+
#ifdef USING_FRAME_POINTER
63+
/* Load parent ebp into edx */
2964
movl 4*4(%esp), %edx
65+
#else
66+
/* There's no frame pointer, load the appropriate stack addr instead */
67+
lea 4*4(%esp), %edx
68+
#endif
69+
70+
movl (MCOUNT_FRAME+4)*4(%esp), %eax /* load the rip */
3071
/* Get the parent ip */
31-
movl 0x4(%edx), %edx
72+
movl 4(%edx), %edx /* edx has ebp */
73+
3274
movl function_trace_op, %ecx
3375
subl $MCOUNT_INSN_SIZE, %eax
3476

@@ -40,7 +82,14 @@ ftrace_call:
4082
popl %edx
4183
popl %ecx
4284
popl %eax
85+
#ifdef USING_FRAME_POINTER
4386
popl %ebp
87+
# ifdef CC_USING_FENTRY
88+
addl $4,%esp /* skip function ip */
89+
popl %ebp /* this is the orig bp */
90+
addl $4, %esp /* skip parent ip */
91+
# endif
92+
#endif
4493
.Lftrace_ret:
4594
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
4695
.globl ftrace_graph_call
@@ -81,6 +130,10 @@ ENTRY(ftrace_regs_caller)
81130
pushl %edx
82131
pushl %ecx
83132
pushl %ebx
133+
#ifdef CC_USING_FENTRY
134+
/* Load 4 off of the parent ip addr into ebp */
135+
lea 14*4(%esp), %ebp
136+
#endif
84137

85138
movl 12*4(%esp), %eax /* Load ip (1st parameter) */
86139
subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */
@@ -119,7 +172,7 @@ GLOBAL(ftrace_regs_call)
119172
jmp .Lftrace_ret
120173
#else /* ! CONFIG_DYNAMIC_FTRACE */
121174

122-
ENTRY(mcount)
175+
ENTRY(function_hook)
123176
cmpl $__PAGE_OFFSET, %esp
124177
jb ftrace_stub /* Paging not enabled yet? */
125178

@@ -151,19 +204,24 @@ ftrace_stub:
151204
popl %ecx
152205
popl %eax
153206
jmp ftrace_stub
154-
END(mcount)
207+
END(function_hook)
155208
#endif /* CONFIG_DYNAMIC_FTRACE */
156-
EXPORT_SYMBOL(mcount)
157209
#endif /* CONFIG_FUNCTION_TRACER */
158210

159211
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
160212
ENTRY(ftrace_graph_caller)
161213
pushl %eax
162214
pushl %ecx
163215
pushl %edx
164-
movl 0xc(%esp), %eax
216+
movl 3*4(%esp), %eax
217+
/* Even with frame pointers, fentry doesn't have one here */
218+
#ifdef CC_USING_FENTRY
219+
lea 4*4(%esp), %edx
220+
movl $0, %ecx
221+
#else
165222
lea 0x4(%ebp), %edx
166223
movl (%ebp), %ecx
224+
#endif
167225
subl $MCOUNT_INSN_SIZE, %eax
168226
call prepare_ftrace_return
169227
popl %edx
@@ -176,7 +234,11 @@ END(ftrace_graph_caller)
176234
return_to_handler:
177235
pushl %eax
178236
pushl %edx
237+
#ifdef CC_USING_FENTRY
238+
movl $0, %eax
239+
#else
179240
movl %ebp, %eax
241+
#endif
180242
call ftrace_return_to_handler
181243
movl %eax, %ecx
182244
popl %edx

0 commit comments

Comments
 (0)