# RVVM: a RISC-V virtual machine built around a tracing JIT

> RVVM is a virtual machine and emulator for RISC-V guests that emphasises performance, lean code and portability, with a tracing JIT that has x86_64, ARM64 and RISC-V backends and claims to be faster than QEMU TCG, and it already boots Linux, Haiku, FreeBSD and OpenBSD. It suits anyone who wants RISC-V on a machine that is not RISC-V, and it ships a library so the emulator can be embedded in other programs.

**LekKit/RVVM** — The RISC-V Virtual Machine 

- Repository: https://github.com/LekKit/RVVM
- Stars: 1,312 · Forks: 98
- Language: C
- License: GPL-3.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/lekkit-rvvm

## What RVVM is and how it is different

RVVM is a virtual machine and emulator for RISC-V guests, and the README lists the priorities in one line: it emphasises performance, security, lean code and portability.

The interesting technical decision is the tracing JIT, and the feature list is explicit about it. RVVM has a tracing JIT with x86_64, ARM64 and RISC-V backends, and the README states that it is faster than QEMU TCG.

The difference in approach is worth spelling out, because it is the same difference that separates a JIT from any translator. A tracing JIT watches a block of guest code as it executes, compiles that block into native code for the host, and runs it directly. The overhead moves to compilation rather than to every instruction, and the price is that you need a compiler backend for each host architecture you care about.

RVVM has three of them, and the RISC-V one means the emulator can run on a RISC-V host and still be fast, which is the case a portable interpreter handles worst.

The instruction set support is specific too. It is fully spec compliant for the rv64imafdcb instruction set, with the Zkr, Zicbom, Zicboz and Sstc extensions, and the default is 64-bit with a switch for 32-bit guests.

The code is C, the primary language of the repository, and the project is licensed under GPL-3.0 with the library under MPL.

## The guest operating systems that actually boot

The claim about guests is concrete, and it is the part that tells you whether the emulator is a research prototype or a usable tool.

RVVM already runs a lot of guest operating systems, including Linux, Haiku, FreeBSD and OpenBSD. The main features list repeats it with the firmware layer included: working OpenSBI and U-Boot, and Linux, FreeBSD, OpenBSD and Haiku guests.

OpenSBI and U-Boot is the pair that matters most for a RISC-V system, because that is where the privilege levels start. RISC-V machines boot in machine mode, and OpenSBI is the firmware that sets up the next stage and drops into the supervisor mode the operating system expects. A guest that boots under both of those is booting the way real RISC-V hardware boots, not taking a shortcut.

The device set supports that. There is a framebuffer display, HID mouse and keyboard, and a UART terminal, which is the minimum for a graphical guest and for a serial console. Storage is NVMe with TRIM support, described as deallocating space on the host, and fast multi-threaded IO. The networking userland stack works on any host OS, which is an interesting choice, because it moves the network stack out of the guest and into the host process rather than emulating a network card.

The other notable device is VFIO PCIe passthrough, for GPUs and similar hardware, which is the feature that turns an emulator into something you can put a real accelerator into.

The project also maintains a WASM demo, linked from the README, which is a small sign of how portable the core has been made.

## The library API, and userland emulation

The most interesting architectural decision in the project is the split between the emulator library and the binaries.

There is a library API, librvvm, for machine and userland emulation, including the ability to implement new devices. That is what makes the emulator embeddable. You can put a RISC-V machine inside your own program, give it your own devices, and drive it, rather than running it as a separate process and talking to it over a socket.

The userland emulation side is the other half of the idea, and it is the part that changes the use case. The README says RVVM also aims to run RISC-V applications on a foreign architecture host without a full OS guest and without isolation, which is userland emulation. Instead of booting Linux and running the program inside it, the program itself is translated and run in the host's address space.

That is much lighter than a full virtual machine, and it is the shape you want when the goal is to run one RISC-V binary on a developer machine rather than to test an operating system. The userland emulation is marked as work in progress, and so is the shadow page table acceleration.

Security is handled at the kernel level, with the feature list describing isolation to prevent and contain vulnerability exploitation, which is the right layer to do it at for a machine that runs hostile code. The security posture is part of the design rather than an afterthought.

## Building it, and the build system as a project spec

The build is deliberately plain, and the README recommends GNU Make with CMake as an alternative.

```sh
git clone https://github.com/LekKit/RVVM
cd RVVM
make
cd release.linux.x86_64
./rvvm_x86_64 -h
```

```sh
git clone https://github.com/LekKit/RVVM
cd RVVM
cmake -S. -Bbuild
cmake --build build --target all
cd build
./rvvm -h
```

The Makefile is described as a build system in itself atop GNU Make, aiming at simplicity and easy cross-compilation, and the design is that the project specification lives in a separate file, project.mk, containing the name, the sources, the feature use flags and the binary and library targets. The Makefile holds the machinery and the variables.

Those variables are the interface, and they are worth a look because they explain what the project expects from a build environment. There is the build directory, which defaults to a name like release.windows.x86_64, the usual compiler and flag variables, and pkg-config. Then there are the informational ones, the compiler brand, version and target triplet, the target and host architecture and operating system, and the project version taken from git describe.

And then the switches that matter for a project like this: link time optimisation, building dynamic libraries, static libraries, shared project libraries, an intermediate object file build step, an optimised build with debug info, a full debug build without optimisations, and the UndefinedBehaviorSanitizer and AddressSanitizer options, with the sanitizer builds implying the debug configuration. For an emulator, having the sanitizers as first class build options rather than something you patch in is a good sign about how the code is tested.

Nightly build artifacts and an Arch package are available for people who do not want to build.

## Running a machine

The example command is a good summary of the interface, because it shows the whole model of a machine in one line.

```sh
rvvm fw_payload.bin -i drive.img -m 2G -smp 2 -res 1280x720 -portfwd tcp/127.0.0.1:2022=22
```

That launches a dual-core virtual machine with 2 GiB of RAM and a 1280 by 720 display, runs the OpenSBI and U-Boot firmware, boots an EFI guest from the disk image, and forwards host port 2022 into the guest SSH port.

The argument list is short and each one maps to a piece of the machine model.

```
[fw_payload.bin]    Initial M-mode firmware, OpenSBI + U-Boot in this case
-i  drive.img       Attach preferred storage image (Currently as NVMe)
-m 2G               Memory amount (may be suffixed by k/M/G), default 256M
-smp 2              Amount of cores, single-core machine by default
-res 1280x720       Set display(s) resolution
-portfwd 8080=80    Port forwarding (Extended: tcp/127.0.0.1:8080=80)
-rv32               Enable 32-bit RISC-V, 64-bit by default
-v                  Verbose mode
-h                  Extended help
```

Note the defaults, since they are the ones you will hit if you leave an argument out. Memory defaults to 256 megabytes, a single core by default, and 64-bit RISC-V unless you pass the 32-bit switch. The port forwarding syntax is the extended form with the protocol and the host address, so the same flag covers a plain port and a specific interface.

The wiki pages are where the recommended guest firmware and images are listed, and the running page has the full argument explanation.

## The licence split, the contributors and the state of the project

The licensing is two-tier, and the reasoning is stated.

The librvvm library is licensed under the non-viral MPL 2.0 licence. If you wish to use librvvm as a component of a larger project that is not GPL compliant, you are free to do so in any form, static linkage, binary distribution or modules, as long as you comply with MPL 2.0. The MPL terms also apply to Java JNI bindings.

The RVVM Manager and the Linux userland emulator binaries, rvvm and rvvm-user, are under the copyleft GPL 3.0, since they are intended for end users. The stated reason is that all the heavy lifting is done by librvvm anyway, so the library is the part worth keeping permissively licensed for people embedding it.

That is a sensible arrangement for an emulator, and it matters for anyone who wants to embed the machine model inside a commercial product, since the library can be linked without dragging the copyleft into the host project.

The contributor table in the README shows the shape of the project. LekKit does the API and infrastructure, the interpreter for rv64imafdc, the MMU, interrupts and privilege handling, the JIT compiler with the x86 and RISC-V backends, and the devices including NVMe, the RTL8169 network card and VFIO. Other contributors cover the ARM and ARM64 JIT backends, the initial C, M and Zicsr extensions, the initial UART and the VM debugger, the userspace network work, the Haiku GUI and I2C HID, the OpenBSD and PLIC fixes, and the relative input mode. The project also asks for hardware donations, specifically a Milk-V Megrez for KVM work.

On the state of it, the tagged releases are v0.6 from March 2024 and v0.5 from April 2023, the version badge reads 0.7-git, and the default branch is staging rather than main, with the README asking contributors to check the staging branch when reporting issues. The last push was on 2026-10-12, so the work is active even though the releases are old.

## Conclusion

Adopt RVVM if you need to run RISC-V binaries on a machine with a different architecture, or if you are building a tool that needs to emulate RISC-V, because the library API lets you embed the emulator rather than shelling out to a virtual machine. Do not adopt it if you need a stable, long lived release line, because the tagged versions stop in 2024 while the default branch is a staging branch that moves constantly. Before you build, check which host backends your machine needs and whether the release you pick has them, and read the licence split, since the library and the binaries are under different terms.

## FAQ

### What is RVVM?

It is a virtual machine and emulator for RISC-V guests that emphasises performance, security, lean code and portability. It has a tracing JIT with x86_64, ARM64 and RISC-V backends, which the README states is faster than QEMU TCG, and it runs Linux, Haiku, FreeBSD and OpenBSD guests.

### How do I build RVVM?

With GNU Make, which is the recommended path, by cloning the repository and running make, then running the binary from the release directory, or with CMake using cmake -S. -Bbuild followed by cmake --build build --target all. The project specification lives in project.mk, and the Makefile exposes options for link time optimisation, debug builds and the sanitizers.

### How do I run a RISC-V Linux guest with RVVM?

The documented example is rvvm fw_payload.bin -i drive.img -m 2G -smp 2 -res 1280x720 -portfwd tcp/127.0.0.1:2022=22, where the first argument is the machine mode firmware such as OpenSBI and U-Boot, the -i flag attaches the storage image, -m sets memory, -smp the core count, -res the display resolution and -portfwd forwards a host port into the guest.

### Can I use librvvm in a project that is not GPL licensed?

Yes. The librvvm library is under the non-viral MPL 2.0 licence, and the README states you may use it as a component of a larger non-GPL compliant project in any form, static linkage, binary distribution or modules, as long as you comply with MPL 2.0. The rvvm and rvvm-user binaries themselves are GPL 3.0.

## Sources

- [Issues](https://github.com/LekKit/RVVM/issues)
- [LekKit/RVVM on GitHub](https://github.com/LekKit/RVVM)
- [License: GPL-3.0](https://github.com/LekKit/RVVM/blob/staging/LICENSE)
- [README](https://github.com/LekKit/RVVM/blob/staging/README.md)
- [Releases](https://github.com/LekKit/RVVM/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lekkit-rvvm
