Two glowing green and cyan lines tracing the CPU load of a RISC-V virtual machine over ten minutes, on a black background.

CPU usage of a RISC-V guest, as Xen Orchestra graphed it.

XCP-ng and Xen Orchestra on RISC-V: a progress report from the emulator

RISC-V Oct 23, 2026

In November 2025, at KubeCon in Atlanta, we showed XCP-ng on Ampere: an Ampere Altra-based System76 Thelio Astra running XCP-ng, managed by Xen Orchestra. In October we set ourselves the same goal on RISC-V: a host that Xen Orchestra can manage, and a guest on it running containers: Docker first, then Kubernetes with K3s.

In QEMU, we got there. Xen Orchestra lists the RISC-V host and its VMs, opens their consoles, shows their stats, starts and stops them. A Debian guest on that host runs Docker, and K3s reports Ready about a minute after starting. As a bonus, the same guest shows an XFCE desktop in Xen Orchestra's console tab.

Before anyone gets excited: unlike the Arm demo, all of this runs in QEMU, emulated on an x86 machine. We have not run this full stack on a RISC-V board yet. This is a prototype: research and development, not a tech preview, and this post is a progress report rather than an announcement.

Where this work sits

Baptiste Le Duc and Oleksii Kurochko have been porting the Xen hypervisor itself to RISC-V for a while now, and this blog has followed them: Xen booted a guest on real RISC-V hardware in September. Then Zheng Zhang (ISCAS, Institute of Software, Chinese Academy of Sciences) took those patches and booted Xen on his own SpacemiT K3, the first RVA23 board Xen runs on.

A hypervisor is not a virtualization platform, though. XCP-ng is Xen plus a dom0 with its whole package set, plus XAPI, the toolstack that Xen Orchestra talks to. Baptiste's trees already carry the RISC-V Xen, the RISC-V toolstack (XAPI, xenopsd, xenguest), the dom0 kernel, and the dom0 image build. Since early October, we have been working on the layer around them: package that stack for riscv64, boot it, fix what breaks along the way, and get Xen Orchestra to manage the result.

A word on method: I built much of this with heavy help from AI coding assistants, so expect parts of it to change as the patches go through upstream review.

What works today

The stack runs in QEMU with 3 harts and 5 GiB of RAM. The dom0 is AlmaLinux Kitten running the riscv64 RPMs of our latest build round, round 19, Xen and the dom0 kernel included. Xen Orchestra 6.9.1 is a riscv64 build of its own (gounthar/xen-orchestra-riscv64). On October 20th, on that round, it gave:

  • the host and its VMs in the inventory
  • host and VM consoles
  • host and VM stats (the graphs are in the XO 5 interface, which XO 6 links to)
  • start, clean shutdown, force shutdown, and start again
  • a Debian 13 (trixie) guest with a disk on a storage repository and a network that reaches the internet
  • an XFCE desktop in the VM's console tab
Figure 1. A Debian 13 RISC-V guest booting to a login prompt, in the Xen Orchestra 6 console.
Figure 2. CPU, memory, network, and disk statistics for the same guest, in Xen Orchestra 5.

Inside that guest, on a kernel built with the container options, Docker runs riscv64 containers and K3s reports Ready.

There are still rough edges. On one start, Xen Orchestra showed no IP address for the guest for more than five minutes, although the guest had its lease after 24 seconds. Xen Orchestra reports the guest's disk as 1 GiB when the guest sees 8 GiB, and Docker pulls sometimes need a retry.

The packages are public, as experimental and unsigned releases in gounthar/xcpng-riscv64-rpms: 19 build rounds so far, published from round 10. They come from Yann Dirson's meta-xcpng BitBake layer, with a riscv64 port of ours on top that is not part of his layer. In a riscv64 AlmaLinux Kitten container, with the Kitten repositories and the latest round, dnf install xen-hypervisor xen-tools kernel-xcpng-riscv64 xcp-networkd xcp-ng-release-config resolves and installs. That proves the packaging, not that the stack runs. Like the Xen Orchestra build, these packages are a personal, unsupported, and not production-ready project.

Starting a VM twice in one boot

For the first few days, we could start exactly one VM per boot. Shut it down, and the next start never ran.

The dead guest was never freed, and it took a fix on each side. In Xen, the RISC-V functions that release a dead domain's resources were still stubs, and foreign mappings never dropped the page reference they take. In the dom0 kernel, the function that should unmap a guest's pages returned success without telling Xen anything, so about 28 MB of every dead guest stayed pinned. With both fixes, we ran three start, shutdown, start cycles in a row, and free memory came back to its baseline each time. Both fixes are merge requests on Baptiste's trees, waiting for his review.

Getting the guest on the network

No network, no container images, so this one was on the way to Docker. The first networked guest gave up right away: grant table add_to_physmap failed, err=-38. -38 is ENOSYS. Xen on RISC-V did not yet implement the call a guest uses to grow its grant table, and a network frontend needs 512 grants to start. The Arm port has that case; RISC-V did not.

We expected one patch and needed three: the missing case in Xen, a scratch page for grant seeding in libxenguest, and an init function in the RISC-V Linux port that returned an error and stopped grant table setup halfway. After those, the guest was able to ping the dom0, and later reached the internet. These are also merge requests on Baptiste's trees, waiting for review.

A desktop in the console tab

Both consoles in Xen Orchestra (XO) were text-only at first. Julian Vetter had already solved this for the Arm port, so we borrowed his approach: QEMU runs in dom0 only as a Xen PV backend, the guest uses Xen's PV framebuffer, and Xen Orchestra connects to it like any other console. On RISC-V that meant building a riscv64 QEMU from his XCP-ng QEMU branch plus two RISC-V patches, teaching xenopsd's RISC-V builder to start it, and enabling the keyboard and mouse frontend in the guest kernel. Then platform:vfb=true on the VM, and XFCE shows up in the console tab.

Figure 3. An XFCE desktop on a RISC-V guest, in the Xen Orchestra 6 console tab. uname -a reports riscv64.

One fix that came from upstream

For a while, Xen Orchestra would lose the RISC-V pool every time XAPI was restarted, and only a restart of xo-server would bring it back. We didn't have to fix that one ourselves: Xen Orchestra 6.9.0 fixed it. Since we updated, xo-server reconnects on its own, about 20 seconds after a XAPI restart.

What emulation costs

QEMU emulating RISC-V on x86 is slow, and it shows. That minute for K3s is emulation time; a guest reads its disk at about 800 KB/s, and a clean shutdown takes about 20 seconds. The packages are built under emulation too: the OCaml build alone takes 72 minutes. None of those figures say anything about RISC-V hardware. They only explain why we want to switch to using a real hardware board.

What's next

Three directions, none of them dated:

  • Real RISC-V hardware. Our boot path still assumes QEMU's virtual machine layout. Booting the full stack on a board, as our Arm demo did on Ampere, is the next milestone.
  • Upstreaming. Our patches go to Baptiste's Xen, Linux, and toolstack trees first, for review, then upstream from there. Some are merged in his trees; most are still waiting.
  • Reproducible package builds. Native builds on a RISC-V board instead of emulation, and a riscv64 port that fits meta-xcpng cleanly.

How to help

You don't need a RISC-V board to contribute. Start with the packages: in a riscv64 AlmaLinux Kitten container, download the latest round and install it as a local repository, as the repository's README shows and run the install command above. That only proves they install, but a dependency that does not resolve or a file in the wrong place is a bug, and telling us about it on the forum is already a contribution. If you know RISC-V, virtualization, or packaging, you are welcome to review Baptiste's Xen tree, Linux tree, and xen-api fork.

Tags

Bruno Verachten

Along with Baptiste Le Duc, Yann Sionneau, Julian Vetter

Community Manager & Technical Evangelist at Vates (XCP-ng, Xen Orchestra), because hypervisors deserve better word-of-mouth than "it's like VMware but free." Ex-Jenkins contributor, RISC-V obsessive, beekeeper, permie, father of two.