Skip to content

M6: macOS, Windows, Arm, RISC-V #7

Open

Description

@tamnd

The seventh milestone in spec/23-milestones.md. macOS, Windows, Arm and RISC-V, and the desktop.

Why

Developers on Apple silicon and Windows are the second largest group, and they arrive with a desktop, so the UIs arrive with them.

Accelerators

Machines

JIT

  • RISC-V guest including RVV and the H extension
  • riscv64 host backend

UI and audio

  • Cocoa, GTK, SDL, VNC and the D-Bus display
  • Audio backends for those hosts

Exit criterion

  1. On macOS AArch64, a Linux aarch64 guest and Windows 11 on Arm boot under HVF with virtio-gpu and graphical output.
  2. On Windows x86-64, a Linux guest boots under WHPX.
  3. A RISC-V Linux guest boots under TCG on every tier 1 host.
  4. QEMU's qtest suites for aarch64 and riscv64 pass at QEMU's rate for these machines, and tests/tcg for riscv64 passes.

Depends on

M4.

Spec

spec/06-accelerators.md, spec/09-guest-targets.md, spec/11-machines-and-firmware.md, spec/15-net-chardev-ui-audio.md.

Activity

  1. added
    status/gateHas an exit criterion that decides whether the milestone is done.
    kind/milestoneA milestone from spec/23-milestones.md.
    area/hvfThe Hypervisor.framework accelerator.
    area/whpxThe Windows Hypervisor Platform accelerator.
    area/machineMachine types, boards, ACPI, device trees, firmware.
    area/uiDisplays, input, audio.
    on Sep 30, 2026
  2. tamnd commented on Oct 7, 2026

    @tamnd
    OwnerAuthor

    #157 is merged, the first M6 slice. There is now a RISC-V guest on TCG (RV64GC with M, S and U modes, Sv39/48/57 paging, PMP and the Zb* extensions) and a riscv -M virt board with the PLIC, ACLINT, UART, virtio-mmio, fw_cfg, RTC, the test finisher, OpenSBI loading and a device tree.

    All five riscv64 system tests from QEMU's tests/tcg (issue1060, test-mepc-masking, doubletrap, interruptedmemory, test-crc32) exit with code 0 with QEMU's own options.

    No boxes ticked yet, since RVV, the H extension, AIA, PCIe and ACPI are still missing. Next is a RISC-V Linux kernel booting to a shell on an x86-64 host and on an aarch64 host. After that I'll compare the device tree against real QEMU once the server's QEMU 11.1 build finishes.

  3. tamnd commented on Oct 7, 2026

    @tamnd
    OwnerAuthor

    #158 is merged. A Debian 6.12 riscv64 kernel now boots to a busybox shell under TCG on -M virt with OpenSBI, at 1, 2 and 4 vCPUs, on an x86-64 host and on an aarch64 host (Apple M4 in colima). Median time to the prompt is 13.9 to 19.9 s on a shared x86-64 server and 8.3 to 10.9 s on the M4. Getting there fixed a lock order deadlock that hit every boot with more than one vCPU. That covers exit criterion 3 for the Linux hosts. RVV and the H extension are next.

  4. added a commit that references this issue on Oct 7, 2026
  5. tamnd commented on Oct 7, 2026

    @tamnd
    OwnerAuthor

    Released v0.4.1, which includes #157 and #158.

  6. tamnd commented on Oct 7, 2026

    @tamnd
    OwnerAuthor

    #161 is in. The riscv guest now has the vector extension (V, the Zve subsets, Zvfh and the bf16 vector extensions) with the full vector crypto set, and the H extension with two-stage translation, the hypervisor CSRs, HLV, HLVX and HSV, and VS interrupt routing. H is on by default and V is opt in with -cpu rv64,v=on, both as in QEMU 11.1. A bare metal H test prints the same 251 lines on ruvm and QEMU, and Linux reports rv64imafdch at -smp 2. Still left on riscv virt: guest external interrupts and AIA, the PCIe host bridge, ACPI, -cpu max, and closing the 1.7x gap to QEMU on the boot to a shell.

  7. tamnd commented on Oct 7, 2026

    @tamnd
    OwnerAuthor

    Released 0.4.2 (https://github.com/tamnd/ruvm/releases/tag/v0.4.2) with the RVV and H work from #161. Next on riscv virt: the PCIe host bridge, -cpu max and AIA.

  8. tamnd commented on Oct 7, 2026

    @tamnd
    OwnerAuthor

    #163 is in. riscv virt now has QEMU's generic PCIe host bridge (gpex) at the same addresses as QEMU 11.1, and -device virtio-{blk,rng,serial}-pci and -drive if=virtio work behind it. Against QEMU on the same command line the device tree differs only in rng-seed, the config space of every function is byte for byte the same, and Linux puts the virtio devices on the same PLIC lines. The "riscv virt with AIA, PCIe and ACPI" box stays open until AIA and ACPI land. -cpu max and the named riscv CPU models are next.

  9. 76 remaining items

  10. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    Merged #305, which adds query-cpu-model-expansion on Arm and takes sve, the sve<N> vector lengths, pmu and aarch64=on in -cpu the way QEMU does, including length maps with gaps such as the one sve512=on gives. 330 expansion requests under 8 -cpu settings, with TCG and with the qtest accelerator, and the startup errors of 19 -cpu strings gave the same answers as QEMU 11.1. The qtest counts are unchanged at 73 of 447 on aarch64 and 79 of 241 on riscv64, because arm-cpu-features still stops at gic-version=max, which is next.

  11. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #307 merged: gic-version on Arm virt now takes max and host like QEMU 11.1, and x-5 replaces 5. Under TCG and qtest max picks GICv3, and host fails with "gic-version=host requires KVM". arm-cpu-features now passes 3/3 against ruvm, the same as QEMU.

    Counts in docs/qtest-status.md: aarch64 passes 76 of 447 test cases, riscv64 passes 79 of 241.

    Next: device vmstate for the Arm virt board (pl011, pl031, pl061, gpio-key), the first step toward migration-test on virt.

  12. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #310 merged: the PL011, PL031, PL061 and GPIO key of Arm virt now save and load the pl011, pl031, pl061 and gpio-key sections QEMU 11.1 sends, checked byte for byte against a stream QEMU wrote for virt. The board does not register them yet, so no count changes: aarch64 76 of 447, riscv64 79 of 241.

    Next, in small PRs: the migration stream with the timer, RAM and globalstate sections on virt, then the CPU state, then the GIC, then the devices. Separately, a docs PR moves the qmp-cmd-test rows to the stock test against a QEMU build with VNC.

  13. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #311 merged. virt on TCG now migrates with QEMU 11.1's timer, ram and globalstate sections and the configuration section (virt-11.1, target-page-bits 12, uuid). The RAM block list has mach-virt.ram, virt.flash0 and virt.flash1 in QEMU's order, and QEMU's analyze-migration.py reads the stream ruvm writes. The PL011, PL031, PL061 and GPIO key from #310 are not registered with the board yet.

    Counts are unchanged: aarch64 76 of 447, riscv64 79 of 241. migration-test still stops at its first case because ruvm refuses x-ignore-shared. That is the next PR.

  14. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #314 merged: migration now takes the x-ignore-shared capability, and with it each RAM block in the setup list carries its guest address, as QEMU 11.1 writes it. I compared the configuration section and the block list of a virt stream from ruvm with one from QEMU 11.1 byte for byte; they match apart from the three /rom@etc ACPI blocks QEMU has and ruvm does not have yet.

    In migration-test the analyze-script case now passes. The next case (multifd) still hangs, because the destination runs its vCPUs from reset until the CPU state slice lands, which is what I am on now.

    Counts: aarch64 77 of 447, riscv64 79 of 241.

  15. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #315 merged: the qmp-cmd-test rows now come from the stock test of a second QEMU 11.1 build with --enable-vnc --enable-pixman, instead of a patched copy of the test. That build's test passes 61 of 61 against its own QEMU and 64 of 64 against ruvm on both targets. The three extra cases are the TPM queries, which ruvm answers and which QEMU built with --without-default-features leaves out of its schema.

    Counts: aarch64 124 of 449, riscv64 126 of 243.

  16. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #320 merged: virt on TCG now migrates its vCPUs in QEMU 11.1's cpu_common and cpu sections, with the same 362 register indexes and the same subsections QEMU sends for max. The streams still differ in a few reset values and in the ID registers, as written in docs/qtest-status.md.

    Counts are unchanged: aarch64 124 of 449 and riscv64 126 of 243. migration-test stays at 1 of 12 on the debug build. Its multifd case now moves the guest and the destination goes on running, but a debug build is too slow for the 480 s timeout, so I will count it with a release build. The GICv3 and ITS sections are next.

  17. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #322 merged: virt on TCG now migrates the GICv3 and its ITS in QEMU 11.1's arm_gicv3 and arm_gicv3_its sections, with QEMU's section ids and stream order. For -cpu max with -S both sections match QEMU field for field apart from the NMI subsections, which QEMU sends because its max has FEAT_NMI. A guest migrated over TCP between two ruvm processes keeps running on the destination.

    Counts are unchanged: aarch64 124 of 449 and riscv64 126 of 243. migration-test stays at 1 of 12 until I count it with a release build. Next is the generic timer counter, which should follow the migrated virtual clock as QEMU's does.

  18. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #324 merged: the Arm generic timers and the PMU cycle counter now count the board's virtual clock, which stops while the VM is stopped and which the timer section carries. A Linux guest moved with migration goes on with its uptime on the destination, as it does under QEMU 11.1. migration-test was counted with a release build this time: 5 of 12 pass (analyze-script, multifd/tcp/plain/zlib, multifd/tcp/plain/cancel, multifd/tcp/uri/plain/none, multifd/file/mapped-ram/dio). postcopy/plain fails because ruvm does not take the postcopy-blocktime capability yet, and the test bails out there. qtests now pass: aarch64 128 of 449, riscv64 126 of 243. Next is postcopy-blocktime, so the postcopy cases can run.

  19. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #325 merged: ruvm takes the postcopy-blocktime capability and reports the blocktime and latency of the destination as QEMU 11.1 does. postcopy/plain now passes, so migration-test gives 6 of 12 on aarch64. The next case, postcopy/recovery/plain, fails on migrate-pause, as ruvm has no postcopy recovery yet. Counts with a release build on server2: aarch64 129 of 449, riscv64 126 of 243. docs/qtest-status.md has the details.

  20. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #328 merged: virt now migrates its PL011 UARTs, PL031 RTC, PL061 GPIO controllers and GPIO power key, in the order QEMU 11.1 creates them, and keeps the section ids of the PCI host, ACPI GED, fw_cfg and ACPI table sections it does not send yet. #327 landed between my checks and the merge, so I rebuilt the merged main (23f8031) on server2 and ran the compare again: against QEMU 11.1 the section names, instances and ids match for the default board, with two -serial and with secure=on, and the four device sections match field for field apart from the time the RTC holds. migration-test on aarch64 stays at 6 of 12, failing at postcopy/recovery/plain on migrate-pause. The other counts are unchanged from the last full run: aarch64 129 of 449, riscv64 126 of 243. Next: the two pflash_cfi01 sections.

  21. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #335 merged: virt now migrates its two CFI01 flashes in QEMU 11.1's pflash_cfi01 sections (ids 3 and 4), with the pflash_cfi01_blk_write subsection while a write to buffer is in progress. Against QEMU 11.1 with a raw guest, the flash sections match byte for byte in status mode and in a stopped write to buffer, a ruvm destination passes the same state on, and a destination with a flash image writes the migrated contents back. Checked on 01b3b12 plus the diff, which is the merged commit.

    Counts are unchanged: aarch64 129 of 449, riscv64 126 of 243. migration-test on aarch64 stays at 6 of 12, and a Linux guest migrated between two ruvm instances keeps running.

    Also #334 fixes x86::tests::vfio_pci_properties, which #330 broke on Linux.

    Next: the PCI host sections (gpex_root, PCIHost, PCIBUS), then fw_cfg and the ACPI blocks.

  22. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #338 is merged (debd8d2). virt now migrates its PCI host in QEMU 11.1's 0000:00:00.0/gpex_root, PCIHost and PCIBUS sections. They match QEMU byte for byte with one serial port, with two, with secure=on, and after a raw guest has run for a second. A Linux guest moved mid-run keeps going on the destination with its uptime counting on. The remaining virt sections are fw_cfg and virt_acpi_build, plus the PCI devices and the /rom@etc blocks.

    Counts are unchanged: aarch64 129 of 449, riscv64 126 of 243, and migration-test on aarch64 6 of 12 (release build).

  23. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #340 merged as ad204ac. virt on TCG now migrates fw_cfg (with the fw_cfg/acpi_mr subsection, also on q35) and virt_acpi_build, and both match QEMU 11.1 byte for byte with one and two serials, secure=on and acpi=off. Without firmware the stream now has every section QEMU 11.1 sends for virt.

    Counts are unchanged: aarch64 129 of 449, riscv64 126 of 243, migration-test 6 of 12 on a release build.

    Checks rerun on ad204ac itself on server2: clippy -D warnings clean for hw-core, machine-arm, machine-x86 and system; ruvm-system lib 113 passed, hw-core 44 passed, machine-arm lib 36 and tests/virt 42 passed, machine-x86 lib migration 35 passed.

  24. tamnd commented on Oct 14, 2026

    @tamnd
    OwnerAuthor

    #342 merged as 8fb1fee. virt on TCG now migrates its ACPI GED in QEMU 11.1's acpi-ged section with the acpi-ged/memhp subsection. With -bios the section matches QEMU's, and so do the ids of fw_cfg, virt_acpi_build and globalstate after it. So with or without firmware, the stream now has every section QEMU 11.1 sends for virt. The GED and memory hotplug descriptions now live in ruvm_hw_acpi::vmstate, shared with microvm.

    The counts haven't changed: aarch64 129 of 449, riscv64 126 of 243, and migration-test 6 of 12 on a release build. postcopy/recovery/plain still fails first.

    I ran these on e7c7db9 plus the change, which is the tree that merged:

    • The release compare against QEMU 11.1 for firmware, the default board and acpi=off.
    • migration-test.
    • A Linux guest migrated between two ruvm instances, which kept running on the destination.

    The ship hook ran on the same tree and passed:

    • clippy -D warnings and the tests for hw-acpi, machine-arm, machine-x86 and system.
    • cargo check --workspace.
    • The xtask checks and the Windows check.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/hvfThe Hypervisor.framework accelerator.area/machineMachine types, boards, ACPI, device trees, firmware.area/uiDisplays, input, audio.area/whpxThe Windows Hypervisor Platform accelerator.kind/milestoneA milestone from spec/23-milestones.md.priority/p2Real, and it waits.status/gateHas an exit criterion that decides whether the milestone is done.

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions