Skip to content

feat: add RISC-V 64-bit JIT backend for eBPF#146

Closed
CN-TangLin wants to merge 1 commit into
qmonnet:mainfrom
CN-TangLin:feat/jit-multi-arch
Closed

feat: add RISC-V 64-bit JIT backend for eBPF#146
CN-TangLin wants to merge 1 commit into
qmonnet:mainfrom
CN-TangLin:feat/jit-multi-arch

Conversation

@CN-TangLin

Copy link
Copy Markdown

概述

在现有 x86_64 手写 JIT 后端基础上,添加 RISC-V 64 位 JIT 后端,使 rbpf 支持多架构 JIT 编译。

背景

rbpf 目前仅支持 x86_64 架构的手写 JIT 编译(src/jit.rs),以及基于 Cranelift 的通用 JIT。本 PR 添加 RISC-V 64 位的手写 JIT 后端,为 RISC-V 平台提供高性能 eBPF 执行能力。

变更内容

src/jit_riscv64.rs(~850 行,新增)

寄存器映射(与 RV64 ABI 自然对齐):

BPF r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10
RV64 A0 A1 A2 A3 A4 A5 S1 S2 S3 S4 S5(栈指针)

支持的 eBPF 指令

  • ALU/ALU64:ADD/SUB/MUL/DIV/MOD/OR/AND/XOR/LSH/RSH/ARSH/NEG/MOV(32 位操作后自动零扩展 SLLI+SRLI)
  • JMP/JMP32:JEQ/JGT/JGE/JLT/JLE/JSET/JNE/JSGT/JSGE/JSLT/JSLE(使用逆条件 + backfill)
  • LD/ST/LDX/STX:B/H/W/DW 四种宽度,BPF 栈帧偏移自动调整
  • LD_DW_IMM:LUI+ADDIW+SLLI+LUI+ADDIW+ADD 标准 6 指令序列
  • BPF_END:BE16/BE32/BE64 字节序转换(LE 为 no-op)
  • CALL:Helper 函数通过 load_imm + JALR 间接调用
  • DIV/MOD 除零保护:BEQ skip 模式(DIV 返回 0,MOD 保持 dst 不变)

Prologue/Epilogue

  • Prologue:ADDI SP,-560 + 保存 RA/S1-S5(6 个 callee-saved × 8 = 48 字节)
  • Epilogue:恢复 callee-saved + ADDI SP,+560 + JALR x0, ra, 0
  • BPF 栈 512 字节 + callee-saved 48 字节 = FRAME_SIZE 560

跳转实现

  • 无条件跳转:AUIPC + load_imm + ADD + JALR(PC 相对)
  • 条件跳转:逆条件 Bxx + AUIPC + load_imm + ADD + JALR(动态 backfill)

src/jit.rs(修改)

  • JitMemory::new() 添加 #[cfg(target_arch)] 条件编译,在 riscv64 上使用 RiscV64Compiler
  • 添加 #[cfg(target_arch = "riscv64")] mod jit_riscv64;

设计决策

  1. 单模块条件编译:riscv64 后端作为 jit 模块的子模块(mod jit_riscv64),通过 #[cfg(target_arch)] 选择编译器,不影响 x86_64 后端
  2. 共享 JitMemory:riscv64 复用 x86_64 的 JitMemory(页对齐可执行内存分配),仅替换编译逻辑
  3. Backfill 跳转策略:与 x86_64 后端一致的单遍编译 + 跳转回填,无需预计算代码大小

验证

  • cargo build:x86_64 编译通过
  • cargo test --test ubpf_jit_x86_64:131/131 x86_64 JIT 测试通过,无回归
  • cargo test:全部测试通过
  • ⚠️ RISC-V 64 测试需要在 riscv64 主机/QEMU 上运行(CI 暂不支持)

后续工作

  • 添加 AArch64 JIT 后端
  • 补全 JMP32 指令支持
  • 添加 LD_ABS/LD_IND 包数据加载支持
  • 向上游 qmonnet/rbpf 提交 PR

Add jit_riscv64.rs with complete eBPF-to-RISC-V instruction translation:
- Register mapping: r0-r10 → A0-A5, S1-S5
- Full ALU/ALU64 operations with 32-bit zero extension
- JMP/JMP32 conditional jumps with backfill
- LD/ST/LDX/STX memory operations with BPF stack adjustment
- LD_DW_IMM 64-bit immediate loading (LUI+ADDIW+SLLI+LUI+ADDIW+ADD)
- Helper function calls via indirect JALR
- BE/LE endianness conversion
- DIV/MOD zero-division protection
- Prologue/Epilogue with callee-saved register save/restore

Architecture selection via #[cfg(target_arch)] in JitMemory::new().
x86_64 JIT tests (131) all pass, no regressions.

Signed-off-by: CN-TangLin <2242120212@qq.com>
@CN-TangLin CN-TangLin force-pushed the feat/jit-multi-arch branch from 2fb1cc0 to 4e8cf99 Compare May 29, 2026 08:13
@CN-TangLin CN-TangLin closed this May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant