Commit 0fd1fd01 authored by Pu Lehui's avatar Pu Lehui Committed by Daniel Borkmann

riscv, bpf: Factor out emit_call for kernel and bpf context

The current emit_call function is not suitable for kernel function call as
it store return value to bpf R0 register. We can separate it out for common
use. Meanwhile, simplify judgment logic, that is, fixed function address
can use jal or auipc+jalr, while the unfixed can use only auipc+jalr.
Signed-off-by: default avatarPu Lehui <pulehui@huawei.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Tested-by: default avatarBjörn Töpel <bjorn@rivosinc.com>
Acked-by: default avatarBjörn Töpel <bjorn@rivosinc.com>
Link: https://lore.kernel.org/bpf/20230215135205.1411105-3-pulehui@huaweicloud.com
parent 5e57fb7b
...@@ -428,12 +428,12 @@ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx) ...@@ -428,12 +428,12 @@ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx)
*rd = RV_REG_T2; *rd = RV_REG_T2;
} }
static int emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr, static int emit_jump_and_link(u8 rd, s64 rvoff, bool fixed_addr,
struct rv_jit_context *ctx) struct rv_jit_context *ctx)
{ {
s64 upper, lower; s64 upper, lower;
if (rvoff && is_21b_int(rvoff) && !force_jalr) { if (rvoff && fixed_addr && is_21b_int(rvoff)) {
emit(rv_jal(rd, rvoff >> 1), ctx); emit(rv_jal(rd, rvoff >> 1), ctx);
return 0; return 0;
} else if (in_auipc_jalr_range(rvoff)) { } else if (in_auipc_jalr_range(rvoff)) {
...@@ -454,24 +454,17 @@ static bool is_signed_bpf_cond(u8 cond) ...@@ -454,24 +454,17 @@ static bool is_signed_bpf_cond(u8 cond)
cond == BPF_JSGE || cond == BPF_JSLE; cond == BPF_JSGE || cond == BPF_JSLE;
} }
static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx) static int emit_call(u64 addr, bool fixed_addr, struct rv_jit_context *ctx)
{ {
s64 off = 0; s64 off = 0;
u64 ip; u64 ip;
u8 rd;
int ret;
if (addr && ctx->insns) { if (addr && ctx->insns) {
ip = (u64)(long)(ctx->insns + ctx->ninsns); ip = (u64)(long)(ctx->insns + ctx->ninsns);
off = addr - ip; off = addr - ip;
} }
ret = emit_jump_and_link(RV_REG_RA, off, !fixed, ctx); return emit_jump_and_link(RV_REG_RA, off, fixed_addr, ctx);
if (ret)
return ret;
rd = bpf_to_rv_reg(BPF_REG_0, ctx);
emit_mv(rd, RV_REG_A0, ctx);
return 0;
} }
static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64, static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
...@@ -913,7 +906,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, ...@@ -913,7 +906,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
/* JUMP off */ /* JUMP off */
case BPF_JMP | BPF_JA: case BPF_JMP | BPF_JA:
rvoff = rv_offset(i, off, ctx); rvoff = rv_offset(i, off, ctx);
ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx); ret = emit_jump_and_link(RV_REG_ZERO, rvoff, true, ctx);
if (ret) if (ret)
return ret; return ret;
break; break;
...@@ -1032,17 +1025,20 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, ...@@ -1032,17 +1025,20 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
/* function call */ /* function call */
case BPF_JMP | BPF_CALL: case BPF_JMP | BPF_CALL:
{ {
bool fixed; bool fixed_addr;
u64 addr; u64 addr;
mark_call(ctx); mark_call(ctx);
ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass, &addr, ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass,
&fixed); &addr, &fixed_addr);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = emit_call(fixed, addr, ctx);
ret = emit_call(addr, fixed_addr, ctx);
if (ret) if (ret)
return ret; return ret;
emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx);
break; break;
} }
/* tail call */ /* tail call */
...@@ -1057,7 +1053,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, ...@@ -1057,7 +1053,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
break; break;
rvoff = epilogue_offset(ctx); rvoff = epilogue_offset(ctx);
ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx); ret = emit_jump_and_link(RV_REG_ZERO, rvoff, true, ctx);
if (ret) if (ret)
return ret; return ret;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment