Commit Graph

11071 Commits

Author SHA1 Message Date
Isaku Yamahata
9d3451a56a vmm: Fix aarch64 vmm::vm::unit_tests::test_create_fdt_with_devices()
test_create_fdt_with_devices() fails with a divide by zero.  The caller
passes Some((0, 0, 0, 0)) for CPU topology as (threads_per_core,
cores_per_die, dies_per_package, packages).  The valid default is
(1, 1, 1, 1), not all zero. Pass None because the eventual callee,
create_cpu_nodes(), checks None to get the right default value.

This affects the unit test only.  A real VM never hits it because
VmConfig::validate() rejects zero with an error.

Fixes: 7fb980f17 ("arch, vmm: Pass cpu topology configuation to FDT")
Assisted-by: Claude:Opus-4.8 (1M context)
Signed-off-by: Isaku Yamahata <iyamahata@crusoe.ai>
2026-07-22 08:53:04 +00:00
Alexander Lvov
013604319d block: vhdx: validate buffer length against logical sector size
Reject buf.len() that isn't sector_count * logical_sector_size in
io::read/write (VhdxIoError::InvalidBufferLength), and reject buf.len()
not a multiple of the sector size in Vhdx's Read/Write impl, before it's
converted to a sector count/index.

Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
2026-07-21 13:36:25 +00:00
Alexander Lvov
8d6a38770f block: vhdx: restrict logical sector size to 512 bytes
cloud-hypervisor always advertises a 512-byte logical block size over
virtio-blk, so a 4096-byte-sector VHDx image could never be addressed
correctly. Reject it at metadata parse time, matching QEMU's VHDx
support.

Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
2026-07-21 13:36:25 +00:00
Alexander Lvov
d414127b08 block: vhdx: fix I/O slice length to use the real logical sector size
io::read/write sliced buf using free_sectors * SECTOR_SIZE, a hardcoded
512-byte constant, instead of the file's real logical sector size
([MS-VHDX] allows 512 or 4,096). On a 4096-byte-sector image, only the
first 512 bytes of each sector were transferred while the full 4096 was
reported as done.

Use sector.free_bytes instead.

Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
2026-07-21 13:36:25 +00:00
Anatol Belski
4f9fcfa22b block: raw: Route aio and uring bounce through the vectored API
Reimplement run_unaligned_operation over AlignedFile read_vectored_at
and write_vectored_at instead of scattering and gathering through the
per operation write_bytes_at and read_bytes_at closures. The aio and
uring engines already reach this helper for the O_DIRECT misaligned
case, so both now share the same vectored bounce path as the sync
engine and the scatter gather logic lives only in AlignedFile.

The operation iovecs point at the same memory that write_bytes_at and
read_bytes_at reach, and the aligned fast path already hands those
iovecs to the kernel, so the direct vectored call is equivalent. For
guest memory read targets the destination pages are marked dirty by
mark_read_dirty in execute_async before the operation is submitted,
independent of how the bounce copies bytes, so the raw iovec path
preserves dirty tracking. Drop the now unneeded mut bindings at the
call sites.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-21 08:37:00 +00:00
Anatol Belski
441eb0671a block: Test AlignedFile vectored positioned I/O
Cover the empty iovec noop, the fast path where iovecs go straight to
preadv or pwritev, and misaligned O_DIRECT scatter and gather across
multiple iovecs including a partial block read-modify-write.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-21 08:37:00 +00:00
Anatol Belski
206cb1e100 block: raw: Add vectored positioned I/O to AlignedFile
Add read_vectored_at and write_vectored_at to AlignedFile. They take
the aligned fast path with a single preadv or pwritev when the offset
and every iovec base and length satisfy the O_DIRECT alignment, and
otherwise bounce through an AlignedBuffer, scattering on read and
gathering with a read-modify-write on write.

Convert the raw sync engine to these methods and drop its raw preadv
and pwritev block. The methods are unsafe because their soundness
depends on the caller passing iovecs that describe valid memory for
iov_len bytes.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-21 08:37:00 +00:00
Rob Bradford
3cd8abcd8c vmm: cpu: Ensure guest eject is for expected vCPU
CPU unplug requires co-operation between the guest and the VMM. Ensure
that the CPU the guest marks for eject is the one the VMM expects to be
removed. If the guest were to remove a different vCPU there would be
unexpected behaviour. Further ensure that the boot vCPU is never
unplugged.

Signed-off-by: Rob Bradford <rbradford@meta.com>
2026-07-21 08:36:37 +00:00
dependabot[bot]
061b2cda60 build(deps): bump actions/setup-python from 6 to 7
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 00:39:06 +00:00
Alyssa Ross
cd2089eb69 build: Bump vm-memory and dependents
vm-memory 0.18 has renamed GuestMemory to GuestMemoryBackend, and made
GuestMemory refer to something less specific.  For simplicity, we keep
using GuestMemoryBackend (formerly GuestMemory) everywhere for now.  We
can adjust bounds to be less specific later if we find ourselves needing
the newly enabled flexibility.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
Signed-off-by: Rob Bradford <rbradford@meta.com>
2026-07-20 17:51:23 +00:00
Pascal Scholz
1a1c21024a docs: Include description for zone_updates parameter
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-20 16:06:55 +00:00
Pascal Scholz
69e7d53a5f openapi: Update OpenAPI doc to include zone_updates parameter
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-20 16:06:55 +00:00
Pascal Scholz
ec304f6d50 vmm: Improve VmReceiveMigrationConfigError with additional variants
All error cases used `ValidationError` with a String containing context
about the error. This is suboptimal as the error kind itself does not
contain any context about the actual failure cause. Furthermore, this
does not allow to build error chains as underlaying errors are replaced
with the respective message string.

We improve the situation by introducing specific error variants for
failure case. This also allows us to test the respective code paths
more easily.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-20 16:06:55 +00:00
Pascal Scholz
d419338a47 vmm: Add parsing logic for zone_updates
This commit adds support for parsing `zone_updates` from the CLI
for the live migration and restore paths.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.
2026-07-20 16:06:55 +00:00
Pascal Scholz
ad3790a0ea vmm: Update memory zones
We consume `zone_updates` from `VmReceiveMigrationData` and
`RestoreConfig` to remap already existing `MemoryZone`s to different
host NUMA nodes. For now, we do not support further changes, such as
altering the size of the respective `MemoryZone`s.

These changes allow to migrate a VM to a host that has the capacity to
host the same `MemoryZone`s on a different NUMA layout.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-20 16:06:55 +00:00
Pascal Scholz
9198fcf833 vmm: Add function to update MemoryZone
We use this function in the commit directly following this one to
update the VM configuration. This commit also introduces a test.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-20 16:06:55 +00:00
Pascal Scholz
c2da8fed8e vmm: Allow receiving information about changing MemoryZones
It is possible to migrate a VM to a host that might have a different
but compatible NUMA configuration. For example, it should be possible
to move a `MemoryZone` from NUMA node 2 and 3 of the sender to nodes
0 and 1 on the receiver, given sender and receiver nodes are compatible
with respect to available memory.

In such a case, we need to adjust the mapping of guest memory to host
nodes. We need this information for live migration as well as for
snapshot (when performing cold migration). We consume this information
in the following commit.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-20 16:06:55 +00:00
Anatol Belski
febe70ae36 performance-metrics: Abort the run when a guest survives cleanup
When a test process group cannot be reaped, the host is left with an
orphaned guest whose ports and interfaces block later tests. Continuing
produces cascading failures that hide the original issue.

Treat a failed cleanup as a test error. By default the runner aborts,
and under --continue-on-failure it records the failure and keeps going.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-20 09:51:53 +00:00
Anatol Belski
b53c339388 test_infra: Reap process group synchronously in cleanup
ProcessRegistry::cleanup sent SIGKILL to a test's process group and
returned at once. SIGKILL is asynchronous, so a killed process could
still hold its boot listener socket when the next test started, causing
an EADDRINUSE bind failure.

Reap the group after the signal and wait for it to exit before
returning. Return an error if it does not exit within the timeout so a
caller can react to a guest that survived cleanup.

Since cleanup now reaps the whole group, the unit tests drop their Child
handles without waiting. They carry expect(clippy::zombie_processes),
since cleanup already reaps them.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-20 09:51:53 +00:00
CMGS
b68e7f3d91 block: flush cached qcow2 metadata on device pause
The qcow2 backend caches L2 table and refcount updates in memory and
only writes them back on a guest-initiated flush, clean shutdown or
drop. A paused VM therefore leaves the on-disk image without the
mappings for any cluster allocated since the last guest flush: the
data clusters are present in the file, but nothing references them.

Anything that reads the image while the VM is paused sees those
writes as missing. Copying the disk alongside vm.snapshot (the
documented snapshot workflow) captures a stale image, and live
migration releases the disk locks after pausing so the destination
reopens the file with the same stale metadata. In both cases writes
the guest has completed, and may later read back, silently disappear.

Add a MetadataSync capability trait with a no-op default, fold it
into FullDiskFile, implement it for the qcow2 backend as a metadata
cache flush, and call it from the virtio-block pause path after
in-flight requests have drained. Pause is the quiesce point both
flows rely on, and it is a cold path, so the extra flush does not
affect runtime I/O.

Reproduced by writing to a qcow2 disk from the guest with O_DIRECT
and no explicit flush, pausing the VM and copying the image: qemu-img
map on the copy shows no mapped clusters and reads return zeros. With
this change the copy contains every completed write. A unit test
covers the same sequence at the format level: a completed write is
invisible to a fresh reader until sync_metadata, and visible after.

Signed-off-by: CMGS <ilskdw@gmail.com>
2026-07-19 18:26:37 +00:00
Anatol Belski
320c96a9e2 tests: Cap concurrent Windows guests with a nextest profile
Each Windows integration test boots a full Windows Server guest using
several vCPUs and gigabytes of RAM. nextest runs up to one test per
logical CPU by default, so the whole suite started at once and thrashed
the host.

Add a dedicated 'windows' nextest profile that inherits from
integration and assigns the tests to a 'windows' test group capped at
four concurrent runs. Point the Windows test scripts at the profile and
drop the redundant retries flag, which now comes from the profile.

Running the tests in parallel is safe because every guest gets a unique
network via next_guest_id, so there is no shared address to conflict
over.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-19 18:24:54 +00:00
Peter Delevoryas
5b68d7694d virtio-devices: Replay in-order vhost-user queues after reconnect
When reconnecting to a vhost-user backend, Cloud Hypervisor keeps the
same queues and currently restarts them from avail_idx.

That can skip descriptors that were made available by the guest but not
completed before the old backend crashed. For queues where
VIRTIO_F_IN_ORDER was negotiated, used_idx is a safe completion
boundary, so reconnect can resume from used_idx and kick the queue if
work remains.

Do not do this when inflight tracking is active, because the backend
inflight state is the more precise recovery mechanism. Also leave queues
without VIRTIO_F_IN_ORDER on the existing avail_idx path, since used_idx
does not identify which descriptors completed for out-of-order devices.

Signed-off-by: Peter Delevoryas <pdel@meta.com>
2026-07-18 19:18:40 +00:00
Chinmoy
c070d5dfa4 virtio-devices: Abort vhost-user client connect on kill_evt
Client connect retried for a full minute on every failure and did not
watch kill_evt for early exit, unlike reconnect, so teardown and
permanent connect errors both stalled for CONNECT_TIMEOUT.

Update the client path to watch kill_evt for early abort, fail
non-retryable errors immediately, and surface timeout with a dedicated
error.

Partially Fixes #8052

Signed-off-by: Chinmoy <daschinmoyy21@gmail.com>
Assisted-by: GLM 5.2
2026-07-18 18:52:28 +00:00
Anatol Belski
9474c07526 block: sparse: Add unit tests for write_zeroes and punch_hole fallback
Exercise the EOPNOTSUPP fallback path using memfd, which shares
the same backing as tmpfs and triggers the fallback without
requiring privileges or a specific filesystem.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-18 17:47:50 +00:00
Anatol Belski
028c99b39c block: raw: Remove EOPNOTSUPP skip from test_write_zeroes
The WriteZeroesAt fallback means write_zeroes no longer fails on
filesystems that lack fallocate support. The skip is now dead
code.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-18 17:47:50 +00:00
Anatol Belski
d7a7d73622 block: Fall back to write when fallocate returns EOPNOTSUPP
Filesystems such as tmpfs do not support fallocate with
FALLOC_FL_ZERO_RANGE or FALLOC_FL_PUNCH_HOLE and return EOPNOTSUPP.
When a raw disk image lives on such a filesystem, virtio write zeroes
and discard requests fail with IOERR.

Use the WriteZeroesAt trait from vmm_sys_util through AlignedFile,
which already bundles fallocate with a positional write fallback.
For punch_hole, catch EOPNOTSUPP and fall back to the same trait.

The io_uring engine previously submitted fallocate directly through
the ring, where the async EOPNOTSUPP completion had no retry path.
Route it through the same sync helpers that the other engines
already use.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-18 17:47:50 +00:00
Sebastien Boeuf
e37f63282c net_util: Only set host MAC address from user input
In case the host MAC address associated with a TAP device wasn't
explicitly provided by the user, Cloud Hypervisor would get the host MAC
associated by default with this TAP device and store it through the
network config. Problem is, in the context of a snapshot/restore, that
meant the network config provided by the user was different on the
destination host compared to the source host. This was causing an issue
when Cloud Hypervisor wasn't started with CAP_NET_ADMIN permissions as
it couldn't set the host MAC address on the destination, while the
source never needed these permissions since the MAC was automatically
allocated by the kernel.

We're fixing this issue by setting the host MAC address when it's
explicitly requested by the user through the network config, and making
the host MAC immutable so that it can't be changed at runtime.

Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
2026-07-18 09:42:40 +00:00
Anatol Belski
b0369bf2da ci: Bump virtio-villain to v0.5.5
Further stability improvements in the villain harness keep printed
verdicts when a batch times out, stop batch timeouts from wedging
benign tests, and capture VMM stderr separately so it cannot
corrupt verdict markers, reducing spurious WEDGED results.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-17 13:38:04 +00:00
Sebastien Boeuf
1ad1de1398 vmm: Perform sparse initial memory transfer for live migration
Add sparse region support to remote live migration as it will save some
of the network bandwidth and therefore speed up the migration to the
destination VM.

Instead of sending the entire guest RAM over the network, only send
ranges which have been populated during the first iteration. Pages full
of holes are simply skipped.

Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-8
2026-07-17 12:39:03 +00:00
Leander Kohler
b67e7da10c pci: Detect masked BAR size probes
A PCI BAR stores its address in the upper bits and type information in
the lower bits. To determine the BAR size, an operating system disables
memory decoding, writes ones to the BAR's address bits, and reads the
value back. Bits that remain zero reveal the required alignment and
therefore the size.

We currently recognize only 0xffffffff as a size probe. OpenBSD instead
writes the memory BAR address mask 0xfffffff0, without setting the lower
four non-address bits [0][1].

We misinterpret that probe as a real BAR relocation. Because OpenBSD has
disabled memory space, the relocation remains pending. We apply it when
OpenBSD enables memory space again, moving the virtio block BAR away
from its mapped address and preventing the guest from booting.

Recognize probes using the address mask for each BAR type and exclude
them from BAR reprogramming. Add a test for the OpenBSD memory BAR
probe.

[0]: 54a2bc1e54/sys/dev/pci/pci_map.c (L154-L180)
[1]: 54a2bc1e54/sys/dev/pci/pcireg.h (L429-L443)

Co-authored-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
2026-07-17 11:58:32 +00:00
dependabot[bot]
668e8f789a build(deps): bump the non-rust-vmm group across 2 directories with 22 updates
Bumps the non-rust-vmm group with 14 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [jiff](https://github.com/BurntSushi/jiff) | `0.2.31` | `0.2.32` |
| [rustls](https://github.com/rustls/rustls) | `0.23.41` | `0.23.42` |
| [uuid](https://github.com/uuid-rs/uuid) | `1.23.4` | `1.23.5` |
| [zerocopy](https://github.com/google/zerocopy) | `0.8.53` | `0.8.54` |
| [crc-any](https://github.com/magiclen/crc-any) | `3.0.0` | `3.0.1` |
| [zbus](https://github.com/z-galaxy/zbus) | `5.16.0` | `5.17.0` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.66` | `1.2.67` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.8.2` | `2.8.3` |
| [regex](https://github.com/rust-lang/regex) | `1.12.4` | `1.13.0` |
| [rustc-demangle](https://github.com/rust-lang/rustc-demangle) | `0.1.27` | `0.1.28` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.22` | `1.0.23` |
| [spin](https://github.com/mvdnes/spin-rs) | `0.9.8` | `0.9.9` |
| [winnow](https://github.com/winnow-rs/winnow) | `1.0.3` | `1.0.4` |
| [zmij](https://github.com/dtolnay/zmij) | `1.0.21` | `1.0.23` |

Bumps the non-rust-vmm group with 8 updates in the /fuzz directory:

| Package | From | To |
| --- | --- | --- |
| [rustls](https://github.com/rustls/rustls) | `0.23.41` | `0.23.42` |
| [uuid](https://github.com/uuid-rs/uuid) | `1.23.4` | `1.23.5` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.66` | `1.2.67` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.8.2` | `2.8.3` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.22` | `1.0.23` |
| [spin](https://github.com/mvdnes/spin-rs) | `0.9.8` | `0.9.9` |
| [winnow](https://github.com/winnow-rs/winnow) | `1.0.3` | `1.0.4` |
| [zmij](https://github.com/dtolnay/zmij) | `1.0.21` | `1.0.23` |



Updates `jiff` from 0.2.31 to 0.2.32
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.31...jiff-static-0.2.32)

Updates `rustls` from 0.23.41 to 0.23.42
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.41...v/0.23.42)

Updates `uuid` from 1.23.4 to 1.23.5
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.23.4...v1.23.5)

Updates `zerocopy` from 0.8.53 to 0.8.54
- [Release notes](https://github.com/google/zerocopy/releases)
- [Commits](https://github.com/google/zerocopy/compare/v0.8.53...v0.8.54)

Updates `crc-any` from 3.0.0 to 3.0.1
- [Commits](https://github.com/magiclen/crc-any/compare/v3.0.0...v3.0.1)

Updates `zbus` from 5.16.0 to 5.17.0
- [Release notes](https://github.com/z-galaxy/zbus/releases)
- [Changelog](https://github.com/z-galaxy/zbus/blob/main/release-plz.toml)
- [Commits](https://github.com/z-galaxy/zbus/compare/zbus-5.16.0...zbus-5.17.0)

Updates `cc` from 1.2.66 to 1.2.67
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.66...cc-v1.2.67)

Updates `jiff-static` from 0.2.31 to 0.2.32
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.31...jiff-static-0.2.32)

Updates `memchr` from 2.8.2 to 2.8.3
- [Commits](https://github.com/BurntSushi/memchr/compare/2.8.2...2.8.3)

Updates `regex` from 1.12.4 to 1.13.0
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.12.4...1.13.0)

Updates `regex-automata` from 0.4.14 to 0.4.16
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/regex-automata-0.4.14...regex-automata-0.4.16)

Updates `rustc-demangle` from 0.1.27 to 0.1.28
- [Release notes](https://github.com/rust-lang/rustc-demangle/releases)
- [Changelog](https://github.com/rust-lang/rustc-demangle/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/rustc-demangle/compare/rustc-demangle-v0.1.27...rustc-demangle-v0.1.28)

Updates `rustversion` from 1.0.22 to 1.0.23
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.22...1.0.23)

Updates `spin` from 0.9.8 to 0.9.9
- [Changelog](https://github.com/zesterer/spin-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mvdnes/spin-rs/commits)

Updates `winnow` from 1.0.3 to 1.0.4
- [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md)
- [Commits](https://github.com/winnow-rs/winnow/compare/v1.0.3...v1.0.4)

Updates `zbus_macros` from 5.16.0 to 5.17.0
- [Release notes](https://github.com/z-galaxy/zbus/releases)
- [Changelog](https://github.com/z-galaxy/zbus/blob/main/release-plz.toml)
- [Commits](https://github.com/z-galaxy/zbus/compare/zbus_macros-5.16.0...zbus_macros-5.17.0)

Updates `zbus_names` from 4.3.2 to 4.3.3
- [Release notes](https://github.com/z-galaxy/zbus/releases)
- [Changelog](https://github.com/z-galaxy/zbus/blob/main/release-plz.toml)
- [Commits](https://github.com/z-galaxy/zbus/compare/zbus_names-4.3.2...zbus_names-4.3.3)

Updates `zerocopy-derive` from 0.8.53 to 0.8.54
- [Release notes](https://github.com/google/zerocopy/releases)
- [Commits](https://github.com/google/zerocopy/compare/v0.8.53...v0.8.54)

Updates `zmij` from 1.0.21 to 1.0.23
- [Release notes](https://github.com/dtolnay/zmij/releases)
- [Commits](https://github.com/dtolnay/zmij/compare/1.0.21...1.0.23)

Updates `zvariant` from 5.12.0 to 5.13.0
- [Release notes](https://github.com/z-galaxy/zbus/releases)
- [Changelog](https://github.com/z-galaxy/zbus/blob/main/release-plz.toml)
- [Commits](https://github.com/z-galaxy/zbus/compare/zvariant-5.12.0...zvariant-5.13.0)

Updates `zvariant_derive` from 5.12.0 to 5.13.0
- [Release notes](https://github.com/z-galaxy/zbus/releases)
- [Changelog](https://github.com/z-galaxy/zbus/blob/main/release-plz.toml)
- [Commits](https://github.com/z-galaxy/zbus/compare/zvariant_derive-5.12.0...zvariant_derive-5.13.0)

Updates `zvariant_utils` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/z-galaxy/zbus/releases)
- [Changelog](https://github.com/z-galaxy/zbus/blob/main/release-plz.toml)
- [Commits](https://github.com/z-galaxy/zbus/compare/zvariant_utils-3.4.0...zvariant_utils-3.5.0)

Updates `rustls` from 0.23.41 to 0.23.42
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.41...v/0.23.42)

Updates `uuid` from 1.23.4 to 1.23.5
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.23.4...v1.23.5)

Updates `crc-any` from 2.5.1 to 3.0.1
- [Commits](https://github.com/magiclen/crc-any/compare/v3.0.0...v3.0.1)

Updates `cc` from 1.2.66 to 1.2.67
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.66...cc-v1.2.67)

Updates `memchr` from 2.8.2 to 2.8.3
- [Commits](https://github.com/BurntSushi/memchr/compare/2.8.2...2.8.3)

Updates `rustversion` from 1.0.22 to 1.0.23
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.22...1.0.23)

Updates `spin` from 0.9.8 to 0.9.9
- [Changelog](https://github.com/zesterer/spin-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mvdnes/spin-rs/commits)

Updates `winnow` from 1.0.3 to 1.0.4
- [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md)
- [Commits](https://github.com/winnow-rs/winnow/compare/v1.0.3...v1.0.4)

Updates `zmij` from 1.0.21 to 1.0.23
- [Release notes](https://github.com/dtolnay/zmij/releases)
- [Commits](https://github.com/dtolnay/zmij/compare/1.0.21...1.0.23)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: rustls
  dependency-version: 0.23.42
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: uuid
  dependency-version: 1.23.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zerocopy
  dependency-version: 0.8.54
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: crc-any
  dependency-version: 3.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zbus
  dependency-version: 5.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.67
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: jiff-static
  dependency-version: 0.2.32
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: memchr
  dependency-version: 2.8.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: regex
  dependency-version: 1.13.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: regex-automata
  dependency-version: 0.4.16
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: rustc-demangle
  dependency-version: 0.1.28
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: rustversion
  dependency-version: 1.0.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: spin
  dependency-version: 0.9.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: winnow
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zbus_macros
  dependency-version: 5.17.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: zbus_names
  dependency-version: 4.3.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zerocopy-derive
  dependency-version: 0.8.54
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zmij
  dependency-version: 1.0.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zvariant
  dependency-version: 5.13.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: zvariant_derive
  dependency-version: 5.13.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: zvariant_utils
  dependency-version: 3.5.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: non-rust-vmm
- dependency-name: rustls
  dependency-version: 0.23.42
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: uuid
  dependency-version: 1.23.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: crc-any
  dependency-version: 3.0.1
  dependency-type: indirect
  update-type: version-update:semver-major
  dependency-group: non-rust-vmm
- dependency-name: cc
  dependency-version: 1.2.67
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: memchr
  dependency-version: 2.8.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: rustversion
  dependency-version: 1.0.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: spin
  dependency-version: 0.9.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: winnow
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
- dependency-name: zmij
  dependency-version: 1.0.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: non-rust-vmm
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-17 00:58:43 +00:00
Anatol Belski
d0dc2c2cb1 ci: Exclude flaky villain tests S0094 and PCI0006
Both tests intermittently report WEDGED because the villain harness
can lose the guest verdict marker when the VM exits before the VMM
drains the console virtqueue, so the host reads a console with no
marker under load. This is a harness race, not a CH defect, and it
lands on a random test each run. Exclude the two most affected
until the harness drains the console on shutdown.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-16 13:04:25 +00:00
Anatol Belski
2ea2209920 block: qcow: Test reopen finds no stranded clusters
After churning a single L2 region with an fsync per write, close and
reopen the image. parse_qcow rebuilds the free list from the on disk
refcounts, so a reopen that recovers many clusters means the runtime
allocator stranded them. Without the fix the reopen recovered every
relocated cluster. Now it finds none.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-16 13:03:48 +00:00
Anatol Belski
8acefad893 block: qcow: Test freed clusters stay on the free list
After churning a single L2 region with an fsync per write, scan the file
for refcount==0 clusters and assert every one is on the runtime free
list. The reuse bug left relocated refcount block clusters free on disk
but off the list, so this fails without the fix, reporting the exact
count of stranded clusters.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-16 13:03:48 +00:00
Anatol Belski
365d6b8017 block: qcow: Test relocated metadata cluster reuse
Add a regression test that churns one L2 region with an fsync per write,
relocating the L2 table and its refcount block every iteration, and
asserts committed host blocks track live data instead of doubling. Data
written across the churn is read back to confirm integrity.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-16 13:03:48 +00:00
Anatol Belski
57f67a543a block: qcow: Reuse relocated refcount block clusters
Metadata tables use relocate on write. The first modification after a
flush writes the table to a new cluster and frees the old one. The L2
path returns the old cluster to the free list, but the refcount block
path did not. QcowState::set_cluster_refcount set the dropped refcount
block cluster to refcount 0 yet never pushed it onto unref_clusters, so
it stayed committed on the host and was invisible to the allocator.
Every refcount block relocation stranded one cluster, and
get_new_cluster extended the file instead of reusing it.

Under a sync heavy workload each fsync that dirties a table relocates
it, so the physical footprint grew at roughly twice the live data
without bound. qemu-img check stayed clean because the refcounts are
correct, and a reopen, which rebuilds the free list from refcounts,
recovered the space.

Push the dropped refcount block cluster onto unref_clusters so the
running allocator reuses it, matching the L2 table path.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-16 13:03:48 +00:00
Saravanan D
8b61fd0238 docs: Document VFIO live migration support
Add a live migration section to the VFIO documentation covering the
requirements beyond snapshot and restore, the dirty tracking behavior,
the destination file descriptor substitution with an example, and the
failure recovery behavior. Link it from the live migration and
snapshot sections.

Signed-off-by: Saravanan D <saravanand@crusoe.ai>
2026-07-15 22:45:08 +00:00
Saravanan D
59a6563a51 vmm, ch-remote: Allow VFIO fd substitution at receive-migration
The VmConfig that arrives over the migration stream carries the
source's device paths and stale FDs, none of which are usable on the
destination. A received VFIO device therefore needs fresh descriptors
supplied with the request.

VmReceiveMigrationData gains vfio_fds, pairing each device id with a
cdev FD, and iommufd_fd for the backing iommufd, both arriving over
SCM_RIGHTS. Once the received VmConfig is available, each named
device's path or FD is swapped for the received one and the iommufd is
installed before the VM is built, so the device comes up FD backed.

The request is rejected when a substituted device lacks the iommufd
backend, when an id is unknown or repeated, or when a device names no
replacement in vfio_fds. These checks run against the migrated VmConfig
once it has been received.

ch-remote gains the vfio_fds and iommufd_fd options and forwards the
descriptors over SCM_RIGHTS. The D-Bus transport cannot carry file
descriptors and drops them.

Signed-off-by: Saravanan D <saravanand@crusoe.ai>
2026-07-15 22:45:08 +00:00
Saravanan D
2214dceb07 vmm, ch-remote: Allow VFIO fd substitution at restore
A VFIO device restored onto a different host has a device path and
iommufd that are meaningless there, and an FD backed device cannot
serialize a live descriptor into the snapshot at all. Restoring one
therefore needs fresh descriptors supplied with the request.

RestoreConfig gains vfio_fds, pairing each device id with a cdev FD,
and iommufd_fd for the backing iommufd. Both arrive over SCM_RIGHTS on
the restore request. vm_restore swaps each named device's stale path
or FD for the received one and installs the iommufd before the VM is
built, so the device comes up FD backed.

The request is rejected when a substituted device lacks the iommufd
backend, when an id is unknown or repeated, or when an FD backed device
names no replacement.

ch-remote gains the vfio_fds and iommufd_fd options and forwards the
descriptors through the SCM_RIGHTS pool.

Signed-off-by: Saravanan D <saravanand@crusoe.ai>
2026-07-15 22:45:08 +00:00
Saravanan D
c3c4281069 pci: vfio: Implement dirty page tracking for VfioPciDevice
Wire the previously empty Migratable implementation on VfioPciDevice to
VFIO DMA logging so the pages the device writes to guest memory are
tracked during a live migration. The Vfio trait gains the DMA logging
operations with defaults that report no migration support.

Without a virtual IOMMU the device sees an identity mapping of guest
memory, so the tracked ranges are the guest memory regions with iova
equal to gpa. The requested page size is only a hint, so the device
reports back the granularity it actually applied.

A device that does not support migration, or one behind a virtual
IOMMU, is refused at migration start rather than silently skipping
dirty tracking and producing an incorrect log. Under a virtual IOMMU
the reported IOVAs are not guest addresses and the logged range set
would have to track the mapping changes a guest makes mid migration,
so that configuration is out of scope.

Signed-off-by: Saravanan D <saravanand@crusoe.ai>
2026-07-15 22:45:08 +00:00
Saravanan D
794997f241 pci: vfio: Recover failed state transitions
A failed VFIO_DEVICE_FEATURE_MIG_DEVICE_STATE set can leave the device
in its original state, midway along a combination transition, or in
ERROR. The uAPI leaves recovery to the user, and from ERROR only a
VFIO_DEVICE_RESET brings the device back to RUNNING.

Previously a failed transition left the device wherever it landed, so
one that reached ERROR stayed wedged for the life of the guest even
though a reset would have recovered it.

On a failed transition the caller now names an optional recovery state
to attempt first, falling back to a device reset. Pause, resume, and
the return to STOP after STOP_COPY name no recovery state, so their
failure resets directly. The original transition error is always
propagated and recovery failures are logged.

Signed-off-by: Saravanan D <saravanand@crusoe.ai>
2026-07-15 22:45:08 +00:00
Anatol Belski
43a090e44c ci: Bump virtio-villain to v0.5.2
The S0094 state test could be reported as WEDGED when the host per
test timeout killed the VM before the guest finished its wait,
dropping the verdict marker. v0.5.2 accepts that timeout case as a
pass since the device does not consume the buffer before DRIVER_OK.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-15 18:58:12 +00:00
Anatol Belski
c03701f0de docs: Rewrite KDCOM debugging to use convey bridge
Replace the QEMU debugger VM approach with a simpler setup that runs
WinDbg directly on a Windows host. Cloud Hypervisor exposes the guest
serial port on a UNIX socket, socat turns it into a TCP listener, and
the convey tool bridges the TCP endpoint to a named pipe that WinDbg
attaches to.

This drops the need for a second Windows VM and the socat SYSTEM shell
script wrapping.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-15 17:27:01 +00:00
dependabot[bot]
94eda91811 build(deps): bump actions/cache from 4 to 6
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-15 00:43:55 +00:00
Anatol Belski
a8738c5897 ci: Add virtio-villain test suite job
Add a GitHub Actions job that runs the virtio-villain suite against
cloud-hypervisor, giving continuous coverage of how the virtio device
model responds to guest input that violates the driver side rules of
the virtio specification. The suite drives the device model from the
guest side with out of spec virtqueue input, malformed descriptor
chains, transport register abuse, and device specific requests, then
checks that each violation is handled without crashing the device or
leaving it wedged. This makes a class of guest triggered failures a
signal that shows up on every relevant change rather than found by
chance.

The job builds cloud-hypervisor with the kvm feature, clones
virtio-villain at a pinned tag, builds its initramfs, and runs the
tests in short lived VMs, rerunning a wedged batch in isolation so a
failure is attributed to the offending test. Results reach the run
summary page, and the JUnit report plus per test logs upload as an
artifact. The compiled harness, the initramfs, and the fetched guest
kernel are cached under the resolved villain commit, so an unchanged
pin skips the rebuild.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-07-14 20:51:43 +01:00
Ruben Hakobyan
f9f07b49d2 vmm: igvm: Use kvm-bindings for SNP page types
Replace the hard-coded KVM SNP page type constants with the
KVM_SEV_SNP_PAGE_TYPE_* values from kvm-bindings.

Signed-off-by: Ruben Hakobyan <hruben@meta.com>
2026-07-14 13:56:32 +00:00
Ruben Hakobyan
6d2d66bcd3 vmm, hypervisor: Make the VMSA page type optional
KVM builds the VMSA internally, so the logic in igvm-loader passing a
VMSA page for KVM is misleading. The page is silently dropped later
in import_isolated_pages(). Only MSHV actually imports it.

Make PageTypeConfig::vmsa an Option that is None on KVM and push the
VMSA page only when it is set. As KVM no longer produces a VMSA page,
remove the now-dead skip in import_isolated_pages().

Signed-off-by: Ruben Hakobyan <hruben@meta.com>
2026-07-14 13:56:32 +00:00
Pascal Scholz
3ddcf50149 option_parser: Improve test coverage for Tuple and TupleList parsing
We increase test coverage by adding tests for code paths that were not
tested up until now.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-14 13:52:18 +00:00
Pascal Scholz
840028c64f option_parser: Reject Tuple keys only consisting of whitespaace
We reject keys only consisting of whitespace as empty as it can
occur as an input artifact.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-14 13:52:18 +00:00
Pascal Scholz
e32f8846c2 option_parser: Remove surrounding space
We remove whitespace from `Tuple` input to allow input of the form
" key@value ".

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
2026-07-14 13:52:18 +00:00