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
Install QEMU, KVM, and libvirt

To install uvtool you will need to run:

sudo apt-get install -y uvtool
Install uvtool


To install support for RISC-V emulation you will need to run:

sudo apt-get install -y qemu-system-misc u-boot-qemu
Install RISC-V emulation support

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:

  1. 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'
    
  2. 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
    
  3. Delete the folder /usr/lib/python3/dist-packages/uvtool/libvirt/__pycache__

  4. 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
Download the Cloud Image of Ubuntu 22.04 for RISC-V 64

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)
Show downloaded Ubuntu Cloud Images

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 using ssh-keygen.
  • I have created a Netplan configuration file at /tmp/myvm-net.yaml for myvm 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
Example Netplan configuration file for the VM

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
Ubuntu 22.04 RISC-V Login MOTD

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
Ubuntu 22.04 VM Emulated RISC-V CPU Details