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

powerpc64/bpf: jit support for signed division and modulo

Add jit support for sign division and modulo. Tested using test_bpf
module.

Signed-off-by: Artem Savkov <asavkov@redhat.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20240517075650.248801-6-asavkov@redhat.com

authored by

Artem Savkov and committed by
Michael Ellerman
fde31832 597b1710

+34 -8
+1
arch/powerpc/include/asm/ppc-opcode.h
··· 536 536 #define PPC_RAW_MULI(d, a, i) (0x1c000000 | ___PPC_RT(d) | ___PPC_RA(a) | IMM_L(i)) 537 537 #define PPC_RAW_DIVW(d, a, b) (0x7c0003d6 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) 538 538 #define PPC_RAW_DIVWU(d, a, b) (0x7c000396 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) 539 + #define PPC_RAW_DIVD(d, a, b) (0x7c0003d2 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) 539 540 #define PPC_RAW_DIVDU(d, a, b) (0x7c000392 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) 540 541 #define PPC_RAW_DIVDE(t, a, b) (0x7c000352 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) 541 542 #define PPC_RAW_DIVDE_DOT(t, a, b) (0x7c000352 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b) | 0x1)
+33 -8
arch/powerpc/net/bpf_jit_comp64.c
··· 510 510 case BPF_ALU | BPF_DIV | BPF_X: /* (u32) dst /= (u32) src */ 511 511 case BPF_ALU | BPF_MOD | BPF_X: /* (u32) dst %= (u32) src */ 512 512 if (BPF_OP(code) == BPF_MOD) { 513 - EMIT(PPC_RAW_DIVWU(tmp1_reg, dst_reg, src_reg)); 513 + if (off) 514 + EMIT(PPC_RAW_DIVW(tmp1_reg, dst_reg, src_reg)); 515 + else 516 + EMIT(PPC_RAW_DIVWU(tmp1_reg, dst_reg, src_reg)); 517 + 514 518 EMIT(PPC_RAW_MULW(tmp1_reg, src_reg, tmp1_reg)); 515 519 EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 516 520 } else 517 - EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, src_reg)); 521 + if (off) 522 + EMIT(PPC_RAW_DIVW(dst_reg, dst_reg, src_reg)); 523 + else 524 + EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, src_reg)); 518 525 goto bpf_alu32_trunc; 519 526 case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */ 520 527 case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */ 521 528 if (BPF_OP(code) == BPF_MOD) { 522 - EMIT(PPC_RAW_DIVDU(tmp1_reg, dst_reg, src_reg)); 529 + if (off) 530 + EMIT(PPC_RAW_DIVD(tmp1_reg, dst_reg, src_reg)); 531 + else 532 + EMIT(PPC_RAW_DIVDU(tmp1_reg, dst_reg, src_reg)); 523 533 EMIT(PPC_RAW_MULD(tmp1_reg, src_reg, tmp1_reg)); 524 534 EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 525 535 } else 526 - EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, src_reg)); 536 + if (off) 537 + EMIT(PPC_RAW_DIVD(dst_reg, dst_reg, src_reg)); 538 + else 539 + EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, src_reg)); 527 540 break; 528 541 case BPF_ALU | BPF_MOD | BPF_K: /* (u32) dst %= (u32) imm */ 529 542 case BPF_ALU | BPF_DIV | BPF_K: /* (u32) dst /= (u32) imm */ ··· 557 544 switch (BPF_CLASS(code)) { 558 545 case BPF_ALU: 559 546 if (BPF_OP(code) == BPF_MOD) { 560 - EMIT(PPC_RAW_DIVWU(tmp2_reg, dst_reg, tmp1_reg)); 547 + if (off) 548 + EMIT(PPC_RAW_DIVW(tmp2_reg, dst_reg, tmp1_reg)); 549 + else 550 + EMIT(PPC_RAW_DIVWU(tmp2_reg, dst_reg, tmp1_reg)); 561 551 EMIT(PPC_RAW_MULW(tmp1_reg, tmp1_reg, tmp2_reg)); 562 552 EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 563 553 } else 564 - EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, tmp1_reg)); 554 + if (off) 555 + EMIT(PPC_RAW_DIVW(dst_reg, dst_reg, tmp1_reg)); 556 + else 557 + EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, tmp1_reg)); 565 558 break; 566 559 case BPF_ALU64: 567 560 if (BPF_OP(code) == BPF_MOD) { 568 - EMIT(PPC_RAW_DIVDU(tmp2_reg, dst_reg, tmp1_reg)); 561 + if (off) 562 + EMIT(PPC_RAW_DIVD(tmp2_reg, dst_reg, tmp1_reg)); 563 + else 564 + EMIT(PPC_RAW_DIVDU(tmp2_reg, dst_reg, tmp1_reg)); 569 565 EMIT(PPC_RAW_MULD(tmp1_reg, tmp1_reg, tmp2_reg)); 570 566 EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 571 567 } else 572 - EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, tmp1_reg)); 568 + if (off) 569 + EMIT(PPC_RAW_DIVD(dst_reg, dst_reg, tmp1_reg)); 570 + else 571 + EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, tmp1_reg)); 573 572 break; 574 573 } 575 574 goto bpf_alu32_trunc;