Luke Nelson writes: > From: Luke Nelson <luke.r.nels@xxxxxxxxx> > > This is an eBPF JIT for RV32G, adapted from the JIT for RV64G. > Any feedback would be greatly appreciated. > > It passes 359 out of 378 tests in test_bpf.ko. The failing tests are > features that are not supported right now: > - ALU64 DIV/MOD: > These require loops to emulate on 32-bit hardware, > and are not supported on other 32-bit JITs like > ARM32. > - BPF_XADD | BPF_DW: > RV32G does not have atomic instructions for operating > on double words. This is similar to ARM32. > - Tail calls: > I'm working on adding support for these now, but couldn't > find any test cases that use them. What's the best way > of testing tail call code? > - Far branches > These are not supported in RV64G either. > > There are two main changes required for this to work compared to the > RV64 JIT. > > First, eBPF registers are 64-bit, while RV32G registers are 32-bit. > I take an approach similar to ARM32: most BPF registers map directly to > 2 RISC-V registers, while some reside in stack scratch space and must > be saved / restored when used. > > Second, many 64-bit ALU operations do not trivially map to 32-bit > operations. Operations that move bits between high and low words, such > as ADD, LSH, MUL, and others must emulate the 64-bit behavior in terms > of 32-bit instructions. > > Signed-off-by: Luke Nelson <luke.r.nels@xxxxxxxxx> > Cc: Xi Wang <xi.wang@xxxxxxxxx> > --- > arch/riscv/Kconfig | 2 +- > arch/riscv/net/Makefile | 7 +- > arch/riscv/net/bpf_jit_comp32.c | 1460 +++++++++++++++++++++++++++++++ > 3 files changed, 1467 insertions(+), 2 deletions(-) > create mode 100644 arch/riscv/net/bpf_jit_comp32.c > <snip> > +static void rv32_bpf_put_reg32(const s8 *reg, const s8 *src, > + struct rv_jit_context *ctx) > +{ > + if (is_stacked(reg[1])) { > + emit(rv_sw(RV_REG_FP, reg[1], src[1]), ctx); > + emit(rv_sw(RV_REG_FP, reg[0], RV_REG_ZERO), ctx); > + } else { > + emit(rv_addi(reg[0], RV_REG_ZERO, 0), ctx); > + } > +} > + Looks to me 32-bit optimization is not enabled. If you define bpf_jit_needs_zext to return true bool bpf_jit_needs_zext(void) { return true; } Then you don't need to zero high 32-bit when writing 32-bit sub-register and you just need to implement the explicit zero extension insn which is a special variant of BPF_MOV. This can save quite a few instructions. RV64 and arches like arm has implemented this, please search "aux->verifier_zext". And there is a doc for this optimization: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/tree/Documentation/bpf/bpf_design_QA.rst#n168 Regards, Jiong