QEMU provides good support for system-level RISC-V emulation. A full %%FreeBSD%% system can be run using its ''%%virt%%'' platform. To run %%FreeBSD%%/RISC-V, QEMU version 5.0 or later is required. This can be installed via [[https://www.freshports.org/emulators/qemu50/|emulators/qemu50]] or [[https://www.freshports.org/emulators/qemu-devel/|emulators/qemu-devel]]. Also required is the %%OpenSBI%% bootloader, which can be installed from the [[https://www.freshports.org/sysutils/opensbi/|sysutils/opensbi]] port or package. ===== Generate a root filesystem ===== If you have built %%FreeBSD%% by hand and would like to generate a root filesystem and bootable image, you can follow these steps. If you downloaded a bootable %%FreeBSD%% image, skip to [[#Boot FreeBSD]]. **Create root partition** # Install the system to a staging directory setenv ROOTFSDIR $HOME/rootfsstage make TARGET=riscv DESTDIR=$ROOTFSDIR NO_ROOT=yes installworld make TARGET=riscv DESTDIR=$ROOTFSDIR NO_ROOT=yes installkernel make TARGET=riscv DESTDIR=$ROOTFSDIR NO_ROOT=yes distribution # Make any desired tweaks to the system, e.g. /etc/fstab echo "# Device Mountpoint FStype Options Dump Pass#" > $ROOTFSDIR/etc/fstab echo "/dev/gpt/rootfs / ufs rw,noatime 1 1" >> $ROOTFSDIR/etc/fstab echo "/dev/gpt/swapfs none swap sw 0 0" >> $ROOTFSDIR/etc/fstab echo "hostname=qemu" > $ROOTFSDIR/etc/rc.conf # Add be sure to add them to METALOG echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> $ROOTFSDIR/METALOG echo "./etc/rc.conf type=file uname=root gname=wheel mode=0644" >> $ROOTFSDIR/METALOG # Create a UFS root filesystem from that directory cd $ROOTFSDIR makefs -B little \ -o label=rootfs -o version=2 -o softupdates=1 \ -D -s 6g \ rootfs.ufs METALOG //Note: specify -s or -f to ensure the filesystem is created with free inodes// **Create EFI partition** # Copy the EFI bootloader setenv EFIDIR $HOME/efistage mkdir -p $EFIDIR/EFI/BOOT/ cp $ROOTFSDIR/boot/loader.efi $EFIDIR/EFI/BOOT/BOOTRISCV64.EFI # Create an EFI partition (msdosfs) makefs -t msdos \ -o fat_type=32 -o sectors_per_cluster=1 -o volume_label=EFISYS \ -s 50m \ efi.part $EFIDIR **Create Image File** Now, to combine our root and EFI partitions into a final image file: mkimg -s gpt -f raw \ # GPT partition scheme -p efi:=efi.part \ -p freebsd-swap/swapfs::2G \ # Swap partition (optional) -p freebsd-ufs/rootfs:=rootfs.ufs \ -o riscv.img ''%%riscv.img%%'' is the final output. You may clean up all other temporary objects as you choose. ===== Boot FreeBSD ===== To boot using u-boot, install [[https://www.freshports.org/sysutils/u-boot-qemu-riscv64|sysutils/u-boot-qemu-riscv64]]. qemu-system-riscv64 -machine virt -smp 2 -m 2048 -nographic \ -bios /usr/local/share/opensbi/lp64/generic/firmware/fw_jump.elf \ -kernel /usr/local/share/u-boot/u-boot-qemu-riscv64/u-boot.bin \ -drive file=/path/to/riscv.img,format=raw,id=hd0 \ -device virtio-blk-device,drive=hd0 The %%FreeBSD%% kernel can also be booted directly, skipping the u-boot and ''%%loader(8)%%'' stages. This can be useful for quicker turnaround during kernel development, but is in general less flexible compare to u-boot. qemu-system-riscv64 -machine virt -smp 2 -m 2048 -nographic \ -bios /path/to/opensbi/fw_jump.elf \ -kernel /path/to/freebsd/kernel \ -drive file=/path/to/riscv.img,format=raw,id=hd0 \ -device virtio-blk-device,drive=hd0 ===== Networking ===== There are two main networking backends offered by QEMU, user and tap. User-mode networking requires almost no configuration, but tap based networking offers better performance, and allows the guest to obtain its own IP address on the network. ==== Configure tap(4) (Optional) ==== If using tap(4) for networking (as opposed to user-mode networking), you will need to load the (tun)tap module(s) if not already loaded. If %%FreeBSD%% >= 13: sudo kldload if_tuntap Else: sudo kldload if_tun if_tap Configure the network with tap(4): ifconfig tap0 create up ifconfig bridge0 create up ifconfig bridge0 addm em0 addm tap0 # em0 might depend on your ethernet device ==== User Networking ==== Add the following arguments to the QEMU commandline: -netdev user,id=net0,ipv6=off,hostfwd=tcp::8022-:22 -device virtio-net-device,netdev=net0 This will forward port 8022 on the host to port 22 in the guest, meaning you can connect via ssh(1): $ ssh -p 8022 root@localhost ==== Tap Networking ==== Add the following arguments to the QEMU commandline. # ifname points to your tap device of choice -netdev tap,ifname=tap0,script=no,id=net0 -device virtio-net-device,netdev=net0 ===== Tips & Tricks ===== ==== Commandline arguments ==== You can specify kernel commandline arguments via QEMU's ''%%-append%%'' option. For example: -append "-v vfs.root.mountfrom=/dev/vtbd1p3" The ''%%-v%%'' argument enables verbose boot messages, while the variable assignment instructs the system to attempt to mount root from ''%%/dev/vtbd1p3%%''. These will be ignored if booting with loader(8).