]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
LoongArch: BPF: Implement bpf_addr_space_cast instruction
authorHengqi Chen <hengqi.chen@gmail.com>
Tue, 10 Feb 2026 11:31:18 +0000 (19:31 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Tue, 10 Feb 2026 11:31:18 +0000 (19:31 +0800)
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>
arch/loongarch/net/bpf_jit.c
arch/loongarch/net/bpf_jit.h

index b20ecc326a38fce1eedeb5e7f848093421634ed0..ceb7939088cdf6f7010eaf285d4c8a4e63764052 100644 (file)
@@ -559,6 +559,15 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
        /* dst = src */
        case BPF_ALU | BPF_MOV | BPF_X:
        case BPF_ALU64 | BPF_MOV | BPF_X:
+               if (insn_is_cast_user(insn)) {
+                       move_reg(ctx, t1, src);
+                       emit_zext_32(ctx, t1, true);
+                       move_imm(ctx, dst, (ctx->user_vm_start >> 32) << 32, false);
+                       emit_insn(ctx, beq, t1, LOONGARCH_GPR_ZERO, 1);
+                       emit_insn(ctx, or, t1, dst, t1);
+                       move_reg(ctx, dst, t1);
+                       break;
+               }
                switch (off) {
                case 0:
                        move_reg(ctx, dst, src);
@@ -1955,6 +1964,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        memset(&ctx, 0, sizeof(ctx));
        ctx.prog = prog;
        ctx.arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
+       ctx.user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
 
        ctx.offset = kvcalloc(prog->len + 1, sizeof(u32), GFP_KERNEL);
        if (ctx.offset == NULL) {
@@ -2110,6 +2120,11 @@ bool bpf_jit_bypass_spec_v4(void)
        return true;
 }
 
+bool bpf_jit_supports_arena(void)
+{
+       return true;
+}
+
 /* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
 bool bpf_jit_supports_subprog_tailcalls(void)
 {
index 8816ac106f2f00c9c7052651cca7f32d7fc3cda8..a8e29be35fa815b8e43affbd5546c9581420b16d 100644 (file)
@@ -21,6 +21,7 @@ struct jit_ctx {
        union loongarch_instruction *ro_image;
        u32 stack_size;
        u64 arena_vm_start;
+       u64 user_vm_start;
 };
 
 struct jit_data {