Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

powerpc64/bpf: fix kfunc call support

Commit 61688a82e047 ("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: 61688a82e047 ("powerpc/bpf: enable kfunc call")
Cc: stable@vger.kernel.org
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20260303181031.390073-7-hbathini@linux.ibm.com

authored by

Hari Bathini and committed by
Madhavan Srinivasan
01b6ac72 51b8de4b

+94 -9
+1 -1
arch/powerpc/net/bpf_jit_comp.c
··· 450 450 451 451 bool bpf_jit_supports_kfunc_call(void) 452 452 { 453 - return true; 453 + return IS_ENABLED(CONFIG_PPC64); 454 454 } 455 455 456 456 bool bpf_jit_supports_arena(void)
+93 -8
arch/powerpc/net/bpf_jit_comp64.c
··· 499 499 return 0; 500 500 } 501 501 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 + 502 579 static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out) 503 580 { 504 581 /* ··· 1220 1143 /* special mov32 for zext */ 1221 1144 EMIT(PPC_RAW_RLWINM(dst_reg, dst_reg, 0, 0, 31)); 1222 1145 break; 1223 - } else if (off == 8) { 1224 - EMIT(PPC_RAW_EXTSB(dst_reg, src_reg)); 1225 - } else if (off == 16) { 1226 - EMIT(PPC_RAW_EXTSH(dst_reg, src_reg)); 1227 - } else if (off == 32) { 1228 - EMIT(PPC_RAW_EXTSW(dst_reg, src_reg)); 1229 - } else if (dst_reg != src_reg) 1230 - EMIT(PPC_RAW_MR(dst_reg, src_reg)); 1146 + } 1147 + if (off == 0) { 1148 + /* MOV */ 1149 + if (dst_reg != src_reg) 1150 + EMIT(PPC_RAW_MR(dst_reg, src_reg)); 1151 + } else { 1152 + /* MOVSX: dst = (s8,s16,s32)src (off = 8,16,32) */ 1153 + if (sign_extend(image, ctx, src_reg, dst_reg, off / 8)) 1154 + return -1; 1155 + } 1231 1156 goto bpf_alu32_trunc; 1232 1157 case BPF_ALU | BPF_MOV | BPF_K: /* (u32) dst = imm */ 1233 1158 case BPF_ALU64 | BPF_MOV | BPF_K: /* dst = (s64) imm */ ··· 1696 1617 &func_addr, &func_addr_fixed); 1697 1618 if (ret < 0) 1698 1619 return ret; 1620 + 1621 + /* Take care of powerpc ABI requirements before kfunc call */ 1622 + if (insn[i].src_reg == BPF_PSEUDO_KFUNC_CALL) { 1623 + if (prepare_for_kfunc_call(fp, image, ctx, &insn[i])) 1624 + return -1; 1625 + } 1699 1626 1700 1627 ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr); 1701 1628 if (ret)