RISC-V is a shiny new instruction set that’s getting a lot of hype among computer nerds – and not just among internet randos. Western Digital, Alibaba, and MIT, among others, have been working on the platform. But what is it, and how can you play around with it today?

Its claim to fame is that unlike most of the big ISAs out there, like x86, ARM, and AVR, it’s available under a permissive license. Now this isn’t completely unique – for instance, IBM has started opening up its POWER architecture via the OpenPOWER Foundation. And Wave Computing has had an on-again-off-again plan to open up MIPS. But unlike these, RISC-V also has another nerd cred advantage: it’s been designed totally from scratch.

Now I’m not normally one to advocate for designing brand new systems for funsies. But, in chip design, backwards compatibility usually trumps all – if you’re running an x86 machine, you have hardware support for 16-bit addressing, segmentation, and other such fragments of millenia past.

You can actually buy some RISC-V boards today – SiFive has a few offerings. Or you can run a soft core, like SweRV or VexRiscv on an FPGA. But why spend money when you could not spend money? Let’s see how to set up a RISC-V virtual machine with Debian installed.

Setting up QEMU

QEMU (Quick EMUlator) is an open source virtual machine for Linux, Mac, Windows, with ports to various BSDs and sundry as well. It’s super useful since it supports a wide range of guest architectures – x86, the various flavors of ARM, m68k, S390x, and even RISC-V.

For our purposes, we’ll be focusing specifically on RV64GC (64-bit RISC-V with extensions for General purpose and Compressed instructions). This is the target that several Linux distros seem to be targeting.

The QEMU target for RV64GC can be installed through many package managers:

  • Arch: sudo pacman -S qemu-arch-extra
  • Ubuntu 20.10: sudo apt install qemu-system-riscv64
  • Fedora 33: sudo dnf install qemu-system-riscv
  • Alpine: sudo apk add qemu-system-riscv64

Getting a Debian RISC-V port image

So as far as I’m aware, no Linux distro has an official port for RISC-V yet. Fedora apparently has a port in progress, but let’s be real, Debian is the go-to distro for bizarre architectures.

Download a pre-built Debian RISC-V image:

wget "https://gitlab.com/api/v4/projects/giomasce%2Fdqib/jobs/artifacts/master/download?job=convert_riscv64-virt" -O debian-rv64.zip

Unpack the files:

mkdir debian-rv64
cd debian-rv64
unzip ../debian-rv64.zip
cd artifacts

Get the OpenSBI and U-Boot binaries

OpenSBI is a standardized piece of glue for RISC-V platforms to switch from firmware mode (M-Mode) up to the kernel layer (S-Mode). Its source code is available here, and a high-ish level overview of the RISC-V boot process is available here.

U-Boot is an open source bootloader which supports a wide variety of architectures, including, but not limited to, RISC-V.

For Ubuntu 20.10 and Debian unstable, this is fairly straightforward:

sudo apt install u-boot-qemu opensbi

For Arch Linux, it’s less straightforward. OpenSBI comes as part of qemu-arch-extra, and is installed at /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.elf.

I was unable, however, to find an equivalent package for u-boot-qemu. I ended up just downloading and extracting the binary from the Debian package.

# Grab the URL from https://packages.debian.org/sid/u-boot-qemu
wget "http://ftp.us.debian.org/debian/pool/main/u/u-boot/u-boot-qemu_2021.01+dfsg-2_all.deb" -O u-boot-qemu.deb
mkdir u-boot-qemu
cd u-boot-qemu
ar -x ../u-boot-qemu.deb
tar xvf data.tar.xz
cp ./usr/lib/u-boot/qemu-riscv64_smode/uboot.elf ./uboot.elf

Make an overlay image

While not strictly required, this lets you reset the machine to a clean state when you inevitably break something.

qemu-img create -o backing_file=image.qcow2,backing_fmt=qcow2 -f qcow2 overlay.qcow2

Boot the damn thing

On Arch:

qemu-system-riscv64 \
    -machine virt \
    -cpu rv64 \
    -m 1G \
    -device virtio-blk-device,drive=hd \
    -drive file=overlay.qcow2,if=none,id=hd \
    -device virtio-net-device,netdev=net \
    -netdev user,id=net,hostfwd=tcp::2222-:22 \
    -bios /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.elf \
    -kernel ./u-boot-qemu/uboot.elf \
    -object rng-random,filename=/dev/urandom,id=rng \
    -device virtio-rng-device,rng=rng \
    -append "root=LABEL=rootfs console=ttyS0" \
    -nographic

On Debian or Ubuntu:

qemu-system-riscv64 \
    -machine virt \
    -cpu rv64 \
    -m 1G \
    -device virtio-blk-device,drive=hd \
    -drive file=overlay.qcow2,if=none,id=hd \
    -device virtio-net-device,netdev=net \
    -netdev user,id=net,hostfwd=tcp::2222-:22 \
    -bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.elf \
    -kernel /usr/lib/u-boot/qemu-riscv64_smode/uboot.elf \
    -object rng-random,filename=/dev/urandom,id=rng \
    -device virtio-rng-device,rng=rng \
    -append "root=LABEL=rootfs console=ttyS0" \
    -nographic

A teardown of this flag menagerie:

  • -cpu rv64: Emulate RISC-V 64-bit.
  • -m 1G: 1 GB of RAM. Tweak as needed.
  • -netdev user,id=net,hostfwd=tcp::2222-:22: Make port 22 accessible as localhost:2222. This lets us forward SSH connections.
  • -bios /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.elf: If needed, replace with the location of your OpenBSI. But make sure it’s the same configuration.
  • -kernel ./u-boot-qemu/uboot.elf: Replace with the path to your U-Boot image.
  • -nographic: Run in serial TTY mode. This should give you decently-accurate terminal emulation.

The image is configured with two accounts: debian (password: debian) and root (password: root).

SSH access

The image runs sshd by default, which is nice because it lets you get comfier terminal access.

Note that in this mode, you may want to replace -nographic with -daemonize, which makes qemu run nicely in the background.

You can log in using either username/password:

ssh debian@localhost -p 2222

Or using one of the SSH keys included with the image:

chmod 600 ssh_user_ed25519_key
ssh debian@localhost -p 2222 -i ssh_user_ed25519_key

Playing around

Screengrab of an SSH session to the VM

The world is now your oyster. I was actually surprised at how complete the package offering seems to be. You can install OpenJDK, GCC, git, and most importantly, cowsay. I did have some issues installing vim, but thankfully, neovim was installable without a hitch.

Hopefully this was informative, and best of luck with your real fake hardware!