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

LoongArch: BPF: Implement bpf_addr_space_cast instruction

LLVM generates bpf_addr_space_cast instruction while translating pointers
between native (zero) address space and __attribute__((address_space(N))).
The addr_space=0 is reserved as bpf_arena address space.

rY = addr_space_cast(rX, 0, 1) is processed by the verifier and converted
to normal 32-bit move: wX = wY

rY = addr_space_cast(rX, 1, 0) has to be converted by JIT.

With this, the following test cases passed:

$ ./test_progs -a arena_htab,arena_list,arena_strsearch,verifier_arena,verifier_arena_large
#4/1 arena_htab/arena_htab_llvm:OK
#4/2 arena_htab/arena_htab_asm:OK
#4 arena_htab:OK
#5/1 arena_list/arena_list_1:OK
#5/2 arena_list/arena_list_1000:OK
#5 arena_list:OK
#7/1 arena_strsearch/arena_strsearch:OK
#7 arena_strsearch:OK
#507/1 verifier_arena/basic_alloc1:OK
#507/2 verifier_arena/basic_alloc2:OK
#507/3 verifier_arena/basic_alloc3:OK
#507/4 verifier_arena/basic_reserve1:OK
#507/5 verifier_arena/basic_reserve2:OK
#507/6 verifier_arena/reserve_twice:OK
#507/7 verifier_arena/reserve_invalid_region:OK
#507/8 verifier_arena/iter_maps1:OK
#507/9 verifier_arena/iter_maps2:OK
#507/10 verifier_arena/iter_maps3:OK
#507 verifier_arena:OK
#508/1 verifier_arena_large/big_alloc1:OK
#508/2 verifier_arena_large/access_reserved:OK
#508/3 verifier_arena_large/request_partially_reserved:OK
#508/4 verifier_arena_large/free_reserved:OK
#508/5 verifier_arena_large/big_alloc2:OK
#508 verifier_arena_large:OK
Summary: 5/20 PASSED, 0 SKIPPED, 0 FAILED

Acked-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Tested-by: Vincent Li <vincent.mc.li@gmail.com>
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Hengqi Chen and committed by
Huacai Chen
4fdb5dd8 ef54c517

+16
+15
arch/loongarch/net/bpf_jit.c
··· 559 559 /* dst = src */ 560 560 case BPF_ALU | BPF_MOV | BPF_X: 561 561 case BPF_ALU64 | BPF_MOV | BPF_X: 562 + if (insn_is_cast_user(insn)) { 563 + move_reg(ctx, t1, src); 564 + emit_zext_32(ctx, t1, true); 565 + move_imm(ctx, dst, (ctx->user_vm_start >> 32) << 32, false); 566 + emit_insn(ctx, beq, t1, LOONGARCH_GPR_ZERO, 1); 567 + emit_insn(ctx, or, t1, dst, t1); 568 + move_reg(ctx, dst, t1); 569 + break; 570 + } 562 571 switch (off) { 563 572 case 0: 564 573 move_reg(ctx, dst, src); ··· 1964 1955 memset(&ctx, 0, sizeof(ctx)); 1965 1956 ctx.prog = prog; 1966 1957 ctx.arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena); 1958 + ctx.user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena); 1967 1959 1968 1960 ctx.offset = kvcalloc(prog->len + 1, sizeof(u32), GFP_KERNEL); 1969 1961 if (ctx.offset == NULL) { ··· 2116 2106 } 2117 2107 2118 2108 bool bpf_jit_bypass_spec_v4(void) 2109 + { 2110 + return true; 2111 + } 2112 + 2113 + bool bpf_jit_supports_arena(void) 2119 2114 { 2120 2115 return true; 2121 2116 }
+1
arch/loongarch/net/bpf_jit.h
··· 21 21 union loongarch_instruction *ro_image; 22 22 u32 stack_size; 23 23 u64 arena_vm_start; 24 + u64 user_vm_start; 24 25 }; 25 26 26 27 struct jit_data {