Skip to content

Commit 01b6ac7

Browse files
hbathinimaddy-kerneldev
authored andcommitted
powerpc64/bpf: fix kfunc call support
Commit 61688a8 ("powerpc/bpf: enable kfunc call") inadvertently enabled kfunc call support for 32-bit powerpc but that support will not be possible until ABI mismatch between 32-bit powerpc and eBPF is handled in 32-bit powerpc JIT code. Till then, advertise support only for 64-bit powerpc. Also, in powerpc ABI, caller needs to extend the arguments properly based on signedness. The JIT code is responsible for handling this explicitly for kfunc calls as verifier can't handle this for each architecture-specific ABI needs. But this was not taken care of while kfunc call support was enabled for powerpc. Fix it by handling this with bpf_jit_find_kfunc_model() and using zero_extend() & sign_extend() helper functions. Fixes: 61688a8 ("powerpc/bpf: enable kfunc call") Cc: [email protected] Signed-off-by: Hari Bathini <[email protected]> Signed-off-by: Madhavan Srinivasan <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 51b8de4 commit 01b6ac7

2 files changed

Lines changed: 94 additions & 9 deletions

File tree

arch/powerpc/net/bpf_jit_comp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ bool bpf_jit_supports_subprog_tailcalls(void)
450450

451451
bool bpf_jit_supports_kfunc_call(void)
452452
{
453-
return true;
453+
return IS_ENABLED(CONFIG_PPC64);
454454
}
455455

456456
bool bpf_jit_supports_arena(void)

arch/powerpc/net/bpf_jit_comp64.c

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,83 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
499499
return 0;
500500
}
501501

502+
static int zero_extend(u32 *image, struct codegen_context *ctx, u32 src_reg, u32 dst_reg, u32 size)
503+
{
504+
switch (size) {
505+
case 1:
506+
/* zero-extend 8 bits into 64 bits */
507+
EMIT(PPC_RAW_RLDICL(dst_reg, src_reg, 0, 56));
508+
return 0;
509+
case 2:
510+
/* zero-extend 16 bits into 64 bits */
511+
EMIT(PPC_RAW_RLDICL(dst_reg, src_reg, 0, 48));
512+
return 0;
513+
case 4:
514+
/* zero-extend 32 bits into 64 bits */
515+
EMIT(PPC_RAW_RLDICL(dst_reg, src_reg, 0, 32));
516+
fallthrough;
517+
case 8:
518+
/* Nothing to do */
519+
return 0;
520+
default:
521+
return -1;
522+
}
523+
}
524+
525+
static int sign_extend(u32 *image, struct codegen_context *ctx, u32 src_reg, u32 dst_reg, u32 size)
526+
{
527+
switch (size) {
528+
case 1:
529+
/* sign-extend 8 bits into 64 bits */
530+
EMIT(PPC_RAW_EXTSB(dst_reg, src_reg));
531+
return 0;
532+
case 2:
533+
/* sign-extend 16 bits into 64 bits */
534+
EMIT(PPC_RAW_EXTSH(dst_reg, src_reg));
535+
return 0;
536+
case 4:
537+
/* sign-extend 32 bits into 64 bits */
538+
EMIT(PPC_RAW_EXTSW(dst_reg, src_reg));
539+
fallthrough;
540+
case 8:
541+
/* Nothing to do */
542+
return 0;
543+
default:
544+
return -1;
545+
}
546+
}
547+
548+
/*
549+
* Handle powerpc ABI expectations from caller:
550+
* - Unsigned arguments are zero-extended.
551+
* - Signed arguments are sign-extended.
552+
*/
553+
static int prepare_for_kfunc_call(const struct bpf_prog *fp, u32 *image,
554+
struct codegen_context *ctx,
555+
const struct bpf_insn *insn)
556+
{
557+
const struct btf_func_model *m = bpf_jit_find_kfunc_model(fp, insn);
558+
int i;
559+
560+
if (!m)
561+
return -1;
562+
563+
for (i = 0; i < m->nr_args; i++) {
564+
/* Note that BPF ABI only allows up to 5 args for kfuncs */
565+
u32 reg = bpf_to_ppc(BPF_REG_1 + i), size = m->arg_size[i];
566+
567+
if (!(m->arg_flags[i] & BTF_FMODEL_SIGNED_ARG)) {
568+
if (zero_extend(image, ctx, reg, reg, size))
569+
return -1;
570+
} else {
571+
if (sign_extend(image, ctx, reg, reg, size))
572+
return -1;
573+
}
574+
}
575+
576+
return 0;
577+
}
578+
502579
static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
503580
{
504581
/*
@@ -1143,14 +1220,16 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
11431220
/* special mov32 for zext */
11441221
EMIT(PPC_RAW_RLWINM(dst_reg, dst_reg, 0, 0, 31));
11451222
break;
1146-
} else if (off == 8) {
1147-
EMIT(PPC_RAW_EXTSB(dst_reg, src_reg));
1148-
} else if (off == 16) {
1149-
EMIT(PPC_RAW_EXTSH(dst_reg, src_reg));
1150-
} else if (off == 32) {
1151-
EMIT(PPC_RAW_EXTSW(dst_reg, src_reg));
1152-
} else if (dst_reg != src_reg)
1153-
EMIT(PPC_RAW_MR(dst_reg, src_reg));
1223+
}
1224+
if (off == 0) {
1225+
/* MOV */
1226+
if (dst_reg != src_reg)
1227+
EMIT(PPC_RAW_MR(dst_reg, src_reg));
1228+
} else {
1229+
/* MOVSX: dst = (s8,s16,s32)src (off = 8,16,32) */
1230+
if (sign_extend(image, ctx, src_reg, dst_reg, off / 8))
1231+
return -1;
1232+
}
11541233
goto bpf_alu32_trunc;
11551234
case BPF_ALU | BPF_MOV | BPF_K: /* (u32) dst = imm */
11561235
case BPF_ALU64 | BPF_MOV | BPF_K: /* dst = (s64) imm */
@@ -1618,6 +1697,12 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
16181697
if (ret < 0)
16191698
return ret;
16201699

1700+
/* Take care of powerpc ABI requirements before kfunc call */
1701+
if (insn[i].src_reg == BPF_PSEUDO_KFUNC_CALL) {
1702+
if (prepare_for_kfunc_call(fp, image, ctx, &insn[i]))
1703+
return -1;
1704+
}
1705+
16211706
ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
16221707
if (ret)
16231708
return ret;

0 commit comments

Comments
 (0)