System emulation

May 20, 2026 ยท View on GitHub

rv32emu provides experimental system emulation capable of booting an RV32 Linux kernel and running user-space binaries. This document covers building and running system mode, attaching virtio block devices, customizing bootargs, and building a Linux image from source.

Device Tree compiler (dtc) is required:

  • Debian/Ubuntu Linux: sudo apt install device-tree-compiler
  • macOS: brew install dtc

Build and run

Build and run using default images (fetched from rv32emu-prebuilt before running). If ENABLE_ARCH_TEST=1 was previously set, run make distclean before proceeding.

$ make ENABLE_SYSTEM=1 system

For improved performance, JIT compilation can be enabled in system emulation mode:

$ make system_jit_defconfig
$ make system

Build and run using specified images (readonly option makes the virtual block device read-only):

$ make ENABLE_SYSTEM=1
$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path> [-x vblk:<virtio_blk_img_path>[,readonly]]

mk/system.mk auto-sizes the initrd region from the on-disk rootfs.cpio when present (file size + 2 MiB), falling back to 32 MiB. Override INITRD_SIZE on the make line for SDL-oriented workloads that ship larger asset bundles:

$ make system ENABLE_SYSTEM=1 ENABLE_SDL=1 INITRD_SIZE=64

Once logged into the guestOS, run doom-riscv or quake or smolnes. To terminate SDL-oriented applications, use the built-in exit utility, ctrl-c or the SDL window close button(X).

Virtio block device (optional)

Generate ext4 image file for virtio block device in Unix-like system:

$ dd if=/dev/zero of=disk.img bs=4M count=32
$ mkfs.ext4 disk.img

Instead of creating a new block device image, you can share the hostOS's existing block devices. For example, on macOS host, specify the block device path as -x vblk:/dev/disk3, or on Linux host as -x vblk:/dev/loop3, assuming these paths point to valid block devices.

Mount the virtual block device and create a test file after booting, note that root privilege is required to mount and unmount a disk:

# mkdir mnt
# mount /dev/vda mnt
# echo "rv32emu" > mnt/emu.txt
# umount mnt

Reboot and re-mount the virtual block device, the written file should remain existing.

To specify multiple virtual block devices, pass multiple -x vblk options when launching the emulator. Each option can point to either a disk image or a hostOS block device, with optional read-only mode. For example:

$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path> -x vblk:disk.img -x vblk:/dev/loop22,readonly

Note that the /dev/vdx device order in guestOS is assigned in reverse: the first -x vblk argument corresponds to the device with the highest letter, while subsequent arguments receive lower-lettered device names.

Out-of-tree filesystems

In addition to the built-in ext4 filesystem support, other out-of-tree filesystems such as simplefs are also supported. To use simplefs, first follow the instructions here to generate the simplefs disk image, and then attach it to the guestOS via the virtio block device. An additional ext4 image containing simplefs.ko must also be attached to the guestOS, since simplefs.ko is out-of-tree kernel module. The pre-built simplefs.ko can be found at build/linux-image/ (run make artifact ENABLE_SYSTEM=1 to get the artifacts).

$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path> -x vblk:<ext4_disk_img_path> -x vblk:<simplefs_disk_img_path>

Once the guestOS is booted, insert the simplefs.ko kernel module. After loading the kernel module, the simplefs disk will be recognized by the Linux kernel and can be mounted and used as a regular filesystem:

# mkdir -p mnt && mount /dev/vdb mnt # mount the ext4 disk that contains simplefs.ko

# insmod mnt/simplefs.ko # insert simplefs.ko

# mkdir -p simplefs && mount -t simplefs /dev/vda simplefs # mount the simplefs disk

Customize bootargs

Build and run with customized bootargs to boot the guestOS. Otherwise, the default bootargs defined in src/devices/minimal.dts will be used:

$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path> [-b <bootargs>]

Build Linux image from source

An automated build script is provided to compile the RISC-V cross-compiler, Busybox, and Linux kernel from source. Please note that it only supports the Linux host environment. It can be found at tools/build-linux-image.sh.

$ make build-linux-image