Ubuntu RISC-V 64 Guest on an x86_64 KVM Host
Ubuntu's uvtool utility is fantastic for easily creating small Cloud VMs (Virtual Machines). Sadly, it didn't yet support creating VMs that provide RISC-V emulation on x86_64 hosts. However, with a little bit of patching to Ubuntu 22.04's uvtool
package, I was able to get it to create an (emulated) RISC-V Ubuntu 22.04 KVM guest VM.
My Host system was:
- Intel Xeon E5-1650v3
- Ubuntu 22.04.3 LTS
- QEMU emulator version 6.2.0 (installed from Ubuntu's apt)
- libvirt 8.0.0-1 (installed from Ubuntu's apt)
- uvtool 0~git178-0 (installed from Ubuntu's apt)
If you don't already have QEMU, KVM, and libvirt installed you will need to run:
sudo apt install -y cpu-checker qemu qemu-kvm libvirt-daemon libvirt-clients bridge-utils dnsmasq
To install uvtool you will need to run:
sudo apt-get install -y uvtool
To install support for RISC-V emulation you will need to run:
sudo apt-get install -y qemu-system-misc u-boot-qemu
Patching uvtool to Support riscv64 Emulation
The latest version of uvtool (version 0~git178-0) at the time of writing does not support emulation of riscv64 via QEMU. However, by applying my patches you can get this work.
If you are familiar with Git and Python, you can find my patches here: https://code.launchpad.net/~adam-retter/ubuntu/+source/uvtool/+git/uvtool/+merge/457260
If you are not, then you can take the following steps to apply my changes manually:
-
Make a backup of the file:
/usr/lib/python3/dist-packages/uvtool/libvirt/kvm.py
, and then make the following changes to the original by replacing:if target_arch == 'armhf': return '/usr/share/uvtool/libvirt/template-emu-armhf.xml'
with:
if target_arch == 'armhf': return '/usr/share/uvtool/libvirt/template-emu-armhf.xml' if target_arch == 'riscv64': return '/usr/share/uvtool/libvirt/template-emu-riscv64.xml'
-
Make a backup of the file:
/usr/lib/python3/dist-packages/uvtool/libvirt/__init__.py
, and then make the following changes to the original by replacing:'ppc64le': 'ppc64el',
with:
'ppc64le': 'ppc64el', 'riscv64': 'riscv64',
and, by replacing:
# early exit on not supported emulations if target_arch != 'armhf': return False
with:
# early exit on not supported emulations if target_arch != 'armhf' and target_arch != 'riscv64': return False
-
Delete the folder
/usr/lib/python3/dist-packages/uvtool/libvirt/__pycache__
-
Create the following file at
/usr/share/uvtool/libvirt/template-emu-riscv64.xml
:<domain type='qemu'> <os> <type arch='riscv64' machine='virt'>hvm</type> <kernel>/usr/lib/u-boot/qemu-riscv64_smode/uboot.elf</kernel> <cmdline>root=/dev/vda1</cmdline> <boot dev='hd'/> </os> <features> <acpi/> </features> <devices> <emulator>/usr/bin/qemu-system-riscv64</emulator> <interface type='network'> <source network='default'/> <target dev='vnet0'/> </interface> <console type='pty'> <target type='serial' port='0'/> </console> </devices> </domain>
Creating a riscv64 Emulated KVM Guest with uvtool
First, we will use uvtool to download a Cloud Image of Ubuntu 22.04 (Jammy Jellyfish) for RISC-V 64, this can be done by running:
sudo uvt-simplestreams-libvirt sync arch=riscv64 release=jammy
After that completes, you can check that you have successfully downloaded the image by running the following command and observing the output:
sudo uvt-simplestreams-libvirt query
release=jammy arch=riscv64 label=release (20231211)
To create an emulated RISC-V 64 KVM guest with uvtool
, you need to pass the argument --guest-arch riscv64
to its uvt-kvm
command. For example:
sudo uvt-kvm create \
--guest-arch riscv64 --cpu 2 --memory 16384 --disk 40 \
--bridge virbr1 --network-config /tmp/myvm-net.yaml \
--ssh-public-key-file /tmp/ssh/myvm.pub \
myvm \
arch=riscv64 release=jammy label=release
You may need to vary the above configuration depending on your network settings:
- I already have
virbr1
configured as a virtual network bridge on the host. - I have already generated an SSH key-pair at
/tmp/ssh
usingssh-keygen
. - I have created a Netplan configuration file at
/tmp/myvm-net.yaml
formyvm
that will be deployed by cloud-init when the VM first boots:
version: 2
ethernets:
enp1s0:
addresses:
- 10.0.0.10/32
- fc00:10:0:0::10/128
nameservers:
addresses:
- 10.0.0.253
- fc00:10:0:0::253
search:
- home.dom
routes:
- to: 0.0.0.0/0
via: 10.0.0.254
on-link: true
- to: "::/0"
via: "fc00:10:0:0::254"
on-link: true
After uvt-kvm
completes successfully we can check the status of the VM, by running:
virsh list --all
Id Name State
-----------------------------
1 myvm running
You can then observe the console of the VM by running: virsh console myvm
, or by SSH'ing to the IP address of the VM using the SSH key-pair previously generated and the username ubuntu
, e.g. ssh -i /tmp/ssh/myvm ubuntu@10.0.0.10
. After logging, in you will see a banner like this:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.19.0-1021-generic riscv64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Mon Dec 11 18:28:49 UTC 2023
System load: 0.15380859375
Usage of /: 4.1% of 38.60GB
Memory usage: 1%
Swap usage: 0%
Processes: 101
Users logged in: 0
IPv4 address for enp1s0: 10.0.0.10
IPv6 address for enp1s0: fc00:10:0:0::10
Finally, running uname -av
and cat /proc/cpuinfo
confirms that this is indeed a RISC-V 64 system:
uname -av
Linux blackberry 5.19.0-1021-generic #23~22.04.1-Ubuntu SMP Thu Jun 22 12:49:35 UTC 2023 riscv64 riscv64 riscv64 GNU/Linux
cat /proc/cpuinfo
processor : 0
hart : 0
isa : rv64imafdc
mmu : sv48
processor : 1
hart : 1
isa : rv64imafdc
mmu : sv48