Add generic polling helpers for integration tests and build the
SSH wait helpers on top of them.
This lets follow-up test changes replace fixed sleeps with
condition-based waits without duplicating retry logic at each call
site.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
The MMIO64 allocator size is computed with alignment truncation:
size = (range / alignment) * alignment
This loses up to one alignment unit (4 GiB) at the top of the
address space. When a guest (Windows with virtio-win 0.1.285)
programs a BAR near the top of the physical address space, the
allocation fails because the address falls in the truncated gap.
Give the last PCI segment allocator all remaining space up to
the end of the device area, so no addresses are lost.
The `end` parameter of create_mmio_allocators() is an inclusive
address (the last valid byte). Fix the 32-bit caller and tests
to pass inclusive values, consistent with the 64-bit caller
which already uses the inclusive end_of_device_area().
Signed-off-by: CMGS <ilskdw@gmail.com>
When BAR reprogramming is detected, detect_bar_reprogramming()
eagerly updates the BAR address in config space before the actual
MMIO remapping occurs. If the subsequent move_bar() fails (e.g.
the new address falls outside the allocator range), the config
register retains the new address while the MMIO bus still uses
the old one, leaving the device broken.
Add restore_bar_addr() to undo the config space update when
move_bar() fails, so the device remains functional at its
original address.
For 64-bit BARs, restore both the low and high BAR slots as well
as the corresponding config registers, mirroring the two-slot
update logic in detect_bar_reprogramming().
Implement restore_bar_addr() for all PciDevice implementations
(VirtioPciDevice, VfioPciDevice, VfioUserPciDevice, IvshmemDevice,
PvPanicDevice, and PvmemcontrolPciDevice) by delegating to their
respective PciConfiguration::restore_bar_addr().
Signed-off-by: CMGS <ilskdw@gmail.com>
Add a --continue-on-failure CLI flag that allows the test harness to
continue executing remaining tests after encountering a failure, instead
of aborting immediately. When set, failed tests are recorded with zeroed
metrics and a "FAILED" status, the report file is always generated, and
the process exits with a non-zero code if any test failed.
Without the flag, the existing fail-fast behavior is preserved.
Also add a "status" field ("PASSED"/"FAILED") to PerformanceTestResult
so report consumers can distinguish successful tests from failed ones.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Instrument the two main downtime-phase operations on the destination
side - receiving state and resuming the VM - so their costs are visible
in logs and can be iterated on.
The new log messages may look like this:
```text
cloud-hypervisor: 7.283424s: <vmm> DEBUG:vmm/src/lib.rs:948 -- Migration (incoming): recv_snapshot:3ms restore:10ms
cloud-hypervisor: 7.284824s: <vmm> DEBUG:vmm/src/lib.rs:967 -- Migration (incoming): resume:1ms
cloud-hypervisor: 7.284842s: <vmm> DEBUG:vmm/src/lib.rs:977 -- Migration (incoming): Receiving final state and resuming the VM took 15ms
```
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Use OngoingMigrationContext to measure and log the effective VM downtime
(pause to remote resume) and the cost of each non-trivial step in the
downtime window: snapshotting, sending the snapshot, and awaiting
completion. This makes it straightforward to identify and reduce
downtime as live migration matures.
Example:
```
cloud-hypervisor: 7.703402s: <vmm> INFO:vmm/src/lib.rs:1494 -- Migration completed after 2.2s with a downtime of 298ms (goal was 300ms)
cloud-hypervisor: 7.703453s: <vmm> DEBUG:vmm/src/lib.rs:1500 -- Downtime breakdown: 298ms (final_iter:269ms state:7ms send_state:19ms complete:1ms)
```
Note: downtime is measured on the source only; cross-host clock skew
may cause unreliable results.
# Terminology
At first glance, the use of "state" and "[VM] snapshot" may seem
confusing. As discussed in [0], we use "state" consistently in the
migration code. On the VM side, "snapshotting" is merely the mechanism
used to obtain the VM state.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7979#discussion_r3061359899
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Add a small helper that returns both the successful result of an
operation and the time it took to complete.
Subsequent migration instrumentation uses this to keep timing code
compact and consistent.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Add migration-level context types that extend the existing memory-only
metrics with overall migration duration and downtime breakdown.
OngoingMigrationContext models the sender-side migration progress until
all inputs needed for final downtime accounting are available.
CompletedMigrationContext then stores the finalized migration metrics,
including the final memory iteration, snapshotting, snapshot transfer,
and completion phase.
This provides the data needed to log effective downtime in the VMM and
lays the groundwork for future migration statistics reporting.
# Terminology
At first glance, the use of "state" and "[VM] snapshot" may seem
confusing. As discussed in [0], we use "state" consistently in the
migration code. On the VM side, "snapshotting" is merely the mechanism
used to obtain the VM state.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7979#discussion_r3061359899
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Expose the finalized per-iteration timing fields needed by higher-level
migration metrics and factor the iteration-overhead calculation into a
small helper.
This keeps the existing MemoryMigrationContext behavior intact while
making the timing data easier to consume from migration-level context
in the following commits.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Extend test_pci_multiple_segments_numa_node to assert that every
PNP0A08 host bridge in the guest DSDT exposes a unique _UID
matching its PCI segment id. Linux surfaces the evaluated _UID
value through /sys/bus/acpi/devices/PNP0A08:*/uid, so the check
is a single additional ssh command on top of the existing test
plumbing.
This test is used (rather than test_pci_multiple_segments) so
that the assertion runs on both x86_64 and aarch64: the numa_node
variant boots through edk2 firmware on aarch64, making ACPI (and
PNP0A08 host bridges) available, whereas the non-firmware variant
uses FDT on aarch64 and exposes no PNP0A08 nodes.
Without a per-segment _UID, two PNP0A08 nodes share _UID=0 which
violates ACPI 6.5 section 6.1.12 and triggers BSOD 0xA5 on
Windows guests. This assertion would catch any future regression
of that kind.
Signed-off-by: Max Makarov <maxpain@linux.com>
The ACPI specification requires _UID to be unique across devices
sharing the same _HID (ACPI 6.5 section 6.1.12). Currently every
PciSegment emits _UID=0 for its PNP0A08 host bridge, which violates
the spec when num_pci_segments > 1.
Windows guests detect this during ACPI namespace enumeration and
abort boot with BSOD 0xA5 ACPI_BIOS_ERROR, pointing at the _UID
object of the second PNP0A08 node. Linux guests are lenient and
silently accept the collision, so the issue has gone unnoticed.
Use self.id as _UID, matching what _SEG does on the line above.
For single-segment VMs (id == 0) this is a no-op at runtime.
Signed-off-by: Max Makarov <maxpain@linux.com>
This is a preexisting bug in the MSHV integration tests,
but previously it only caused a warning. With commit
Fixes: 5b67b8994a ("ci: Use set -eufo pipefail") it becomes an error.
Fixes: 5b67b8994a ("ci: Use set -eufo pipefail")
Fixes: #7996
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
On aarch64 with 64K host pages, VFIO passthrough of devices with
sub-page BARs (e.g. 16K NVMe BAR0) crashes with EINVAL from
KVM_SET_USER_MEMORY_REGION, which requires memory_size to be a
multiple of the host page size.
Expand the mmap to page size instead of rejecting it, matching
QEMU's approach. The kernel's vfio_pci_probe_mmaps() already
verifies that sub-page BARs are page-aligned and reserves the
remainder of the page, so expansion is safe at offset 0. Reject
sub-page sparse areas at non-zero offsets where this guarantee
does not apply.
The expanded mmap region will not overlap with the relocated MSI-X
trap region because fixup_msix_region() ensures MSI-X relocation
at >= page_size offset.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Rename download_ovmf to download_amd64_ovmf and add a separate
download_aarch64_ovmf for CLOUDHV_EFI.fd
Replace build_edk2 with download_aarch64_ovmf in aarch64 scripts
Update OVMF firmware tag to ch-1e1b96f126
Update CLOUDHV.fd sha1sum in sha1sums-x86_64
Add CLOUDHV_EFI.fd sha1sum in sha1sums-aarch64-common
Fixes: #7622
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Currently, when snapshoting a running VFIO device with MSI-X enabled,
we get a snapshot where `msix_config.state.enabled` is not consistent
with `msix_state.cap.msg_ctl`,
```jsonc
{
"snapshots": {
"vfio_common": {
"snapshots": {
"msix_config": {
"snapshots": {},
"state": {
"enabled": true
// ...
}
},
// ..
},
"state": {
"msix_state": {
"cap": {
"msg_ctl": 3,
"table": 1,
"pba": 2049
},
// ...
}
// ...
}
}
},
// ...
}
```
The root cause is, after a `MsixCap` is parsed from the device PCI
config space and propagated to a corresponding `MsixConfig`,
`MsixCap::msg_ctl` is never get updated at runtime, only
`MsixConfig::msg_ctl` is updated.
This commit makes `VfioMsix::update` update both `VfioMsix::bar` (of
type `MsixConfig`) and `VfioMsix::cap` (of type `MsixCap`).
Signed-off-by: Changyuan Lyu <changyuanl@google.com>
Add a `mergeable` field to `MemoryZoneConfig` so that KSM page merging
can be enabled selectively per memory zone rather than globally for all
guest RAM.
Previously, `MADV_MERGEABLE` was only controllable via the top-level
`--memory mergeable=on` flag, which applied uniformly to all regions.
With this change, users can leave boot memory unmerged while enabling
KSM only on hotplug zones:
--memory size=0,hotplug_method=virtio-mem
--memory-zone id=boot,size=512M,shared=on,mergeable=off
--memory-zone id=hotplug,size=256M,hotplug_size=1G,shared=off,mergeable=on
The `MemoryZone` runtime struct now carries the `mergeable` flag so
that both `allocate_address_space` and `add_ram_region` can apply
per-zone `MADV_MERGEABLE` instead of the global `self.mergeable`.
The top-level `--memory mergeable=on` path continues to work unchanged:
the default zone is synthesised from `MemoryConfig` and inherits its
`mergeable` value.
AI/LLM disclosure: this patch was co-authored with
GitHub Copilot and Claude Code (Opus 4.6).
Signed-off-by: JP Kobryn <inwardvessel@gmail.com>
Workflow runs fail in the "Get Location" step with:
jq: error (at <stdin>:9): string ("100") and number (0) cannot be added
Use tonumber to explicitly convert string to number instead of the "+ 0"
trick.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Add an `iommufd` flag to existing VFIO integration tests. When false,
tests use the legacy vfio container/group backend (existing behavior).
When true, tests use vfio cdev with iommufd and vfio_p2p_dma=off.
vfio_p2p_dma=off is required because the VFIO test runner uses a stock
Ubuntu 24.04 kernel (v6.8) which does not support mapping device MMIO
pages (VM_PFNMAP) through iommufd, causing IOMMU_IOAS_MAP to fail with
-EFAULT on MMIO BAR regions.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Add a user-configurable option to control whether VFIO device MMIO BAR
regions are DMA-mapped into the host IOMMU address space.
This mapping is required for peer-to-peer DMA between devices (e.g.
NVLink, RDMA NIC accessing GPU VRAM). However, iommufd on upstream
kernels does not support mapping device MMIO pages (VM_PFNMAP), causing
IOMMU_IOAS_MAP to fail with -EFAULT. Kernels with the NVIDIA PFNMAP
workaround or future kernels with DMABUF-based mapping
(IOMMU_IOAS_MAP_FILE) handle this correctly.
The option defaults to `on` to preserve existing behavior. Users on
vanilla kernels using iommufd should set `vfio_p2p_dma=off` to skip
MMIO BAR DMA mapping.
A validation check ensures that `x_nv_gpudirect_clique` (which depends
on P2P DMA) cannot be used when `vfio_p2p_dma=off`.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
When `--platform iommufd=on` is set, use the vfio cdev interface backed
by iommufd instead of the legacy vfio container/group interface for
device passthrough.
The cdev path opens '/dev/iommu' via IommuFd, allocates an IOAS, and
binds VFIO devices through VfioIommufd. The legacy container/group path
remains the default and is used when iommufd is not enabled.
Add iommufd-ioctls as a workspace dependency and enable the "vfio_cdev"
feature on vfio-ioctls for KVM builds.
Fixes: #6892
Signed-off-by: Bo Chen <bchen@crusoe.ai>
This option allows user to configure VFIO device pass-through with
iommufd (e.g. vfio cdev mode) or not (e.g. vfio legacy mode).
Signed-off-by: Bo Chen <bchen@crusoe.ai>
The `--platform` help string was hardcoded and did not reflect which
optional features (tdx, sev_snp) were actually enabled in. Build the
syntax string dynamically as `PlatformConfig::syntax()`, conditionally
appending feature-gated options so the CLI help stays accurate.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
A 4M uefi_region is allocated unconditionally. When directly booting a
kernel, it goes unused. Avoid the allocation in this case by moving the
call to add_uefi_flash() to load_firmware().
Also extended add_uefi_flash() to riscv64 since it shares the
load_firmware() path. It looked like up to this point a firmware boot on
riscv64 would panic with an uninitialized uefi_flash.
Signed-off-by: JP Kobryn <inwardvessel@gmail.com>
The aarch64 dbus, fw_cfg & ivshmem tests don't build the mshv feature
causing them to fail when run on MSHV. Fix by building the mshv feature
too just like the x86 version of the script does.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
It is desirable to be able to track the progress of memory hotplug.
Update the memory_actual_size field to query the current plugged size
from virtio-mem to enable this.
Signed-off-by: Jared White <git@jaredwhite.dev>
After a vDPA device reset, activate_vdpa() read avail_idx from guest
memory to pass as the vring base via VHOST_SET_VRING_BASE. However,
the guest memory still contained the stale avail_idx from the previous
session. For a 256-entry ring, this meant base=256, causing the
hardware to believe the entire RX ring was consumed with no available
buffers — RX silently stopped while TX continued to work.
QEMU handles this correctly by tracking last_avail_idx internally
(reset to 0 in virtio_reset()) and passing that value, rather than
reading from guest memory.
Fix by always passing base=0 to set_vring_base(). After a device
reset, both the guest driver and the vhost backend restart their rings
from index 0. For live migration, the correct base should come from
VHOST_GET_VRING_BASE (saved before the migration), not guest memory.
Tested with mlx5_vdpa (ConnectX-6 Dx) + Windows Server 2025 (netkvm).
Before: RX=0 after 3rd driver activation. After: full connectivity.
Signed-off-by: Max Makarov <maxpain@linux.com>
KVM_GET_MSR_INDEX_LIST does not consistently include all
guest-programmable MTRR MSRs.
During save/restore while booting, the VMM initially sets only
MSR_MTRRdefType, then guest firmware or other early boot code can
program additional MTRR state before the snapshot is taken. If those
MSRs are missing from the vCPU MSR buffer, snapshot omits part of the
guest's MTRR configuration and restore resumes with an incomplete
MTRR map.
Add the guest-programmable MTRR MSRs to the KVM MSR index list used
to build the vCPU MSR buffer so the existing snapshot/restore path
preserves the guest's MTRR state.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Some guests update the MSI-X capability through a 32-bit write at
offset 0 instead of a 16-bit write at offset 2. Update the cached
Message Control state for that path as well so MSI-X enablement stays
in sync with the guest configuration.
Add a short comment documenting why the dword write path also updates
the cached MSI-X Message Control state.
This is important for passthrough GPUs, where MSI-X interrupts are used
during NVIDIA Fabric Manager registration. Without updating the cached
state on the dword write path, interrupt delivery can remain stale and
GPU initialization or fabric registration can fail.
Signed-off-by: Damian Barabonkov <dbctl@pm.me>