Skip to content

Commit 443574b

Browse files
Pu LehuiAlexei Starovoitov
authored andcommitted
riscv, bpf: Fix kfunc parameters incompatibility between bpf and riscv abi
We encountered a failing case when running selftest in no_alu32 mode: The failure case is `kfunc_call/kfunc_call_test4` and its source code is like bellow: ``` long bpf_kfunc_call_test4(signed char a, short b, int c, long d) __ksym; int kfunc_call_test4(struct __sk_buff *skb) { ... tmp = bpf_kfunc_call_test4(-3, -30, -200, -1000); ... } ``` And its corresponding asm code is: ``` 0: r1 = -3 1: r2 = -30 2: r3 = 0xffffff38 # opcode: 18 03 00 00 38 ff ff ff 00 00 00 00 00 00 00 00 4: r4 = -1000 5: call bpf_kfunc_call_test4 ``` insn 2 is parsed to ld_imm64 insn to emit 0x00000000ffffff38 imm, and converted to int type and then send to bpf_kfunc_call_test4. But since it is zero-extended in the bpf calling convention, riscv jit will directly treat it as an unsigned 32-bit int value, and then fails with the message "actual 4294966063 != expected -1234". The reason is the incompatibility between bpf and riscv abi, that is, bpf will do zero-extension on uint, but riscv64 requires sign-extension on int or uint. We can solve this problem by sign extending the 32-bit parameters in kfunc. The issue is related to [0], and thanks to Yonghong and Alexei. Link: llvm/llvm-project#84874 [0] Fixes: d40c384 ("riscv, bpf: Add kfunc support for RV64") Signed-off-by: Pu Lehui <pulehui@huawei.com> Tested-by: Puranjay Mohan <puranjay12@gmail.com> Reviewed-by: Puranjay Mohan <puranjay12@gmail.com> Link: https://lore.kernel.org/r/20240324103306.2202954-1-pulehui@huaweicloud.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 122fdbd commit 443574b

1 file changed

Lines changed: 16 additions & 0 deletions

File tree

arch/riscv/net/bpf_jit_comp64.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,22 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
14631463
if (ret < 0)
14641464
return ret;
14651465

1466+
if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
1467+
const struct btf_func_model *fm;
1468+
int idx;
1469+
1470+
fm = bpf_jit_find_kfunc_model(ctx->prog, insn);
1471+
if (!fm)
1472+
return -EINVAL;
1473+
1474+
for (idx = 0; idx < fm->nr_args; idx++) {
1475+
u8 reg = bpf_to_rv_reg(BPF_REG_1 + idx, ctx);
1476+
1477+
if (fm->arg_size[idx] == sizeof(int))
1478+
emit_sextw(reg, reg, ctx);
1479+
}
1480+
}
1481+
14661482
ret = emit_call(addr, fixed_addr, ctx);
14671483
if (ret)
14681484
return ret;

0 commit comments

Comments
 (0)