Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bpf-arm64-indirect-jumps'

Puranjay Mohan says:

====================
bpf: arm64: Indirect jumps

Changes in v1->v2:
v1: https://lore.kernel.org/all/20251117004656.33292-1-puranjay@kernel.org/
- Dropped patch 3 that was ignoring relocations for .jumptables. LLVM
has been fixed to not emit relocations for .jumptables, so this patch
is not needed.
- Added Reviewed-by: Anton Protopopov <a.s.protopopov@gmail.com>

This set adds the support of indirect jumps to the arm64 JIT. It
involves calling bpf_prog_update_insn_ptrs() to support instructions
array map. The second piece is supporting BPF_JMP|BPF_X|BPF_JA, SRC=0,
DST=Rx, off=0, imm=0 instruction that is trivial to implement on arm64.

The final patch enables selftests on arm64:

[root@localhost bpf]# ./test_progs-cpuv4 -a "*gotox*"
#20/1 bpf_gotox/one-switch:OK
#20/2 bpf_gotox/one-switch-non-zero-sec-offset:OK
#20/3 bpf_gotox/two-switches:OK
#20/4 bpf_gotox/big-jump-table:OK
#20/5 bpf_gotox/static-global:OK
#20/6 bpf_gotox/nonstatic-global:OK
#20/7 bpf_gotox/other-sec:OK
#20/8 bpf_gotox/static-global-other-sec:OK
#20/9 bpf_gotox/nonstatic-global-other-sec:OK
#20/10 bpf_gotox/one-jump-two-maps:OK
#20/11 bpf_gotox/one-map-two-jumps:OK
#20 bpf_gotox:OK
#537/1 verifier_gotox/jump_table_ok:OK
#537/2 verifier_gotox/jump_table_reserved_field_src_reg:OK
#537/3 verifier_gotox/jump_table_reserved_field_non_zero_off:OK
#537/4 verifier_gotox/jump_table_reserved_field_non_zero_imm:OK
#537/5 verifier_gotox/jump_table_no_jump_table:OK
#537/6 verifier_gotox/jump_table_incorrect_dst_reg_type:OK
#537/7 verifier_gotox/jump_table_invalid_read_size_u32:OK
#537/8 verifier_gotox/jump_table_invalid_read_size_u16:OK
#537/9 verifier_gotox/jump_table_invalid_read_size_u8:OK
#537/10 verifier_gotox/jump_table_misaligned_access:OK
#537/11 verifier_gotox/jump_table_invalid_mem_acceess_pos:OK
#537/12 verifier_gotox/jump_table_invalid_mem_acceess_neg:OK
#537/13 verifier_gotox/jump_table_add_sub_ok:OK
#537/14 verifier_gotox/jump_table_no_writes:OK
#537/15 verifier_gotox/jump_table_use_reg_r0:OK
#537/16 verifier_gotox/jump_table_use_reg_r1:OK
#537/17 verifier_gotox/jump_table_use_reg_r2:OK
#537/18 verifier_gotox/jump_table_use_reg_r3:OK
#537/19 verifier_gotox/jump_table_use_reg_r4:OK
#537/20 verifier_gotox/jump_table_use_reg_r5:OK
#537/21 verifier_gotox/jump_table_use_reg_r6:OK
#537/22 verifier_gotox/jump_table_use_reg_r7:OK
#537/23 verifier_gotox/jump_table_use_reg_r8:OK
#537/24 verifier_gotox/jump_table_use_reg_r9:OK
#537/25 verifier_gotox/jump_table_outside_subprog:OK
#537/26 verifier_gotox/jump_table_contains_non_unique_values:OK
#537 verifier_gotox:OK
Summary: 2/37 PASSED, 0 SKIPPED, 0 FAILED
====================

Link: https://patch.msgid.link/20251117130732.11107-1-puranjay@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+13 -2
+11
arch/arm64/net/bpf_jit_comp.c
··· 1452 1452 emit(A64_ASR(is64, dst, dst, imm), ctx); 1453 1453 break; 1454 1454 1455 + /* JUMP reg */ 1456 + case BPF_JMP | BPF_JA | BPF_X: 1457 + emit(A64_BR(dst), ctx); 1458 + break; 1455 1459 /* JUMP off */ 1456 1460 case BPF_JMP | BPF_JA: 1457 1461 case BPF_JMP32 | BPF_JA: ··· 2235 2231 for (i = 0; i <= prog->len; i++) 2236 2232 ctx.offset[i] *= AARCH64_INSN_SIZE; 2237 2233 bpf_prog_fill_jited_linfo(prog, ctx.offset + 1); 2234 + /* 2235 + * The bpf_prog_update_insn_ptrs function expects offsets to 2236 + * point to the first byte of the jitted instruction (unlike 2237 + * the bpf_prog_fill_jited_linfo above, which, for historical 2238 + * reasons, expects to point to the next instruction) 2239 + */ 2240 + bpf_prog_update_insn_ptrs(prog, ctx.offset, ctx.ro_image); 2238 2241 out_off: 2239 2242 if (!ro_header && priv_stack_ptr) { 2240 2243 free_percpu(priv_stack_ptr);
+2 -2
tools/testing/selftests/bpf/progs/verifier_gotox.c
··· 6 6 #include "bpf_misc.h" 7 7 #include "../../../include/linux/filter.h" 8 8 9 - #ifdef __TARGET_ARCH_x86 9 + #if defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) 10 10 11 11 #define DEFINE_SIMPLE_JUMP_TABLE_PROG(NAME, SRC_REG, OFF, IMM, OUTCOME) \ 12 12 \ ··· 384 384 : __clobber_all); 385 385 } 386 386 387 - #endif /* __TARGET_ARCH_x86 */ 387 + #endif /* __TARGET_ARCH_x86 || __TARGET_ARCH_arm64 */ 388 388 389 389 char _license[] SEC("license") = "GPL";