feat(jit): add RISC-V 64 and AArch64 JIT backends#152
Open
CN-TangLin wants to merge 3 commits into
Open
Conversation
Add a RISC-V 64-bit JIT compiler (RiscV64Compiler) based on the existing x86_64 JitCompiler pattern. The backend supports the full eBPF instruction set for 64-bit RISC-V targets, using a three-field relocation scheme (pc_locs / jumps / special_targets) consistent with the existing x86_64 compiler. Refactor JitMemory::new() to use #[cfg(target_arch)] dispatch so both x86_64 and riscv64 backends coexist. Make the jit module public so users can call JitMemory::new() directly for custom executable memory control, which is required for integration into OS kernels or custom runtimes. The module remains private on Windows where executable memory allocation is not supported.
Add a new AArch64 JIT compiler (Aarch64Compiler) that translates eBPF bytecode to native AArch64 machine code. The backend follows the same pattern as the existing RiscV64Compiler: - Single-pass compilation with pc_locs/jumps/special_targets relocation - All A64 instruction encodings (ADD/SUB/AND/ORR/EOR/MADD/UDIV, UBFM/SBFM for shifts, LDR/STR variants, STP/LDP for frame management, conditional and unconditional branches) - BPF_END handled via native REV16/REV32/REV64 instructions - Full ALU32/ALU64, LDX/ST/STX, JMP32/JMP64, CALL, and EXIT support - Register mapping: BPF R0-R5 → x0-x5, BPF R6-R9 → x19-x22, BPF R10 → x25 - Frame: 512-byte BPF stack + 64-byte callee-saved area (x19-x22,x25,x29,x30) Integrated into JitMemory::new() via #[cfg(target_arch = "aarch64")] dispatch, matching the existing x86_64 and riscv64 patterns.
Move the x86_64 JIT compiler from src/jit.rs into its own file (src/jit_x86_64.rs), leaving only the arch-agnostic infrastructure (JitMemory, MachineCode, constants, arch dispatch) in jit.rs. This unifies the code organization with the newly-added riscv64 and aarch64 backends: each architecture now has its own dedicated file, and jit.rs serves as the common entry point with #[cfg(target_arch)] dispatch. The extraction uses #[path] attributes to keep all backend files as siblings in the src/ directory, avoiding the need for a jit/ subdirectory while maintaining Rust 2024 edition module resolution. No functional changes to the x86_64 JIT logic.
This was referenced Jun 13, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds native JIT compiler backends for RISC-V 64-bit and AArch64 (ARM64) architectures, and refactors the existing x86_64 backend into a separate file to unify the code organization.
Why not use the existing Cranelift feature?
The
craneliftfeature (behind#[cfg(feature = "cranelift")]) provides multi-architecture JIT via the Cranelift codegen framework, which is the right tool for user-space applications. However, for OS kernel integration scenarios, a native JIT backend is preferred:Zero external dependencies: The native backends use only the
byteordercrate (already in the dependency tree). Cranelift adds 5 additional crates (cranelift-codegen,cranelift-frontend,cranelift-jit,cranelift-module,cranelift-native) which are unsuitable forno_stdkernel environments.Lighter weight: The native backends generate compact machine code directly without going through an IR layer. This means faster compilation and smaller code footprint, which matters in resource-constrained embedded or kernel contexts.
Kernel compatibility: The
no_stdvariant ofJitMemory::new()already supports caller-provided executable memory — this is essential for kernels that manage their own page tables and memory protection. The Cranelift JIT path assumes a user-space allocator.In short: Cranelift serves user-space well; native backends serve kernel/embedded use cases. They complement rather than replace each other.
On maintainership
These backends are derived from and actively used in the StarryOS kernel (https://github.com/rcore-os/tgoskits), where they have been running eBPF programs on RISC-V and AArch64 hardware for months. We are committed to maintaining them in rbpf as well — we will respond to issues, keep them up to date with eBPF ISA changes, and fix bugs as they arise.
Changes (3 commits)
feat(jit): add RISC-V 64-bit JIT backend and multi-arch dispatch
src/jit_riscv64.rs— full RISC-V 64 JIT compilersrc/lib.rs:pub mod jitfor external accessfeat(jit): add AArch64 (ARM64) JIT backend
src/jit_aarch64.rs— full AArch64 JIT compiler#[cfg(feature = "std")]gated (useslibc::mprotect)refactor(jit): extract x86_64 backend into separate file
src/jit.rsintosrc/jit_x86_64.rsjit.rsnow contains only arch-agnostic infrastructure (JitMemory, constants, dispatch)#[path]attributes for Rust 2024 edition module resolutionRegarding tests
I acknowledge that
tests/ubpf_jit_x86_64.rsalready provides comprehensive execution-level tests (95+ test functions) for the x86_64 JIT. The unit tests that were in the earlier separate PR (#151) have been removed from this submission — the existing integration test suite is more thorough and covers the entire eBPF ISA.For the new RISC-V and AArch64 backends, we rely on real-hardware testing in the StarryOS kernel (QEMU virt machines for riscv64 and aarch64), and the existing interpreter tests which exercise the same code paths regardless of JIT backend.
Verification
cargo clippy --all-features: zero warningscargo test --all-features: all 117 unit tests + JIT integration tests pass