s390/bpf: Implement bpf_jit_supports_kfunc_call()
Implement calling kernel functions from eBPF. In general, the eBPF ABI is fairly close to that of s390x, with one important difference: on s390x callers should sign-extend signed arguments. Handle that by using information returned by bpf_jit_find_kfunc_model(). Here is an example of how sign extensions works. Suppose we need to call the following function from BPF: ; long noinline bpf_kfunc_call_test4(signed char a, short b, int c, long d) 0000000000936a78 <bpf_kfunc_call_test4>: 936a78: c0 04 00 00 00 00 jgnop bpf_kfunc_call_test4 ; return (long)a + (long)b + (long)c + d; 936a7e: b9 08 00 45 agr %r4,%r5 936a82: b9 08 00 43 agr %r4,%r3 936a86: b9 08 00 24 agr %r2,%r4 936a8a: c0 f4 00 1e 3b 27 jg <__s390_indirect_jump_r14> As per the s390x ABI, bpf_kfunc_call_test4() has the right to assume that a, b and c are sign-extended by the caller, which results in using 64-bit additions (agr) without any additional conversions. Without sign extension we would have the following on the JITed code side: ; tmp = bpf_kfunc_call_test4(-3, -30, -200, -1000); ; 5: b4 10 00 00 ff ff ff fd w1 = -3 0x3ff7fdcdad4: llilf %r2,0xfffffffd ; 6: b4 20 00 00 ff ff ff e2 w2 = -30 0x3ff7fdcdada: llilf %r3,0xffffffe2 ; 7: b4 30 00 00 ff ff ff 38 w3 = -200 0x3ff7fdcdae0: llilf %r4,0xffffff38 ; 8: b7 40 00 00 ff ff fc 18 r4 = -1000 0x3ff7fdcdae6: lgfi %r5,-1000 0x3ff7fdcdaec: mvc 64(4,%r15),160(%r15) 0x3ff7fdcdaf2: lgrl %r1,bpf_kfunc_call_test4@GOT 0x3ff7fdcdaf8: brasl %r14,__s390_indirect_jump_r1 This first 3 llilfs are 32-bit loads, that need to be sign-extended to 64 bits. Note: at the moment bpf_jit_find_kfunc_model() does not seem to play nicely with XDP metadata functions: add_kfunc_call() adds an "abstract" bpf_*() version to kfunc_btf_tab, but then fixup_kfunc_call() puts the concrete version into insn->imm, which bpf_jit_find_kfunc_model() cannot find. But this seems to be a common code problem. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Link: https://lore.kernel.org/r/20230129190501.1624747-7-iii@linux.ibm.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
dd691e847d
commit
63d7b53ab5
@ -1401,9 +1401,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
*/
|
||||
case BPF_JMP | BPF_CALL:
|
||||
{
|
||||
u64 func;
|
||||
const struct btf_func_model *m;
|
||||
bool func_addr_fixed;
|
||||
int ret;
|
||||
int j, ret;
|
||||
u64 func;
|
||||
|
||||
ret = bpf_jit_get_func_addr(fp, insn, extra_pass,
|
||||
&func, &func_addr_fixed);
|
||||
@ -1425,6 +1426,21 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
/* mvc STK_OFF_TCCNT(4,%r15),N(%r15) */
|
||||
_EMIT6(0xd203f000 | STK_OFF_TCCNT,
|
||||
0xf000 | (STK_OFF_TCCNT + STK_OFF + stack_depth));
|
||||
|
||||
/* Sign-extend the kfunc arguments. */
|
||||
if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
|
||||
m = bpf_jit_find_kfunc_model(fp, insn);
|
||||
if (!m)
|
||||
return -1;
|
||||
|
||||
for (j = 0; j < m->nr_args; j++) {
|
||||
if (sign_extend(jit, BPF_REG_1 + j,
|
||||
m->arg_size[j],
|
||||
m->arg_flags[j]))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* lgrl %w1,func */
|
||||
EMIT6_PCREL_RILB(0xc4080000, REG_W1, _EMIT_CONST_U64(func));
|
||||
/* %r1() */
|
||||
@ -1980,6 +1996,11 @@ out:
|
||||
return fp;
|
||||
}
|
||||
|
||||
bool bpf_jit_supports_kfunc_call(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||
void *old_addr, void *new_addr)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user