Skip to content

Commit 3193c08

Browse files
jpoimboeKAGA-KOKO
authored andcommitted
bpf: Disable GCC -fgcse optimization for ___bpf_prog_run()
On x86-64, with CONFIG_RETPOLINE=n, GCC's "global common subexpression elimination" optimization results in ___bpf_prog_run()'s jumptable code changing from this: select_insn: jmp *jumptable(, %rax, 8) ... ALU64_ADD_X: ... jmp *jumptable(, %rax, 8) ALU_ADD_X: ... jmp *jumptable(, %rax, 8) to this: select_insn: mov jumptable, %r12 jmp *(%r12, %rax, 8) ... ALU64_ADD_X: ... jmp *(%r12, %rax, 8) ALU_ADD_X: ... jmp *(%r12, %rax, 8) The jumptable address is placed in a register once, at the beginning of the function. The function execution can then go through multiple indirect jumps which rely on that same register value. This has a few issues: 1) Objtool isn't smart enough to be able to track such a register value across multiple recursive indirect jumps through the jump table. 2) With CONFIG_RETPOLINE enabled, this optimization actually results in a small slowdown. I measured a ~4.7% slowdown in the test_bpf "tcpdump port 22" selftest. This slowdown is actually predicted by the GCC manual: Note: When compiling a program using computed gotos, a GCC extension, you may get better run-time performance if you disable the global common subexpression elimination pass by adding -fno-gcse to the command line. So just disable the optimization for this function. Fixes: e55a732 ("bpf: Fix ORC unwinding in non-JIT BPF code") Reported-by: Randy Dunlap <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/30c3ca29ba037afcbd860a8672eef0021addf9fe.1563413318.git.jpoimboe@redhat.com
1 parent 82e844a commit 3193c08

File tree

3 files changed

+7
-1
lines changed

3 files changed

+7
-1
lines changed

include/linux/compiler-gcc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,5 @@
170170
#else
171171
#define __diag_GCC_8(s)
172172
#endif
173+
174+
#define __no_fgcse __attribute__((optimize("-fno-gcse")))

include/linux/compiler_types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ struct ftrace_likely_data {
189189
#define asm_volatile_goto(x...) asm goto(x)
190190
#endif
191191

192+
#ifndef __no_fgcse
193+
# define __no_fgcse
194+
#endif
195+
192196
/* Are two types/vars the same type (ignoring qualifiers)? */
193197
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
194198

kernel/bpf/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1295,7 +1295,7 @@ bool bpf_opcode_in_insntable(u8 code)
12951295
*
12961296
* Decode and execute eBPF instructions.
12971297
*/
1298-
static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)
1298+
static u64 __no_fgcse ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)
12991299
{
13001300
#define BPF_INSN_2_LBL(x, y) [BPF_##x | BPF_##y] = &&x##_##y
13011301
#define BPF_INSN_3_LBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = &&x##_##y##_##z

0 commit comments

Comments
 (0)