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 <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20261013171230.523677-12-daniel@iogearbox.net
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
Daniel Borkmann 2026-10-13 19:12:23 +02:00 committed by Kumar Kartikeya Dwivedi
parent f2a5c00a80
commit 74309a9294
No known key found for this signature in database
GPG Key ID: 472D377B63542F83

View File

@ -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,