Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 9 additions & 19 deletions arch/loongarch/net/bpf_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,7 @@ bool bpf_jit_supports_far_kfunc_call(void)
return true;
}

/* initialized on the first pass of build_body() */
static int out_offset = -1;
static int emit_bpf_tail_call(struct jit_ctx *ctx)
static int emit_bpf_tail_call(int insn, struct jit_ctx *ctx)
{
int off;
u8 tcc = tail_call_reg(ctx);
Expand All @@ -220,9 +218,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
u8 t2 = LOONGARCH_GPR_T2;
u8 t3 = LOONGARCH_GPR_T3;
const int idx0 = ctx->idx;

#define cur_offset (ctx->idx - idx0)
#define jmp_offset (out_offset - (cur_offset))
int tc_ninsn = 0;
int jmp_offset = 0;

/*
* a0: &ctx
Expand All @@ -232,8 +229,11 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
* if (index >= array->map.max_entries)
* goto out;
*/
tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] :
ctx->offset[0];
off = offsetof(struct bpf_array, map.max_entries);
emit_insn(ctx, ldwu, t1, a1, off);
jmp_offset = tc_ninsn - (ctx->idx - idx0);
/* bgeu $a2, $t1, jmp_offset */
if (emit_tailcall_jmp(ctx, BPF_JGE, a2, t1, jmp_offset) < 0)
goto toofar;
Expand All @@ -243,6 +243,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
* goto out;
*/
emit_insn(ctx, addid, REG_TCC, tcc, -1);
jmp_offset = tc_ninsn - (ctx->idx - idx0);
if (emit_tailcall_jmp(ctx, BPF_JSLT, REG_TCC, LOONGARCH_GPR_ZERO, jmp_offset) < 0)
goto toofar;

Expand All @@ -254,6 +255,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
emit_insn(ctx, alsld, t2, a2, a1, 2);
off = offsetof(struct bpf_array, ptrs);
emit_insn(ctx, ldd, t2, t2, off);
jmp_offset = tc_ninsn - (ctx->idx - idx0);
/* beq $t2, $zero, jmp_offset */
if (emit_tailcall_jmp(ctx, BPF_JEQ, t2, LOONGARCH_GPR_ZERO, jmp_offset) < 0)
goto toofar;
Expand All @@ -263,22 +265,11 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
emit_insn(ctx, ldd, t3, t2, off);
__build_epilogue(ctx, true);

/* out: */
if (out_offset == -1)
out_offset = cur_offset;
if (cur_offset != out_offset) {
pr_err_once("tail_call out_offset = %d, expected %d!\n",
cur_offset, out_offset);
return -1;
}

return 0;

toofar:
pr_info_once("tail_call: jump too far\n");
return -1;
#undef cur_offset
#undef jmp_offset
}

static void emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
Expand Down Expand Up @@ -916,7 +907,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
/* tail call */
case BPF_JMP | BPF_TAIL_CALL:
mark_tail_call(ctx);
if (emit_bpf_tail_call(ctx) < 0)
if (emit_bpf_tail_call(i, ctx) < 0)
return -EINVAL;
break;

Expand Down Expand Up @@ -1342,7 +1333,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
if (tmp_blinded)
bpf_jit_prog_release_other(prog, prog == orig_prog ? tmp : orig_prog);

out_offset = -1;

return prog;

Expand Down
Loading