From 74309a9294a74975fee75e4d6259eef026495325 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 13 Oct 2026 19:12:23 +0200 Subject: [PATCH] bpf, x86: Fold the PROBE_MEM address computation into a lea The kernel address check in front of a BPF_PROBE_MEM load computed src_reg + off - VSYSCALL_ADDR with a mov of VSYSCALL_ADDR, a mov of the base register, an add of the offset in imm32 form and a sub, that is 20 bytes and 4 uops. VSYSCALL_ADDR is -10 MiB, so together with the 16-bit instruction offset it fits into a 32-bit displacement and a single lea does the same in 7 bytes and 1 uop on Intel and AMD. Before, for the check on r0 = *(u64 *)(r1 + 16): 49 c7 c2 00 00 60 ff movq $0xffffffffff600000,%r10 49 89 fb movq %rdi,%r11 49 81 c3 10 00 00 00 addq $0x10,%r11 4d 29 d3 subq %r10,%r11 After: 4c 8d 9f 10 00 a0 00 leaq 0xa00010(%rdi),%r11 Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20261013171230.523677-12-daniel@iogearbox.net Signed-off-by: Kumar Kartikeya Dwivedi --- arch/x86/net/bpf_jit_comp.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index de49d7f51a54..75194f9caa5a 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -2853,22 +2853,16 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int * u64 limit = TASK_SIZE_MAX + PAGE_SIZE - VSYSCALL_ADDR; u8 *end_of_jmp; - /* movabsq r10, VSYSCALL_ADDR */ - emit_mov_imm64(&prog, BPF_REG_AX, (long)VSYSCALL_ADDR >> 32, - (u32)(long)VSYSCALL_ADDR); - - /* mov src_reg, r11 */ - EMIT_mov(AUX_REG, src_reg); - - if (insn->off) { - /* add r11, insn->off */ - maybe_emit_1mod(&prog, AUX_REG, true); - EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off); - } - - /* sub r11, r10 */ - maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true); - EMIT2(0x29, add_2reg(0xC0, AUX_REG, BPF_REG_AX)); + /* + * lea r11, [src_reg + insn->off - VSYSCALL_ADDR] + * + * VSYSCALL_ADDR is a small negative number, so the + * whole offset fits into the 32-bit displacement. + */ + BUILD_BUG_ON((long)(s32)VSYSCALL_ADDR != (long)VSYSCALL_ADDR); + EMIT2(add_2mod(0x48, src_reg, AUX_REG), 0x8D); + emit_insn_suffix(&prog, src_reg, AUX_REG, + insn->off - (s32)VSYSCALL_ADDR); /* movabsq r10, limit */ emit_mov_imm64(&prog, BPF_REG_AX, (long)limit >> 32,