Building Linux Images for SimRV
This guide explains how to build RISC-V RV32GC (or RV64GC) Linux kernel and rootfs images for SimRV testing.
Overview
SimRV supports full Linux OS boot as part of its integration validation gate. You need:
SIMRV_LINUX_MEM_IMG: Firmware payload image (BBL + Linux kernel)SIMRV_LINUX_DISK_IMG: Root filesystem imageSIMRV_LINUX_DTB(optional): Device tree blob
Pre-built images for both RV32 and RV64 should be placed under
linux-images/rv32/ and linux-images/rv64/ respectively. The
scripts/build-linux-image.sh script automates
building them from source.
Quick Start
One-Command Build
# Default build (auto-detects musl / glibc toolchain)
./scripts/build-linux-image.sh
# Build with explicit C library target & cross compiler prefix
./scripts/build-linux-image.sh --libc musl --cross-compile riscv64-unknown-linux-musl-
./scripts/build-linux-image.sh --libc glibc --cross-compile riscv64-unknown-linux-gnu-
This will:
- ✅ Check for a pre-installed RISC-V GNU toolchain (or build one from source)
- ✅ Download Linux kernel and Buildroot sources
- ✅ Build kernel and rootfs
- ✅ Create compatible images in
./linux-images/rv32/
Time estimate:
| Scenario | First Build | Subsequent |
|---|---|---|
| With pre-installed toolchain | ~10–15 min | ~5–10 min |
| Building toolchain from scratch | ~25–40 min | ~5–10 min |
Setup Environment
After building, export the image paths:
This exports SIMRV_LINUX_MEM_IMG, SIMRV_LINUX_DISK_IMG, and SIMRV_LINUX_DTB.
Direct lifecycle helper
Generated root filesystems include simrv-power, a small root-only /dev/mem
fallback for directly exercising SimRV's power MMIO device:
Normal OS poweroff and reboot commands remain preferred because they sync
filesystems and stop services first. The helper writes the SiFive test-finisher
register at physical address 0x00100000; use it only on SimRV and only as root.
The shell builtin exit merely ends the current login shell, after which init may
spawn another login. Use simrv-power exit [status] to terminate the simulator,
including its TUI. This exit request is a SimRV extension; the other requests use
the platform's SiFive test-finisher protocol.
Run Linux Boot Test
Direct invocation:
source ./linux-images/rv32/setup.sh
./build/rv32-release/SimRV \
-m $SIMRV_LINUX_MEM_IMG \
-D $SIMRV_LINUX_DISK_IMG \
-f $SIMRV_LINUX_DTB
TUI mode:
Standard console mode:
Full integration gate (includes Linux boot test):
Prerequisites
Required system packages:
Ubuntu / Debian
sudo apt-get install -y \
build-essential flex bison bc libssl-dev \
git wget texinfo device-tree-compiler
Fedora / RHEL
Toolchain Setup
The build script needs a RISC-V cross-compilation toolchain. You have two options:
Option A: Pre-installed Toolchain (Recommended)
Install the riscv-gnu-toolchain
and make sure riscv64-unknown-linux-gnu-gcc (for RV32) or riscv64-linux-gnu-gcc
is in your PATH, or set RISCV_GNU_TOOLCHAIN_DIR:
Option B: Build Toolchain from Source
If no toolchain is found, the script will automatically build one from source. This adds ~25–40 minutes to the first run and requires ~3–5 GB of disk space.
Building Variants
Clean Rebuild
Deletes the previous build and starts fresh.
Parallel Jobs
Control build parallelism:
Default is $(nproc) (number of CPU cores).
Architecture Selection
RV32GC is the default. For RV64GC:
The CMake linux-images target uses the SIMRV_XLEN preset automatically:
cmake --build --preset rv32-release --target linux-images
cmake --build --preset rv64-release --target linux-images
What Gets Built
Directory Structure
linux-build/
├── sources/
│ ├── linux-6.1.x.tar.xz
│ └── buildroot-2026.02.tar.gz
├── linux/
│ └── arch/riscv/boot/Image
├── buildroot/
│ └── output/images/rootfs.ext2
└── riscv-gnu-toolchain/ # (if built from scratch)
└── bin/riscv64-unknown-linux-gnu-*
linux-images/
├── rv32/
│ ├── fw_payload.bin # Berkeley Boot Loader + Linux kernel
│ ├── root.bin # Root filesystem image
│ ├── devicetree.dtb # Device tree blob
│ ├── virt.dts # Device tree source
│ └── setup.sh # Environment variable export script
└── rv64/ # (when built with --arch rv64)
└── ...
Output Components
fw_payload.bin (Firmware Payload)
Combined Berkeley Boot Loader (BBL) + Linux kernel image. Loaded by SimRV via
-m and executed starting at 0x80000000.
root.bin (Root Filesystem)
Minimal ext2 filesystem containing:
- BusyBox shell utilities
- Essential C libraries (musl or glibc)
- Basic device nodes
- Init system
devicetree.dtb (Device Tree)
Describes the simulated hardware to Linux. Includes:
- CPU core (RV32GC or RV64GC, 1 hart)
- 256 MB DRAM at
0x80000000 - UART serial console
- VirtIO block device controller (disk)
- PLIC interrupt controller
- CLINT timer
[!NOTE] The DRAM size in the device tree must match the SimRV build-time
SIMRV_DRAM_SIZE_MBsetting (default: 256 MB).
Troubleshooting
Command not found: riscv64-unknown-linux-gnu-gcc
The RISC-V cross-compiler was not found. Install the toolchain or point the script at an existing one:
Or install the toolchain from source:
git clone https://github.com/riscv-collab/riscv-gnu-toolchain
cd riscv-gnu-toolchain
./configure --prefix=/opt/riscv --with-arch=rv32gc --with-abi=ilp32d
make linux -j$(nproc)
Cannot find sources
Internet connectivity issue. Clear the source cache and retry:
linux-images/ directory empty after build
Verify the underlying build artifacts exist:
If files exist there but not under linux-images/, the copy step failed —
check the script output for errors.
dtc not found warning
Install the device-tree compiler and retry:
Or compile the device tree manually:
Customization
Kernel Configuration
- Start a build:
./scripts/build-linux-image.sh - Stop at the desired point (or use
--cleanto reset) - Uncomment the
make menuconfigline in the script to enable interactive kernel config - Re-run the script
Rootfs Contents
Edit the Buildroot config section in create_rootfs_buildroot() inside the script:
Then rebuild:
Integration with Validation Gates
The generated images integrate with the comprehensive CMake validation gate:
The Linux boot test runs SimRV with a 1,000,000 cycle limit and checks for a
clean boot sequence. It is labeled gate;regress;linux in CTest and included
in integration-gate.
Performance Notes
- First build (with pre-installed toolchain): ~10–15 min
- First build (toolchain from scratch): ~25–40 min
- Subsequent builds: ~5–10 min
- Parallel speedup: Near-linear with CPU cores (
JOBS=N) - Disk space: ~3–5 GB total
References
Next Steps
After images are ready:
- ✅ Export environment:
source linux-images/rv32/setup.sh - ✅ Manual boot test:
./build/rv32-release/SimRV -m $SIMRV_LINUX_MEM_IMG -D $SIMRV_LINUX_DISK_IMG -f $SIMRV_LINUX_DTB - ✅ TUI boot:
cmake --build --preset rv32-release --target run-tui - ✅ Full validation:
cmake --build --preset rv32-release --target integration-gate