RISC-V QEMU ‘virt’ is a generic platform which does not correspond to any real hardware.
EDK2 for RISC-V virt platform is a payload (S-mode) for the previous stage M-mode firmware like OpenSBI. It follows PEI less design.
The minimum QEMU version required is 8.1 or with commit 7efd65423a which supports separate pflash devices for EDK2 code and variable storage.
git clone --recurse-submodule git@github.com:tianocore/edk2.git
Prerequisite: RISC-V GNU compiler toolchain should be installed.
export WORKSPACE=`pwd` export GCC5_RISCV64_PREFIX=riscv64-linux-gnu- export PACKAGES_PATH=$WORKSPACE/edk2 export EDK_TOOLS_PATH=$WORKSPACE/edk2/BaseTools source edk2/edksetup.sh --reconfig make -C edk2/BaseTools source edk2/edksetup.sh BaseTools build -a RISCV64 --buildtarget RELEASE -p OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc -t GCC5
Prerequisite: LLVM toolchain with clang and lld should be installed.
export WORKSPACE=`pwd` export CLANGDWARF_BIN=/usr/bin/ export PACKAGES_PATH=$WORKSPACE/edk2 export EDK_TOOLS_PATH=$WORKSPACE/edk2/BaseTools source edk2/edksetup.sh --reconfig make -C edk2/BaseTools source edk2/edksetup.sh BaseTools build -a RISCV64 --buildtarget RELEASE -p OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc -t CLANGDWARF
After a successful build, two files namely RISCV_VIRT_CODE.fd and RISCV_VIRT_VARS.fd are created.
Below example shows how to boot openSUSE Tumbleweed E20.
RISC-V QEMU pflash devices should be of of size 32MiB.
truncate -s 32M RISCV_VIRT_CODE.fd
truncate -s 32M RISCV_VIRT_VARS.fd
Running QEMU
qemu-system-riscv64 \ -M virt,pflash0=pflash0,pflash1=pflash1,acpi=off \ -m 4096 -smp 2 \ -serial mon:stdio \ -device virtio-gpu-pci -full-screen \ -device qemu-xhci \ -device usb-kbd \ -device virtio-rng-pci \ -blockdev node-name=pflash0,driver=file,read-only=on,filename=RISCV_VIRT_CODE.fd \ -blockdev node-name=pflash1,driver=file,filename=RISCV_VIRT_VARS.fd \ -netdev user,id=net0 \ -device virtio-net-pci,netdev=net0 \ -device virtio-blk-device,drive=hd0 \ -drive file=openSUSE-Tumbleweed-RISC-V-E20-efi.riscv64.raw,format=raw,id=hd0
Note: the acpi=off
machine property is specified because Linux guest support for ACPI (that is, the ACPI consumer side) is a work in progress. Currently, acpi=off
is recommended unless you are developing ACPI support yourself.
Running QEMU with direct kernel boot
The following example boots the same guest, but loads the kernel image and the initial RAM disk (which were extracted from openSUSE-Tumbleweed-RISC-V-E20-efi.riscv64.raw
) from the host filesystem. It also sets the guest kernel command line on the QEMU command line.
CMDLINE=(root=UUID=76d9b92d-09e9-4df0-8262-c1a7a466f2bc systemd.show_status=1 ignore_loglevel console=ttyS0 earlycon=uart8250,mmio,0x10000000) qemu-system-riscv64 \ -M virt,pflash0=pflash0,pflash1=pflash1,acpi=off \ -m 4096 -smp 2 \ -serial mon:stdio \ -device virtio-gpu-pci -full-screen \ -device qemu-xhci \ -device usb-kbd \ -device virtio-rng-pci \ -blockdev node-name=pflash0,driver=file,read-only=on,filename=RISCV_VIRT_CODE.fd \ -blockdev node-name=pflash1,driver=file,filename=RISCV_VIRT_VARS.fd \ -netdev user,id=net0 \ -device virtio-net-pci,netdev=net0 \ -device virtio-blk-device,drive=hd0 \ -drive file=openSUSE-Tumbleweed-RISC-V-E20-efi.riscv64.raw,format=raw,id=hd0 \ -kernel Image-6.5.2-1-default \ -initrd initrd-6.5.2-1-default \ -append "${CMDLINE[*]}"
Using the above QEMU command lines, RISCV_VIRT_CODE.fd is launched by the OpenSBI binary that is bundled with QEMU. You can build your own OpenSBI binary as well:
OPENSBI_DIR=... git clone https://github.com/riscv/opensbi.git $OPENSBI_DIR make -C $OPENSBI_DIR \ -j $(getconf _NPROCESSORS_ONLN) \ CROSS_COMPILE=riscv64-linux-gnu- \ PLATFORM=generic
then specify that binary for QEMU, with the following additional command line option:
-bios $OPENSBI_DIR/build/platform/generic/firmware/fw_dynamic.bin
Note that the above only makes a difference with software emulation (which you can force with -M accel=tcg
). With hardware virtualization (-M accel=kvm
), KVM services the SBI (Supervisor Binary Interface) calls internally, therefore any OpenSBI binary specified with -bios
is rejected.