Add a Windows integration test that verifies kernel network debugging
(KDNET) works over a Cloud Hypervisor virtio-net device.
The test boots a Windows guest with a dedicated second virtio-net NIC,
enables KDNET on it via bcdedit (selecting the adapter by the PCI bus
params discovered over SSH), reboots, and then listens on the debugger
host address. Receiving a KDNET poll datagram from the debuggee proves
the whole virtio-net device path works: discovery, feature negotiation,
virtqueue setup and the TX doorbell. No debugger is needed because KDNET
connections are initiated by the target.
Gated to x86-64, where the Windows image ships the virtio-net KDNET
module. The test exercises only the generic virtio-net doorbell path,
so it runs under both KVM and MSHV.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:Opus-4.8
Windows can run its KDNET kernel-debugging transport over a Cloud
Hypervisor virtio-net device. Add a guide describing how it works.
Link to the new guide from the Windows support document.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:Opus-4.8
The Windows serial (COM/KDCOM) kernel debugging instructions lived in a
long subsection of the Windows support document. Move them verbatim
into a dedicated docs/windows-kdcom-debugging.md and leave a short
pointer in windows.md, so the debugging methods can be documented and
extended independently.
Drop the useless disclaimer. Things should work the same across
different Windows versions.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:Opus-4.8
A virtqueue notification (doorbell) is normally delivered to the device
through an ioeventfd registered on the notify address, so a plain MMIO
write to the notify register is consumed by the hypervisor and never
reaches write_bar().
It does reach write_bar() when the driver rings the doorbell through the
VIRTIO_PCI_CAP_PCI_CFG window (write_cap_pci_cfg -> write_bar) instead
of a mapped BAR, or on backends that deliver the write to the VMM such
as SEV-SNP.
The notification arm of write_bar() only re-signalled the matching
queue eventfd under the sev_snp feature and logged an error
otherwise, so a doorbell delivered through the PCI_CFG window was
silently dropped on standard builds and the queue was never
processed.
The virtio spec allows driving the device purely through the PCI_CFG
window, so signal the matching queue eventfd for any doorbell that
reaches write_bar() on every build.
Add unit tests that ring a queue's doorbell via write_bar() and
assert only the addressed queue's eventfd is signalled.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:Opus-4.8
The Windows integration test scripts tore down their device-mapper
snapshot and loop devices with 'dmsetup remove_all -f' and 'losetup
-D'. Both operate on every such device on the host, not just the ones
the script created.
On a host whose root filesystem is device-mapper backed (for example an
LVM root), 'dmsetup remove_all -f' replaces the in-use root device's
table with an error target. The host is wedged until reboot. This is
harmless in CI, which runs in a disposable VM, but destroys a developer
machine.
It turns out windows-snapshot-base is not used at all. Drop it.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:Opus-4.8
Use std::thread::available_parallelism() when sizing the prefault
worker threads so the number of threads scales with the host CPU
count instead of relying on unsafe sysconf.
Fixes: #8495
Signed-off-by: Pulak Kanti Bhowmick <pkbhowmick007@gmail.com>
The generic vhost-user device took its virtio device type on the
command line via the `virtio_id` parameter, but the same value is
called `device_type` in the API and the resulting config struct. This
irregularity was due to churn during the review process, `device_type`
was the intended name.
Accept `device_type` on the command line and keep `virtio_id` as a
deprecated alias that logs a warning. The alias will then be removed in
a later release.
Fixes: #8545
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
On Intel MSHV the memory-intercept guest_physical_address and the
MSHV_VP_TRANSLATE_GVA ioctl both return a page-aligned GPA, while
guest_virtual_address is byte-exact. Returning the cached/translated
GPA unchanged made byte-sized MMIO land at BAR offset 0: virtio
device_status writes (BAR+0x14) hit device_feature_select, so
VIRTIO_F_VERSION_1 was never acked and virtio_blk/net/rng probes
failed with -EINVAL, leaving the guest unable to mount rootfs.
Splice gva & 0xfff into the returned GPA on both the intercept fast
path and the translate_gva fallback, and relax the cached-GVA match
to page granularity so it still hits for other byte offsets in the
same page.
This issue is reproducible on Intel machine, launching
Cloud-Hypervisor on nested scenario, using the Linux Dom0
image as the guest image to turn on nested hypervisor
into the guest.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Muminul Islam <muislam@microsoft.com>
A hot-unplug leaves the PCI node in the device tree until the guest
acknowledges the ejection, but VmConfig drops the device entry
immediately.
Move the config removal into DeviceManager::remove_device() and fail
when it returns false, so a second remove-device request cannot reuse
the stale device-tree node.
Assisted-by: OpenAI:Codex-GPT-5
Signed-off-by: Rob Bradford <rbradford@meta.com>
common_thread_rules() holds the syscalls every thread needs for the
SIGSYS violation handler added in #8449: the handler prints a
diagnostic to stderr (write()) after identifying the offending
thread (gettid()).
#8449 added gettid() to common_thread_rules() but left the per-thread
copies in place (9 rule sets still list it, 2 do not). write() is
likewise listed unconditionally in every thread's rule set.
Add write() to common_thread_rules() and drop the per-thread
duplicates of both gettid() and write(). Every thread already allowed
both, so there is no change in behaviour.
write() suggested by @phip1611 in #8490.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Across the last 20 MQ runs, all 13 vfio runner failures came from two
flaky tests. Both are now skipped and tracked in #8548 and #8549.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Check that we can make a successful snapshot (and restore it) after
another restore. Also check that snapshot it refused until restore is
complete.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
If there is an active on-demand restoration then reject any requests to
migrate or snapshot this VM as the memory will not be available for the
snapshot.
Signed-off-by: Rob Bradford <rbradford@meta.com>
In order to deny migration or snapshot when currently doing an on-demand
restore it is necessary to track whether the prefaulting is completed.
This is a proxy for on-demand restoring being completed as pages that
have been restored by a userfaultfd request will excluded from the
prefault set.
Fixes: #8525
Signed-off-by: Rob Bradford <rbradford@meta.com>
The request can be spread over multiple descriptors but the virtio-block
specification (and this code) expects that is a whole number of sectors
(512 bytes).
Signed-off-by: Rob Bradford <rbradford@meta.com>
When writing the header after a resize the compression type field was
always set to 0, which selects zlib, even when the image was originally
created with zstd. The resized image would then no longer be usable.
Write the actual configured compression type instead.
Fixes: #8558
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use a pair of structs for the basic QCOW V2 header and V3 additional
fields and serialize them to/from disk via the zerocopy crate.
This removes the need to manage the position to read from/write to.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Remove the internal and worker submodule layers from the VHDX format
directory. The bat, header, io, and metadata parsers move up as
direct children, internal/mod.rs becomes parser.rs, and the sync
backend moves up as engine_sync.rs. The declaration only
worker/mod.rs is dropped.
The public types are surfaced at the vhdx module level, so callers
use block::formats::vhdx instead of reaching into the internal
module.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Remove the internal and worker submodule layers from the VHD format
directory. The footer and fixed parsers move up as footer.rs and
fixed.rs, and the backends move up as engine_sync.rs and
engine_uring.rs. Both internal/mod.rs and worker/mod.rs held only
module declarations and are dropped.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Remove the worker submodule layer from the raw format directory. The
backend files move up as engine_sync.rs, engine_uring.rs, and
engine_aio.rs, the shared test helpers move up as tests.rs, and the
two alignment helper functions from worker/mod.rs merge into the raw
module.
The vhd backends that reused the raw io_uring and sync engines are
updated to the new block::formats::raw::engine_* paths.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Remove the internal and worker submodule layers from the QCOW2
format directory. The former internal files become direct children
of qcow, with internal/mod.rs turning into parser.rs. The worker
backends move up as engine_sync.rs and engine_uring.rs, and
worker/mod.rs, which held only module declarations, is dropped.
The public parser types are now surfaced at the qcow module level,
so external callers use block::formats::qcow instead of reaching
into the internal module.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The metrics test list has grown significantly and no longer finishes
even within the 60-minute timeout. Exclude the block_qcow2 group (30
tests) in addition to the micro benchmarks, leaving a 30-test set that
completes meaningfully (~41 minutes in my testing). Trimming and
re-tuning the metrics test list is tracked in #8551.
Since the underlying bare-metal system is also retired, run the metrics
tests on the garm-jammy-16 (Azure VM) runner instead.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
The '--test-filter' and '--test-exclude' arguments only accepted a
single keyword, even though the underlying selection logic already
matches against a list. Add a comma value delimiter to both so multiple
keywords can be passed in one invocation.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Rather than instantiating a vector for parsing the descriptor chain in
advance instead use a SmallVec bounded by the expected length of the
descriptor chain. This removes vector allocations from those paths.
As smallvec was already a block dependency move it to a workspace
dependency and use it from there.
Fixes: #5079
Signed-off-by: Rob Bradford <rbradford@meta.com>
The vhost-user (fs, net, block, generic) and vsock worker threads allow
socket() unconditionally in their seccomp rules. These threads only ever
open AF_UNIX sockets: the vhost-user transport connects/binds a Unix
socket (via the vhost crate's Endpoint/Listener), and the vsock device's
host side is a Unix socket. None of them open AF_INET/AF_INET6 sockets.
Restrict their socket() rule to AF_UNIX. Because these threads are
spawned by the VMM thread and inherit its filter, socket() was already
limited to the VMM's set (AF_UNIX/AF_INET/AF_INET6); this narrows it
further to just AF_UNIX, so each worker is confined to what it actually
uses rather than the broader inherited set.
Related to #8490 (giving each thread a more restrictive filter than the
VMM thread).
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
num_buffers sits at offset 10 of the virtio net header, so only
vnet_hdr_len() bytes need to translate contiguously to compute
its host address. Shrink the translate_gva length from desc.len()
to vnet_hdr_len() so the request matches what is actually read.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
VhdxSync::submit_data_operation() passed every read/write straight to
the underlying Vhdx without checking the request against the virtual
disk's logical size. A request that started inside the image but
extended past its end (or an offset past the end entirely) was passed
through unchecked, silently reading/writing out of the intended
bounds.
Call AsyncIoOperation::validate_bounds() from submit_data_operation()
before dispatching the operation, the same way the VHD sync worker
does. The check rejects any request whose offset + length exceeds the
logical size.
Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
Reuse global validate_bounds() operation helper instead of
having a local implementation in vhd/worker/common.rs
Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
Extract the dynamic VHDX qemu-img helper into a shared vhdx::
test_util module to reuse inside the upcoming VhdxSync bounds-check.
Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
```
warning: you seem to be trying to move all elements into a new `Vec`
--> pci/src/configuration.rs:951:24
|
951 | return self.pending_bar_reprogram.drain(..).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `mem::take` to avoid creating a new allocation: `std::mem::take(&mut self.pending_bar_reprogram)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#drain_collect
= note: `-D clippy::drain-collect` implied by `-D clippy::all`
```
Signed-off-by: Rob Bradford <rbradford@meta.com>
```
warning: using `chunks_exact` with a constant chunk size
--> block/src/formats/qcow/internal/header.rs:253:39
|
253 | for entry in data.chunks_exact(FEATURE_NAME_ENTRY_SIZE) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#chunks_exact_to_as_chunks
= note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D clippy::all`
```
Signed-off-by: Rob Bradford <rbradford@meta.com>
igvm and sev_snp only need the MSHV backend when a caller selects that
backend. Stop enabling mshv implicitly from those top-level features so
KVM SEV-SNP builds do not compile unused MSHV backend code.
Require igvm and sev_snp to be built with kvm or mshv. Backend-less
configurations having no runtime hypervisor are not supported.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Decoupling removes the old implicit MSHV coverage from standalone igvm
and sev_snp jobs. Replace those jobs with explicit KVM feature sets and
add MSHV igvm and sev_snp build and clippy jobs so both backends remain
covered.
This keeps the previous implicit combinations tested while making the
selected backend visible in CI.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
IGVM no longer implies the MSHV backend at the feature layer. Gate the
loader paths that use MSHV page types, MSHV SNP launch defaults, or
MSHV-specific CPUID page rewriting on the MSHV feature.
This preserves existing MSHV behavior while letting KVM SEV-SNP use the
shared IGVM loader without compiling the full MSHV backend.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The region table overlap fix in RegionInfo::new computes each entry's
end offset as `file_offset + length`. Both values are taken verbatim
from the image, so a crafted or corrupt VHDX can set a file offset near
u64::MAX and make that addition wrap. A wrapped end offset compares as a
small value, which can slip a genuinely overlapping region past the
half-open interval check that #8483 added.
Use checked_add for the end offset and return a new RegionEntryOverflow
error when it wraps, so a malformed entry is rejected instead of being
folded into a valid-looking range. The computed end is now reused for
the region_entries map so the bound is only calculated once. Add a
regression test for a wrapping entry.
Signed-off-by: Sayed Kaif <metsw24@gmail.com>
Only set the VIRTIO_NET_S_ANNOUNCE status bit if the feature
VIRTIO_NET_F_GUEST_ANNOUNCE was acknowledged.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The virtio-iommu translation required the whole [addr, addr+size) span
to be covered by a single mapping. A guest is free to describe one
contiguous buffer with several adjacent mappings: the specification lets
the driver map at page granularity and the Linux IOMMU core splits a
single mapping request at page size boundaries. A descriptor buffer
backed this way was rejected as an invalid translation even though every
page was mapped, wedging the device.
Walk consecutive mappings when no single one covers the span, accepting
the translation once the mappings are adjacent in IOVA space and
contiguous in guest-physical space. A non-contiguous span cannot be
represented by the single returned address and is still rejected.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add an integration test to verify the newly added code to expose
cache topology information in PPTT.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Read the host cache info from sysfs and pass through the same to the
guest via the PPTT table. This is the same as the approach taken for
FDT. Similar to that, assume that the L3 cache is always shared and the
L2 cache is unique per CPU.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Both arch/src/aarch64/fdt.rs and vmm/src/cpu.rs declared the same
~14 cache info locals (size/line_size/sets for L1D/L1I/L2/L3, plus
shared flags for L2/L3), checked for /sys/devices/system/cpu/cpu0/cache,
and populated those locals via get_cache_size /
get_cache_coherency_line_size / get_cache_number_of_sets /
get_cache_shared. Two near-identical ~30-line blocks.
Add a CacheTopologyInfo struct in arch/src/aarch64/cache.rs whose
field names mirror the existing locals, plus a read_cache_topology()
helper that returns None when the sysfs hierarchy is missing and
only queries get_cache_shared for L2/L3 when their size is non-zero
(preserving current behavior).
Both call sites now obtain the info via read_cache_topology() and
destructure it back into locals of the same name, so all downstream
references are unchanged.
Assisted-by: Copilot-CLI:Claude-Opus-4.7
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Replace 1024, 1024u32.pow(2), and 1024u32.pow(3) with 1u32 << 10,
1u32 << 20, and 1u32 << 30 in get_cache_size. The shift form makes
the binary (KiB/MiB/GiB) nature of the conversion immediately
obvious and is easier to read at a glance.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
fdt.rs has helper functions to query host cache details (topology, size
etc.). Extract these helpers to a new file cache.rs so that they can be
used for PPTT construction as well.
No functional change.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Use the helpers from the acpi_tables crate to construct the PPTT. This
is in preparation for adding cache hierarchy info to the PPTT which is
simpler using the helpers.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
A Windows guest that launches nested Hyper-V (for example to run WSL2)
fails to start its hypervisor on cloud-hypervisor's HW-reduced-ACPI
FADT. hvloader's hypervisor-launch path (0x18000f01c -> 0x180015628 ->
0x180015788) registers every legacy PM register block via 0x1800158dc
and rejects any block whose GAS address is 0 with status 8
(STATUS_INVALID_DEVICE_REQUEST). hvix64 then never launches and
HypervisorPresent stays False. The HW-reduced FADT leaves those blocks
zero.
Emit valid PM1a event/control blocks (I/O ports, lengths and X_GAS) in
the FADT and reserve those ports in the I/O allocator so nothing else
claims them. The HW-reduced guest OS ignores the legacy ports; only
hvloader's ACPI validation reads them.
These blocks are only useful to a guest that itself runs an enlightened
hypervisor, so emit them only when both guest nesting and the Hyper-V
enlightenments are enabled (--cpu nested=on,kvm_hyperv=on).
Signed-off-by: doge <me@crackerben.com>
The previous CI (removed in #7760) built natively inside a riscv64 QEMU
VM over SSH on a self-hosted host. That setup was disabled for chronic
infrastructure flakiness (#7758).
Reintroduce coverage deliberately minimal: cross-compile the
cloud-hypervisor binary on a stock ubuntu-latest runner, and nothing
more.
- No integration tests: no riscv64 hardware needed.
- No clippy: cross clippy with -D warnings currently trips on
riscv64-gated lints that need a separate cleanup commit first.
Cross-compiling needs only a riscv64 linker, not Docker/cross: the
binary does not pull openssl-sys (that arrives via a dev-dependency of
test_infra, unused by -p cloud-hypervisor), so no cross sysroot is
required.
Signed-off-by: Gauthier Jolly <contact@gjolly.fr>
Nothing reads or writes the AlignedFile through a cursor anymore, so
remove the Read, Write, and Seek impls together with the in memory
position field. SeekHole no longer tracks a position. The cursor unit
tests move to read_at and write_at, dropping the one that duplicated
existing coverage.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The disk size in sectors was computed by seeking the AlignedFile to the
end. Use query_device_size instead, which also handles block devices,
and drop the now unused Seek and SeekFrom imports.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Request::execute seeked the disk to the request sector and then read or
wrote sequentially through the cursor. Walk a running offset with
read_exact_at and write_all_at instead, and flush with fsync, so the
bound becomes FileExt and FileSync rather than Seek, Read, and Write.
The seek step is gone, so drop the now unused ExecuteError::Seek.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
detect_image_type read the first block through the AlignedFile Read
cursor. Read it with read_exact_at at offset 0 instead, so image type
detection no longer depends on the cursor.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Read the trailing footer sector with query_device_size and
read_exact_at instead of seeking to the end of the AlignedFile and
reading through its cursor.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The `tpm` module in the `devices` crate is disabled on riscv64 (see
commit 0042447fb "devices: Disable tpm module for riscv64"), and every
use of `tpm` in the device manager is already gated behind
`#[cfg(not(target_arch = "riscv64"))]`. However, the import itself was
merged into the unconditional `use devices::{...}` line in commit
025e782e5 "vmm: trim qualified paths", which broke the riscv64 build:
error[E0432]: unresolved import `devices::tpm`
--> vmm/src/device_manager.rs:70:83
Split the `tpm` import out into its own line gated with
`#[cfg(not(target_arch = "riscv64"))]`, matching all of its usages.
Signed-off-by: Gauthier Jolly <contact@gjolly.fr>
mmap(NULL, ...) only guarantees page-sized alignment, so the device
MMIO regions mapped for VFIO passthrough were not necessarily aligned
on a huge page boundary and thus could not take fast paths in the
kernel.
Align the address to the largest possible size. This allows VFIO to take
fast paths when walking the page table.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:Opus-4.8
Assisted-by: Copilot:GPT-5.5
The updated image is configured in a same way as before
SSH and RDP are enabled.
Includes latest stable virtio-win 0.1.285 drivers.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert the qcow image compressor test helper to positional access
instead of the cursor. Test only change.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert the qcow sync worker test helpers to positional access instead
of the cursor. Test only change.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert the qcow header test helpers to positional access instead of
the AlignedFile cursor. Test only change.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert the QcowRawFile unit test verifications to positional access
instead of the cursor. Test only change.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert the qcow header feature bit writes to positional access and
drop the now unused Seek imports. The result is unchanged.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert the qcow header reader and writer to positional access instead
of the AlignedFile Read, Write, and Seek cursor. The writes still go
through the AlignedFile O_DIRECT bounce, so alignment is unchanged.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
zfs and virtiofs do not eagerly account a mode-0 fallocate() in
st_blocks, so detect those filesystems with fstatfs() and skip the
physical-size assertions there. A skip now names a proven platform
limitation instead of being inferred from the value under test, and
every assertion still runs unconditionally on ext4/xfs.
Fixes#8296
Signed-off-by: Adel-Ayoub <adelayoub.maaziz@gmail.com>
The virtio-net guest announce feature bit was accidentally dropped
during upstreaming, so the device never advertised it to guests. Restore
the feature offer for virtio-net.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Now that IntegerList can handle any width number type use that for the
queue_sizes parameter on `--generic-vhost-user`
Signed-off-by: Rob Bradford <rbradford@meta.com>
This allows its use for all integer types and will generate an error if
the value is too wide for the type.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Advertise `VIRTIO_NET_F_GUEST_ANNOUNCE` on virtio-net devices, surface
`VIRTIO_NET_S_ANNOUNCE` through config status, and handle
`VIRTIO_NET_CTRL_ANNOUNCE_ACK` on the control queue.
This adds the guest-visible state needed for post-migration or
post-restore announce requests; the VMM side triggering is added in
follow-up commits.
The motivation is to reduce post-migration and post-restore
connectivity gap. After a live migration or after restoring, it can
take the guest several seconds to be reachable again over the network.
With these announcements, the network path should be refreshed within a
few milliseconds.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Expose `VIRTIO_NET_S_LINK_UP` through the virtio-net config status field
when `VIRTIO_NET_F_STATUS` was negotiated.
This makes the guest-visible status bits reflect the device runtime
state and prepares the config status path used by later post-migration
announce handling.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Add a Snapshot and Restore section to docs/vfio.md covering the
migration v2 requirements (Linux 5.18 kernel, variant VFIO
driver such as mlx5_vfio_pci) and the restore sequence for
devices that advertise migration v2.
The behavior description covers the full restore sequence. It
documents the RUNNING to RESUMING single transition (the kernel
walks the intermediate STOP arc), the post load PCI_COMMAND push
to the device, and the MSI or MSI-X eventfd rearm that the
kernel state does not carry. Behavior matches QEMU
vfio_pci_load_config().
It notes one limitation, the snapshot format stores the opaque
device blob as base64 inside the snapshot JSON, which may benefit
from a binary transport path for very large state.
docs/snapshot_restore.md replaces its VFIO out of scope
limitation with a short section that points to docs/vfio.md for
the requirements and behavior.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
The VFIO save and load paths drive the kernel migration state machine
through a strict transition sequence and must recover correctly when a
transition or the data transfer fails. Validating that on real hardware
needs a migratable device, which CI does not have, so the behavior would
otherwise go unverified until it breaks in the field.
Introduce a mock Vfio wrapper that records state transitions and keeps
the migration blob in memory, then test VfioCommon save and load against
it. This pins the transition ordering, the data round trip, and the
failure recovery in CI on any host, independent of hardware. The trait
defaults and the VfioMigrationState conversions are covered too, so a
non migratable device and an unknown state value stay well defined. A
restore that carries migration state onto a device without migration
support is checked to fail instead of dropping the state.
A shadow sync test guards the related save path change, confirming a non
BAR config write reaches the PciConfiguration shadow so a snapshot
captures the live value instead of the post init zero.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
When a snapshot is loaded, walk the migration v2 state machine
from VfioCommon::set_state() after interrupt state has been
restored. If the device supports migration and a blob is
present, drive RUNNING to RESUMING in a single transition and
write the blob to the data_fd. The kernel handles the
intermediate STOP arc internally. An explicit STOP dwell was
observed to make mlx5_vfio_pci re initialize SQ, CQ, and EQ
indices on top of the just loaded blob, wedging queue state on
resume. The device is left in RESUMING and resume() drives it
to RUNNING during VM resume.
set_state() also pushes PCI_COMMAND to the device via
write_config() after the blob load. Rebuilding the in memory
MSI or MSI-X structs does not touch the kernel's view of
PCI_COMMAND, so without this the VF sits at post reset defaults
with no bus master and mlx5_core ACCESS_REG times out. It
rearms VFIO_DEVICE_SET_IRQS via enable_msi or enable_msix for
the same reason, since replaying the in memory interrupt state
does not reissue the ioctl and the kernel has no eventfds for
this device until it does. Both match QEMU
vfio_pci_load_config().
In allocate_bars, skip add_pci_bar and add_pci_rom_bar on
restore. PciConfiguration::new(Some(state)) already populated
the BAR registers with used=true, so the extra call trips
BarInUse. The bars vec and mmio_regions pushes still need to
happen so the caller can wire bus mappings.
set_state() retrieves the migration blob from the snapshot
unconditionally and rejects a snapshot that carries migration
state when the device does not support migration, rather than
silently dropping the saved state. A device without migration
support and no blob, including vfio-user, still skips the load.
On any transition or write failure during restore, STOP is
attempted as best effort before bubbling the error.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Wire a migratable VFIO device's migration state to the VM lifecycle so
the device's internal state survives snapshot and restore. A device such
as a ConnectX VF bound to mlx5_vfio_pci would otherwise come back blank,
because a plain snapshot saves only the PCI configuration Cloud
Hypervisor owns, not the device's own state.
On save, pause moves the device to STOP and snapshot() drives it through
STOP_COPY to extract the opaque state blob, attached to the device
snapshot as a base64 encoded child. resume() returns it to RUNNING.
All new behavior is gated on migration_flags.is_some(), so devices
without migration support (including vfio-user) retain their previous
snapshot behavior.
If the data read fails after STOP_COPY was entered, the device is
returned to STOP before the error is bubbled, since the STOP_COPY
to STOP arc stays valid. A failed transition into STOP_COPY returns
immediately because a STOP from the resulting ERROR state cannot
help. Full recovery including device reset is deferred.
Since the non BAR write path goes directly to the VFIO device and not
the shadow, the PciConfiguration shadow can get stale. Mirror every
non BAR, non MSI config write into the shadow via write_byte /
write_word / write_reg so snapshot() can capture PCI_COMMAND. Without
this the shadow keeps the values set at device init and snapshot()
encodes PCI_COMMAND as zero.
Use the raw write_byte, write_word, and write_reg helpers rather than
PciConfiguration::write_config_register, which would otherwise drain
pending_bar_reprogram, consumed by the BAR block below, and rerun
MSI-X set_msg_ctl, already done by update_msix_capabilities.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Probe VFIO_DEVICE_FEATURE_MIGRATION during VfioCommon::new() and store
the result in a new migration_flags field so later migration phases can
gate state machine transitions.
The probe runs on every instantiation, including snapshot restore,
because migration capability is a property of the host kernel and its
variant driver rather than of any saved VM state.
migration_flags() is added to the internal Vfio trait with a default
implementation that returns Ok(None), meaning not migratable.
VfioDeviceWrapper overrides it to issue the kernel ioctl, while
vfio-user devices keep the default and are always treated as non
migratable.
Allow the VFIO_DEVICE_FEATURE ioctl in the VMM seccomp filter.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Add a write side counterpart to read_unaligned_propagates_closure_error.
The test drives write_unaligned with a gather closure that returns an
error and checks that write_unaligned surfaces it unchanged.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the qcow2 magic and the non qcow magic cases of the AlignedFile
detect_image_type, which now reads the magic positionally.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Opening a raw backing file issued a seek to the end for its size and
then rewound the cursor. RawBacking reads through read_exact_at, so
the cursor reset was dead. Query the size through query_device_size,
matching the crate convention and returning the right size for a
block device backing file as well, and drop the rewind. The now
unused SeekFrom import is removed.
The result is unchanged.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
detect_image_type saved the cursor, rewound, read the magic, then
restored the cursor. Read the four magic bytes with read_exact_at at
offset 0 and decode with from_be_bytes, so the save, rewind, and
restore go away. BeUint moves to the test module, its only remaining
user in this file.
The result is unchanged.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The refcount rebuild check issued a seek to the refcount table and to
the first refblock before each cursor read. Read the fixed size fields
with read_exact_at at their offsets and decode with from_be_bytes. The
seeks and the matching error paths go away.
The result is unchanged.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The compressed cluster write and read and the L1 resize size query
went through a seek on the AlignedFile cursor before the access. Pass
the target offset to write_at and read_exact_at, and read the file
length from physical_size.
The result is unchanged. The compressed paths keep routing through the
AlignedFile O_DIRECT bounce.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Check that the MMIO accesses is 4 bytes long as otherwise it would
be possible for the guest to trigger a panic when the memory ranges base
and length are copied for fulfilling the MMIO read.
This pattern of check matches similar checks in CpuManager and
DeviceManager.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Fill the target MMIO buffer with zeroes to handle reads with access
sizes larger than the data and also check that the read access length
does not exceed the size of the backing slice (previously it just
checked the access size vs length not taking the offset into account).
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Broaden error!() to cover any user-initiated action that fails to do
what was expected (e.g. failed hotplug or live migration), not only
unrecoverable startup errors. Retarget info!() at operators and users,
clarify the warn!() and debug!() audiences, and document trace!().
Part of #8440.
Co-authored-by: Philipp Schuster <phip1611@gmail.com>
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Suggested by phip1611 on #8446.
This adds the repo's first clippy.toml, carving arch out of the
absolute_paths deny from #7670. Glob imports and trait imports that
must be in scope for method-call resolution (e.g. DeviceInfoForFdt for
.irq()) are left as-is.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Cover read_unaligned and write_unaligned directly: a scatter read at an
unaligned offset, a short read at EOF, a read-modify-write gather that
preserves head and tail padding, and error propagation from the
scatter closure.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
run_unaligned_operation staged every unaligned request in a plain Vec
and then handed it to AlignedFile, which bounced again through an
aligned buffer. That Vec only gave the operation a contiguous range to
scatter into or gather from, which the aligned buffer already is, so
each slow path request paid for an extra allocation and a full length
copy.
Add read_unaligned and write_unaligned on AlignedFile that own the
single aligned bounce and scatter or gather through a closure over the
staging slice. run_unaligned_operation and the FileExt read_at and
write_at impls both route through them, so the staging and
read-modify-write logic lives in one place. The closures keep
AlignedFile free of any AsyncIoOperation dependency.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace the use of unsafe struct casting with zerocopy trait derivation.
This fixes a Rust UB where the struct was being filled with a slice of
length greater than the size of the struct.
As a compromise the guid handling was changed to handle the uuids as
opaque bytes as they are mixed endian. This has no impact on the
functionality as they are only used for comparison and has the positive
impact of reducing some of the uuid handling complexity.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
The struct already implements ByteValued so this unsafe block can be
changed to call as_slice() from that trait.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The struct already implements ByteValued so this unsafe block can be
changed to call as_slice() from that trait.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Migrate the MSHV integration tests to run natively on the self-hosted
runner instead of spinning up a separate VM. This simplifies the
workflow pipeline & mitigates Azure capacity issues.
Signed-off-by: Aastha Rawat <aastharawat@microsoft.com>
Cover refcount block round trip for the byte aligned and sub byte
paths, and add_cluster_end appending an aligned cluster and staying
within the maximum offset bound.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
add_cluster_end queried the file length by seeking to the end. Use the
existing physical_size helper instead, which reads the length from the
file metadata. This removes the final cursor access in QcowRawFile, so
the Seek and SeekFrom imports are no longer needed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The refcount block read and write helpers took a file whose cursor was
positioned by a preceding seek. Pass the target offset down instead and
use positional read_exact_at and write_all_at on the AlignedFile, so
the block methods no longer seek. The byte aligned and sub byte writers
build a buffer and issue one positional write, keeping the previous
batching.
The result is unchanged, as the calls still route through the
AlignedFile O_DIRECT bounce.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Make the testing overview describe the dev_cli.sh workflow instead of
implying that every Cloud Hypervisor build must run in a container.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
We cannot reliably send Request::abandon() on every kind of failure on
the sender side, as we might be in the middle of a memory transmission.
The receiver would not reliably know what to do with that. So instead,
when the receiver cannot read from the socket, we log that the migration
sender failed, which is the only likely cause of that failure.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This improves the observability whether a migration failed because of
the sender or because of some error on the receiving side.
Using a simple log message is simpler than introducing a new error enum
to differentiate between SendError and RemoteError.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
When the receiver of a live migration encounters an error, it sends an
error response. The sender of the migration would then send an abandon
request and wait for a response. This abandon request is not necessary,
because the receiver already abandoned the migration due to the error it
encountered.
From now on this function will not send an abandon request to the
receiver anymore, thus it was renamed to "ok_or_error".
Also, this case was always broken, because after sending the error
response, the receiver just exits without waiting for the additional
abandon request.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
The `read_aligned_block_size()` function used `Vec::from_raw_parts()`
incorrectly, causing undefined behavior when deallocating the `Vec<u8>`.
One of the safety invariants of `Vec::from_raw_parts()` is that the
provided pointer must be allocated with the exact same alignment as `T`
(`u8` in this case), but this is clearly not true: `align_of::<u8>()` is
1, but the pointer was allocated with aligment of `blocksize` (typically
512 or greater).
Fix this by using the existing `AlignedFile` helper to read the header
block when probing the image type. This is slightly less efficient than
using `AlignedBuffer` directly, but since this is only called once per
disk image at startup, the difference is probably not worth the extra
verbosity.
Signed-off-by: Daniel Verkamp <drv@meta.com>
Add unit tests for add_pci_capabilities covering the configless
device path. The device config capability is present when the
config region is sized and absent when the size is zero.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The watchdog, rng, and rtc devices expose no device specific
configuration fields. Each now reports a config size of zero so the
transport omits the device configuration capability instead of
advertising an unbacked region that the device cannot service.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a config_size method to VirtioDevice and use it when building the
PCI device configuration capability. The transport advertises the size
reported by the device and omits the capability entirely when the size
is zero, because the virtio driver rejects a zero length capability.
The method defaults to None, so every device keeps its current
capability size.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover read_pointer_table round trip and masking, and the
write_cluster then zero_cluster round trip, exercising the positional
read_exact_at, write_all_at, and write_all_zeroes_at paths on the
AlignedFile.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace the seek then read/write metadata access in QcowRawFile with
positional read_exact_at, write_all_at, and write_all_zeroes_at on the
AlignedFile. read_pointer_table, write_pointer_table,
write_pointer_table_direct, zero_cluster, and write_cluster no longer
move the file cursor.
These calls still route through AlignedFile, which implements FileExt
and WriteZeroesAt with the O_DIRECT alignment bounce, so the unaligned
behavior is preserved. Each access already issued an absolute seek
before touching the file, so the cursor never carried state between
calls and dropping it is unobservable.
Decoding the pointer table now uses native from_be_bytes over the read
buffer, matching the to_be_bytes path on the write side.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The region table overlap check in RegionInfo::new only rejected a new
region that strictly engulfed an existing one. Identical, fully
contained, and partially overlapping regions passed undetected, so a
malformed VHDX with overlapping region entries was wrongly accepted.
Per [MS-VHDX] all region objects MUST be non-overlapping, so such an
image should be rejected. Replace the faulty predicate with a correct
half-open interval overlap test, extracted into a small pure helper
(ranges_overlap).
Add a unit test for the predicate and an integration test that feeds a
crafted region table with two overlapping entries through the real
RegionInfo::new, confirming it is now rejected with RegionOverlap.
Related to #8009 (broader VHDX overlap validation).
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Receiving a migration happens inside the VMM thread, which blocks the
API until a migration was received. On the other hand, sending a
migration is actually just a dispatch operation. We adjust the wording
to improve clarity of the error messages.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Adds three recommendation bits to CPUID 0x40000004.EAX so Windows /
Hyper-V-aware guests use the corresponding paravirtualized hypercalls
instead of falling back to architectural primitives. The hypercalls
themselves are emulated unconditionally by KVM and surfaced via the
corresponding KVM_CAP_HYPERV_* info caps; no userspace cap negotiation
is needed because KVM advertises support to the guest at hypercall
issue time:
KVM_CAP_HYPERV_TLBFLUSH advertises HvFlush{VirtualAddressSpace,Ex,
List,ListEx} (api.rst 8.18, info-only cap).
KVM_CAP_HYPERV_SEND_IPI advertises HvCallSendSyntheticClusterIpi{,Ex}
(api.rst 8.20, also info-only).
Leaf 0x40000004.EAX (HV_CPUID_ENLIGHTMENT_INFO):
bit 1 LocalTlbFlushRecommended
bit 2 RemoteTlbFlushRecommended
Recommend HvFlushVirtualAddressSpace / List in place of
architectural INVPCID / INVLPG broadcasts. Remote shoot-down
via hypercall lets the host skip vCPUs that are not currently
scheduled, instead of waiting for an IPI ack.
bit 10 ClusterIpiRecommended
Recommend HvCallSendSyntheticClusterIpi over per-target APIC
ICR writes. A single hypercall can target up to 64 vCPUs (or
all of them via the Ex variant) versus one VM exit per APIC
access on the architectural path.
These bits depend on AccessVpIndex (0x40000003.EAX bit 6), which is
advertised by the partition-privileges change.
Sources:
Microsoft Hypervisor Top-Level Functional Specification 7.4.5
qemu/qemu docs/system/i386/hyperv.rst (hv-tlbflush, hv-ipi)
Linux Documentation/virt/kvm/api.rst 8.18, 8.20
Signed-off-by: CMGS <ilskdw@gmail.com>
Extends the Hyper-V partition feature CPUID leaf 0x40000003 with bits
that KVM emulates unconditionally and that Windows / Hyper-V-aware
guests consult to skip slow fallback paths. No KVM capability
negotiation is required for any of these -- they are hints to the
guest about what is already legal to use.
Leaf 0x40000003.EAX (HV_CPUID_FEATURES):
bit 0 AccessVpRuntimeReg -- HV_X64_MSR_VP_RUNTIME (0x40000010)
bit 4 AccessIntrCtrlRegs -- HV_X64_MSR_{EOI,ICR,TPR,APIC_ASSIST}
bit 11 AccessFrequencyMsrs -- HV_X64_MSR_{TSC,APIC}_FREQUENCY (skips
guest TSC/APIC calibration loops)
Leaf 0x40000003.EDX (HV_CPUID_FEATURES, TLFS rev 6.0c):
bit 4 FastHypercall -- HV_HYPERCALL_PARAMS_XMM_AVAILABLE
bit 8 ExtendedGvaRangesForFlushVirtualAddressList -- pairs with the
tlbflush-ext recommendation bit
AccessHypercallMsrs (bit 5) and AccessVpIndex (bit 6) are already
advertised by the partition-privileges change.
Sources:
Microsoft Hypervisor Top-Level Functional Specification 7.4.{2,5}
qemu/qemu docs/system/i386/hyperv.rst (hv-vapic, hv-frequencies,
hv-vpruntime)
Signed-off-by: CMGS <ilskdw@gmail.com>
On the receiver side, a live migration with status "aborted" does not
return an error. Thus, management software will think that the live
migration was successful (from just looking at the API response). This
is not expected behaviour.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
So far, we only have seccomp rules for the postcopy-send thread. This
commit introduces the basic plumbing to add seccomp rules also for the
migration worker (the migration coordinator) as well as the TCP workers
(both, send and receive) in the following.
To streamline code setup, all filters are created at a central place
early in the migration code. Although this means that some filters are
created without the need to do so (e.g., postcopy), this massively
simplifies code setup and error handling. This overhead is negligible.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
ReceiveAdditionalConnections got quite complicated, especially with the
many threads involved for precopy and the special-case of postcopy. We
therefore should add comprehensive documentation.
I tried to keep it short and concise - what remains provides high value
and improves the mental model of the code.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Live migration can deadlock if the guest triggers a virtio device
activation while the migration worker owns the VM.
The failure shows up when starting live migrations during boot and
firmware startup, where the guest can reset and reinitialize virtio
devices while precopy is running. In the failing case, the source log
shows a pending virtio activation that never completes:
8.115833s _virtio-pci-net_0: Needs activation; returning barrier
8.115854s vmm/src/vm.rs:464 -- Waiting for barrier
24.875452s Entering downtime phase
24.875481s stopping vcpu throttling thread
...
vCPU thread did not respond in 10ms to signal - retrying
vCPU thread did not respond in 20ms to signal - retrying
...
thread 'throttle-vcpu' (1029) panicked
...
Pause(Error signalling vCPUs: Timeout when waiting for signal
to be acknowledged)
The vCPU blocks on the activation barrier and never reaches the normal
pause checkpoint. Later, migration enters downtime and stops the vCPU
throttle thread. In the failing case, that thread is still inside a
CpuManager::pause() call, which waits for every vCPU to acknowledge
the signal. The blocked vCPU never does, so the pause times out.
Fix this by storing the DeviceManager inside VmOwnership::Migration.
This keeps just enough state on the VMM thread to drain pending virtio
activations while the migration worker owns the Vm. The barrier logic
stays unchanged. The VMM now releases the same activation barrier during
migration that it already released before migration started.
This keeps the guest from getting stuck in the activation wait and
lets the later pause succeed.
Co-authored-by: Leander Kohler <leander.kohler@cyberus-technology.de>
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
When seccomp traps a SIGSYS, print the syscall number that caused it,
the current thread id and thread name to make violations easier to
debug.
This change requires that all threads are allowed to execute the
`gettid` and the `prctl` syscalls, thus the seccomp filters have also
been adjusted.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Getting rid of the unsafe ByteValued implementation for MemoryRange,
Request and Response structures, by relying on zerocopy's safe
implementation instead.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-8
In [0] we agreed on the current format. When ch-remote or
cloud-hypervisor exit with an error, they nicely print the whole chain.
This, however, doesn't work when simply doing `error!("error: {e}")`
- which is what we currently do for migration-related errors.
This commit walks the chain of errors and prints all components in a
single line. This massively improves the quality of error messages and
helps tracing down where an error is originating from. Using ` => ` as
separator is better than `\n` which doesn't work well in our current
log format.
# Example (Before - Bad)
```
cloud-hypervisor: 2.859287s: <vmm> ERROR:vmm/src/lib.rs:2021 -- Migration failed: Failed to send migratable component snapshot
```
# Example (New - Better)
```
cloud-hypervisor: 2.296160s: <vmm> ERROR:vmm/src/lib.rs:2038 -- Migration failed: Failed to send migratable component snapshot => Error connecting to TCP socket => Connection refused (os error 111)
```
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7066
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Keep the original error sources while adding operation context to the
straightforward migration send and receive paths. This keeps up a
chain of errors that can be printed nicely and in a helpful way.
This commit does that for all MigratableError-occurences where this
change is easily applicable.
Co-authored-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
static.docs.arm.com no longer serves the PL031 RTC technical reference
manual; point the comment at the current developer.arm.com location.
Clears the lychee link check, as requested on the review.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
size_of is part of std::prelude as of Rust 1.80 (with size_of_val,
align_of, align_of_val), and the workspace MSRV is 1.89, so qualifying
it (mem::size_of, std::mem::size_of, core::mem::size_of) is unnecessary.
Convert every qualified size_of call-site to the bare prelude form and
drop the now-redundant `use std::mem::size_of;` imports, keeping
`use std::mem;` where it still serves non-prelude items (transmute,
swap, replace, take, zeroed, MaybeUninit, offset_of). size_of is the
only one of the four currently used in the tree.
Pure refactor, no behavioural change. Follow-up to the
clippy::absolute_paths cleanup (#7670), as discussed in #8444.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the modules used in the integration tests instead of spelling
the full paths at every use site, and drop the file's now-unnecessary
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the modules used in the crate instead of spelling the full paths
at every use site, and drop the now-unnecessary crate-level
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
We have larger cloud deployments and analyzed the logs. Let's silence
some messages that generally provide little value on the `info!` level.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
We have larger cloud deployments and analyzed the logs. Let's silence
some messages that generally provide little value on the `info!` level.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Applying seccomp filtering to the migration postcopy thread running on
the source VM during migration.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-8
Wire up the source side of postcopy migration over TCP. When
`mode=postcopy` is requested on vm.send-migration, the source skips
the pre-copy dirty-tracking loop and lets the destination resume early,
then serves guest pages on demand over a dedicated connection.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Add an --ondemand flag to the offload daemon's restore subcommand to
support the post-copy mechanism from the live migration protocol.
In on-demand mode, the daemon creates empty memfds to back the guest
memory and sends them over to the VMM. This lets the VM start quickly,
right after the memfds are mapped into CH's address space.
At runtime, when the guest accesses a page (or the prefault handler
requests it), the daemon faults it in by copying the page content into
its shared memory mapping, then replies to the PageFault request so the
VMM can consider the page present.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Plumb the SocketUffdMemorySource into the receiving side of live
migration. When memory_mode=postcopy is requested, the destination
brings up a dedicated fault connection, registers userfaultfd on the
restored memory regions, and serves guest pages on demand over that
connection while the VM resumes early.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Add the socket-backed UffdMemorySource that resolves each fault by
sending a Command::PageFault request to the peer over a dedicated fault
connection.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Introducing a migration mode to both sides of the migration (send and
receive), so that a user can desribe which way the memory should be
migrated between the source and destination VMs.
For now, we only introduce `precopy` and `postcopy` as viable options,
but we can expect other modes (more optimized) to be added in the
future.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-8
Extract the page content provider out of the userfaultfd handler so it
can be plugged with different backends in followup commits.
No functional change intended.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Introducing PageFault as the new wire command needed by both postcopy
live migration and on demand restore from the offload daemon. This new
command describes the need from the destination to fault the page
content in. This request describes the page through a MemoryRange
structure, and the response can be either 0 or the actual page size.
In case it is 0, that means the source had access to the guest memory
and was able to copy the page content directly. In case the response is
the actual page size, there is a payload associated which contains the
page content.
We can expect local live migration and offload restore to run locally
and therefore have access to the guest memory. The remote live migration
over the network is the case where we would expect the page content to
be sent over the wire.
This command is served through an additional connection happening on the
UNIX or TCP socket. The goal is to keep the same codepath between local
and remote migrations. This additional channel allows PageFault commands
to be issued asynchronously so they can be served without blocking the
main connection.
A connection role is introduced in order to identify an additional
connection related to pre-copy memory versus the newly introduced
channel for serving post-copy requests.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
BlockBackend predated the disk_file trait family and only carried
logical_size and physical_size, which the disk backends expose
through the disk_file traits DiskSize and PhysicalSize.
It added no polymorphism while its Read, Write and Seek supertraits
forced an unused cursor. Dropping the trait removes the dead code
it was keeping alive.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Import the modules used in the shared common test helpers instead of
spelling the full paths at every use site, and drop the now-unnecessary
crate-level #![expect(clippy::absolute_paths)] from integration_cvm.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the modules used in the crate instead of spelling the full paths
at every use site, and drop the now-unnecessary crate-level
generated msr_index.rs was trimmed separately.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the modules used in the binary instead of spelling the full
paths at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Restoring a snapshot (snapshot restore or live-migration receive) sets
each vCPU's TSC by writing MSR_IA32_TSC as the vCPU is created.
However because CpuManager creates and restores vCPUs one at a time, the
host TSC advances between the per-vCPU writes and KVM derives a slightly
different TSC offset for each vCPU.
KVM only engages its masterclock when every offset matches. This has a
side effect of breaking the HyperV TSC reference clock page resulting in
significantly reduced performance on Windows.
After restore synchronise all vCPU's TSC offset to the boot vCPU's via
the KVM_VCPU_TSC_CTRL device attribute group (Linux 5.16+) this allows
the KVM TSC masterclock to engage and mitigates performance issues with
the KVM HyperV emulation.
See: #8383
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude <claude-opus-4-8>
Import the modules used in the binary instead of spelling the full
paths at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
This puts the send-migration action into a dedicated thread, laying the
groundwork for many follow-ups towards first-class live-migration in
CH.
This means:
1. The send-migration call will exit sooner (just trigger the
migration - dispatch semantics)
2. Other API calls can be triggered while a migration is ongoing but
will not be able to alter the VM as the VM's ownership is transferred
from the VMM to the migration thread. Example: hotplugging won't work
(which is good).
3. This is the basis for migration statistics via a dedicated endpoint
(future work).
The whole change was done with a special focus on graceful recover and
cleanup: even if anything on the migration paths go wrong, the proper
cleanups are already executed and the VMM can take back the ownership
of the VM.
The receive-migration API call remains blocking. To observe any status
changes about the migration on the sender side, one can observe the
event-monitor output and look for `vm.migration-{failed,finished}`.
These changes are inspired by [0] but differ significantly in details.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7038
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This initializes the module and the thread that will handle (control)
the migration. This introduces the new types without the necessary
wiring.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Trim the one fully-qualified std::iter::successors path in the library
crate down to an imported module, and drop the now-unnecessary
crate-level #![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
The two synchronous completion paths add the head to the used ring with
desc_chain.memory() but reload self.mem.memory() to enable
notifications. Keep both on the snapshot the chain was parsed from so
the used ring update and the notification enable always act on one
guest memory view rather than two independent atomic loads.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a parameterized helper that creates a 1 GiB ext4 loop filesystem
with 4096 byte sectors, populates it with a small data disk in the
requested format, attaches that disk with direct=on, and runs a 4096
byte aligned dd round trip with oflag=direct and iflag=direct
followed by cmp.
Wrappers exercise raw, qcow2, fixed VHD, and vhdx. The qcow2 and vhdx
wrappers expect the guest to see the on disk LBS of 512. The others
expect the host LBS of 4096.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The qcow workers carried their own O_DIRECT alignment requirement
and bounced unaligned cluster accesses through AlignedBuffer. Now
that the data file is an AlignedFile that handles O_DIRECT
transparently, the qcow layer can read and write through plain
buffers and let AlignedFile perform the aligned bounce.
Remove the alignment field and the per cluster AlignedBuffer RMW
branches from both the sync and async workers. The async io_uring
fast path still needs to avoid submitting unaligned guest iovecs
under O_DIRECT, so gate it on is_direct rather than on a stored
alignment value.
Drop the QcowAsync alignment override so it reports the trait
default sector size, matching QcowSync. qcow never submits guest
iovecs to the kernel under O_DIRECT, so reporting a larger value
only forced the request layer into an extra bounce buffer.
This adds one buffer copy per unaligned O_DIRECT cluster but moves
all alignment handling into a single place. The buffered path is
unchanged.
With qcow no longer the only caller, AlignedBuffer::read_exact_from
becomes dead code, so remove it and switch its tests to read_from.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Thread the direct flag from the disk open options through VhdDisk into
the AlignedFile the workers run on, so a fixed VHD opened with direct=on
issues O_DIRECT I/O instead of buffered I/O. Alignment is probed once on
that AlignedFile and reused by the sync and io_uring workers.
Advertise host topology from VhdDisk::topology by probing the underlying
file. On a 4096 byte sector filesystem opened with O_DIRECT this reports
logical_block_size 4096 to the guest, so the guest never issues 512 byte
I/O that the host kernel would reject as misaligned. Falls back to the
default topology with a warning when the probe fails.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Read the trailing footer sector through an AlignedFile rather than
probing the device topology and reading a full logical block. The
AlignedFile bounce buffer serves the trailing sector of an O_DIRECT
fd whose offset is unaligned against the device block size, so the
read no longer fails with EINVAL on a 4k sector backing store.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The raw sync, io_uring and AIO workers now own an AlignedFile and use
it for the O_DIRECT alignment value and for the unaligned fallback.
Aligned operations keep the fast preadv and pwritev iovec path straight
to the kernel. When the offset or an iovec base or length is not a
multiple of the probed alignment, the worker gathers the iovecs into
one contiguous host buffer and runs a synchronous RMW through
AlignedFile, then scatters the result back into guest memory.
RawDisk constructs the AlignedFile from the disk file and the direct
flag and passes it into each worker, so alignment is probed once at
open time. The fixed VHD workers are threaded through the same
AlignedFile based constructors using a non-direct AlignedFile to
preserve current behavior.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
RawFile wrapped AlignedFile only to add a seek position and the file
trait impls that the qcow and vhost_user_block code expects. Fold that
position and every impl onto AlignedFile so the wrapper layer goes away
and callers work with a single O_DIRECT aware file type.
AlignedFile now tracks a cursor and implements Read, Write, Seek,
WriteZeroesAt, PunchHole, FileSync, SeekHole, BlockBackend, Clone,
AsRawFd and AsFd in addition to the positional FileExt path. The
direct_io flag is dropped because alignment already encodes it, where
a zero alignment means the file was not opened with O_DIRECT.
All RawFile uses in the qcow internals and vhost_user_block move to
AlignedFile, and raw_file.rs is removed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move the statx STATX_DIOALIGN probe out of DiskTopology into a free
probe_direct_alignment helper keyed on a raw fd. The helper gates on the
O_DIRECT open flag and returns the kernel reported alignment only when
direct I/O is in effect, and None otherwise. DiskTopology::probe keeps
the same call path and result.
AlignedFile::new now determines its O_DIRECT block alignment from
probe_direct_alignment instead of trial reads at 512 and 4096, falling
back to SECTOR_SIZE when the kernel does not report a value. This
matches how the raw and fixed VHD workers determine alignment, so all
backends agree on one source of truth.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The boot time tests inferred guest readiness from the two debug I/O
port markers on stderr. Heavier boots could miss the fixed sleep
window, capture a single marker, and panic.
Wait on the cloud-init injected notify-booted callback through
guest.wait_vm_boot() instead. Once the callback fires, both markers
are guaranteed present, so they are parsed only for the metric. The
host side keeps an overall timeout, so a guest that never boots is
still reaped.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This was already handled with user memory zones but not with the default
memory. Make a small refactoring to move the boot RAM check into
MemoryManager rather than split across Vm and MemoryManager.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Import the std modules used in the crate instead of spelling the full
paths at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Add an aarch64 test that pauses a running VM, waits out an interval, and
resumes it on the same host, then asserts the guest wall clock still
matches the host. On aarch64 the architected counter free-runs across
the pause, so the guest self-corrects.
The downtime and skew tolerance are shared with the snapshot clock test.
x86_64 has its own kvmclock path and is covered by the snapshot clock
test.
Signed-off-by: Atish Patra <atishp@meta.com>
Add a variation of _test_snapshot_restore that, after taking a snapshot,
waits out a simulated off-host interval and then restores and resumes,
asserting that the guest's wall clock has caught up to the host. This
exercises the clock catch-up that each architecture provides on restore:
kvmclock (KVM_CLOCK_REALTIME) on x86_64 today, and the CNTVCT advance on
aarch64 with later commits.
On x86_64 the guest is booted with clocksource=kvm-clock as the guest
clock is caught up after pause/resume only in that mode. A
tsc-clocksource guest's restored TSC freezes across the interval and
would never catch up.
Take this opportunity to improve the snapshot restore test as the
existing bare boolean mechanism was bit hard to read with new test.
Signed-off-by: Atish Patra <atishp@meta.com>
Currently, Cloud Hypervisor round-trips CNTVCT_EL0 through
KVM_GET_REG_LIST/SET_ONE_REG, which leaves a cold-restored or migrated
guest behind real UTC by the downtime. Same-host pause/resume
self-corrects (the physical counter keeps running across the pause), so
only restore and migration cases required the clock to catch up to wall
clock time.
Since ARM has no kernel helper, compute the difference in wall clock
time and compute the ticks so that it can advance the CNTVCT correctly.
It is set via vcpu0 only as it affects a single VM wide value after
Linux 6.4. For older kernels, it was a truly vcpu value which needs to
be invoked for every vcpu.
Gated on all(target_arch = "aarch64", feature = "kvm"); x86 is
unchanged.
Basic manual test case (aarch64 + KVM) verified both in intra host and
inter host snapshot save/restore:
1. Boot a Linux guest; in the guest, `date -u` tracks the host's UTC.
2. Pause and snapshot the VM (ch-remote pause; ch-remote snapshot
file:///<dir>).
3. Leave it down for several minutes (the off-host interval).
4. Restore and resume into a fresh VMM (ch-remote restore
source_url=file:///<dir>,resume=true).
5. In the guest, run `date -u` again and compare to the host: the guest
now tracks current UTC, having advanced by ~the time it spent down.
Before this change the restored guest reads behind real UTC by the
downtime; after it, the guest clock is back in sync (to within the
snapshot-to-restore sampling slop).
Signed-off-by: Atish Patra <atishp@meta.com>
Unlike x86, ARM64 has no kvmclock support to sync guest time upon
required. However, the guest reads the architected virtual timer
(CNTVCT_EL0) directly which can be modified by the VMM to update the
time after snapshot restore. Since the CNTVCT is in ticks, we also need
to read CNTFRQ (via mrs due to lack of ONEREG interface) to compute the
ticks from wall clock difference.
Because the counter is a vCPU register, the capture must run with the
vCPUs quiesced, so the VMM now captures the clock just after
cpu_manager.pause() through the boot vCPU. This is behaviorally
identical for x86, whose clock is VM-wide. There is no restore/advance
yet, so aarch64 guests still resume behind real time until the following
commit.
Signed-off-by: Atish Patra <atishp@meta.com>
Currently, VM pause/resume/snapshot paths invoke architecture specific
bits for guest clock udpates which ideally belongs to hypervisor layer.
Route it through the snapshot_clock()/restore_clock() pair added in the
previous commit instead, so the VMM no longer depends on an architecture
specific clock API and the upcoming aarch64 backend can hook the same
path without a parallel branch in vm.rs.
Signed-off-by: Atish Patra <atishp@meta.com>
Preserving the guest clock across pause/resume and snapshot/restore is
currently open-coded in the VMM against the x86-only
get_clock/set_clock. aarch64 needs the same correction but via a
different mechanism (i.e. the architected counter, CNTVCT). Having a
common backend-agnostic interface that VMM can drive uniformly allows us
to keep the architecture details behind the Hypervisor abstraction.
This commit only introduces the abstraction while the future commits
will actually move the implementation to use it.
Use this opportunity to fix the full path to get SystemTime as well.
Suggested-by: Sebastien Boeuf <sboeuf@meta.com>
Signed-off-by: Atish Patra <atishp@meta.com>
Import the std module used in the generated MSR-index file instead of
spelling the full paths at every use site.
The crate-level #![expect(clippy::absolute_paths)] is kept; the
remaining sites in the rest of the crate are handled by a follow-up.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
OpenBSD expects the ACPI _S5_ object to provide both sleep type values.
The single-value package made acpi_init_states() parse an invalid object
and fault during early ACPI setup with:
```
...
acpi0 at bios0: ACPI 6.3
acpi0: sleep statesfatal protection fault in supervisor mode
trap type 4 code 0 rip ffffffff814af264 cs 8 rflags 10282 cr2 0 cpl e rsp ffffffff81a06a30
gsbase 0xffffffff81755ff0 kgsbase 0x0
panic: trap type 4, code=0, pc=ffffffff814af264
Starting stack trace...
panic(ffffffff81a06980,4,ffffffff81a06a58,ffffffff81756ae0,ffffffff81a06960,ffffffff81a068e0) at panic+0x12e
kerntrap(ffffffff81a06aa0,ffff800000232400,ffffffff81261681,ffffffff81a06970,ffffffff81a06980,4) at kerntrap+0xe1
alltraps_kern_meltdown(4,ef0d316e102be1f4,ffff800000232480,0,ffffffff81a06aa0,ffff800000232400) at alltraps_kern_meltdown+0x7b
aml_val2int(ef0d316e102be1f4,0,10,ffffffff81a06a30,10282,8) at aml_val2int+0x24
acpi_init_states(1,ffff800000232400,ffff800000232470,0,ef0d316e102be1f4,5f35535f) at acpi_init_states+0xd5
acpi_attach_common(ffff800000235300,ffffffff81a06cf0,ffffffff81762a00,ffff800000232400,ffff800000232424,ef0d316e102be1f4) at acpi_attach_common+0x311
config_attach(ffffffff81a06d30,ffff800000235300,50,118,ffff80003158c004,ffffffff813e3270) at config_attach+0x1d2
bios_attach(ffff800000235280,ffffffff81a06e28,ffffffff8175ca50,ffff800000235300,ffff800000235324,ef0d316e102be1f4) at bios_attach+0x898
config_attach(ffffffff81a06e28,ffff800000235280,ffffffff81757e68,ffff800000235280,ffff8000002352a4,ffffffff8128c510) at config_attach+0x1d2
mainbus_attach(0,0,ef0d316e102be1f4,ffffffff81a06e50,ffffffff81a06ec0,3000000010) at mainbus_attach+0x70
config_attach(8,1001000,805f50,1000000,ffffffff81a00008,0) at config_attach+0x1d2
cpu_configure(8,1001000,ffffffff814f3859,ffffffff81a06f20,8,1001000) at cpu_configure+0x29
main(1001000,ef0d316e102be1f4,ffffffff812e8b2f,ffffffff81a06f40,8,1001000) at main+0x3af
end trace frame: 0x0, count: 244
End of stack trace.
```
Advertise S5 as the conventional four-element package as described in
the ACPI spec [1]. Cover the generated AML bytes with a unit test.
In AML, the package now looks like this:
```
Name (_S5, Package () {
0x05, 0x05, 0x00, 0x00
})
```
[1] https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/07_Power_and_Performance_Mgmt/oem-supplied-system-level-control-methods.html#sx-system-states
On-behalf-of: SAP thomas.prescher@sap.com
Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
In #8053 it was agreed to use the ring backend in preference to
aws-lc-rs as it is pure Rust. However since aws-lc-rs is a default
feature of rustls the addition of ring was additive not a replacement.
Fix the features to exclude awc-lc-rs.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Closing an io_uring fd does not synchronously finish requests that
already reached the kernel. During block worker teardown this can let
an io-wq worker keep using retained guest-memory iovecs after reset.
Drain UringDataIo in Drop: retry any published SQEs and wait for CQEs
until no retained operation remains. If draining fails, leak retained
buffers. Drop QcowAsync's ring before its data fd so retrying
published SQEs still uses a valid descriptor.
To avoid a potential infinite loop when completions fail to be delivered
cap the number of iterations of the loop (2x the number of inflight
requests).
Assisted-by: Codex:GPT-5
Signed-off-by: Rob Bradford <rbradford@meta.com>
This is not a blocking job but the worker is no longer handling the jobs
so it remains pending indefinitely.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Import the modules used in the crate instead of spelling the full paths
at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Extending the snapshot/restore documentation so that it explains what
are the goals behind this offloaded snapshot/restore feature, how to use
it in practice, and also by documenting the protocol used by the offload
daemon so that anyone could write its own daemon.
By relying on the existing local live migration support and reusing the
semantics and the protocol associated with it, we intend to provide a
way for snapshotting and restoring a VM to/from a dedicated process that
we can call the offload daemon.
By allowing an external process to perform the snapshot/restore actions
on behalf of Cloud Hypervisor, we give our users the opportunity to
implement their own offloaded daemon. The goal is to avoid bloating
Cloud Hypervisor with numerous features related to snapshot/restore, and
let the user decide how to perform the snapshot/restore actions. One
example is that we can decide to encrypt the guest RAM on the fly in
order to avoid writing an unencrypted version to local disk. Another
example is to be able to send guest RAM and associated state/config data
over the network without having to persist the data first to local
storage.
There might be other reasons to choose going with an offloaded daemon to
perform the snapshot/restore of the VM, but in every case, this empowers
the user to make their own choice.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Copy only populated extents when writing the snapshot file and when
filling the restore memfd, leaving unwritten ranges as holes. Both
the on-disk snapshot and the restored guest RAM stay sparse, so that
untouched guest pages cost no disk space or host memory.
This brings the offload daemon closer to be at feature parity with CH's
internal implementation of snapshot/restore. The only missing piece is
on-demand paging at this point.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Move next_data_extent and write_region_sparse out of memory_manager.rs
into a new vmm::sparse module so the snapshot writer, the restore
reader, and the offload daemon can share one implementation.
No functional change intended.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Adding a new dedicated binary that is meant to be used as a reference
implementation for validating that offloaded snapshot/restore works and
meant to be used through tests in general.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Expose VmMigrationConfig as a public facing structure that can be used
by an offload daemon to act as if it was the VM to migrate to, or the VM
to migrate from.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Import the std modules used in the crate instead of spelling the full
paths at every use site, and drop the now-unnecessary
#[cfg_attr(target_arch = "x86_64", expect(clippy::absolute_paths))].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the crate instead of spelling the full
paths at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Fix disk hot unplug failure caused by seccomp SIGSYS kill.
When performing disk hot unplug, the vcpu thread calls fsync()
on the block device file descriptor to flush pending I/O.
The seccomp filter previously blocked SYS_fsync, triggering SIGSYS
and terminating the vcpu thread, which makes the hot unplug
operation fail. This issue exists on both x86 and AArch64.
Strace log snippet captured during failure:
```
[pid 3118852] fsync(142) = 142
[pid 3118852] ---SIGSYS {si_signo=SIGSYS,si_code=SYS_SECCOMP,si_call_addr=0xffff9c931df8, si_syscall=__NR_fsync,si_arch=AUDIT_ARCH_AARCH64}
```
Add unrestricted SYS_fsync entry to vcpu thread syscall allowlist,
consistent with existing file I/O syscalls such as fcntl and fstat.
Signed-off-by: yanjianqing <yanjianqing@kylinos.cn>
Replace assertions for incorrect access sizes with logged errors. The
write_table() method already handled it like this and this commit
extends the same pattern to read_table() and read_pba().
Signed-off-by: Rob Bradford <rbradford@meta.com>
Import the std modules used in the crate instead of spelling the full
paths at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the test module instead of spelling the
full paths at every use site, and drop the now-unnecessary
#[expect(clippy::absolute_paths)] on the vhdx internal test module.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Convert the still-needed #[allow] to #[expect] so it warns if the
lint stops firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow] to #[expect] so it warns if the
lint stops firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow]s to #[expect] so they warn if the
lints stop firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow] to #[expect] so it warns if the
lint stops firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow]s to #[expect] so they warn if the
lints stop firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow] to #[expect] so it warns if the
lint stops firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow]s to #[expect] so they warn if the
lints stop firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Import the std modules used in the crate instead of spelling the full
paths at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the crate instead of spelling the full
paths at every use site, and drop the now-unnecessary
#[expect(clippy::absolute_paths)] on the test module.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the crate instead of spelling the full
paths at every use site, and drop the now-unnecessary crate-level
#![expect(clippy::absolute_paths)].
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
The tests expect some generated images and assets so make sure that they
are there (directly copied from the x86-64 test).
Signed-off-by: Rob Bradford <rbradford@meta.com>
These fail more than they pass due to infrastructure reasons (rather
than tests failing) and so because they are constantly seen as failing
they are ignored (i.e. alarm fatigue).
It is better not to run them until the infrastructure issues have been
fixed.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The sync I/O worker only checked that the operation offset did
not start past the end of the virtual disk (offset >= size) -
did not verify that the operation end (offset + len) stays
within bounds.
A read or write that started inside the image but extended
beyond the logical size was silently passed to the raw backend.
The async io_uring worker already had the correct check
(offset + len > size with overflow protection). I extracted it
into a shared helper in worker/common.rs and reused inside the
sync path to eliminate duplication and close the gap.
Fixes#8311
Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
Reject without asserting that the ACPI CPU hotplug register accesses
match those that are specified by the ACPI definitions.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:Opus-4.7
Reject without asserting that the ACPI PCI hotplug register request
matches what is defined in the ACPI definition.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:Opus-4.7
These devices should only be accessed by single byte accesses as
specified through the ACPI definitions for them.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:Opus-4.7
The RISC-V device tree's timebase-frequency was hardcoded to 10 MHz
(0x989680). Actual hardware uses different frequencies.
Read the timebase frequency from KVM_GET_ONE_REG via
KVM_REG_RISCV_TIMER (offset 0, kvm_riscv_timer.frequency),
thread it through the VMM to arch to FDT layers, and fall back to
the 10 MHz default when KVM returns no value.
Signed-off-by: Meng Zhuo <mengzhuo@iscas.ac.cn>
The number of wired interrupt sources (SRCS) must be less than the
KVM device's maximum interrupt identities (kvm_riscv_aia_max_ids).
Platforms with smaller IMSIC capacity reject values that exceed this
limit.
Query KVM_DEV_RISCV_AIA_CONFIG_IDS before setting SRCS and clamp the
requested value to the reported nr_ids (which equals max_ids - 1).
Signed-off-by: Meng Zhuo <mengzhuo@iscas.ac.cn>
Removal of absolute paths is currently in progress. To avoid regressing
those changes add a clippy deny at the workspace level and at the crate
level override with #[expect(clippy::absolute_paths)]
See: #7670
Signed-off-by: Rob Bradford <rbradford@meta.com>
Acquiring an image lock can be interrupted with EINTR. In this case, we
returned with an error. Instead, we now retry acquiring the lock.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
The CLI `--platform` option now accepts `iommufd_fd=<n>` alongside the
existing `iommufd=on|off`.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Assisted-by: Claude:Opus-4.7
`path` is no longer required in the DeviceConfig, since a VFIO
device may also be supplied via a pre-opened cdev FD passed via
SCM_RIGHTS alongside the /vm.add-device request.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Assisted-by: Claude:Opus-4.7
Add a new `fd: Option<i32>` field to DeviceConfig so a caller can
supply a pre-opened vfio cdev FD (e.g. /dev/vfio/devices/vfioN) in
addition to the existing sysfs path. The CLI `--device` option now
accepts `fd=<n>`, parsed alongside the existing options.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Assisted-by: Claude:Opus-4.7
Relax DeviceConfig::path from PathBuf to Option<PathBuf> in preparation
to accept an externally-opened vfio cdev FD. The parser and OpenAPI spec
still enforces that `path` is set, so callers see no behavior change.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Assisted-by: Claude:Opus-4.7
Update the seccomp filter for vmm and vcpu thread, because `Drop for
VfioIommufd` since vfio-ioctls v0.6.1 now issues IOMMU_DESTROY
to release the IOAS allocated for each VM boot.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Submit a head only virtio-blk chain, confirm Request::parse rejects
it, and verify that add_used with len 0 returns the head to the
guest by advancing the used ring index.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When Request::parse failed, for example for a chain containing only
the head descriptor, process_queue_submit returned the error via
`?`. The caller process_queue_submit_and_signal swallowed
Error::RequestParsing with a warn! and returned Ok(()), but
queue.iter().next() had already consumed the head from the avail
ring. The head was never written to the used ring, so the descriptor
slot leaked and the queue could be stalled by a guest that keeps
submitting malformed chains.
Handle the parse error in line. Log a warning, add the head to the
used ring with len 0, reenable notifications, and continue draining
the queue. A VIRTIO_BLK_S_IOERR status cannot be written because the
status descriptor address is exactly what failed to parse.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introducing a new enum that models the various states of VM ownership
from the perspective of the VMM.
This is an important prerequisite for the asynchronization of the
migration, where the ownership of the Vm struct is transferred to the
migration thread. Specifically, this allows to introduces a new
"Migration(ThreadHandle)" variant and all existing match statements
can be easily extended to react accordingly.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
By redirecting VHDx I/O through the AlignedFile the required RMW
semantics can be achieved for writes less than the logical block size
whilt reusing the same logic used for other backend implementations.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Reuse the functionality in the AlignedFile wrapper for the QCOW RawFile
wrapper. This makes alignment handling more transparent.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Provide a single home for O_DIRECT alignment and RMW behavior behind an
std::os::unix::fs::FileExt implementation built on AlignedBuffer.
Unaligned requests are bounced through an AlignedBuffer (applying RMW
for writes) and aligned requests pass straight through to the inner
File.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace the use of the pread64/pwrite64 helpers with versions from
std::os::unix::fs::FileExt.
As this was the last use of these pread functions remove them and their
tests.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace the qcow specific AlignedBuf along with the pread64/pwrite64
helpers with the new common AlignedBuffer implementation.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace use of raw pread64/pwrite64 functions with
std::os::unix::fs::FileExt for I/O without a cursor.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace the manual alloc_zeroed/dealloc and pread64/pwrite64 with use of
the new AlignedBuffer structure.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
The block code repeatedly open-codes O_DIRECT alignment calculations and
bounce-buffer allocation at each I/O site. Add an AlignedBuffer struct
that handles the alignment and allocation in one place, using FileExt
(read_exact_at and write_all_at) for the I/O (so no need for custom libc
wrappers).
The caller creates an AlignedBuffer with an offset, length and
alignment, then uses read_from and write_to for aligned I/O and as_slice
and as_mut_slice to access the logical data portion within the aligned
region.
This is a lot like the AlignedBuf that was already existing in the QCOW2
code but is a more generalised version.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
Implement std::os::unix::fs::FileExt for RawFile by delegating to the
inner File. This enables callers holding a reference to a RawFile to use
read_exact_at and write_all_at directly for non-cursor I/O (like pread,
etc) without going through custom helper functions.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
The Microsoft "Requirements for Implementing the Microsoft Hypervisor
Interface" document marks exactly two privileges in CPUID leaf
0x40000003 EAX as "Must be set": AccessHypercallMsrs (bit 5) and
AccessVpIndex (bit 6). Cloud Hypervisor advertised neither.
Without bit 5, Windows guests abort enlightened-mode initialization
before timer-API selection: HalpHvTimerApi is left NULL and every
QueryPerformanceCounter call falls back to reading
HV_X64_MSR_TIME_REF_COUNT (0x40000020), costing one VM exit per call.
The guest never writes HV_X64_MSR_REFERENCE_TSC (0x40000021) to enable
the reference TSC page, even though AccessPartitionReferenceTsc (bit 9)
is advertised.
With both bits set, Windows 10 22H2 and Windows 11 25H2 guests enable
the reference TSC page at boot. Measured QueryPerformanceCounter
throughput on a nested-KVM host went from ~71K calls/sec (14 us/call,
one MSR exit each) to ~1.3M calls/sec (free, no exits); on bare metal
from ~390K to ~1.9M calls/sec. Guest idle CPU and interrupt-service
time drop correspondingly.
Both MSR ranges are already handled in-kernel by KVM unconditionally,
so no backend change is needed. Bisection across the full delta to
QEMU's Hyper-V CPUID layout (vendor ID, max leaf, leaves 4-6 contents,
build number) shows bit 5 is the only load-bearing change; bit 6 is
included per the conformance document's mandate.
Signed-off-by: Tonic Li <tonic@simular.ai>
Signed-off-by: tonic <tonicbupt@gmail.com>
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Cover the prior commit by constructing a Request directly and a stub
AsyncIo whose backend methods are unreachable, then submit a payload
with sector + num_sectors past u64::MAX and assert BadRequest.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
In Request::execute_async the WriteZeroes arm multiplied wz_sector
by SECTOR_SIZE before the checked_add of sector and num_sectors.
A wz_sector near u64::MAX overflows the multiplication.
Reorder the arm to run the checked_add and disk_nsectors check
first, matching the Discard arm above.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used in the disk-format handlers instead of
spelling the full paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
During pause the block backend's async I/O path can have unfinished I/O
requests. A snapshot or migration RAM copy taken after pause returns can
then race with kernel writes and capture torn pages.
Since vCPUs are already paused, the VMM thread can stop new block
submissions and wait for the worker to drain before parking the worker
threads.
Assisted-by: Codex:GPT-5
Signed-off-by: Dylan Reid <dgreid@fb.com>
Remove stale #[allow]s whose lints no longer fire, convert the
unconditionally-firing ones to #[expect], and keep the conditional
ones as #[allow] (e.g. large_enum_variant only fires when both kvm
and mshv are enabled; a nonminimal_bool only on x86). The many
unreachable_patterns allows are feature-gated and left as #[allow].
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Remove stale #[allow]s whose lints no longer fire (a module-level
non_camel_case_types in mpspec, and a too_many_arguments on a riscv64
configure_system that no longer exceeds the argument threshold), and
convert the still-needed ones to #[expect].
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow]s to #[expect] so they warn if the
lints stop firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Since igvm is a required feature of sev_snp and also sev_snp is x86-64
only the cfg attributes at build time can be consolidated & simplified.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Validate that the PCI segment specified is a valid PCI segment ID (less
than the number of segments specified) defaulting to default if no
segments are specified because no there is no platform configuration.
See: #8376
Signed-off-by: Rob Bradford <rbradford@meta.com>
This test has a copy and paste error where the PCI segment ID was being
set with no extra segments configured.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This test has a copy and paste error where the PCI segment ID was being
set with no extra segments configured.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Validate that all files that are necessary for TLS encryption are in the
given folder. The knowledge which files are necessary is part of the TLS
module.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
As we now have more than one parameter for the receive migration call,
this commit also adds parsing and validation for those parameters. We
maintain backwards compatibility by also correctly parsing the case
where the caller only provides a URL.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
For TLS we have to parse the hostname from the given migration URL. For
that we have to make a few assumptions about the URL (e.g. it always has
a port). To catch problems early, we tighten the URL validation.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Extend ReceiveListener with a TLS-backed listener variant for migration
receivers.
Store the TCP listener together with the server TLS configuration, wrap
accepted sockets in TlsStream::new_server(), and preserver the existing
listener cloning and fd polling behavior so receive-side migration code
can treat TLS listeners like the existing TCP and UNIX cases.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Teach the migration transport to handle TLS-backed streams alongside
plain TCP and UNIX sockets.
Introduce a Tls variant in SocketStream and implement the necessary
traits.
Also updates the local-migration error path to reject any non-UNIX
transport, which now includes TLS-wrapped TCP connections.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
TLS connections have a TLS server (listens for incoming connections) and
a TLS client (initiates the connection). This commit adds the code for
the client side, which is the sender of a migration
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
ReadVolatile already provides a default read_volatile_exact()
implementation, and WriteVolatile a default write_volatile_exact()
implementation. Overriding these functions adds no behavioral value, but
duplicates logic and needs to be updated whenever SocketStream gains or
changes a variant.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
When the host half-closed the socket this was wrongly interpreted as a
full shutdown preventing the guest from sending any more data. Instead
propagate the half-close by setting just `VSOCK_FLAGS_SHUTDOWN_SEND`,
leaving the connection alive so that guest-to-host writes are still
forwarded. The connection is only torn down once the guest also shuts
down its send side or a host write fails.
Fixes: #8300
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Rob Bradford <rbradford@meta.com>
When the guest did a half-close (shutting down only its send side) the
connection state was updated but the write half of the host Unix socket
was never closed so the host peer never saw an EOF. This caused issues
with newer systemd (v256+) as it now half closes its socket and waits
for the host side to react and fully close the connection.
Propagate the guest's half-close to the host by shutting down the write
half of the backing stream. This is deferred until any buffered guest
data has been flushed so that no data is lost, and the connection is
left open so that host-to-guest data keeps flowing.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Rob Bradford <rbradford@meta.com>
Split `add_pci_device()` into two phases: `allocate_pci_bars()` which
only allocates BAR address space, and `commit_pci_device()` which
makes the device visible to the guest on the PCI bus.
All callers now follow the pattern: allocate BARs → perform device-
specific setup (ioeventfd, device_tree, mmio mapping) → commit device.
This eliminates a race window where the guest could discover a
partially-initialized device via `acpiphp_check_bridge()` during rapid
sequential hotplug, causing BAR reprogramming to fail because
ioeventfds and device_tree entries were not yet in place.
Signed-off-by: wuxinyue <wuxinyue.wxy@antgroup.com>
Assisted-by: Claude:Opus-4.6
`PciBus::register_mapping()` operates on `mmio_bus` and `io_bus`
which are passed in as external parameters and have nothing to do
with PciBus internal state. Move this logic into
`DeviceManager::register_bar_mapping()` where it belongs, and move
the `PioInsert`/`MmioInsert` error variants from `PciRootError` to
`DeviceManagerError` accordingly.
Signed-off-by: wuxinyue <wuxinyue.wxy@antgroup.com>
Assisted-by: Claude:Opus-4.6
Remove stale #[allow]s whose lints no longer fire, convert the
unconditionally-firing ones to #[expect], and keep the
arch/feature-conditional ones as #[allow]. Verified across kvm/mshv,
x86_64/aarch64, and --all-features.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Convert the still-needed #[allow]s to #[expect] so they warn if the
lints stop firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Drop stale #[allow]s whose lints no longer fire and convert the
still-needed ones to #[expect] so they warn if the lints stop firing.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Remove a stale #[allow(non_camel_case_types)] whose lint no longer
fires; the enum variants are already CamelCase.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
Currently ejecting a device leaks its mapping keeping the container fd
open. Remove the mapping so the fd can be closed.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Dylan Reid <dgreid@fb.com>
Document how live migration protocol versions are handled, including
the supported current/previous version window and the need to migrate
through an intermediate Cloud Hypervisor version for larger version
gaps.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Print the supported vm-migration protocol version range in
cloud-hypervisor --version as an extra line:
vm-migration protocol versions v0-v1
This makes the currently supported compatibility window
visible without having to inspect the migration code.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
The cloud-hypervisor binary prints vm-migration protocol constants
directly, so it needs its own dependency on the vm-migration crate
instead of relying on vmm's transitive dependency.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Validate the sender's migration protocol version when
handling the initial Start request.
Read the version from the Start command header, accept only
the supported version window n-1..=n, and reject unsupported
versions with Error. A rejected Start moves the receiver to
the aborted state.
This keeps compatibility one-way, from older protocol
versions to newer ones, and leaves later version-based
branching on the receiver side.
Log the protocol version on both sender and receiver to make
the active migration path visible.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Add protocol-side support for migration protocol versioning.
Use the existing 6-byte Start command header, which was
previously zero padding, to carry the sender's migration
protocol version without changing the wire layout.
Store the version as a little-endian u16 in the first two
bytes and ignore the remaining four bytes. A zeroed command
header continues to mean a legacy v0 sender.
This keeps the message flow unchanged for rollout:
Start is still followed by plain OK or Error (Aborted), and no new
command is needed.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Import the modules used in the crate instead of spelling the
fully-qualified paths at every use site, and collapse Result<T,
io::Error> into io::Result<T>. This covers the feature-gated modules
(fw_cfg, ivshmem, pvmemcontrol) as well, leaving the whole crate free
of clippy::absolute_paths warnings.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Drop stale #[allow]s whose lints no longer fire and convert the
rest to #[expect], which warns if they ever stop being needed.
Part of #8326.
Signed-off-by: Tushar Khatri <hello@tusharkhatri.in>
During migration send one final set of changed memory after capturing
the snapshot/state. This captures any memory changed as a side effect of
capturing that state. In particular with vhost-user capturing the device
state can lead to inflight requests being drained/flushed which could
change memory. As this is related to the snapshot account for this
memory transfer in the snapshot metrics.
No equivalent change is needed for snapshot as the memory is written
after the state is snapshotted.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Query and save the dirty log before shutting down the vhost-user device.
This allows any final dirty memory ranges to be recorded before it
becomes impossible to do that as the vhost-user handle has been closed.
This is required to ensure that all memory writes have been correctly
recorded that may be triggered by inflight I/O drains from vhost-user
device state capture.
One small implementation wrinkle: with local migrations there is no
dirty logging (since we just pass the memory FD over the socket) so
calling dirty_log() would generate an error. As there is no clean way to
query if dirty logging has been started add a boolean to track if its
active.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Rather than each device implementation holding a reference to the guest
memory move this to VhostUserCommon. This refactoring simplifies the
function signatures but also allows for methods that act on
VhostUserCommon that don't have the memory available to them.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Currently both kvm and mshv require an IGVM file to boot a SEV-SNP VM.
This is already configured in the top-level cloud-hypervisor
Cargo.toml where sev_snp depends on igvm.
Add a similar dependency in the vmm crate which helps simplify some of
the in-code cfg blocks by removing the ones that are within a sev_snp
cfg block.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Import the modules used in the crate instead of spelling the
fully-qualified paths at every use site. This covers std paths along
with a few crate-internal and external-crate paths, leaving pci free of
clippy::absolute_paths warnings.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Re-enable the fw_cfg integration tests for MSHV now that port string I/O
is handled by the hypervisor backend.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:GPT-5.5
Handle MSHV INS/OUTS port intercepts by translating the guest string
operand through MshvEmulatorContext and copying data between guest
memory and existing PIO callbacks.
Support REP counts, zero-count REP, and direction-flag based RSI/RDI
updates. Commit RIP plus RCX/RSI/RDI after the transfer completes.
This removes the fw_cfg/debug-port skip. OVMF can now use the real
string I/O path instead of relying on ignored ports.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:GPT-5.5
Decode MSHV port access size, direction, string, and REP state through
small helpers instead of open-coded bitfield reads.
Keep scalar I/O behavior unchanged and continue rejecting string I/O in
this step. Put the x86_64 port I/O helpers in their own module so the
string emulation path can grow without bloating the top-level MSHV code.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:GPT-5.5
Move common string instruction bookkeeping into the x86 instruction
emulator so MOVS, STOS, and MSHV port string I/O use one implementation
for REP counts, direction-flag handling, and index advancement.
This keeps existing MOVS/STOS behavior unchanged while removing the need
for MSHV to open-code the same string-operation details.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:GPT-5.5
Move scalar HVMSG_X64_IO_PORT_INTERCEPT handling into a helper so the
string I/O implementation can build on the same dispatch path.
Keep the existing fw_cfg/debug-port skip plus string/REP assertions in
place. This is only code movement so later changes are easier to review.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Copilot:GPT-5.5
Turn reserve=on for the hugepage-backed memory zone in the UFFD
snapshot/restore integration test. Hugepages are the most likely place
to want reserve (an over-committed huge page pool is exactly the case
that otherwise SIGBUSes the guest), so this is the natural test to give
the option real coverage, as suggested in review.
It exercises the reserve mmap path twice: once on the source VM boot and
once on the demand-paged restore. The existing skip guard already
requires the 256 free 2MiB pages this zone needs, and the source VM is
killed before the restore VM is started, so reserving from the pool
never has to back two VMs at once.
Assisted-by: Claude Code (Opus 4.8)
Signed-off-by: Ian Klemm <hi@ianklemm.de>
Cloud Hypervisor maps guest RAM with MAP_NORESERVE, so the kernel never
reserves the backing pages at mmap time. On a host whose hugepage pool
cannot satisfy every guest, a VM is created successfully and then takes
a SIGBUS when the guest faults a page the pool can no longer back. This
is the failure mode reported in #5730 and #7387. As noted on #5730,
checking free pool headroom up front is not a reliable fix: another
process can consume pages between the check and the fault.
Add a reserve=on parameter to --memory and --memory-zone (default off,
preserving the current MAP_NORESERVE behaviour). When set, the region
is mapped without MAP_NORESERVE, so the kernel reserves the backing
pages (swap, or huge pages for hugepage-backed memory) at mmap time,
atomically with the mapping. An over-committed configuration then
fails cleanly at VM creation with an mmap ENOMEM instead of crashing
the guest later. Unlike prefault it does not fault the memory in, so
it does not slow down boot.
This mirrors QEMU's memory-backend reserve property, which has the same
name and meaning (reserve=off maps with MAP_NORESERVE). reserve is
threaded through the same mmap paths as the existing prefault option,
and is exposed in the OpenAPI schema, CLI help and docs. The top-level
--memory reserve=on path is unchanged: the default zone is synthesised
from MemoryConfig and inherits its reserve value.
Assisted-by: Claude Code (Opus 4.8)
Signed-off-by: Ian Klemm <hi@ianklemm.de>
remove_userspace_mapping tears down the KVM mapping but never returns
the slot id to the allocator's free list. Call `free_memory_slot` to
avoid the leak.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Bring the confidential VM (CVM) integration tests up on the KVM SEV-SNP
backend in addition to MSHV. On KVM the IGVM is an Oak stage0 firmware
image and the guest kernel is supplied separately: stage0 reads the
kernel, cmdline and E820 over fw_cfg. The test harness selects this
model when a guest kernel is present at /igvm_files/bzImage, mirroring
how the stage0 IGVM is discovered; MSHV keeps using the monolithic IGVM
with the kernel baked in.
- test_infra: stage0 + direct-kernel + fw_cfg boot wiring (both the
command line and the HTTP/D-Bus API path) plus an on_kvm_sev_snp()
helper for tests to branch on.
- tests: the CVM tests that don't work on the KVM SEV-SNP path yet are
gated with #[cfg(not(feature = "kvm"))] inside the common_cvm module.
The MSHV build enables mshv,igvm,sev_snp (no kvm feature) while the
KVM build enables kvm,igvm,sev_snp,fw_cfg, so the cfg compiles these
tests into the MSHV binary only and drops them on KVM; both
hypervisors run the single common_cvm nextest profile. They all still
run on MSHV:
* test_pci_multiple_segments - stage0 places all 64-bit BARs in a
single global window, so a BAR allocated in a different
per-segment window is relocated cross-window and wedges boot.
* test_dmi_uuid / test_dmi_oem_strings /
test_dmi_system_and_chassis - SMBIOS is not delivered to SEV-SNP
guests on the KVM stage0 boot path, so the guest's DMI tables
read empty. VMM follow-up.
* test_vdpa_block - needs host vdpa_sim_blk setup, and vDPA DMA
into SEV-SNP-encrypted memory is unsupported (the guest hangs).
Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
FwCfgConfig already has a Default impl (e820/kernel/cmdline/initramfs/
acpi_tables = true, items = None), but deserialization did not use it:
without serde default every field was mandatory, so any caller building
a payload config over the API had to spell out the whole object even to
flip a single flag.
Add a container-level #[serde(default)] so missing fields fall back to
FwCfgConfig::default(). The container form is required here because the
defaults are all true; a per-field #[serde(default)] would resolve bool
to false and contradict the Default impl.
This lets callers send only the fields that differ from the defaults.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
validate_memory() asserts that the guest's reported MemTotal exceeds the
expected size, but on failure printed nothing about either value.
Include both the actual and expected figures in the panic message so a
failing run is self-explanatory.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
The KVM SEV-SNP net-hotplug integration tests (supported added in
later commits) intermittently kill the VMM with SIGSYS on the
http-server thread. The thread is seen reading
/proc/sys/vm/overcommit_memory (openat + read).
Allow the syscalls there, gated on sev_snp+kvm. seccomp can't match
a path, so the open is restricted to O_RDONLY.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
On KVM, an SEV-SNP guest opens /dev/sev at VM creation and passes
its fd as kvm_sev_cmd.sev_fd. KVM uses it to issue the SNP_LAUNCH_*
commands. The open happens after the landlock ruleset is applied,
so grant rw access to /dev/sev when the sev_snp platform feature
is enabled.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
A confidential guest (e.g. SEV-SNP) requires every virtio device to
advertise VIRTIO_F_ACCESS_PLATFORM so the guest driver routes DMA
through the platform's bounce-buffer path; the driver refuses a device
that does not offer it.
Add VIRTIO_F_ACCESS_PLATFORM support to virtio-{watchdog,iommu} which
are exercised as part of the CVM integration tests.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Import the std modules used in the crate instead of spelling the full
paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import std::fmt and std::result instead of spelling the full paths at
every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
The guest kernel build instructions in the README referenced the
ch-6.12.8 branch, which was inconsistent with the version used by the
test scripts (scripts/test-util.sh uses ch-6.16.9). Update the README
to point at ch-6.16.9 so documentation and CI stay in sync.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Delete the now unused QcowFile implementation it was only used for
creating disk images for the tests and for the performance-metrics. It
was not used for the virtio-block device.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Pull rebuild_refcounts out of QcowFile so QcowFile can be removed in a
follow up commit. This function is still required by parse_qcow().
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Port the internal/mod.rs tests from QcowFile to QcowDisk so
the surviving tests exercise the code paths that are hit when used via
QcowDisk (and thus virtio-block).
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Fuzzing QcowFile, which is not used by virtio-block, is less helpful
than using the abstraction that is. Ensure we cover at least the same
functionality as before.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch from QcowFile to QcowDisk taking advantage of QcowTempDisk where
appropriate.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Port tests over to QcowTempDisk and also over to QcowDisk rather than
QcowFile where necessary.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
A common pattern in the test code is to create a temporary file, format
it as QCOW2 and then open it as a QcowDisk. Create a helper struct that
can be used in those tests. This is marked as #[cfg(test)] as initially
it will only be used by the test suite.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add a method to format a file as a QCOW2 file which will mainly be used
by the test infrastructure. This copies the logic from QcowFile. It
doesn't refactor it as the removal of QcowFile is planned.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Rob Bradford <rbradford@meta.com>
With socket serial output now buffered and replayed on connect, a
late-connecting client receives the whole boot backlog. The pty
interaction test had three problems with that:
- pty_read() slept a second between 512-byte reads and the loop consumed
one chunk per two-second tick, far too slow to drain the backlog. Read
in larger chunks without the per-read sleep and drain everything
available each round; bound the loop so a missing marker can't run to
the harness timeout.
- it wrote the login keystrokes before reading, so the unread backlog
back-pressured the sender and the keystrokes never reached the prompt.
Start reading concurrently with typing instead.
- the socat pty was created with echo on, so the replayed backlog was
echoed back to the guest as serial input, flooding it (UART input
overrun, login never completing). Create the pty with echo=0.
Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
In Socket serial mode the device output sink was only installed once a
client connected, so output produced beforehand (kernel boot messages,
cloud-init) was dropped, and a client attaching after boot saw a blank
screen. Only PTY mode wrapped the sink in a SerialBuffer.
Install a persistent SerialBuffer as the Socket device's output sink at
SerialManager construction (discarding downstream via io::sink() until a
client connects), so output is captured into the 1 MiB ring even with no
client attached. On connect, retarget the buffer at the accepted client
and flush the backlog before live output resumes; on disconnect, keep
buffering so output produced while no client is attached is delivered to
the next one. The accepted socket is made non-blocking via
set_nonblocking() so a slow client cannot stall the vCPU thread
(SerialBuffer re-buffers on WouldBlock).
The serial-manager thread gains two syscalls under seccomp: sendto
(replaying the backlog is the first time it writes to the socket) and
ioctl restricted to FIONBIO, which is what set_nonblocking() issues.
Fixes: #7907
Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
SerialBuffer owns its downstream writer privately, with no way to
replace it. Buffering the Socket console requires keeping one buffer
alive across client connects and disconnects and pointing it at each
newly accepted client (or a discarding sink when none is connected)
without dropping bytes buffered while no client was attached.
Add set_out(), which swaps the writer while leaving the buffered
contents intact, plus unit tests covering accumulate-while-detached,
replay on connect, live pass-through, delivery of while-detached output
to the next client, and that bytes already drained by one client are not
resent to the next.
Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
Import std::io instead of spelling the full paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
Import the std modules used across the crate instead of spelling the
full paths at every use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.8
KVM will emulate XSAVE for us, so we need only to skip XCRS
setting/retrieval if the respective CPU feature is not available.
Signed-off-by: Nikolas Kyx <55556836+nyx191@users.noreply.github.com>
eject_device calls shutdown, but Block doesn't implement it, so the
worker thread was never joined. Drop for Block does not help either,
VirtioPciDevice keeps an Arc<Mutex<Block>> past eject, so Drop never
runs. The async worker keeps completing in-flight I/O into the guest RAM
that backed it when issued.
Implement shutdown() to call wait_for_epoll_threads(), which drops the
WorkerThreads handle and ensures that worker's io completes.
Signed-off-by: Dylan Reid <dgreid@fb.com>
server_api_error_display_modifier deserialized the JSON error response
into a `Vec<&str>`. However, if the error message contained escaped
characters, it could not deserialize it into a borrowed string `&str`
because unescaping requires allocation. This resulted in a
deserialization error and a failure to print the error chain.
This change switches the deserialization target to `Vec<String>` to
allow allocation.
Signed-off-by: Andrei Vagin <avagin@google.com>
The snapshot and restore subcommands in ch-remote had optional
snapshot_config and restore_config arguments, but the implementation was
unconditionally unwrapping them.
This change marks these arguments as required to handle the missing
argument validation and report a proper error message instead of letting
the application panic.
Signed-off-by: Andrei Vagin <avagin@google.com>
Prevent `SkuNotAvailable` errors for mshv workflow by checking capacity
restrictions for each location. Enhance the VM provisioning logic to
validate resource availibility before deployment.
Signed-off-by: Aastha Rawat <aastharawat@microsoft.com>
Describe --hypervisor as an optional override that defaults to
auto-detection from the host device node (/dev/mshv or /dev/kvm) for
both the build and tests commands and the shared test-script arguments.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Drop the explicit --hypervisor mshv from the mshv integration workflow.
The runner exposes /dev/mshv, so dev_cli.sh now selects MSHV through
auto-detection.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Make the --hypervisor argument optional for the build and tests
commands. Add detect_hypervisor_device() and resolve_hypervisor_device()
helpers that map an explicit kvm/mshv name to its device node, or fall
back to probing /dev/mshv and /dev/kvm on the host when the flag is
omitted. The resolved device is validated before it is mounted into the
container, and an explicit --hypervisor is still forwarded to the test
scripts.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Make the --hypervisor argument optional in process_common_args().
When it is not supplied, detect_hypervisor() now selects the backend
from the host device node: /dev/mshv for MSHV, /dev/kvm for KVM, and
errors out when neither is present. An explicit --hypervisor still
overrides the detection.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Local-time log fields called `jiff::Zoned::now()`, which resolves the
system timezone on every record by reading
`/etc/localtime`/`/etc/timezone` if it doesn't hit the cached version.
This cache miss could then cause a seccomp violation depending on the
thread it was run from.
Avoid this by capturing the value in `Logger`. This avoids opening the
seccomp filter for the whole process.
Signed-off-by: Dylan Reid <dgreid@fb.com>
If `KVM_GET_CLOCK` already filled out the `realtime` field, it sets the
`KVM_CLOCK_REALTIME` flag, but if we instead preserve this flag, the
kernel will automatically adjust the kvmclock clock when calling
`KVM_SET_CLOCK` based on the elapsed wall-clock time between pause and
resume. This just requires removing the `reset_flags()` function, which
allows the `KVM_CLOCK_REALTIME` flag to persist in the serialized clock
state.
However, the kernel does not always fill the `realtime` field, depending
on clock source; in this case, fill `realtime` during pause based on the
system time. This is not as precise as the automatic `KVM_GET_CLOCK`
version, since we query the time slightly after the vCPU was paused, but
it allows the clock to be resumed mostly in sync instead of being wildly
off. In this case, we also set the `KVM_CLOCK_REALTIME` flag in the
saved `struct kvmclock` so `KVM_SET_CLOCK` will adjust the clock on
resume.
Basic test case:
1. Run a VM with a Linux guest.
2. Pause the guest via `vm.pause` API.
3. Wait several minutes.
4. Resume the guest via `vm.resume` API.
5. Verify the guest time (e.g. via `date` command) is valid.
6. Verify guest is still using `kvm-clock` timesource:
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
Before applying the patch, the guest clock would be off by the delta
time between pause and resume; after the patch, the clock is (more or
less) in sync with the correct wall-clock time.
Old snapshots will not have the `KVM_CLOCK_REALTIME` flag populated, so
they will not be affected by the new behavior.
Signed-off-by: Daniel Verkamp <drv@meta.com>
The API socket path was removed unconditionally when the process
exited, including on a failed start. On a failed start where another
running instance already held the path, that deleted the live
instance's socket.
Remove the socket only when start_vmm returned Ok, meaning this process
owned and bound it. A stale socket left by a crash is cleaned up under
the lock by the next start, so dropping the unconditional removal does
not leak sockets, and a failed start no longer clobbers a socket owned
by another instance.
Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
When Cloud Hypervisor crashed or was killed, the API socket file was
left on disk, so the next start failed with EADDRINUSE ("Address already
in use") and the VMM could not restart. This affects any environment
where the socket directory survives across restarts (systemd services,
Kubernetes emptyDir volumes, and so on).
Before binding the path-based API socket, take an exclusive lock on a
sidecar "<socket>.lock" file using the block crate's OFD-lock helper.
Holding it proves no other instance is bound to this path, so a stale
socket left by a crashed run can be removed safely and race-free. If
the lock is already held, fail with a clear "API socket is already in
use" error instead of clobbering the live instance. The lock is held
for the process lifetime and released by the kernel on exit or crash.
The fd-based (socket-activation) path is left unchanged.
This implements the lock-file approach suggested by @DemiMarie.
Fixes: #7784
Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
Fix racy seccomp kill on shutdown. When a VM shuts down the
event-monitor thread's recv() loop ends and the thread exits. glibc's
thread teardown then runs __malloc_arena_thread_freeres, which trims the
per-thread malloc arena with madvise(MADV_DONTNEED).
Add madvise to the allowed calls to match other threads. The crash is
intermittent because it only fires when that thread's arena accumulated
trimmable memory by shutdown.
Signed-off-by: Dylan Reid <dgreid@fb.com>
VmConfig and its nested configuration structs, the VmInfoResponse
wrapper and DeviceNode serialize their Option<T> fields as JSON null
when unset. The OpenAPI specification types these fields as
non-nullable, so strict client generators (for example ogen for Go)
reject /vm.info responses and cannot generate a working API client.
Apply serde_with's skip_serializing_none to the affected structs so
that unset optional fields are omitted from the serialized JSON instead
of being emitted as null. API responses now validate against the
existing specification unchanged; no nullable annotations are required.
Fixes: #7775
Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
The HTTP API mapped every ApiError to 500 Internal Server Error, so an
API client could not distinguish "the VM has not been created yet" from
a genuine server-side failure without parsing the error message text.
Derive the HTTP status code from the error itself in error_response():
errors whose root cause is VmError::VmNotCreated or VmMissingConfig are
now reported as 404 Not Found, regardless of which API action surfaced
them. The existing 400 (bad request) and 429 (too many requests)
mappings are preserved.
State-conflict errors such as VmNotRunning would ideally map to 409
Conflict, but micro_http's StatusCode has no Conflict variant, so they
remain 500 for now.
Fixes: #7774
Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
Feed Ok into VirtioPciDeviceActivator and assert that activate returns
Ok, device_activated becomes true, DEVICE_NEEDS_RESET is not set,
status is otherwise unchanged, no Config interrupt is delivered, and
the barrier waiter unblocks normally.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Feed BadActivate into VirtioPciDeviceActivator and assert that the
error propagates, device_activated stays false, DEVICE_NEEDS_RESET is
set in status, a single Config interrupt is delivered, and a thread
waiting on the activation barrier unblocks. The barrier release is
the deadlock fixed by the NEEDS_RESET on activation failure change.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add TestVirtioDevice with a controllable ActivateResult,
TestVirtioInterrupt that records delivered interrupt types, and a
make_activator helper that builds a complete VirtioPciDeviceActivator
with observable status, activated flag, interrupt log, and barrier.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When the guest writes DRIVER_OK and the device fails to activate, the
VMM previously bubbled the error up via VirtioActivate and never
released the activation barrier, leaving the vCPU that wrote DRIVER_OK
blocked on the barrier and effectively deadlocking the guest.
Per virtio 1.3 section 2.1.2, a device that has experienced an error
it cannot recover from should set DEVICE_NEEDS_RESET in its status and
notify the driver via a configuration change interrupt. Do that on
activation failure through the existing mark_device_needs_reset
helper, then release the activation barrier so the vCPU can resume.
DeviceManager::activate_virtio_devices now logs and continues instead
of aborting the whole pending list, so one failing device does not
take down the VMM or block pause and migration. The activator has
already reported the failure with the device id.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Boot Windows with vTPM enabled and verify the TPM device enumerates
after the guest is reachable.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Extend test_tpm to issue random, fixed-property, PCR read, and PCR
event commands before and after a guest reboot.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Cover the short CRB register accesses and data-buffer boundary
conditions used by Windows Server 2025.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Extract the TPM2_Startup(CLEAR) response-code check so the accepted
swtpm reset results can be covered directly.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Extract CRB completion, register-read, and data-buffer range handling
so the fixed access rules can be tested without a live TPM backend.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Windows reboot recreates the TPM device while the swtpm process keeps
running. Leaving the transferred data fd open made a later CmdSetDatafd
fail, and the backend could remain unstarted after CmdInit.
Close both ends on setup failure, close the local transferred fd after
success, close the data fd on drop, and issue TPM2_Startup(CLEAR) after
CmdInit while tolerating an already-started TPM.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Windows can access CRB registers with byte-sized writes and reads. The
TPM device model used the byte offset as a u32 register index, which
corrupted unaligned accesses and could expose invalid CRB state.
Preserve the containing register on partial writes, read from the
correct byte lane, allow exact-end buffer accesses.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
RX packet assembly checks descriptor capacity before the backend sees
the packet. The backend then updates hdr.len before the header is
written back.
Validate that final length before committing the header, so we never
tell the guest that more bytes were written than fit in the RX buffer.
Assisted-by: Codex:GPT-5
Signed-off-by: Dylan Reid <dgreid@fb.com>
Remove the need for unsafely materializing slices from guest memory
pointers which is, by definition, undefined behavior.
Achieved by introducing a TxBufSource trait that is implemented for both
types of sources (Guest Memory or local copy) and by using the volatile
read/write primities for moving data from a readable or writable to
guest memory.
Assisted-by: Codex:GPT-5
Signed-off-by: Dylan Reid <dgreid@fb.com>
Keep packet data as a checked guest memory range and add helpers for
volatile reads and writes. Arguably VsockPacket should hold a
VolatileSlice for the guest memory usecase, but the lifetime tracking
involved wasn't worth it.
Keep the old slice accessors for now so existing callers still build.
The next commit switches them over.
Assisted-by: Codex:GPT-5
Signed-off-by: Dylan Reid <dgreid@fb.com>
The helper only needs to update the packet len field. Use write_slice()
instead of rebuilding a mutable slice from a raw host pointer.
Assisted-by: Codex:GPT-5
Signed-off-by: Dylan Reid <dgreid@fb.com>
The helper used to communicate the TPM Establishment bit between the
swtpm backend and the CRB device had inverted semantics:
self.established_flag = est.resp.bit == 0;
so `established_flag == true` actually meant "*not* established". The
device-side call site then double-negated:
if !self.emulator.get_established_flag() {
val |= 0x1; // tpmEstablished in TPM_LOC_STATE
}
The end-to-end behaviour was correct but the boundary between the
swtpm-specific backend and the (TCG-spec defined) CRB device was hard
to follow and easy to misuse -- the now-removed pre-init check in
Emulator::new() was an example of that confusion (it errored out with
"TPM not in established state" precisely when the TPM *was*
established).
Per the TCG PC Client Platform TPM Profile (PTP) specification, bit 0
of TPM_LOC_STATE_x is `tpmEstablished`:
* 0 = default state after a cold reset
* 1 = a TPM2_Startup from Locality 3 or 4 has occurred
Rename the backend accessor to `get_established_bit()` and return the
bit value directly (true == 1, false == 0). The CRB device then simply
forwards the bit, with no inversion, which makes the spec mapping
obvious and removes swtpm-flavoured naming from the device layer.
No functional change.
Asissted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Emulator::new() refused to start the VMM unless the TPM Establishment
bit (TPM_LOC_STATE.tpmEstablished, bit 0) was already set, aborting
with "TPM not in established state" otherwise.
That gate is not justified by the TCG PC Client Platform TPM Profile
(PTP) specification:
* tpmEstablished == 0 is the defined default state after a cold
reset of the TPM.
* The bit transitions to 1 only after a TPM2_Startup is issued from
Locality 3 or 4 -- something the guest firmware/OS may or may not
ever do, and which has not happened by the time the VMM is wiring
up the device.
So the check was rejecting the spec-defined normal case. It also had
inverted internal naming (the boolean called "established_flag" was
true when the bit was 0), which is what made the conditional read as
if it were testing the opposite of what it actually tested.
In practice the check happened to pass on KVM and fail on MSHV (issue
socket, but the bug is independent of the backend: the VMM has no
business gating startup on tpmEstablished at all.
Drop the check. The bit is still surfaced to the guest from
Tpm::read() when CRB_LOC_STATE is read, which is the only place the
PTP spec requires it to be visible.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The swtpm control socket is a Unix SOCK_STREAM, so a single read() is
not guaranteed to return the full response in one shot. swtpm may
split a response into multiple writes, in which case the existing
single read() returns only the first chunk and subsequent parsing
fails with "Response for ... cmd is of incorrect length". This has
been observed on Azure Linux during emulator initialization.
In addition, when swtpm encounters an error processing a control
command (e.g. PTM_BAD_ORDINAL = 0x0A returned for commands issued
before CMD_INIT), the swtpm protocol returns only the 4-byte result
code instead of the full response. Blindly looping until msg_len_out
bytes arrive would deadlock in that case.
Add SocketDev::read_exact() that loops until the requested number of
bytes has been received (retrying on EINTR), and rework
run_control_cmd() to:
* read_exact the 4-byte result code first;
* on error, set the result code on the PTM message and return a
clean error without waiting for a payload that will never arrive;
* on success, read_exact the remaining (msg_len_out - 4) payload
bytes.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Cover the malformed header case where backing_file_offset is non
zero but backing_file_size is zero, which must be rejected with the
new dedicated error.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the malformed header case where backing_file_offset is zero
but backing_file_size is non zero, which must be rejected with the
new dedicated error.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the case where backing_file_offset points inside the fixed
header fields, which the new header overlap check must reject.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the boundary positive case where backing_file_offset plus
backing_file_size equals the cluster size, which the spec allows
and the new bound check must accept.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the case where backing_file_offset lies inside the first
cluster but backing_file_offset + backing_file_size crosses the
cluster boundary, so the end of the name spills outside.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover an offset that lies well past the end of the first cluster
to make sure the bound check fires for arbitrary out of range
offsets rather than only the boundary case.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
A backing file string placed exactly at cluster_size starts past
the first cluster boundary, so QcowHeader::new must reject it.
Introduce a read_header_with_patched_backing helper that builds
a valid header, patches backing_file_offset and backing_file_size,
writes it out and re-parses it. Use it to cover this case.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
A qcow2 header with non-zero backing_file_offset that points at a
zero length name is malformed. The parser would otherwise read an
empty path string and store it as a backing file. Reject it with a
dedicated error so the user gets a clear diagnostic.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
A qcow2 header with backing_file_offset == 0 indicates the image
has no backing file, so any non-zero backing_file_size is malformed.
Qemu silently ignores the size in this case, which hides image
corruption. Reject it explicitly with a dedicated error so the user
gets a clear diagnostic.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The qcow2 spec requires the backing file name string to live in the
remaining space between the end of the header extension area and
the end of the first cluster. Header parsing accepted any backing
file offset above zero, including offsets pointing into the fixed
header fields themselves, so a corrupt or malicious image could
redirect the parser into reinterpreting header bytes as the backing
path.
Reject any backing_file_offset that is less than header.header_size
via a new BackingFileOverlapsHeader error. The check fires before
the existing first cluster bound, since an overlap is a different
class of corruption and deserves a distinct diagnostic.
Ref: #8261
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The qcow2 spec requires the backing file name string to live
entirely within the first cluster, between the end of the header
extension area and the cluster boundary. The parser previously
only validated the 1023 byte cap on the name length and accepted
any backing_file_offset, so a corrupt or malicious image could
place the name string anywhere in the file.
Add the cluster bound check in QcowHeader::new and report it via
a new BackingFileOutsideFirstCluster error.
Fixes: #8261
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Take the recent thread refactor further. Bundle a device's worker
JoinHandles together with the kill event that stops them into a single
WorkerThreads value, owned by VirtioCommon. Its Drop signals the workers
to exit, unparks any parked for migration, and joins them.
This makes a detached/leaked worker unrepresentable. reset(),
wait_for_epoll_threads() and VhostUserCommon::shutdown() now happen when
dropping the WorkerThreads, and the unpark-before-join teardown now
lives in one place.
Assisted-by: Claude:Opus-4.8
Signed-off-by: Dylan Reid <dgreid@fb.com>
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace manual thread management with the use of
VhostUserCommon::spawn_worker() which is just a thin layer over
VirtioCommon::spawn_worker() but handling VhostUserCommon reset. This
removes some manual thread management and also triggers a reset upon
spawn failure.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Wrap VirtioCommon::spawn_worker() to also include vhost-user specific
backend cleanup.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace use of spawn_virtio_thread() helper with the new method on
VirtioCommon to handle thread management as well as spawning. As a
result this cleanly handles reset if it fails to spawn the thread.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Implement a method on VirtioCommon for spawning the worker thread. This
method also handles storing the handle to the thread and triggering a
reset on the device if thread spawning fails. The addition of this
helper replaces a repeated pattern across virtio and vhost-user devices
but also ensures correct cleanup when spawning multiple threads for a
device with multiple queues.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Rely on the vector of threads in VirtioCommon for storing all the
handles of the spawned threads rather than storing them in the devices
or in VhostUserCommon directly.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Standard L2 data offsets and L1-referenced L2 table offsets must be
aligned and covered by the current refcount table. The write path
checked both constraints at one call site, while read, cache population,
and deallocation paths only checked alignment or relied on later
refcount lookup errors.
Centralize the validation in QcowState and use it before reading L2
tables, mapping standard L2 entries for reads and writes, and
deallocating existing clusters. Invalid offsets set the corrupt bit and
fail with EIO before data I/O or refcount updates.
Add QcowSync regression tests that corrupt a standard L2 entry past the
refcount-addressable range and verify that reads and writes fail with
EIO and mark the header corrupt.
Assisted-by: Codex:GPT-5
Signed-off-by: Ian Klemm <hi@ianklemm.de>
write_pointer_table() used a BufWriter over a cloned fd because the
per-entry callback also needs mutable access to QcowRawFile.
That couples the final write location to the ambient kernel cursor while
the callback is allowed to perform metadata I/O. Materialize the encoded
entries first, then seek and write the table after callback execution
has finished.
This keeps the pointer-table write independent from current and future
callback behavior without depending on proving that a cursor-moving
callback is reachable in today's synchronous CH path.
Apply the same materialize-then-write shape to
write_pointer_table_direct() for consistent semantics, and cover both
paths with unit tests.
Assisted-by: Codex:GPT-5
Signed-off-by: Ian Klemm <hi@ianklemm.de>
The new event allows management software to handle the migration better
via events. The `vm.migration-receive-ready` event tells that the VMM is
ready to accept connections whereas `vm.migration-receive-started` means
a migration is incoming.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Avoid panicking when nvidia-smi fails during GPU checks. Run the
command through a shell wrapper that preserves stdout and stderr
even when nvidia-smi exits with a failure status.
Keep printing guest dmesg on failure and label the nvidia-smi
text as diagnostic output, since SSH-level failures are reported
through the same path.
Assisted-by: OpenCode:gpt-5.5
Signed-off-by: Damian Barabonkov <dbctl@pm.me>
get_host_cpu_phys_bits() subtracts the SME c-bit reduction from
PhysAddrSize (CPUID 0x80000008 EAX bits 7:0). The result sets the
guest's CPUID and MMIO address space size.
The c-bit reduction is not needed here. QEMU's equivalent
(host_cpu_phys_bits() in target/i386/host-cpu.c) returns
PhysAddrSize without reduction.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
When generating guest CPUID, we set PhysAddrSize (EAX bits 7:0)
based on the host's physical address bits. On AMD hosts with SME,
get_host_cpu_phys_bits() subtracts the c-bit reduction from this
value, but the code here only writes the result to bits 7:0 and
leaves GuestPhysAddrSize (bits 23:16) at the unmodified host value.
This creates a gap: e.g. PhysAddrSize=43 but GuestPhysAddrSize=48.
Guest firmware that reads GuestPhysAddrSize will see a larger
address space than the VMM provides, and may place PCI BARs beyond
the MMIO bus range. However, Cloud-hypervisor sizes its MMIO bus to
phys_bits.
Fix by setting both PhysAddrSize (bits 7:0) and GuestPhysAddrSize
(bits 23:16) to phys_bits, using mask 0xff00_ff00 instead of
0xffff_ff00.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
process_rx writes the packet header back into the descriptor chain
it is currently processing, so the write must go through that
chain's memory snapshot. Rederefing self.mem.memory() resolves to
the same snapshot today, but couples the write on the chain to the
device's atomic handle and obscures intent. Match the pattern used
by the rest of the device by writing through desc_chain.memory().
Suggested-by: Rob Bradford <rbradford@meta.com>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Drive a two descriptor chain with a writable head and a zero
length tail and verify the CheckedDescriptor accessors addr, len,
is_empty, is_write_only and has_next agree with the descriptor
flags and length on each entry.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
After the iterator yields the only descriptor in a chain, the
subsequent None must reflect exhaustion rather than a validation
failure, so failed and failed_addr stay unset.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce a FailingTranslator stub whose translate_gva always
returns an error and verify CheckedDescriptorIter rejects the
descriptor, with failed_addr returning the original descriptor
address before translation.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce an OffsetTranslator stub implementing AccessPlatform and
verify CheckedDescriptorIter applies the translation, so the
yielded descriptor's addr reflects the translated GPA rather than
the raw descriptor address.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Submit a descriptor whose addr plus len would wrap around the u64
address space and verify CheckedDescriptorIter rejects it without
panicking, with failed_addr returning the descriptor's address.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Submit a descriptor whose buffer extends exactly one byte past the
end of guest RAM and verify CheckedDescriptorIter rejects it, with
failed_addr returning the descriptor's start address.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Submit a descriptor whose buffer ends exactly at the last byte of
guest RAM and verify CheckedDescriptorIter accepts it. Guards
against an off by one in the range check that would reject an
otherwise valid descriptor at the memory boundary.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Drive CheckedDescriptorIter with an out of range descriptor and
assert that failed_addr returns Some carrying the GuestAddress of
the rejected descriptor, not just the failed boolean.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the rejection path of the trait method next_checked,
asserting that an out of range descriptor is reported as
Err(addr) carrying the original descriptor address.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the exhausted path of the DescriptorChainExt::next_checked
trait method, asserting that Ok(None) is returned once the chain
has no further descriptors.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the success path of the DescriptorChainExt::next_checked
trait method, asserting that a valid single descriptor is returned
as Ok(Some(_)) with the expected addr and len.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add yields_valid_prefix_then_stops_on_invalid which submits a two
descriptor chain where the first descriptor is valid and the second
overshoots guest memory. The test verifies CheckedDescriptorIter
yields the valid prefix, then terminates with the failed flag set.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add passes_through_zero_length_descriptor which submits a descriptor
with len 0 and verifies CheckedDescriptorIter yields it without
performing a guest memory range check.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add rejects_out_of_range_descriptor which submits a descriptor whose
length overshoots guest memory and verifies CheckedDescriptorIter
yields no descriptor and sets the failed flag.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a unit_tests module with the first test for CheckedDescriptorIter,
covering the happy path where a valid single descriptor is yielded and
the iterator reports no failure. Wire up the virtio-bindings dev
dependency and local test helpers needed by the test.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Drop the local next_checked_desc helper and the inline
translate_gva calls in from_tx_virtq_head and from_rx_virtq_head.
Buffer ranges are now validated by the shared next_checked helper
in vm-virtio, and the validated guest address is read directly
from CheckedDescriptor::addr.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add check_range calls on request and status descriptor addresses to
reject buffers that extend past guest memory.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add check_range calls on request and status descriptor addresses to
reject buffers that extend past guest memory.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace inline translate_gva and check_range with checked_iter, which
validates the descriptor buffer range against guest memory before
yielding each descriptor.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace manual translate_gva calls with checked_iter in both the
inflate/deflate and reporting queue handlers.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace raw desc.addr() usage with checked_iter which validates the
descriptor buffer range against guest memory before I/O.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch Request::parse over to the CheckedDescriptorIter helper from
vm-virtio so the block crate validates each descriptor's translated
(addr, len) range against guest memory through the same centralized
path used by virtio-devices. Any descriptor whose buffer is not fully
backed by guest RAM is now rejected before any I/O is set up against
it.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace manual translate_gva calls in both input and output queue
handlers with checked_iter for centralized range validation.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace manual translate_gva call with checked_iter which validates
the descriptor buffer range against guest memory before I/O.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce a CheckedDescriptorIter adapter over DescriptorChain that
validates each descriptor's translated (addr, len) range against guest
memory before yielding it. Any descriptor whose buffer is not fully
backed by guest RAM is rejected, so the device never performs I/O
against memory the guest does not actually own.
The helper lives in vm-virtio so it can be shared across the
virtio-devices and block crates, both of which already depend on
vm-virtio.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This will allow us to work towards removing network access from the
container.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
This is structured such that if multiple test groups need the same asset
it is only listed once.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
This will allow us to remove the download steps from the build scripts
themselves.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
The structured SMBIOS platform config introduced six new keys
(system_manufacturer, system_product_name, system_version,
system_family, system_sku_number, chassis_asset_tag), but
integration coverage only existed for serial_number, uuid, and
oem_strings.
Add _test_dmi_system_and_chassis, which boots a guest with all
six keys set and checks each value via `dmidecode -s` using the
same leaf name as the CLI key. Execute it in both the regular
and SEV-SNP integration suites.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Add unit tests that walk the SMBIOS binary layout in guest memory and
verify structure ordering, string-set encoding, and error paths.
Tests added:
- smbios_chassis_empty_string_set_has_double_null: verify that
a chassis with no strings emits the double-NUL terminator required
by SMBIOS DSP0134 §6.1.3.
- smbios_chassis_oem_strings_layout: verify the full chain
(BIOS → System → Chassis → OEM → End) when a chassis asset tag and
OEM strings are configured.
- smbios_strings_terminators_default: verify the default table chain
(BIOS → System → End) and check that string indices and string-set
contents match for both structures.
- smbios_strings_too_many: exercise alloc_index up to the u8 limit
(255 strings) and verify the 256th is rejected.
- smbios_uuid_invalid_rejected: ensure a malformed UUID string is
rejected with Error::ParseUuid.
- smbios_uuid_written_le: ensure the UUID is stored in little-endian
byte order as required by SMBIOS Spec 7.2.1.
- smbios_write_fails_with_too_small_memory: verify that setup_smbios
fails with Error::WriteData when guest memory is too small to hold
anything beyond the entry point.
All tests also succeed when run with miri:
cargo +nightly miri test -p arch smbios
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Mark serial_number/uuid as deprecated in the OpenAPI schema and emit
warnings when those legacy --platform keys are used, while continuing to
accept them for compatibility.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Extend SMBIOS System Information with manufacturer, product,
version, family, sku, serial, and uuid fields, add a chassis
asset tag, and pass a structured SMBIOS config from --platform
into arch setup. Keep OEM strings and legacy serial_number/uuid
options working for compatibility. The platform option naming
follows `dmidecode -s <field>`.
Fields:
- system_manufacturer
- system_product_name
- system_version
- system_family
- system_serial_number
- system_uuid
- chassis_asset_tag
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Add a small SMBIOS config that carries serial_number, uuid,
and OEM strings, and pass it from platform config into
x86_64 setup.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Split the System Information write into helper functions and
reuse the string writer so the table layout and inputs are
unchanged.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Since enabling AMX tile state components affect the result returned by
`Hypervisor::get_supported_cpuid` we want this enabled prior to checking
CPUID compatibility between the source and destination VMs.
Although this is not required right now, it will be necessary once we
introduce CPU profiles and it will also be necessary if we decide to
make `check_cpuid_compatibility` (arguably) more thorough by also taking
state components into account.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
We make a slightly more general `check_cpuid_compatibility` function
that permits the caller to specify something else than "source VM" and
"destination VM" when logging an error.
This way we can reuse the existing CPUID compatibility checks to
ensure that the host VM is compatibile with the user selected CPU
profile.
In order to avoid a "refactor the world scenario" we keep the old
function with its signature and instead refactor it to call the new
more general internal function.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
We integrate the CPU profile into the various configs that
ultimately get set by the user.
This quickly ends up involving multiple files, luckily Rust
helps us find which ones via compilation errors.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Introduce a method on `CpuProfile` that is used to adjust the given
CPUID entries according to the chosen CPU profile.
This will be used in a later commit to apply the user chosen CPU
profile.
This commit also introduces a few unit tests using relatively simple,
somewhat contrived input values.
We will introduce snapshot tests with realistic adjustments
and CPUID entries in our planned follow up PR bringing in our
pregenerated CPU profiles.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Introduce a CpuProfile enum that will be deserialized from the user's
selected CPU profile.
Currently we only have a "host" variant, but in the future there will
be a build script automatically constructing this enum based on
pre-generated CPU profiles.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Introduce a struct for holding CPUID adjustments related to a
CPU profile.
Instances of this struct will typically be de-serialized from JSON files
describing a CPU profile.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
We introduce a type representing CPUID parameters that will be utilized
by the CPU profiles.
We place this new type in a module that will be further populated with
types related to adjusting CPUID entries based on the CPU profile
in a follow up commit.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Not all invariants can be effectively enforced by Rust's type system
and when this is the case we typically want tests that assert that the
promised invariants do indeed hold.
To get good confidence that our invariants do indeed hold we want to
check against many inputs, but having to write down many inputs is
tedious, and we may also be "biased" in our choices.
Property based testing helps here as it provides several randomly
generated inputs for us and we can focus on just writing the
test logic.
We thus add the popular user friendly `proptest` library as a
dev-dependency in order to write property based tests in follow up
commits. We emphasize that this will be particularly important in
a follow up PR where we have some relatively complex logic for
filtering MSRs.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Also derive Eq, Serialize and Deserialize for CpuidReg. This will make
it possible to reuse this existing type in the context of CPU profiles.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Serialized CPU profiles will contain information about the CPU vendor.
While there are other ways to encode this, such as going via CPUID, we
find simply serializing the pre-existing enum the simplest.
We also implement some other common traits such as `Debug` and `Eq`
which make it more convenient to work with this type.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Re-export Vhdx from formats::vhdx and update the fuzz target to
use block::formats::vhdx::Vhdx. Remove the vhdx compat alias
from lib.rs.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Update external consumers to use formats::qcow::internal instead
of the top level qcow alias. Keep a crate private use for the
QcowError variant in lib.rs.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Update external consumers and internal test modules to use
formats::raw instead of the raw_disk alias, then remove the
re-export from lib.rs.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move QCOW2 format implementation into a structured directory layout:
qcow/ -> formats/qcow/internal/ (filenames unchanged)
qcow_disk.rs -> formats/qcow/mod.rs (QcowDisk)
qcow_sync.rs -> formats/qcow/worker/sync.rs (QcowSync)
qcow_async.rs -> formats/qcow/worker/async_uring.rs (QcowAsync)
qcow_common.rs -> formats/qcow/common.rs
All internal cross references continue to resolve through
re-exports in lib.rs: formats::qcow::internal as qcow,
formats::qcow as qcow_disk, and
formats::qcow::common as qcow_common.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move VHDX format implementation into a structured directory layout:
vhdx/mod.rs -> formats/vhdx/internal/mod.rs (Vhdx)
vhdx/vhdx_bat.rs -> formats/vhdx/internal/bat.rs
vhdx/vhdx_header.rs -> formats/vhdx/internal/header.rs
vhdx/vhdx_io.rs -> formats/vhdx/internal/io.rs
vhdx/vhdx_metadata.rs -> formats/vhdx/internal/metadata.rs
vhdx_sync.rs -> formats/vhdx/mod.rs (VhdxDisk)
Extract VhdxSync from vhdx_sync.rs into formats/vhdx/worker/sync.rs.
Drop the vhdx_ prefix from internal file names since the parent
directory already provides the namespace. Update all internal cross
references to use the new module paths. Re-export formats::vhdx as
vhdx_sync in lib.rs for backward compatibility.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move VHD format implementation into a structured directory layout:
fixed_vhd.rs -> formats/vhd/internal/fixed.rs (FixedVhd)
fixed_vhd_disk.rs -> formats/vhd/mod.rs (VhdDisk)
vhd.rs -> formats/vhd/internal/footer.rs (VhdFooter)
fixed_vhd_sync.rs -> formats/vhd/worker/sync.rs (FixedVhdSync)
fixed_vhd_async.rs -> formats/vhd/worker/async_uring.rs (FixedVhdAsync)
Add #[allow(dead_code)] to VhdFooter struct and impl because the
module is now pub(crate) and the compiler can see that several
fields and getters are only exercised by unit tests. Re-export
formats::vhd as fixed_vhd_disk in lib.rs for backward
compatibility with external consumers.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move raw format implementation into a structured directory layout:
raw_disk.rs -> formats/raw/mod.rs (RawDisk)
raw_sync.rs -> formats/raw/worker/sync.rs (RawSync)
raw_async.rs -> formats/raw/worker/async_uring.rs (RawAsync)
raw_async_aio.rs -> formats/raw/worker/async_aio.rs (RawAio)
raw_async_io_tests.rs -> formats/raw/worker/tests.rs
Update imports in fixed_vhd_sync.rs and fixed_vhd_async.rs to use
the new paths. Re-export formats::raw as raw_disk in lib.rs to
preserve the external API.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move async_io.rs, fcntl.rs, and request.rs into block/src/io/. These
files are generic I/O infrastructure shared by all formats rather
than format specific code.
The io/ directory name clashes with std::io in lib.rs, so the module
is declared as io_impl via #[path] and the submodules are re-exported
at the crate root to keep existing import paths working.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
FixedVhdDisk is the format level DiskFile wrapper for VHD images.
Rename it to VhdDisk to match the <Format>Disk convention used by
RawDisk, QcowDisk, and VhdxDisk. The Fixed prefix remains on the
workers (FixedVhdSync, FixedVhdAsync) since those are specific to
the fixed subformat.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Align with the <Format>Disk wrapper naming convention. VHDx
has a single on disk format so no variant suffix is needed.
The async backend will be added to VhdxDisk.
No functional change.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Import std::io and std::mem instead of spelling the full paths at every
use site.
Signed-off-by: Henry Hrvoje Tonkovac <htonkovac@gmail.com>
Assisted-by: Claude:Opus-4.7
Build both targets in parallel and then recombine them into a multiarch
digest later. This matches the official docker/build-push-action
multi-platform pattern and preserves the existing tagging behaviour.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Cleaning up the cargo registry so that it can be used in the container
should be done towards the end of the Dockerfile allowing more Rust
tools be to used.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Verify that bar_access_params clamps the access length to cap.length
when the PCI config read buffer is larger.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The VIRTIO_PCI_CAP_PCI_CFG indirect access mechanism was ignoring
the cap.length field written by the guest driver. PCI config register
reads always produce a 4 byte buffer, so when a driver set cap.length
to 1 for a byte wide access to device_status at common config offset
0x14, the VMM passed all 4 bytes to read_bar, dispatching to the
dword handler which does not cover that offset.
Use cap.length to determine the actual BAR access width per virtio
spec 4.1.4.9.1. Also replace the unsafe transmute with the safe
Le32::to_native() conversion.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The VHDX synchronous async I/O backend still converted owned
AsyncIoOperation targets back into raw iovec slices before calling the
VHDX read and write helpers. That kept pointer dereferences in the owned
path and allowed a backend mistake to violate the safety boundary.
Handle owned VHDX reads and writes through AsyncIoOperation copy helpers
instead. The VHDX file operations still run synchronously, but data is
copied through operation-owned buffers or guest-memory targets without
reconstructing Rust slices from raw iovec pointers.
Assisted-by: Codex:GPT-5
Signed-off-by: Dylan Reid <dgreid@fb.com>
Similar to the other functions fixed in this series, qcow has helpers
that dereference whatever pointers are passed but are labeled safe.
Use the newly added ops helpers to, instead, provide a safe interface
and implementation.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Dylan Reid <dgreid@fb.com>
Drop the borrowed iovec AsyncIo entry points now that all callers use
owned operations. Rename the transitional owned batch and completion
methods to the final trait names and remove the borrowed submission
helpers from the queue wrappers.
This removes a bunch of known safety foot-guns so future-us don't
accidentally use them.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Dylan Reid <dgreid@fb.com>
Switch virtio-blk request construction and the users to the owned
AsyncIo data path added in the series. Read bounce buffers now return
through AsyncIoCompletion before being copied back to guest memory.
This makes the main virtio async block I/O path use retained request
memory. qcow still has raw-iovec fallback paths at this point; those
are removed in follow-up commits.
Leave the legacy borrowed iovec trait methods in place for a follow-up
cleanup commit to minimize single-commit churn.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Switch the in-process block microbenchmarks to allocate prefaulted
GuestMemory regions and submit through the memory-target AsyncIo API.
This adds a few setup steps as the existing benchmarks relied on the
unsound iovec API. The new behavior is intended to be as close as
possible to the existing tests and the common path for running
cloud-hypervisor.
Assisted-by: Codex:GPT-5.5
Assisted-by: Claude:Opus-4.7
Signed-off-by: Dylan Reid <dgreid@fb.com>
Similar to the previous commits, use UringDataIo for qcow async. Again,
the legacy interfaces are kept(at the expense of some temporary code).
The temporary code is unsound, like the existing code, but will be
removed soon.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Start using AioDataIo from RawFileAsyncAio. This adds a temporary
submit_borrowed_operation to enable preserving the unsafe iovec api
until we can remove it in the forthcoming commits.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add the new AsyncIo apis to fixed_vhd_async. Later commits update
callers to use them and remove their unsound counterparts that take
iovecs.
While doing this, make the owned path validate offset plus length
instead of only the starting offset, so requests that extend past the
VHD size are rejected.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Route RawFileAsync data I/O through UringDataIo's owned-operation
retention path while keeping borrowed submissions available for the
legacy AsyncIo calls during the transition.
This mostly moves code around, temporarily moving uring handling from
RawFileAsync to the UringDataIo, including the unsafe iovec access.
This enables the UringIo to be added to RawFileAsync incrementally.
Later commits will remove the unsafe paths when the callers are updated
to use the new functions.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Implement the new AsyncIo members for qcow_sync while keeping the
legacy borrowed iovec methods in place.
The code before and after this commit is equally unsound. This
intermediate state is not a safety regression and allows for a
bisectable transition to the fully sound code at the end of the
series.
This temporary state breaks out the iovec accesses to helpers used
from both the old and new code and updates the safety comments to
reflect reality.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Refactor VhdxSync around shared iovec helpers which are marked unsafe.
Use these to implement safe wrappers for the new AsyncIo trait.
Leave the existing, unsound read/write vectored calls in place until
all callers are converted to the new interface later in this series.
In addition VHDX code assume it's safe to create slices to GuestMemory
via the AsyncAdaptor in existing code and explicitly after this
change. This is technically unsound as it can easily create multiple
mut refs. At least this is 'llvm update breaks the code' UB, not guest
exploitable UB...
Signed-off-by: Dylan Reid <dgreid@fb.com>
Implement the safe AsyncIo interface the fixed VHD synchronous wrapper
and delegate the actual I/O through RawFileSync. This maintains the
existing interfaces until the callers are converted later in the series.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Implement the owned AsyncIo path for RawFileSync while keeping the
legacy borrowed iovec methods available until all callers can be
converted.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add owned data-operation, completion, and batch methods to AsyncIo.
These will be used as safe alternatives to the existing, comically
unsafe, but marked safe interface.
Over the course of the following commits, users are converted to the
new interface and after all users of the unsound interfaces are
removed, they are removed.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Similar to uring io added in the parent commit. These async ops deal
with buffer ownership across aio calls.
This will be used in the (increasingly rare) case of io_uring not being
available or desirable.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add the shared helpers and UringDataIo queue that drive uring async I/O
operations. UringDataIo is the key component responsible for keeping the
memory pointers active while async operations are ongoing. It uses the
async core added in previous commits.
Later commits will change the block backends to use this instead of the
lower level abstractions directly.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add `AsyncIoOperation` and `AsyncIoCompletion` as the owned request and
completion types that will be used to ensure buffers for async io
outlive the operations that use them. Later commits will update the
`AsyncIo` trait to expose apis using only these instead of raw iovecs.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add `OwnedIoBuffer` to be used for host owned buffers. These are buffers
backed with either a `Vec` or an aligned allocation and will be used for
bounce buffers. This is host owned memory that can later be copied to
guest memory.
Later commits will use this to ensure backing memory outlives async
operations in a centralized, verified way.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Introduce GuestMemoryTarget to own the combination of an Arc to
GuestMemory and a set of ranges/iovecs. This will be used in the
following commits to replace the iovec pointers that are passed to the
backend operations unsafely.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:Opus-4.7
Signed-off-by: Dylan Reid <dgreid@fb.com>
The current OpenAPI schema format is wrong because uint16 and uint32 are
not valid top-level OpenAPI types. Describe queue_size and virtio_id as
integer types with explicit uint formats instead.
Signed-off-by: Roman <roman@vanesyan.com>
Integration test for virtio-devices/src/rtc.rs. Requires that
the test kernel has the following configs:
CONFIG_PTP_1588_CLOCK=y
CONFIG_VIRTIO_RTC=y
CONFIG_VIRTIO_RTC_PTP=y
Signed-off-by: Cameron Baird <cameronbaird@microsoft.com>
This change will allow us to get accurate time over ptp in guests
started from a MSHV-virtualized Linux host. Implementing it as a
virtio device is preferable to using the existing kvm_ptp because:
kvm_ptp relies on hypercalls that only exist on host kernels running
kvm. Virtio-rtc gives us more flexibility in what clock types we want
to provide. We can later extend the device to implement multiple clocks
(smeared UTC, TAI, monotonic, etc.). Virtio-rtc protocol supports
alarms. Alarms may later enable usecases where the guests can do their
own VM lifecycle management without relying on a host-side
orchestrator.
Implement device backend for virtio-rtc. Currently this implementation
encompasses:
1. CONFIG, CAP, READ, CROSSCAP (returns false)
2. One PTP clock is presented of type
VIRTIO_RTC_CLOCK_UTC_MAYBE_SMEARED with leap_second_smearing
VIRTIO_RTC_SMEAR_UNSPECIFIED
The device is disabled by default, requiring --rtc to be passed
Not implemented but theoretically supported by virtio-rtc is:
1. Cross-timestamping support
2. The alarm queue
Fixes#7730
Signed-off-by: Cameron Baird <cameronbaird@microsoft.com>
Several riscv64 paths are compiled by the KVM build but missed
imports or cfg coverage needed by the current code.
Import the vm-memory Bytes trait for the RISC-V UEFI loader, keep
Instant available for migration timing code, and enable the UEFI flash
error path for riscv64.
Assisted-by: OpenAI-Codex:GPT-5
Signed-off-by: wangyf0611 <wangyufeng@iscas.ac.cn>
riscv64 does not provide the legacy readlink and unlink syscalls, so
libc uses readlinkat and unlinkat for paths that are otherwise allowed
on other architectures.
Permit readlinkat and unlinkat for the VMM and vCPU seccomp filters on
riscv64, matching the existing aarch64 rules.
Assisted-by: OpenAI-Codex:GPT-5
Signed-off-by: wangyf0611 <wangyufeng@iscas.ac.cn>
The RISC-V AIA FDT node currently advertises a fixed riscv,num-ids
value. That can diverge from the interrupt identity count configured by
KVM, which matters for guests running with an emulated IMSIC.
Record the NR_IDS value reported by KVM and expose that value through
the generated device tree. Read back the KVM-selected AIA mode without
forcing an emulation mode.
Assisted-by: OpenAI-Codex:GPT-5
Signed-off-by: wangyf0611 <wangyufeng@iscas.ac.cn>
KVM initializes RISC-V vCPUs with sstateen0 cleared. When AIA is
exposed to the guest, Linux touches supervisor AIA CSRs while bringing
up the IMSIC path, and those accesses fail if the stateen bits remain
disabled.
Program sstateen0 for newly created vCPUs so the guest can use the
supervisor interrupt state needed by AIA.
Assisted-by: OpenAI-Codex:GPT-5
Signed-off-by: wangyf0611 <wangyufeng@iscas.ac.cn>
Each VM reboot re-entered the VFIO/virtio-net add paths and re-appended
the same originating fds, leaving duplicates in preserved_fds and a
double-close hazard at final teardown. Switching to HashSet makes
add_preserved_fds idempotent.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Assisted-by: Claude:Opus-4.7
When SVE is enabled, KVM replaces the FPSIMD V-registers with wider
SVE Z-registers. Attempting to access the old FPSIMD offsets returns
EINVAL.
Fix by classifying each register from KVM_GET_REG_LIST as core, system,
or extended. Extended registers (currently SVE only) are saved as
generic `ExtendedReg` entries split into `pre_finalize_regs` (registers
like SVE VLS that must be written before `vcpu_finalize`) and
`extended_regs`. FPSIMD registers are only accessed when SVE is absent.
Unrecognized register families error immediately so future extensions
like SME fail clearly rather than silently losing state.
The snapshot is deserialized before vCPU init to make pre-finalize
register state available for the init -> VLS -> finalize ordering
required by KVM.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Split the SVE detection and finalization logic out of `init()` into a
dedicated `finalize_sve()` method. This separates the concerns of vCPU
initialization (preferred target, processor features, KVM init) from SVE
finalization, and enables a subsequent commit to insert SVE VLS register
in the restore path without needing to add a restore state in `init()`.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Move the inline FPSIMD register read/write code from `get_regs()` and
`set_regs()` into dedicated `get_fpsimd_regs()` and `set_fpsimd_regs()`
methods on `KvmVcpu`.
This helps keep the larger `{get,set}_regs()` easier to understand and
prepares them for a subsequent commit that needs to conditionally
skip FPSIMD access when SVE registers are used instead.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
QCOW2 compressed L2 entries encode their extent layout in bits that
overlap with the flags used by standard L2 entries. In particular,
bit 0 can be part of the compressed entry layout, so it must not be
interpreted as ZERO_FLAG until the entry has first been ruled out as
compressed.
Keep compressed deallocation ahead of zero-flag handling in both the
shared QcowMetadata path and the legacy QcowFile path. This ensures
WRITE_ZEROES deallocates compressed clusters instead of treating a
compressed entry with bit 0 set as an existing logical-zero marker.
Add regression coverage that forces bit 0 on a compressed L2 entry
and verifies WRITE_ZEROES still clears the entry through the
compressed-cluster path.
Assisted-by: Codex:GPT-5
Signed-off-by: Ian Klemm <hi@ianklemm.de>
QCOW2 empty L2 entries in an overlay mean that reads fall
through to the backing file. Reusing the punch_hole path for
WRITE_ZEROES therefore turns a full-cluster zero operation on an
unallocated overlay cluster into backing data exposure.
Keep discard/punch_hole behavior unchanged, but let WRITE_ZEROES
request a logical-zero marker when the image has a backing file.
ZERO_FLAG entries now read as zeros in both the legacy QcowFile
path and the shared runtime metadata path. Partial writes after
such entries seed new clusters from zeros instead of backing data.
Treat ZERO_FLAG entries as logical holes for SEEK_HOLE/SEEK_DATA.
Empty overlay entries with a backing file still report data because
the data exists in the backing file.
Avoid cluster-sized userspace zero buffers when materializing
zero-flagged clusters by zeroing the allocated host range directly.
This keeps recycled clusters safe without making partial writes
allocate large zero-filled Vecs.
Add regression coverage for legacy QcowFile, QcowSync, direct I/O,
QcowAsync/io_uring overlay paths, and a large-cluster partial-write
case.
Assisted-by: Codex:GPT-5
Signed-off-by: Ian Klemm <hi@ianklemm.de>
Add support for formatting logs following the popular glog crate style.
In particular this can use local or UTC time along with a single
character level.
As an implementation detail of that implement finegrained date time log
outputs including both local and UTC variants.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:Opus-4.6
Extend the TCP live-migration test with a hotplugged block device using
a stable ID before migration. After migration, verify that the disk
still exists on the restored destination VM.
Then hot-remove the disk and add it again with the same ID. This covers
the stale restore snapshot case because the disk ID exists in the
migration snapshot, but the live device tree no longer contains it after
hot-remove.
Assisted-by: Codex:GPT-5.5
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Storing the snapshot causes issues when needing to do a subsequent
hotplug instead just pass it through on all the methods that need it
making the lifecycle cleaner.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
Agents are totally capable of setting up the host and run dev_cli.sh.
The removed text discouraged them to do that even when asked to.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The serial-manager thread was the only VMM-managed thread without a
seccomp filter. Add a Thread::SerialManager variant and whitelist the
31 syscalls needed for its epoll-based I/O loop (read, write, socket
ops, signal handling, memory allocation, glibc internals).
The filter is computed in start_thread() and applied before the epoll
loop, matching the pattern used by other VMM threads.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Assisted-by: Pi-agent:Claude-Opus-4.7
Only Thread::Vmm and Thread::Vcpu need to know the hypervisor type.
Make the type optional, and then simplify the users.
Assisted-by: Pi-agent:Claude-Opus-4.7
Signed-off-by: Wei Liu <liuwe@microsoft.com>
QCOW2 backing file paths stored in image headers may be
relative. These paths should be interpreted relative to the image
that references them, but the block backend opened them relative to
the process working directory.
Resolve the current image path inside parse_qcow() from the open
file descriptor and use its parent directory for relative backing
paths. Recursive backing chains work the same way because each layer
is parsed from its own file descriptor.
Signed-off-by: Rowen-Ye <rowenye1@gmail.com>
Userfaultfd is a great mechanism for providing fast restore to Cloud
Hypervisor VMs. But that means the price to pay for bringing pages in
happens at runtime, which might slow down the guest when it's touching
pages which haven't been brought in yet.
By prefaulting the pages in the background, we're trying to get the best
of both worlds. That means we still get a very fast restore with the
uffd handler, but within a few seconds (depending on VM's RAM size), we
also get the pages fully faulted and we can stop the uffd handler thread
at that point.
Signed-off-by: Sebastien Boeuf <sboeuf@meta.com>
Assisted-by: Claude:claude-opus-4-7
Centralize test configuration (filters, retries, fail-fast,
sequential/parallel scheduling) into nextest profiles, replacing
scattered flags across shell scripts. This simplifies the scripts
and provides a single source of truth for test behavior.
Enable JUnit XML output per profile, giving CI systems structured
test results for better reporting.
Not all test invocations are converted to profiles yet. Just the
ones that are repeated across scripts.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Update the container image tag to trigger a rebuild. The new image
pins cargo-nextest to version 0.9.128, which supports profile
inheritance, needed for the following nextest configuration changes.
Assisted-by: Copilot-CLI:Claude-Opus-4.7
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
The JSON parser expects the field to be named
`iommu_address_width_bits`, but the code declared it as
`iommu_address_width`. This mismatch caused the field to be
unrecognized when deserializing configuration from JSON.
Rename the field to `iommu_address_width_bits` to match the
expected schema.
Signed-off-by: tchaton <thomas.chaton.ai@gmail.com>
Windows 11 PnP rebalance rewrites peer BARs into the same range CH
packed the initial layout at, causing move_bar() failures and boot
deadlock. Pack Mmio64 BARs at 8 MiB stride. Mmio32 isn't wide enough
for the same stride, but its BARs don't participate in guest BAR
rebalancing.
On restore, pin the BAR to the snapshot address (alignment=None) so a
guest-relocated BAR with smaller alignment is accepted.
Signed-off-by: CMGS <ilskdw@gmail.com>
IommuEpollHandler::request_queue() can fail because the guest put in a
bad request or because of a fatal error. Handle those cases differently,
letting the guest continue, but see the error if it can.
This makes debugging from the guest easier as one mistake doesn't cause
a VM reset if it's avoidable.
Signed-off-by: Dylan Reid <dgreid@fb.com>
VfioUserDmaMapping::map panicked when find_region returned an anonymous
mmap region. Change this so a user gets an error instead of a panic.
When the VMM hotplugs a region into a guest that also has a vfio-user
device, all region's handlers are called. With the anonymous memory
backing (no file=, shared=on, or hugepages), region.file_offset()
returns None and the .unwrap() panics the VMM. Replace the unwrap with
an explicit error and use checked_add for the offset combine.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Assert VirtioPciNotifyCap and VirtioPciCap64 size cap_len from
their own type. Catches a future regression of the same shape as
the VirtioPciCfgCap one in any of the sibling capabilities.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Assert the emitted VirtioPciCfgCap carries cfg_type 5, the value
assigned to PciCapabilityType::Pci by virtio 1.2 section 4.1.4.1.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Regression test for the cap_len fix. The emitted VirtioPciCfgCap
must report cap_len 20, covering the trailing pci_cfg_data window
per virtio 1.2 section 4.1.4.9.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
VirtioPciCfgCap::new built its inner header via VirtioPciCap::new,
which sized cap_len from the bare virtio_pci_cap layout, yielding
16. The emitted capability is VirtioPciCfgCap, which appends a four
byte pci_cfg_data window, so the correct value is 20.
The virtio 1.2 specification defines this cap as virtio_pci_cap
followed by pci_cfg_data[4] and requires cap_len to
cover the whole structure. Build the header inline so cap_len
reflects the actual emitted size, matching VirtioPciNotifyCap and
VirtioPciCap64.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This reverts commit ced3762a67.
This change lead to a serious memory regression when not using hugepages
or shared=on.
`MAP_PRIVATE` creates an anonymous memory allocation for every page
written when the backing store is a file. This CoW behaviour is useful
but leads to double allocations when the backing store is an empty file
created by `memfd_create()`. When the page is written to, the CoW
semantics require a real page to be created in the memory for the memfd
(previously before the page was touched they would all point to the zero
page). This real page is filled with zeroes because in theory this page
would be accessible via read/write syscalls on the FD even though in our
implementation it is only ever `mmap()`ed.
The intention of the commit was to enable `fallocate()` to be used to
punch holes but that would only affect the inaccessible backing page and
the page in the CoW anonymous memory would be unaffected. Leading it
likely not to have the desired effect.
Fixes: #8211
Signed-off-by: Rob Bradford <rbradford@meta.com>
When reading from an unregistered PIO address, pio_read() wasn't
initialising the buffer, so guests were reading stale bytes from the
previous PIO transaction rather than all 0xff bytes like master abort
on real hardware.
Fill data with 0xff on invalid reads.
Correct 'read to unregistered address' info message to 'read from
unregistered address' while we're touching this block.
Signed-off-by: Chris Webb <chris@arachsys.com>
When reading from an unregistered MMIO address, mmio_read() wasn't
initialising the buffer, so guests were reading stale bytes from the
previous MMIO transaction rather than all 0xff bytes like master abort
on real hardware.
Fill data with 0xff on invalid reads.
Correct 'read to unregistered address' info message to 'read from
unregistered address' while we're touching this block.
Signed-off-by: Chris Webb <chris@arachsys.com>
The post-migration check used a fixed `thread::sleep(3s)` followed by
`try_wait()` to verify the source VM had exited cleanly. That window
is too tight when the source process is the release binary used by
`test_live_upgrade_*` (i.e. `~/workloads/cloud-hypervisor-static`,
pinned to `migratable_version`).
The released binary is older than the locally-built destination and
its virtio-device teardown (resume-paused-thread -> kill -> join
across pmem, block, net, console, rng workers) regularly takes
longer than 3s on contended hosts, causing the test to report:
thread 'common_parallel::test_live_upgrade_basic' panicked:
Test failed: source VM was not terminated successfully.
even though the source process eventually exits with status 0.
Replace the fixed sleep with a `wait_until(Duration::from_secs(30),
...)` poll that returns as soon as `try_wait()` reports a reaped
child, then keep the existing `success()` check on the exit status.
This makes the assertion robust against the slower release-binary
shutdown path while still failing fast on a genuine error.
The same pattern was duplicated across eight migration helpers plus
the virtio-fs migration variant; convert all nine call sites for
consistency.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Reordering commands or adding commands in-between is breaking the
migration protocol. By using explicit numbers, we can increase the
attention required when touching this code.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
I started by looking at all `Option<Vec<T>>` values in config.rs and
vm_config.rs, and replaced them with `Option<Box<[T]>>`. This has the
advantage that one now can see at a glance if this field will ever
resize during operation or not, reducing cognitive load and increasing
maintainability. All fields that need the properties of a Ver or where
this change was not trivial are kept intact.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Some block devices (ZFS volume) may require BLKDISCARD and BLKZEROOUT
ioctls for discard and write_zeroes operations respectively.
There is no good way to probe whether fallocate is supported on a block
device. Arguably, punch_hole and write_zeroes are rare. Instead of
having a complex scheme for the IO uring backend, we force it to always
use ioctls. The code can be changed if the synchronized ioctls become a
performance issue.
Changes:
- Detect block devices at construction time
- Use BLKDISCARD ioctl for punch_hole (discard) on block devices
- Use BLKZEROOUT ioctl for write_zeroes on block devices
- Add BLKDISCARD/BLKZEROOUT to VirtioBlock seccomp whitelist
- Keep fallocate() path for regular files (no behavior change)
- Consolidate some helper functions to the new sparse module
Signed-off-by: Wei Liu <liuwe@microsoft.com>
probe_sparse_support() and DiskTopology::is_block_device() each carry
their own copy of the same fstat()+S_IFMT dance to ask "is this fd a
block device?". Hoist a single pub helper
pub(crate) fn is_block_device(fd: RawFd) -> bool
into block::lib and route both call sites through it. Drop the
MaybeUninit gymnastics in favour of mem::zeroed() since libc::stat is
POD.
Drop DiskTopology::is_block_device since it is now just a one line
wrapper around the new helper function.
Pure refactor in preparation for the BLKDISCARD/BLKZEROOUT support,
which needs the same probe in three more backends.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
submit_batch_requests pushed each BatchRequest into the io_uring SQ in
turn and used `?` to bail on the first push failure.
Leaving the initial SQEs visible to the kernel — but submitter.submit()
was never called, and every other call site in this file gates submit()
behind a preceding sq.push() that now also fails on the full ring.
This could allow a guest to DoS it's own queue or worse if the buffer is
freed early.
Signed-off-by: Dylan Reid <dgreid@fb.com>
The bounce buffer for an unaligned descriptor was allocated in
execute_async and leaked on error paths, even though, for the sync case
the kernel already had a pointer to the buffer.
Clean this up by moving ownership of the buffer to the AlignedOperation
type. To make it actually safe, stop stashing a guest memory pointer for
the duration of the op. Instead, save the guest address and pass guest
memory back to the complete function.
Signed-off-by: Dylan Reid <dgreid@fb.com>
For non-batch backends execute_async submits the kernel I/O inline
before returning. An early return while processing before inserting in
inflight_requests, meant the request went untracked, the local batch
list was never appended to inflight_requests, even though the request is
pending in the kernel.
To track it, insert into self.inflight_requests as soon as execute_async
returns Ok. The completion path's find_inflight_request now matches the
orphan and the bounce buffer is freed only after the kernel signals it
is done.
Signed-off-by: Dylan Reid <dgreid@fb.com>
A malicious or buggy guest can violate virtio by making the same
descriptor head available twice before the first chain has been placed
on the used ring. The submit path pushed both chains onto the
VecDeque-backed inflight_requests keyed by head_index, and on completion
find_inflight_request() returned the first linear match. That Request's
complete_async() freed its bounce buffer while the other chain's
io_uring op was still targeting it, producing a use-after-free the
kernel could then scribble into.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Signed-off-by: Bo Chen <bchen@crusoe.ai>
When no image_type is specified, sector 0 writes are disabled as a
safety measure for autodetected raw images. Extend this protection
to autodetected fixed VHD images, which carry metadata in the last
sector and are equally susceptible to accidental overwrites of the
first sector when the format is not explicitly acknowledged.
Update the corresponding warning in the virtio block worker to be
format agnostic.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Explanatory comments for the rollback paths in both PCI BAR
relocation branches.
Assisted-by: Claude (Anthropic)
Signed-off-by: CMGS <ilskdw@gmail.com>
After free(old_base), if allocate(new_base) fails the allocator
treats old_base as free even though the MMIO/PIO bus still maps the
device there. Subsequent allocations pick old_base, mmio_bus.insert
hits the live mapping and returns Overlap.
Restore old_base on the failure path in both the Memory*BitRegion
and IoRegion branches before bubbling the error up.
PR #7950 added restore_bar_addr() so the BAR config register stays
consistent on failed move_bar(); this completes the same picture
for the allocator side.
Signed-off-by: CMGS <ilskdw@gmail.com>
Quoting the spec:
> If VHOST_USER_PROTOCOL_F_REPLY_ACK is negotiated, and the back-end
> sets the VHOST_USER_NEED_REPLY flag, the front-end must respond with
> zero when operation is successfully completed, or non-zero
> otherwise.
cloud-hypervisor would previously not send a response to a
VHOST_USER_BACKEND_CONFIG_CHANGE_MSG message, even if
VHOST_USER_PROTOCOL_F_REPLY_ACK had been negotiated and
VHOST_USER_NEED_REPLY was set, in violation of the spec.
Link: https://qemu-project.gitlab.io/qemu/interop/vhost-user.html#back-end-message-types
Fixes: 8d6213338 ("virtio-devices: generic-vhost-user: Config change notification")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Event expectation helpers print detailed diagnostics when the observed
event stream does not match the expected one. That is useful for direct
assertions, but it becomes extremely noisy [0] when the helper is used
as the predicate for wait_until(), because every polling attempt emits
the full mismatch dump.
Add quiet wait wrappers for event polling and emit the existing detailed
diagnostics only once after the timeout expires.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/actions/runs/25745401604/job/75619840718?pr=8021
On-behalf-of: Philipp Schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
The test_vdpa_net integration test brings the vDPA-backed interface
(ens6) up and then asserts that both TX and RX packet counters are
exactly zero before sending an explicit ping. On guest kernels that
perform IPv6 link-local autoconfiguration quickly enough, however,
Router Solicitation / Neighbor Discovery frames are emitted as soon
as the link comes up. The vdpa_sim_net device loops those frames back
to the interface, so by the time the test queries
ip -j -p -s link show ens6 | grep -c '"packets": 0'
the TX and RX counters are already non-zero and the precondition
assertion fails (observed reliably with the Microsoft internal guest
kernel running on MSHV).
Disable IPv6 / accept_ra / autoconf on ens6 before bringing the link
up. With IPv6 disabled no autoconf traffic is generated, the counters
remain at zero until the explicit 'ping 172.16.1.10 -c 6' generates
exactly the 6 packets the rest of the test expects on each direction,
and the vDPA-specific portion of the test is unchanged.
Verified on an MSHV Azure VM (Linux 6.6.121.mshv2):
test common_parallel::test_vdpa_net ... ok
test result: ok. 1 passed; 0 failed; ...; finished in 26.13s
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Using `jiff::Timestamp::now()` instead of `jiff::Zoned::now()` skips the
timezone logic required for `Zoned`. This makes the timestamp UTC, with
the appropriate `Z` suffix.
On-behalf-of: SAP julian.schindel@sap.com
Signed-off-by: Julian Schindel <julian.schindel@cyberus-technology.de>
If a guest observes DEVICE_NEEDS_RESET, resets the device, and tries to
re-initialize it, but the VMM knows the backend is disconnected, we can
short-circuit the doomed activation.
This is not incorrect, but saves the VMM from making several round-trip
calls to a peer process that doesn't exist. It'll also make the logs
cleaner.
Signed-off-by: Dylan Reid <dgreid@fb.com>
resume() mirrors pause() for backend communication: it skips the
vhost-user backend call when the device is already disconnected, and it
marks newly failed resume_vhost_user() calls disconnected only when the
classifier identifies transport loss.
Signed-off-by: Dylan Reid <dgreid@fb.com>
pause() returns DeviceDisconnected without calling into the backend when
VhostUserCommon already knows the socket is gone. DeviceManager treats
only that sentinel as log-and-continue, so one dead vhost-user device
does not abort the whole pause iteration.
Signed-off-by: Dylan Reid <dgreid@fb.com>
For add memory region, if the backend is disconnected or returns an
error, forward the appropriate error type to the caller. If the error
indicates that the vhost user backend has disconnected, mark it as such.
Signed-off-by: Dylan Reid <dgreid@fb.com>
reset() is teardown and must still clean up local state even if the
vhost-user backend has already gone away. When the disconnected flag is
already set, it skips reset_vhost_user() and proceeds with kill-event,
worker-unblock, event logging, and interrupt callback cleanup.
Signed-off-by: Dylan Reid <dgreid@fb.com>
This function hasn't been used since '22.
All callers removed with:
1f0e5eb66 vmm: virtio-devices: Restore every VirtioDevice upon creation
TEST: build and cargo test all still pass, grep returns no results.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add two explicit disconnected-backend error paths before wiring them
into the call sites.
MigratableError::DeviceDisconnected is the lifecycle sentinel for
operations that were skipped because a component is already known to be
disconnected. It lets the caller log and continue without treating it as
a VMM-fatal condition.
Error::BackendDisconnected is the vhost-user-local error used when
VhostUserCommon refuses to call a backend after its disconnected flag is
set. The transport classifier treats socket close/reset/EOF and
vhost-user partial-message/disconnected cases as transport loss, while
backend NACKs, invalid protocol state, and retry-able socket errors
remain ordinary operation failures.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add a 'disconnected' flag shared between VhostUserCommon and
VhostUserEpollHandler. This flag is set whenever the run loop hits an
error that would cause an exit (failed reconnect, broken backend req
handler, unknown event).
Following commits will use this to gate backend calls in order to avoid
repeated timeouts and errors when a backend disappears. This will
simplify shutdown sequencing for orchestrators using vhost-user devices.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Slack's join.* endpoints reject automated GETs
and return 403, so lychee was failing the link availability
check on any PR that touched README.md
Add the join.slack.com/t/ prefix to the .lychee.toml
exclude list
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
cloud-hypervisor/edk2 publishes prebuilt CLOUDHV.fd (x86-64) and
CLOUDHV_EFI.fd (AArch64) as release assets. docs/uefi.md only
described the build from source, and the AArch64 firmware
customizations required for cloud-hypervisor were left undocumented.
Add a "Using Prebuilt UEFI Firmware" section to docs/uefi.md and
an "AArch64 Firmware Notes" section covering both customizations.
Updates to "Building UEFI Firmware for AArch64" section.
Switch the boot examples from --kernel to --firmware, which is the
direct UEFI load path on AArch64.
Minor README.md updates.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Bump the wait_until timeout for the guest-visible memory growth in
test_nvidia_card_memory_hotplug from 5s to 15s. The hot-add path inside
the guest kernel can take longer than 5s particularly when using
virtio-mem, which has been a source of flakes for this test.
Drop the trailing assert!(guest.get_total_memory() > 5_760_000), as it
is redundant.
See: #8160
Signed-off-by: Bo Chen <bchen@crusoe.ai>
The shared /tmp/cloud-hypervisor/ path is created by the first user to
run dev_cli.sh and owned by them, so other users on the same host fail
the +x+w check and cannot chmod it back. Move both tmp paths under
/tmp/cloud-hypervisor-${USER}/ so each user gets their own tree.
While here, fold the local BUILD_DIR in build_container() into the
existing (previously unused) CLH_CTR_BUILD_DIR, which ensure_build_dir()
already creates.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Bo Chen <bchen@crusoe.ai>
TL;DR: Improved developer productivity for many contributors
Add a shared .editorconfig so contributors get lightweight,
editor-native hints while writing code instead of only discovering
formatting issues later in style checks.
This is advisory, but useful: editors can already guide indentation,
whitespace, line endings, and final newlines as you type. They can also
show a visual guide at the 80-character line width, which is one of the
main motivations here. Most LLM-generated code and contributions over
the past year have already conventionally followed the 80-character
limit, so this makes the expected style visible and consistent for
everyone.
.editorconfig is a decade-old standard, and virtually every editor or
IDE supports it.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Initial attempt for a lightweight AGENTS.md to improve working with
LLMs on this repository and avoid common pitfalls.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
User-defined zones may be mapped private. Create a memfd for private
zones so that fallocate operations are available on all regions, not
just shared ones. This prepares for zone management via hole punching.
The MAP_ANONYMOUS flag is now omitted since the memory becomes
tmpfs-backed via memfd.
Signed-off-by: JP Kobryn <inwardvessel@gmail.com>
When a guest resets a device by writing status=0 and reinitializes
without enabling queues before writing DRIVER_OK, the activation
path would collect zero ready queues and treat that as a fatal
error, killing the entire VMM process.
The PCI transport now checks that at least one queue is ready
before reporting that the device needs activation. This prevents
a spurious activation attempt that would fatally fail when no
queues are enabled.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add common PCI device configuration to the virtio-console device
configuration. This allows setting the device ID (the name), ID, the
PCI segment, and the PCI device ID (BDF), which were previously not
configurable for the virtio-console device.
This gives management software, such as libvirt, more control over PCI
resource assignment and aligns virtio-console with other devices that
already support this functionality [0].
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/issues/8175
On-behalf-of: Philipp Schuster <philipp.schuster@sap.com>
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
`--serial` still accepted `iommu=on|off` from the shared serial/console
configuration shape, even though only virtio-console has a meaningful
IOMMU connection.
Cloud Hypervisor wires virtio-iommu support through DMA-capable
virtio/VFIO PCI endpoints. The serial devices are legacy UARTs accessed
through PIO or MMIO registers, so exposing an IOMMU option there is
misleading.
On-behalf-of: Philipp Schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This commit introduces a new struct `CommonConsoleConfig` which is the
base for the split into `ConsoleConfig` and `SerialConfig`. This is a
pre-requisite for allowing more configurable PCI options for the
virtio-console device.
The commit doesn't change or add any functionality.
On-behalf-of: Philipp Schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
config_generation is a u8 and the spec mandates wrap around.
Verify the increment past 0xff lands on 0x00 without panicking
under overflow checks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cover the three observable cases of consume_config_change. With
the flag set the counter advances by one and the flag is cleared.
With the flag clear the call is a no-op. A burst of flag sets
between two reads results in only one bump, which is the wrap
hazard mitigation the spec asks for.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
A Config trigger must set the config_changed flag so the next
device specific configuration read can bump config_generation. A
Queue trigger must leave the flag alone.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Set a config_changed flag in VirtioInterruptMsix when a Config
interrupt fires, and increment config_generation only when the
driver next reads the device specific configuration region. The
flag is cleared by that read so the driver observes a stable
value across the read and a fresh value on any later read.
This avoids the wrap hazard of incrementing on every Config
event, where a burst of interrupts could roll the 8 bit counter
back to its previous value between two driver reads.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert the u8 field to Arc<AtomicU8> so the interrupt path can
mutate it without holding the common config mutex. Reads at
offset 0x15 use Acquire ordering. State serialization preserves
the value.
Update the three unit tests that construct
VirtioPciCommonConfig directly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This prints the time in the local time. The "Z" suffix usually indicates
UTC time. This is left over from when there was manual implementation
using libc::gmtime()
Signed-off-by: Rob Bradford <rbradford@meta.com>
An edk2 boot is needed for ACPI support but the stock ARM64 kernel does
not support ACPI memory hotplug or virtio-pmem. For now disable those
tests but track them in #8187.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This is a niche feature and we were overly testing it. Let's just switch
to two tests. One for live migration and one for plain watchdog. This
will reduce the CI time. As we are now running these tests sequentially
we can also reduce some the delays in the tests.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Focal has served us well for many years but is now beyond EOL. Remove
all remaining use of focal images from the CI.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The PciDeviceHandle::VfioUser arm in eject_device propagated dma_unmap
failures with ?, which short-circuited the subsequent
remove_dma_mapping_handler loop and left stale Arc<VfioUserDmaMapping>
entries in every virtio-mem device's handler map. Log unmap errors
with warn! and continue so the handler map cleanup always runs.
This only happens if a vfio-user process crashes and the same device is
later removed. However, given we've seen similar issues on vhost-user
this is probably worth cleaning up.
Signed-off-by: Dylan Reid <dgreid@fb.com>
The BusDevice read and write arms for B0EJ_FIELD_OFFSET and
PSEG_FIELD_OFFSET opened with assert!/assert_eq! on data.len(), so a
guest 1/2/8-byte MMIO access to either register panicked the vCPU
thread. Replace each assert with a warn! and early return so unusual
access widths are logged and ignored instead of crashing the VMM.
Signed-off-by: Dylan Reid <dgreid@fb.com>
self.balloon and self.virtio_mem_devices are not updated when
eject_device removes the underlying device, leaving stale
Arc<Mutex<...>> entries that resize_balloon / balloon_size and the
virtio-mem DMA-handler iteration would dereference if reached after
eject. Clear self.balloon and retain-out the matching virtio-mem entry
in the PciDeviceHandle::Virtio eject arm, identifying the ejected
device by Arc pointer-equality against the already-resolved
Arc<Mutex<dyn VirtioDevice>>.
This change is defensive: DeviceManager::remove_device currently
rejects VirtioDeviceType::Balloon and VirtioDeviceType::Mem with
RemovalNotAllowed before pci_devices_down is set, so the guest never
sees an eject notification and eject_device is never reached for
either type today. If the allowlist is extended later, this cleanup
keeps the post-eject state consistent.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Currently only the existing format options are supported and the default
format string is unchanged. This allows more fine grained logging
control.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Introduces a custom format string parser for use for log entries. For
now only the existing format string entries are covered and the default
format string matches the existing behaviour.
The format string is tokenized once and then that token stream is used
for each log entry.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
In preparation for extending its functionality, refactor the Logger
struct and its implementation to a new file / module.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Rob Bradford <rbradford@meta.com>
process_queue() unwrapped four guest-reachable Results.
Convert each unwrap to a logged error path. A failed status write is
demoted to len = 0 so the head is still retired via add_used; an
add_used failure breaks the batch (queue is in a bad state); a
needs_notification failure signals; a signal failure is logged. The
daemon stays up.
Signed-off-by: Dylan Reid <dgreid@fb.com>
set_config() split the config slice at `offset` and copy_from_slice'd
the entire suffix, which asserts src.len() == self.len(). This panics if
the guest issues a write shorter than `config_len - offset`.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Although a response is sent to the client these errors are not logged in
the log file making it hard to cross reference these with other log
entries.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Currently when the socket is disconnected by the other end there is no
logging of such an event. Add a log to aid identifying when this has
happened.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Abandon the reconnection to the vhost-user socket if the kill_evt is
fired because e.g. a device removal request has come in during the
reconnection.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace the use of sleeps with a TimerFd. Initially this is functionally
equivalent but it can be extended to also handle other events.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Drop inflate or deflate descriptors whose len exceeds the Linux
driver maximum of VIRTIO_BALLOON_ARRAY_PFNS_MAX PFN entries of 4
bytes each. Without the cap, a guest can submit a descriptor with
a huge len over a small backing and drive an unbounded warn loop
in the device thread.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The old implementation used an ever monotonically increasing u32 counter
to allocate new GSIs. The counter increased every time a new GSI was
allocated, and freeing GSIs was not possible. Thus, Cloud Hypervisor
can run out of GSIs and panics. This currently happened at the 1024th
GSI [0]. Further, this caused the `KVM_SET_GSI_ROUTING` ioctl to carry
much more payload than needed.
This new implementation uses a bitmap for proper tracking of resources
and can gracefully free GSIs - this is abstracted in type
InterruptAllocator.
Please note that this commit only replaces the old mechanism. The next
commit will introduce freeing used GSIs automatically when an
InterruptRoute is dropped.
While being on this, we also propagate the errors that the allocator may
throw where necessary.
Co-authored-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
On-behalf-of: Philipp Schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
When an SEV-SNP guest transitions pages from private to shared via
KVM_HC_MAP_GPA_RANGE, punch holes in the corresponding guest_memfd
backing it. Without this the balloon driver's `set_memory_decrypted()`
path transitions the page attributes but the physical memory stays
pinned in guest_memfd, making virtio-balloon ineffective for memory
overcommit with confidential VMs. Even without ballooning these pages
are unused by the guest so consume resources. This mirrors the hole
punching that the balloon device does for releasing pages.
The memory_slots Arc is cloned into each KvmVcpu at creation so the
punch can happen in the vcpu thread.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace the bare OwnedFd map (guest_memfds) with a KvmMemorySlot struct
wrapped in an Arc so it can later be shared with KvmVcpu. This is a
pure refactor with no functional change; KvmMemorySlot currently holds
only the guest_memfd OwnedFd.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Rob Bradford <rbradford@meta.com>
block::Error implements Display via thiserror, so the user facing
log lines do not need the Debug formatter.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
With the per handler needs_reset() gates removed from net and
block, nothing reads DEVICE_NEEDS_RESET anymore. Drop the
device_needs_reset helper and refresh the doc comment on
mark_device_needs_reset to reflect the central call site in
spawn_virtio_thread, where it runs after the worker has already
exited.
No functional change.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
With virtqueue iterator errors now killing the worker and
spawn_virtio_thread marking NEEDS_RESET centrally, the per
handler needs_reset() gate on process_queue_submit and
process_queue_complete is unreachable.
Drop needs_reset(), the two early returns, the unused
device_status field on BlockEpollHandler and its initializer,
and the device_needs_reset import.
No functional change.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
queue.iter() errors used to be swallowed by
handle_queue_iterator_error(), which marked the device as
NEEDS_RESET and returned Ok so the worker kept running while
disabled. spawn_virtio_thread now does the NEEDS_RESET marking
when the worker exits with an error.
Propagate the iterator error as Error::QueueIterator and escalate
it to EpollHelperError::HandleEvent in
process_queue_submit_and_signal so the worker exits. Per request
errors stay logged. Drop the now unused
handle_queue_iterator_error helper.
No functional change for the guest. NEEDS_RESET is still set and
the config interrupt is still raised on virtqueue corruption.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
spawn_virtio_thread now marks the device as NEEDS_RESET and notifies
the guest whenever the worker thread exits with an error, so the
per handler needs_reset() gate and the handle_queue_iterator_error()
helper in net are redundant.
Let virtqueue iterator errors propagate out of the worker thread
through DeviceError::NetQueuePair. Drop the unused device_status
field and the device_needs_reset and mark_device_needs_reset
imports.
No functional change for the guest. NEEDS_RESET is still set and
the config interrupt is still raised on virtqueue corruption.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Prefer /dev/userfaultfd (Linux 6.1+) over the userfaultfd(2) syscall
for obtaining userfaultfd file descriptors. The device path bypasses
the capable(CAP_SYS_PTRACE) and vm.unprivileged_userfaultfd sysctl
checks that block the syscall in user-namespaced containers, using
file permissions instead.
Falls back to the syscall on older kernels or when the device node
does not exist.
Signed-off-by: Roberto Campesato <render@metalabs.org>
Assisted-by: Claude:claude-opus-4-6
Pass `-p cloud-hypervisor` to all `cargo nextest run` invocations in
the integration test scripts so test discovery and execution are
scoped to the cloud-hypervisor package only, avoiding running tests
from other workspace crates.
This avoids flooding the output messages like below
`test result: ok. 0 passed; 0 failed; 0 ignored;
0 measured; 0 filtered out; finished in 0.00s
Running unittests src/lib.rs`
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Clean up the macvtap interfaces that may have been left from a previous
failed run. Failure to clean those up guarantees that the subsequent
test runs will fail.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use concise <path> placeholders in socket and console help strings
instead of wording every path as a file. This keeps the established
file= config key intact while making the user-facing help wording
match the path terminology requested in the issue.
Signed-off-by: Keith Adler <kadler@cloudflare.com>
When a triple fault happens [0], we now get at least a log message. This
helps to better understand the root cause of sudden reboots.
Broader context: We experience reboots caused by triple faults in
edk2 (6 months old as well as recent). They happen so early in the boot
that one doesn't really see them without looking at the VMM log. An
automatic system reset plus reboot often hides these situations - now
they are at least more visible in the log.
PS: Printing the registers to get more debugging help doesn't help, as
the guest already triple-faulted - the CPU state of the root cause
doesn't exist anymore.
[0] https://elixir.bootlin.com/linux/v6.18.6/source/arch/x86/kvm/x86.c#L11123
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Keep the underlying io_uring submission queue push error in raw async
I/O paths instead of replacing it with a generic full-queue message.
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Request::parse rejected unknown request types with an error, causing
process_queue to report the chain as used with no response written.
The device should write an error response so the driver knows the
request was handled. Move type validation out of parse into
process_queue where a proper response can be constructed.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
Address translation, guest memory read, write, and flush failures on
the transmitq propagated errors that killed the console device thread.
A host-side I/O error such as a PTY disconnect would permanently
disable the console. Log warnings and continue processing instead.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
Address translation or guest memory write failures on the receiveq
propagated errors that killed the console device thread. Log a
warning and break out of the descriptor loop instead.
Also fix a data-loss bug: bytes were drained from the input buffer
before the write to guest memory, so a failed write would silently
discard the data. Copy first, write, then drain only on success.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
The output queue handler read data from every descriptor without
checking the write-only flag. The driver must not put device-writable
buffers in the transmitq. Skip them with a warning.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
The input queue handler wrote data to every descriptor without
checking the write-only flag. The device must not write to
device-readable buffers. Skip them with a warning.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
Remove UnknownRequestType (no longer returned after responding with
ERROR), EventFdWriteFail, EventFdTryCloneFail, MpscRecvFail, and
NotActivatedByGuest which have no call sites. Drop the now-unused
mpsc import.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
A malformed descriptor chain — wrong read/write flags, missing
descriptors, or undersized buffers — caused Request::parse to return
an error that killed the device thread. Log a warning, report the
chain as used with zero length, and continue processing.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
is_range_state() and set_range() took nb_blocks as u16 to match the
wire format, but unplug_all() computed the total block count from
region_size / block_size and cast to u16, silently truncating for
regions larger than 128 GiB. Widen the internal parameter to usize
so unplug_all() resets the full bitmap.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
When is_valid_range() returns false, the handler still computed
offset = addr - config.addr which can underflow if addr is below the
region base, then queried the bitmap at a meaningless index. Return
(ERROR, 0) immediately so no arithmetic runs on invalid input.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
An unknown request type caused process_queue to return an error that
killed the device thread. The request/response descriptors are already
parsed at this point, so respond with VIRTIO_MEM_RESP_ERROR and
continue processing.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
Address translation or memory release errors on the free page
reporting queue propagated up and killed the balloon device thread.
Log a warning and skip the offending descriptor so the device
continues operating.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
A single malformed descriptor — device-writable where device-readable
is expected, non-aligned length, overflowed address, unmapped PFN, or
a failed fallocate/madvise — propagated an error that killed the
balloon device thread. Skip bad descriptors and PFNs with a warning
so the device keeps operating.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
Only the first descriptor in each chain was processed. If the PFN
array spanned multiple chained descriptors the remaining PFNs were
silently dropped. Iterate the full chain so every descriptor is
validated and its PFNs are acted on.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
The inflate and deflate queues carry device-readable PFN arrays: the
driver writes them and the device only reads. The device never writes
to the descriptor buffers, so the used ring entry should report 0
bytes written rather than the descriptor length.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
Fix "Fail tp signal" typo, replace copy-pasted "entropy" comment
with "balloon", and remove EventFdWriteFail and QueueIterator error
variants that have no call sites.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
When address translation or the entropy read fails mid-chain the
handler reset total_len to zero before breaking out of the loop.
If earlier descriptors in the same chain were already filled, the
used ring entry under-reports the bytes actually written to guest
memory. Drop the reset so the used length reflects reality.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
A device-readable descriptor anywhere in the chain caused the handler
to reset the byte count to zero and abandon the rest of the chain.
This discards valid device-writable descriptors that follow and
misreports bytes already written to earlier descriptors.
Skip device-readable and zero-length descriptors individually so
the remaining device-writable buffers still get filled with entropy.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-6
Try and delete the bridge if it exists before setting up for the test.
This prevents cascading failures where if the test fails once any
subsequent run of the test will fail during the setup.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Import common std types used by the userfaultfd wrapper instead of
spelling the full paths at every use site.
Signed-off-by: Keith Adler <kadler@cloudflare.com>
The snapshot/restore hotplug path already waits for the exact
device-removed event through the event monitor. Drop the fixed sleep
before that poll so the test advances as soon as the event arrives.
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Several error paths in process_desc_chain returned the error before
calling queue.add_used for the offending descriptor. The affected
variants were DescriptorChainInvalid, DescriptorChainTooShort,
DescriptorInvalidHeader, and the GuestMemory variants raised during
descriptor chain translation, slice retrieval, or the num_buffers
write on the RX side.
Without an entry in the used ring the head descriptor remained owned
by the device. A guest that kept submitting bad chains could deplete
the queue over time.
Mark the head descriptor used with length 0 before propagating the
error to the caller, so the ring stays consistent regardless of how
the device decides to react to a guest induced failure.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When readv returns fewer bytes than vnet_hdr_len the frame is
truncated. Report the truncated length to the guest in the used
ring instead of returning a fatal InvalidVirtioNetHeader error.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When readv from the TAP returns EINVAL the guest posted a buffer
too small for the vnet_hdr. Return len 0 to the used ring and
continue instead of killing the worker thread. Also move
go_to_previous_position into the appropriate error branches only.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When writev returns fewer bytes than vnet_hdr_len the packet is
truncated. Log the error and drop it instead of returning a fatal
InvalidVirtioNetHeader error that would crash the worker thread.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When writev to the TAP returns EINVAL the guest submitted a
malformed packet. Drop it and continue instead of killing the
worker thread.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Worker threads spawned through spawn_virtio_thread previously wrote to
exit_evt on any clean Err return, taking the whole VMM down on a single
failed device worker. A guest induced fault in any virtio device thus
propagated into a host wide failure.
Route the Err return through the shared mark_device_needs_reset helper
instead. The helper sets the DEVICE_NEEDS_RESET bit on device_status
and triggers a config change interrupt, so the device goes idle and
the guest is informed. The thread exits cleanly without killing the
rest of the VMM.
The panic and the seccomp filter apply paths keep writing to exit_evt.
A panicked worker may have left poisoned locks or partially mutated
state, so a hard exit remains the right policy there.
spawn_virtio_thread now takes the device_status and the interrupt
callback. Every native virtio and vhost-user call site is updated to
pass them in.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Both block and net implement the same DEVICE_NEEDS_RESET bookkeeping
when a corrupted virtqueue request is detected. They set the bit,
trigger a config change interrupt and log a warning. Move that logic
into shared device_needs_reset and mark_device_needs_reset helpers in
lib.rs and update both call sites to use them.
No functional change.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Exercise the new VFIO BAR exclusion option with NVIDIA
passthrough tests so the integration suite checks that selected
BARs are skipped.
The tests cover both legacy VFIO and iommufd paths while
preserving the existing hardware availability guards.
Signed-off-by: Damian Barabonkov <dbctl@pm.me>
Assisted-by: OpenCode:gpt-5.5
Explain how operators can exclude selected VFIO BARs from mmap
when they know their workloads do not require MMIO access to those
regions.
Documenting the option separately keeps the new device argument
discoverable and calls out the valid BAR index range.
Signed-off-by: Damian Barabonkov <dbctl@pm.me>
Assisted-by: OpenCode:gpt-5.5
Allow VFIO devices to list BAR indices that should not be
mmapped into the guest. This lets operators skip large BARs that
are known not to be used by their workload.
When a BAR is skipped, the log also calls out that P2P DMA
mapping is skipped because the VFIO DMA map path uses the same
mmap backing.
Signed-off-by: Damian Barabonkov <dbctl@pm.me>
Assisted-by: OpenCode:gpt-5.5
Reuse the boot notification method we have for the L1 guests for the L2
guest. This removes the need to use SSH based boot tracking for
connecfting to the L2 guest and should make the test more reliable.
This requires making the L2 guest use a different cloud-init
configuration to the L1.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace explicit --cpus boot=N arguments with .default_cpus()
in all performance test functions. For confidential guests,
nested=on is not supported, so using default_cpus() ensures
nested=off is correctly set for confidential VMs.
The net throughput, net latency, and block I/O tests now set
guest.num_cpu to the number of queues before calling
default_cpus(), ensuring the correct vCPU count is used.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Refactor performance_test_new_guest to accept the full
PerformanceTestControl reference instead of just GuestVmType.
This allows the function to also set guest.num_cpu from
control.num_boot_vcpus, ensuring the guest is configured
with the correct number of vCPUs for the test.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Use the VM_TYPE environment variable to conditionally enable
igvm and sev_snp features when building for confidential VMs.
Pass --vm-type confidential to the performance-metrics binary
so it can select the appropriate test configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a --vm-type argument to the tests command in dev_cli.sh to
allow specifying the type of VM (regular or confidential). The
value is passed to the container via the VM_TYPE environment
variable.
Also extract a prepare_igvm_files() helper function to reduce
duplication when copying IGVM files for confidential VM tests,
and call it from both integration_cvm and metrics paths.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The per-domain mapping cap bounds memory inside one domain, but a
guest can still grow the domains map indefinitely with ATTACH
requests for distinct domain IDs. Reject ATTACH with
VIRTIO_IOMMU_S_NOMEM at 64K domains.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The virtio spec says the device must never present a value other
than 0 or 1 for bypass. Mask off the upper bits on write so a
later read does not return whatever the driver wrote.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The device offers VIRTIO_IOMMU_F_INPUT_RANGE when the address
width is constrained, but never validates that guest MAP requests
fall inside the advertised range. The virtio spec requires such
requests to fail with VIRTIO_IOMMU_S_RANGE.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The virtio spec mandates VIRTIO_IOMMU_S_NOENT, not S_INVAL, when
the target domain does not exist.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The handler accepted unknown flag bits, unaligned ranges, and
overlapping mappings, and returned the wrong status code when the
target domain did not exist. The virtio spec requires explicit
rejections for each of these.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The virtio spec requires the device to reject ATTACH with a
non-zero reserved field, an unknown flag bit, or a bypass flag
that conflicts with an existing domain. The current handler
silently accepts all three.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The virtio spec requires the device to leave the reply buffer
untouched and report a used length of zero for an unrecognised
request type, so the driver can tell the request was not handled.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
Domain::mappings only shrinks on UNMAP. Without a bound a guest can
issue MAP for arbitrarily many distinct virt_start values and drive
the VMM heap until the host runs out.
Reject MAP with VIRTIO_IOMMU_S_NOMEM at 1M entries per domain.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
A concurrent DETACH between the read-lock check and the write-lock
get_mut().unwrap() in MAP/UNMAP would panic the worker. Replace the
unwrap with a let-else.
A failure on a later endpoint in the per-endpoint MAP loop, or a
DETACH that races the missing-domain branch, must roll back the
external mappings already installed; otherwise domain.mappings
diverges from VFIO state.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
An UNMAP that would split an existing mapping must be rejected with
VIRTIO_IOMMU_S_RANGE without removing anything. The previous start-only
retain silently left mappings that started outside the unmap range but
overlapped it.
Walk bookkeeping under a read lock and reject before touching VFIO so a
rejection cannot leave VFIO and bookkeeping out of sync.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The DmaRemapping translate_gva and translate_gpa entry points discarded
the size argument that AccessPlatform's signature already carries and
only checked the base address. A buffer beginning inside a mapping but
extending past it was treated as fully translated, allowing reads or
writes outside the IOMMU-authorized window.
Add `size` to the trait, validate the full span fits in a single
mapping, and propagate it through AccessPlatformMapping.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The reply length was `hdr_len + size_of::<tail>()`, computed twice.
Make it explicit via checked_add and reuse the result.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
Remove CI workflow description section as the yaml
files change often and the docs become stale quickly.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The unit tests added in bf3279f09 built sparse files by writing only
at one offset and assuming the surrounding pages stayed unallocated.
That breaks on shmem/tmpfs with huge=within_size: kernel 6.10+ added
large-folio support to shmem, and on first write the kernel allocates
one folio whose order is the largest power-of-two number of pages
that fits inside the file size (capped at PMD-size). For a 64 KiB
test file the very first pwrite anywhere allocates a 64 KiB folio
covering the whole file, so SEEK_HOLE never reports a hole and
written_pages_show_as_data_extents,
sparse_file_yields_extents_at_written_positions, and
single_extent_at_zero_offset all fail. memfd_create lives on shmem
too and inherits the same THP policy from
/sys/kernel/mm/transparent_hugepage/shmem_enabled, so the problem is
not /tmp-specific.
Fix the fixtures, not the production code: build each test file via
a new sparse_layout() helper that writes the requested data extents
and then fallocate(FALLOC_FL_PUNCH_HOLE)s every gap. PUNCH_HOLE is
the explicit "deallocate these pages" syscall and is honored by every
Linux filesystem we run tests on (tmpfs, ext4, xfs, btrfs); the
kernel splits any large folio overlapping the punched range. The
resulting SEEK_DATA/SEEK_HOLE map matches the spec exactly regardless
of folio/THP policy.
For single_extent_at_zero_offset the dst side still loses to the
folio allocator -- writing 8 KiB into a 64 KiB tmpfs file allocates
a 64 KiB folio whether we want it or not -- so the previous
meta.blocks()-based sparseness assertion (which tested the filesystem,
not our code) is replaced with a sentinel pre-fill: dst starts filled
with 0xFE and the post-condition is that bytes outside the
source-data extent are still 0xFE. That directly verifies
write_region_sparse only touched the data extent without depending on
dst-side hole reporting.
Side effect: extent_at_non_zero_src_offset,
two_regions_in_same_destination_file_at_dst_offset, and
round_trip_sparse_write_then_read previously passed by accident on
hosts with mTHP-on-shmem -- their src memfds reported the whole file
as data so write_region_sparse silently fell into a dense copy of
zeros + data. With sparse_layout() the sources are genuinely sparse
and those tests now exercise the sparse path on every host.
Tested on tmpfs (huge=within_size) and ext4 (TMPDIR=/var/tmp); all 9
tests pass on both with no skips.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Dylan Reid <dgreid@fb.com>
Verify that firing a config change interrupt with msix_config
vector beyond the table size returns Ok without panicking.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that a valid in bounds vector with MSI-X enabled
successfully triggers the interrupt source group.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that requesting a notifier with an out-of-bounds MSI-X
vector returns None instead of panicking.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that triggering an interrupt when the vector is set to
VIRTQ_MSI_NO_VECTOR short-circuits and returns Ok.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that firing an interrupt with a queue vector beyond the
MSI-X table size returns Ok without panicking.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
A malicious or buggy guest can write an out-of-bounds value to
queue_msix_vector or msix_config. When the device later triggers
an interrupt, it indexes into table_entries with the unchecked
vector, causing a panic.
Validate the vector against the MSI-X table size in both trigger()
and notifier() paths, logging a warning and returning early when
the vector exceeds the table bounds.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Request::execute and Request::execute_async checked each data descriptor
against `disk_nsectors` using the request's fixed start sector. With
sector = disk_nsectors-1 and N descriptors of 512 bytes each, every
descriptor passed (top = disk_nsectors) but the vectored I/O
collectively read/wrote N*512 bytes starting at the last sector — N-1
sectors past EOF.
For the io_uring/aio raw backends this lets the guest extend the host
disk image beyond its provisioned size, exhausting the host filesystem.
For fixed-VHD images (footer at end of file) the same chain overwrites
the footer with guest-controlled bytes, corrupting the disk image.
Replace the per-descriptor check with a chain-wide check_data_bounds().
Pre-validating the entire request before beginning the operation avoids
having to unroll a partial submit.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Use into_iter() for test_list when building tests_to_run.
This keeps the collected type as Vec<&PerformanceTest>.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Follow the same pattern as other virtio devices using a bool to check if
it needs notification and propagating its own Error enum.
Sadly this does still use `anyhow!()` but this does match with the
behaviour of the other devices in their implementations.
As a side effect we can now remove two errors from the top-level Error
enum in virtio-devices as these were only used by this module and those
errors had mangled descriptions.
Signed-off-by: Rob Bradford <rbradford@meta.com>
If this test flakes is can then cause subsequent invocations to fail as
the test has left its special test interfaces alive.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Rate limiting is implemented in the virtio device layer and does not
apply to vhost-user devices which delegate I/O handling to an external
process.
Add validation to reject configurations where vhost_user is enabled
along with rate limiting options (bw_size, ops_size, or
rate_limit_group) for both disk and network devices.
This prevents users from mistakenly configuring rate limiting that would
be silently ignored when using vhost-user backends.
Signed-off-by: Rob Bradford <rbradford@meta.com>
A malicious or buggy guest can issue an MSI-X table write with an
unexpected size (not 4 or 8 bytes), triggering an assert!() that
crashes the VMM process. Replace the assertion with an error log and
early return to maintain VMM stability under adversarial guest
behavior.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Adding a paused flag to live_migration() tests; when this
flag is set, the VM will be paused before migration is
performed.
Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
This extends migration to also support paused VMs, preserving the
paused state on the destination.
Changes:
- Add CompletePaused protocol command that finalizes migration without
resuming the VM on the destination
- Skip the pause step during migration if the VM is already paused
- On migration failure, only restore the running state if
the VM was originally running (not paused)
Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
`get_host_address_range` used `check_range(addr, size)` as a guard then
unwrapped `get_slice(addr, size)`. This allowed a span across two
regions to hit the unwrap (get_slice limits to one range).
If `size` were zero, then the checks were all skipped. Causing a panic
later on for an invalid address.
Make get_slice the sole authority and reject size==0 explicitly.
Callers already handle None.
Signed-off-by: Dylan Reid <dgreid@fb.com>
The guest can cause submit and completion failures with malformed chains
or invalid addresses. However, this shouldn't permanently stall the
device and terminate the worker.
Genuine reset-worthy failures set needs_reset and return `Ok` anyways
and will more cleanly reset the worker.
Signed-off-by: Dylan Reid <dgreid@fb.com>
process_queue_submit's drain loop builds a fresh queue.iter() per
iteration, which re-reads the guest avail index on every call and has
no per-call cap (the per-iter gap check in virtio-queue only protects
against avail_idx jumping more than queue_size between two reads).
In theory, a malicous or buggy guest could keep adding descriptors and
cause this loop to overflow the iouring submit queue.
Cap a single drain at queue_size. A spec-compliant driver never
produces more than queue_size outstanding entries simultaneously, so
the cap is invisible to well-behaved guests.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Add validation checks to prepare_linux() to catch invalid
kernel option combinations early:
- Error if --build-guest-kernel and CH_CUSTOM_KERNEL are
both provided, as they are mutually exclusive.
- On x86_64, error if only one of CH_CUSTOM_KERNEL or
CH_CUSTOM_BZIMAGE is set; both must be provided together.
- Fix kernel-already-present check: use per-architecture
branches with correct bash syntax (elif instead of
else-if, [[ ]] instead of [ && ]) so aarch64 and x86_64
are each handled properly.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add docs/testing.md covering the dev_cli.sh interface, all
test types (unit, integration, VFIO, Windows, live migration,
rate limiter, CVM), custom kernel/firmware overrides via
environment variables, performance metrics, code coverage,
and the CI workflow matrix.
Assisted-by: GitHub Copilot:Claude-Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add file-existence guards around firmware and OVMF download
calls in integration test scripts that were missing them.
Also guard prepare_linux() in test-util.sh so it returns
early when the kernel binary is already present.
This lets users pre-populate the workloads directory (e.g.
via CH_CUSTOM_KERNEL, CH_CUSTOM_FIRMWARE, CH_CUSTOM_OVMF)
and avoid redundant network fetches or source builds inside
the container.
Updated scripts:
- test-util.sh (prepare_linux early return)
- run_integration_tests_aarch64.sh
- run_integration_tests_vfio.sh
- run_integration_tests_windows_x86_64.sh
- run_integration_tests_windows_aarch64.sh
Assisted-by: GitHub Copilot:Claude-Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Skip sha1sum verification for firmware files that were
provided via CH_CUSTOM_FIRMWARE or CH_CUSTOM_OVMF environment
variables. Custom files will not match the expected checksums,
so we filter them out of the sha1sums list before running
sha1sum --check.
Updated scripts:
- run_integration_tests_x86_64.sh
- run_integration_tests_aarch64.sh
Assisted-by: GitHub Copilot:Claude-Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
When CH_CUSTOM_KERNEL, CH_CUSTOM_FIRMWARE, or CH_CUSTOM_OVMF
environment variables are set, copy the referenced files into
the host workloads directory before starting Docker. The files
land at the default paths the test scripts expect
(vmlinux-x86_64, Image-arm64, hypervisor-fw, CLOUDHV.fd,
CLOUDHV_EFI.fd), so the existing download-if-missing guards
inside the container skip the network fetch.
Each variable is independent; users can override any
combination without affecting the others.
Assisted-by: GitHub Copilot:Claude-Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract a common_env_args bash array with the environment
variables shared by both unit and integration test containers
(BUILD_TARGET, RUSTFLAGS, TARGET_CC). The unit test block
uses common_env_args plus its own LLVM_PROFILE_FILE. After
the unit block, common_env_args is extended with the USER
and AUTH_DOWNLOAD_TOKEN variables used by all integration
test groups.
Assisted-by: GitHub Copilot:Claude-Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract a common_args bash array with the runtime arguments
shared by both unit and integration test containers (name,
workdir, rm, seccomp, volumes). The unit test block uses
common_args plus its own device and cap-add flags. After
the unit block, common_args is extended with the privileged,
ipc, net, tmpfs, and workload-volume flags used by all
integration test groups.
Assisted-by: GitHub Copilot:Claude-Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
KSM will not attempt to merge pages that are mapped as MAP_SHARED, so
configuring memory with both mergeable and shared options is invalid.
Add validation to reject configurations where both options are enabled
for memory or memory zones.
Signed-off-by: Rob Bradford <rbradford@meta.com>
With the `mshv` feature enabled, the immutable `data` `Vec` is mutated
via a pointer. This violates Rust aliasing rules. Fixed by cloning the
`Vec` to a mutable instance when the `mshv` feature is active.
Signed-off-by: Julian Schindel <mail@arctic-alpaca.de>
Add KvmSevSnpIdBlock and KvmSevSnpIdAuth structs matching the AMD
SEV-SNP Firmware ABI Spec (Rev 1.58), and build them from the IGVM
SNP ID block directive during launch finish. This properly populates
id_block_uaddr/id_auth_uaddr in KVM_SEV_SNP_LAUNCH_FINISH and derives
auth_key_en from the assembled author key, matching QEMU's behavior.
Thread the guest policy from sev_snp_init to launch_finish via an
atomic on KvmVm so the ID block gets the correct policy value.
Also track has_snp_id_block in IgvmLoadedInfo to enable the ID block
based on whether the IGVM file actually contains one, rather than
hardcoding it for KVM.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Extract the SNP guest policy from IGVM initialization headers when
available, falling back to the default policy. This matches QEMU's
behaviour where only a non-zero IGVM policy overrides the default.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Preserve the original IGVM import order for KVM SNP launch updates.
The launch digest is order-sensitive, so only coalesce adjacent pages
that already share the same page type and size. MSHV continues to
sort by GPA for hypercall batching.
Signed-off-by: Kevin Hui <kevinhui@meta.com>
Introduce the KVM_SNP_PAGE_TYPE_ZERO page type for ZERO
pages. AMD SEV SNP can accept ZERO pages as a page in which
the page memory is functionally just zeroes
Signed-off-by: Kevin Hui <kevinhui@meta.com>
Verify the SEV hash table layout, GUID placement, kernel/initrd/cmdline
digest values, and the setup_sects > boot_params size branch. These
guard against silent regressions in the launch digest computation.
Signed-off-by: Kevin Hui <kevinhui@meta.com>
This introduces the kernel hashes measured boot table into
cloud hypervisor if a cmdline and kernel is passed into an
SEV-SNP CVM, incorporating a kernel/cmdline/optional initrd
into a memory page that is measured into the launch digest
of a SEV-SNP CVM. If both --kernel and --cmdline are not
provided, we do not insert this data page
Signed-off-by: Kevin Hui <kevinhui@meta.com>
For KVM SEV-SNP guests, the VMM should not modify the kernel
boot header before sending it via fw_cfg. The guest firmware is expected
to set fields like type_of_loader itself.
For upcoming measured boot logic for SEV-SNP, modifying `type_of_loader`
causes the kernel hash computed by the VMM to diverge from the hash that
`sev-snp-measure` (and the guest firmware) compute, resulting in a
launch measurement mismatch.
This matches QEMU's behavior, which skips kernel header modifications
for confidential guests so the data sent via fw_cfg matches the
original kernel file provided by the user.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Walk the input snapshot file extent by extent via lseek(SEEK_DATA) /
lseek(SEEK_HOLE) within each region's slot and read only those bytes
into guest RAM via the existing read_volatile_from primitive. Holes are
left as the guest mapping's natural zero-fill, which matches the source
content.
Symmetric counterpart to sparse-write on snapshot. Works for both new
sparse snapshots and old dense snapshots: a dense file has no holes, so
SEEK_DATA returns the full range as one extent and the I/O pattern
matches the previous behaviour.
If the input file's filesystem does not support SEEK_HOLE the code falls
back to the existing dense read path.
Measured on a 4 GiB shared-memory VM (2 vCPUs, ~340 MiB touched), total
restore time as reported by the in-tree timing instrumentation:
Before (dense): ~1487ms, reads 4.0 GiB from file
After (sparse): ~136ms, reads 340 MiB from file (92% less I/O, 11x faster)
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
For memfd-backed guest RAM regions, walk the backing fd extent by extent
via lseek(SEEK_DATA) / lseek(SEEK_HOLE) and write each populated extent
into the snapshot file's per-region slot via
std::os::unix::fs::FileExt::write_at. Pre-size the file with
set_len(total): on filesystems that support sparse files unwritten bytes
become real holes; on others the kernel zero-fills the allocation, which
is still byte-correct.
If set_len fails (some FUSE backends reject ftruncate-extend with
EOPNOTSUPP), fall back entirely to the dense write path which streams
bytes sequentially via write_volatile_to and never writes past the
growing EOF.
When the guest region has no backing file (anonymous mmap) or the
backing fd does not support SEEK_HOLE (hugetlbfs), fall back to the
dense write path on a per-region basis.
The on-disk byte stream is identical to the dense format from the
perspective of any reader using read/pread/mmap, so old readers see no
change.
Measured on a 4 GiB shared-memory VM (2 vCPUs, ~340 MiB touched), total
snapshot time as reported by the in-tree timing instrumentation:
Before (dense): ~2400ms, 4.0 GiB on disk
After (sparse): ~132ms, 340 MiB on disk (92% smaller, 18x faster)
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Adds next_data_extent: a streaming helper that returns the next
populated extent within a window of a file descriptor using
lseek(SEEK_DATA) / lseek(SEEK_HOLE). Used by subsequent commits to walk
the snapshot file extent-by-extent without collecting the full extent
list.
Returns an error on fds or filesystems without SEEK_HOLE support so the
caller can fall back to a dense write path.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace explicit --kernel and --cmdline arguments with the
default_kernel_cmdline() helper in performance_net_throughput,
performance_net_latency, and performance_block_io. This
simplifies the code and ensures consistency with how the
kernel command line is configured across tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Confidential VMs (CVM) are not currently supported on the
AArch64 architecture. Add an early check in the performance
metrics binary to exit with a clear error message when CVM
mode is selected on AArch64.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a --vm-type command-line argument to allow users to select
between 'regular' (default) and 'confidential' (CVM) VM types
when running performance tests.
Example: --vm-type confidential
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Apply the vm_type override from PerformanceTestOverrides to the
effective_control used during test execution, alongside the
existing test_timeout override.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add an optional vm_type field to PerformanceTestOverrides to
allow overriding the VM type at runtime. Include vm_type in
the Display output for override logging.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace hardcoded GuestVmType::Regular with control.vm_type
in all performance test functions to support CVM benchmarking:
net_throughput, net_latency, boot_time, boot_time_pmem,
block_io, and restore_latency.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Update performance_test_new_guest() to accept a GuestVmType
parameter. When set to Confidential, configure the guest with
CVM-specific settings: vm_type, boot_timeout, and nested
virtualization disabled.
All callers pass GuestVmType::Regular to preserve existing
behavior.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a vm_type field of type GuestVmType to PerformanceTestControl,
defaulting to GuestVmType::Regular. Include vm_type in the Display
output for test control logging.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Consolidate override application into a single effective_control
variable built once before the test loop. This removes duplicated
timeout override logic from both warmup and measurement iterations.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add Display trait implementation for GuestVmType to enable
formatted output of the VM type in logs and diagnostics.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add FromStr trait implementation for GuestVmType to enable
parsing from CLI string arguments. Supports "regular" and
"confidential" string values.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Update mshv-bindings and mshv-ioctls from 0.6.8 to 0.6.9
in workspace Cargo.toml and fuzz/Cargo.toml.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The total RAM in the system needs to consider any hotpluggable RAM that
is hotplugged in as well as the initial static "base" RAM.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The reserve_bootloader_regions() call allocates RAM regions at
KVM-specific addresses (0xffc00000 for stage0, 0xfffffffff000
for VMSA) that are only needed by the KVM SEV-SNP boot path.
The existing #[cfg(all(feature = "kvm", feature = "sev_snp"))]
compile-time guard is insufficient when both 'mshv' and 'kvm'
features are enabled in the same binary. The runtime check only
verified sev_snp_enabled() but not the hypervisor type, causing
these KVM-specific memory regions to be allocated on MSHV.
On MSHV, these spurious RAM mappings at high addresses interfere
with the hypervisor's address space layout. When the guest kernel
subsequently accesses MMIO regions (e.g., IOAPIC at 0xFEC00000),
MSHV incorrectly reports HVMSG_UNACCEPTED_GPA instead of routing
the access through MMIO emulation, crashing the guest.
Add a runtime hypervisor type check to ensure these regions are
only reserved when running on KVM.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The SnpCpuidInfo allocation and guest_memory.read() call in the
isolated page import loop are only needed for KVM's CPUID page
retry logic. However, when building with both 'mshv' and 'kvm'
features, #[cfg(feature = "kvm")] alone is insufficient as a
guard because both features compile into the same binary.
Without a runtime hypervisor type check, this code executes on
MSHV as well, reading guest memory at arbitrary GPAs that may
not be valid in the MSHV memory layout. This can cause undefined
behavior or crashes during IGVM loading.
Add #[cfg(feature = "kvm")] to the variable declarations and
wrap the guest_memory.read() call in a runtime check for
HypervisorType::Kvm to ensure it only executes on KVM.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The PageTypeConfig for MSHV incorrectly mapped the cpuid field
to HV_ISOLATED_PAGE_TYPE_NORMAL (0) and the secrets field to
HV_ISOLATED_PAGE_TYPE_UNMEASURED (3).
The correct MSHV page type constants are:
- CPUID pages: HV_ISOLATED_PAGE_TYPE_CPUID (5)
- Secrets pages: HV_ISOLATED_PAGE_TYPE_SECRETS (4)
This was introduced in commit 75ed2c9f90 ("vmm: add KVM
SEV-SNP support to IGVM loader") which abstracted page types
into a PageTypeConfig struct but assigned wrong values for the
MSHV variant. Using incorrect page types causes the MSHV
hypervisor to reject or mishandle isolated page imports,
leading to guest boot failure.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
For SEV-SNP guests using IGVM, the ACPI tables and system
configuration (MP tables, EBDA, SMBIOS, PVH start info, e820)
are provided by the IGVM file. The rsdp_addr is set to None
for these guests to indicate ACPI table creation was skipped.
Commit 7d65187350 ("vmm: make RSDP address optional in
configure_system") removed the guard that prevented calling
configure_system when rsdp_addr is None. This caused MSHV
SEV-SNP guests to crash because configure_system writes to
guest memory locations that conflict with the IGVM-provided
layout.
Restore the guard by only calling configure_system when
rsdp_addr is Some, which preserves the intended behavior
for CVM guests while still allowing the Option<GuestAddress>
refactoring.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Muminul Islam <muislam@microsoft.com>
If querying the fd's MTU fails (because it was from a different network
namespace). Degrade gracefully by not advertising the VIRTIO_NET_F_MTU
feature and instead let the guest kernel use the default 1500 Ethernet
MTU.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use the VP register page to read and write emulation-related
special registers directly, avoiding expensive IOCTLs for
registers that instruction emulation never touches.
In cpu_state(), read only segments, cr0, and efer from the VP
register page instead of calling get_sregs() which issues
IOCTLs for tr, ldt, gdt, idt, cr2, apic_base, and
pending_interruption.
In update_cpu_state(), when segments change, write only the 6
segment registers to the VP register page and set the segment
dirty bit, instead of calling set_sregs() which issues IOCTLs
for tr, ldt, gdt, idt, cr0-cr4, cr8, efer, and apic_base.
Both paths fall back to the IOCTL-based methods when the VP
register page is not available.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
VfioUserDmaMapping::map is reached from the virtio-iommu MAP handler
with (iova, gpa, size) all guest-controlled. Validate the length of the
region fits, not just the start.
Before this change the vfio-user on the other end could get a size that
spans past the end of its backing storage.
Signed-off-by: Dylan Reid <dgreid@fb.com>
The TX path's inline-data branch didn't check the inline buffer length
against the guest-supplied pkt.len() field. The worker will later panic
when it tries to index the packet.
Add the missing check, mirroring the other TX branches.
Signed-off-by: Dylan Reid <dgreid@fb.com>
dma_unmap computed `iova + size - 1` unchecked while the sibling dma_map
already used checked_add/checked_sub. A guest reaching dma_unmap via
VIRTIO_IOMMU_T_UNMAP could cause a panic.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Catch u64 overflows on map so that later translation requests from the
guest don't have a vector for causing a host panic.
Signed-off-by: Dylan Reid <dgreid@fb.com>
prepare_activator() called queue.is_valid() and only logged the failure,
then still pushed the queue to the activator. This would later panic.
Technically this is a fixup for:
a10508970 "virtio-devices: Support driver programming fewer queues"
But that's been in there since 2021. The intent was to allow a subset of
possible queues to be configured, but the invalid queues slipped through
too.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Replace existing CI files with a consolidated one to delay starting
resource intensive CI jobs until after less resource intensive ones have
completed: e.g. don't start integration tests if the basic build tests
fail.
Architecture:
- Trigger on [pull_request, merge_group]; concurrency keyed per PR/ref.
- preflight job classifies changed paths and exposes a 'full' flag that
gates the heavier build/quality/integration suite. Any CI change
classifies itself as full so it is exercised.
- Leaf jobs gate at the job level using preflight outputs; doc-only,
openapi-only, dockerfile-only and similar PRs skip the full suite.
- integration-x86-64-pr runs the (garm-jammy, gnu) slice on PR and MQ;
integration-x86-64-mq runs the other 3 matrix entries on MQ only.
- integration-{arm64, vfio, windows, rate-limiter} are MQ-only.
- integration jobs gate on dco/quality/build success.
- A single all-green aggregator job is the only required-status check;
it folds in every leaf job via `needs`.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add support for backend that is connected via the vhost-user-generic
frontend to generate an interrupt into the guest when it has made a
change to the configuration. This is useful for devices that can change
the exposed configuration at runtime.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Verify that a freshly created sparse QCOW2 image reports a
physical size smaller than its logical size.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that try_clone preserves the backend dispatch for both
sync and io_uring backends.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that the sync backend disables batch requests and the
io_uring backend enables them.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delete QcowDiskSync and QcowDiskAsync wrapper structs along with
their DiskFile trait impls. Only the AsyncIo worker structs
QcowSync and QcowAsync remain. Reduce module visibility of
qcow_sync and qcow_async to pub(crate).
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace QcowDiskSync and QcowDiskAsync constructors in the
qcow_sync and qcow_async test modules with QcowDisk::new,
passing use_io_uring=false and use_io_uring=true respectively.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Update open_qcow2 to construct QcowDisk instead of choosing
between QcowDiskAsync and QcowDiskSync. The backend decision
is now made inside QcowDisk::create_async_io.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace QcowDiskSync and QcowDiskAsync with QcowDisk in all QCOW2
benchmark helpers. The sync helpers pass use_io_uring=false, the
async helpers pass use_io_uring=true.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce QcowDisk, a unified DiskFile implementation for QCOW2
disk images that handles backend selection at runtime via a
use_io_uring flag, matching the pattern used by FixedVhdDisk.
The wrapper delegates to QcowSync or QcowAsync based on the flag
and includes a compile time guard that returns an error when
io_uring is requested but the feature is not enabled.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The VirtioInterrupt is now always created so the Option<..> can always
be removed.
As a side effect the interrupt_source_group can also be removed from the
struct.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Since this is always created there is no need to make it an Option type
simplifying the code. Historically it was an Option to support INTx
based virtio but that was removed long ago.
Signed-off-by: Rob Bradford <rbradford@meta.com>
msix_num is guaranteed to be at least 1 so this check (and the Option)
that it returns can be removed.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Rather than calculate in the DeviceManager and pass it through do it in
the device where it already has all the required information.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Previously the interrupt was created in VirtioPciDevice, moved via the
Option::take() to the VirtioPciDeviceActivator and then moved to the
VirtioDevice upon activation. On reset it would be moved back ready for
reactivation.
Since this already an Arc type remove the wrapping Option and instead
refcount it such that the VirtioPciDevice can continue to hold onto it
for later activations.
This significantly simplifies the reset() logic as there is no need to
hand back the interrupt.
A few devices used whether the interrupt was Some to make triggering an
interrupt a no-op. However the MSI-X interrupt routing already drops the
interrupt if the driver hasn't yet configured the vector so it is safe
to trigger the interrupt before device activation (e.g. balloon resize
request before driver loaded).
VirtioCommon still retains an Option<..> for the interrupt as the
interrupt is not known until activation time (after this has been
created). A helper VirtioCommon::trigger_interrupt() has been added to
handle this.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Per the virtio spec a device reset must return the device to its
power-on state. The reset path was only zeroing queue_select. Add
VirtioPciCommonConfig::reset() and call it from the transport's reset
path so the configuration is cleared. Also relax the condition to allow
the device to be reset at any time to match the spec.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The virtio specification treats reset as the recovery operation and so
must take the device back to a fresh state, and the driver waits for the
status read-back to converge before continuing. There is no defined way
for the device to report a reset failure to the driver.
Previously the implementations of reset() would return early and not
complete all their cleanup leaving them in an inconsistent state. Now
log errors and continue through the execution.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
The four vhost-user device wrappers (blk, fs, generic_vhost_user, net)
each carried an identical reset() body that resumed the worker thread,
asked the backend to reset, signalled kill_evt and dropped interrupt_cb.
Move the shared body into VhostUserCommon::reset() so behaviour stays in
one place.
No behavioural change.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
`test_live_migration_virtio_fs` and its `_local` variant lived in
`common_sequential` because they shared `~/workloads/shared_dir` as
the virtiofsd backing and wrote/deleted the same `migration_test_file`
and `post_migration_file` paths inside it. Two instances running
concurrently would race on those files.
Give each invocation its own backing directory under `guest.tmp_dir`,
which is already per-test unique and gets cleaned up by the `TempDir`
drop. The test logic is otherwise unchanged. Move both wrappers and
the helper from `common_sequential` to `common_parallel` and update
the sequential-tests comment accordingly.
The boot footprint is small (512 MB src + 512 MB dest), so two
concurrent instances comfortably fit alongside the rest of the
parallel suite. The remaining sequential live-migration tests
(balloon, NUMA) genuinely need their isolation slot for memory
headroom.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Reduce `nr_hugepages` from 12 GB to 6 GB on both architectures. The
number if huge pages needed (if all the tests run at once) is 4GiB so
this gives 50% headroom.
This should reduce the number of tests that fail/flake out due to lack
of memory.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Move the live migration tests themselves into the common scopes allowing
the tests to now run interleaved together hopefully reducing CI time.
On MSHV the live migration tests are now not compiled in rather than
compiled in and skipped (as the helpers are not compiled in for MSHV.)
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Move the helper methods used for live migration to the common utils
(like many other tests use).
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
Move the live migration test running from their own script into the
x86-64 script (on aarch64 they were already in the same script.) They
were historically separate as they were new. Now they are established it
makes sense for them to be combined.
The timeout in the GitHub workflow has been extended to accommodate the
extra work in the same step.
The Rust test scopes are unchanged - the running of the tests has been
moved.
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
The aarch64 integration script hardcoded `LAST_RELEASE_VERSION="v39.0"`
for the live-upgrade binary download, while the live-migration runner
already accepts a `MIGRATABLE_VERSION` env override with a `vxx.0`
regex check. Standardise the aarch64 script on the same env-override
block so both arches honour the same knob with the same validation.
Default is unchanged (v39.0).
Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
This daemon is only a testing tool used during integration testing. The
previous code auto-detected the image type from the file's magic bytes
and opened qcow2 images via QcowFile. Such behaviour has been the cause
of security issues in the past.
Drop the qcow2 detection and open path so only raw images are handled.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The GvaGpaValid flag in the intercept message indicates whether
the provided GPA corresponds to the decoded GVA. Without checking
this flag, the emulator may incorrectly use a stale GPA mapping
when the hypervisor invalidates it.
Add a check for the GvaGpaValid flag before using the cached
(GVA, GPA) mapping. If the flag is clear, use a sentinel value
to force translate() to perform a proper hypercall-based
translation instead of using an invalid cached mapping.
Signed-off-by: Pedro Barbuda <pbarbuda@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
release_memory_range took (range_base, range_len) verbatim from a
guest-controlled descriptor (free-page-reporting and inflate paths) and
called fallocate(PUNCH_HOLE | KEEP_SIZE) on the backing file before any
length check ran. find_region only validates that range_base lands
inside *some* region; range_len can extend past the region's end. When
the operator uses --memory-zone file=PATH against a host file larger
than the zone, the punch zeroes host file content past the guest's
memory extent.
Free-page reporting is advisory, so the VMM is allowed to act on a
subset of a free range. Clamp range_len to the bytes that actually fit
within the region returned by find_region. Going past the end of a
region is most likely a guest bug so log it.
Signed-off-by: Dylan Reid <dgreid@fb.com>
# TL;DR
In https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7990 we
replaced the old deadlock with another deadlock. This commit finally
resolves (hopefully) all dead locks on that code path by not holding
`CpuManager::vcpu_states` while waiting for vCPU pause acknowledgements.
A vCPU can receive the pause kick while servicing the ACPI CPU hotplug
MMIO device, and that MMIO path also needs `vcpu_states`. Holding the
mutex across the wait phase deadlocks pause against that MMIO access.
# Problem
`signal_vcpus()` used to lock `CpuManager::vcpu_states` for the whole
function, signal every vCPU, and then wait for each vCPU to acknowledge
the kick.
That lock scope is too wide. A vCPU is allowed to observe the kick in
userspace rather than returning directly from `KVM_RUN`. During boot,
`vcpu0` can be in an MMIO access on the ACPI CPU hotplug device when
pause arrives. `AcpiCpuHotplugController::read()` and `write()` both
lock `vcpu_states` to inspect or update the selected vCPU state.
The deadlock looks like this:
VMM thread vCPU thread
---------- ----------
lock(vcpu_states)
signal_vcpus()
wait for ack ---------------------> receives pause kick
enters ACPI CPU hotplug MMIO
lock(vcpu_states) [blocks]
wait for ack <--------------------- cannot set vcpu_run_interrupted
The VMM thread waits for `vcpu_run_interrupted` to flip, but the vCPU
cannot reach the pause acknowledgement path because it is sleeping on
the same mutex.
The debug logs matched that cycle exactly: signal delivery kept
working, `vcpu0` stayed in one unmatched `run()` invocation, the stuck
thread sampled in `futex_do_wait`, and the backtrace pointed at
`AcpiCpuHotplugController::read()`.
# Reproducer
This was reproducible by continuously issuing `pause()` / `resume()`
from while a Linux guest was still booting. That boot-tim window
reliably exercises the ACPI CPU hotplug MMIO access that participates in
the deadlock. Once the guest had finished booting, the problem became
much harder to trigger (as there is no MMIO operation without explicit
CPU plugging).
# Solution
Keep the existing two-phase behavior so all vCPUs are still signalled
before the wait phase, but narrow the lifetime of the `vcpu_states`
mutex. Reacquire it only long enough to access one `VcpuState` at a
time in each phase.
That preserves the original pause semantics and the fast signal-all /
wait-all structure, while removing the lock inversion with the ACPI CPU
hotplug MMIO path.
This also remains safe if a vCPU is hot-removed while pause is in
progress. Hot-remove does not shrink `vcpu_states`; it stops the thread
and clears the `VcpuState` handle in place. `signal_vcpus()` can
therefore snapshot the vector length up front, and if a vCPU disappears
between the signal and wait phases,
`wait_until_signal_acknowledged()` will observe `handle.is_none()` and
return successfully.
The interruption handshake itself lives in atomics inside each
`VcpuState`. The outer mutex is only needed to reach the state objects,
not to keep the acknowledgement protocol correct. Dropping the mutex
between iterations therefore does not weaken the pause protocol, but it
does allow MMIO handlers and other `vcpu_states` users to make forward
progress while the VMM waits for the kick to be observed.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Increase the number of parallel integration tests in CI to save ~3-5
minutes per x86_64 run. The thread limit is driven by RAM and disk
space constraints, not CPU availability.
A new `PARALLEL_INTEGRATION_TESTS_NUM` environment variable controls
the thread count. In CI it is set explicitly (12 for x86_64, 25 for
ARM64); locally it falls back to `nproc / 4`, preserving the previous
behavior.
Only the first test group (`common_parallel`, `live_migration_parallel`)
uses the overridden value - subsequent groups (dbus_api, fw_cfg,
ivshmem, aarch64_acpi) continue to use the `nproc / 4` default.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
The physical size of a fixed VHD is the data region plus the 512
byte footer. Verify it differs from the logical size.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Fixed VHDs do not support resize. Verify the error is returned.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that a cloned disk produces the same async I/O backend
as the original for both sync and io_uring paths.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that create_async_io dispatches to the correct backend
depending on use_io_uring. The sync backend does not support
batch requests, while the io_uring backend does.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that FixedVhdDisk::new with the sync backend reads the VHD
footer and reports the correct logical size.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Update open_fixed_vhd to construct FixedVhdDisk instead of choosing
between FixedVhdDiskAsync and FixedVhdDiskSync. The io_uring decision
is now made inside FixedVhdDisk::create_async_io().
Remove FixedVhdDiskSync and FixedVhdDiskAsync DiskFile wrapper structs
from fixed_vhd_sync.rs and fixed_vhd_async.rs. Only the FixedVhdSync
and FixedVhdAsync AsyncIo worker structs remain in those files.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce FixedVhdDisk as a single DiskFile wrapper around FixedVhd.
It accepts a use_io_uring flag at construction time and dispatches to
FixedVhdSync or FixedVhdAsync inside create_async_io() accordingly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that physical size of a sparse file is less than
logical size.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that try_clone preserves the backend variant for
each RawBackend: sync, AIO and io_uring.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify each RawBackend variant stores correctly and
create_async_io dispatches to the matching constructor.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that RawDisk with the sync backend reports the correct
logical size for a temporary file. Introduce make_raw_file helper
and TEST_SIZE constant for reuse in subsequent tests.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Update open_raw to construct RawDisk instead of choosing between
RawFileDisk, RawFileDiskSync and RawFileDiskAio. The backend decision
is now made inside RawDisk::create_async_io.
Remove the DiskFile wrapper structs from raw_sync.rs, raw_async.rs
and raw_async_aio.rs. Only the AsyncIo worker structs remain in those
files. Reduce their module visibility to pub(crate).
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace direct RawFileAsyncAio construction with RawDisk
and create_async_io, consistent with the unified API.
Assisted-by: Claude:Opus-4.6
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Update the fuzz target to use RawDisk instead of RawFileDiskSync,
consistent with the unified API.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add the DiskFile marker and AsyncDiskFile with try_clone and
create_async_io. The dispatch creates RawFileSync, RawFileAsync,
or RawFileAsyncAio depending on the backend selected at
construction. Alignment handling is left to the workers as is,
to be centralized separately per #8050.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use the block device aware resize from RawFileDisk. For block
devices, verify the externally set size matches instead of
calling ftruncate. For regular files, truncate as usual.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce the unified DiskFile wrapper for raw disk images. The
RawBackend enum selects between sync, io_uring, and AIO backends
at construction time.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The trait has no implementations. All format backends now implement
the composable disk_file traits instead. The DiskFileError and
AsyncIo types remain in async_io.rs as they are still used by
format workers.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
All disk format backends now implement AsyncFullDiskFile directly.
The DiskBackend enum that dispatched between Legacy and Next arms
is no longer needed since the factory returns trait objects and vmm
no longer constructs format types manually.
Replace DiskBackend with Box<dyn AsyncFullDiskFile> in the Block
struct and its constructor. Remove the DiskBackend::Next wrapping
in device_manager and the fuzz target.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace the manual match block that constructed each disk format
backend with a single call to block::factory::open_disk. The factory
handles file opening, format detection, async/sync backend selection
and logging internally.
Remove imports and errors for individual format types and helper
functions that are no longer called directly. The factory returns
BlockError with path and operation context attached, surfaced via
the existing Disk variant.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that open_disk() falls back to synchronous backend when both
io_uring and AIO are disabled, and that the returned disk reports
the correct logical size.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Create a minimal QCOW2 temp file via QcowFile::new() and verify
that open_disk() detects it as ImageType::Qcow2.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that open_disk() detects a plain temporary file as RAW and
returns a working backend with synchronous fallback.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that open_disk() returns BlockErrorKind::Io when the disk
image file does not exist.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce block::factory with open_disk() as the single entry point
for opening disk images. It handles file opening, format detection,
async I/O probing, and backend construction.
Per format helpers (open_fixed_vhd, open_raw, open_qcow2, open_vhdx)
prefer io_uring over AIO over synchronous fallback. Warnings only
fire when a backend was eligible but its runtime probe failed, not
when the user intentionally disabled it.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Microsoft Hypervisor's hyperclear technology supports at most two
threads per core.
Practically all x64 CPUs nowadays only support two threads per core.
Enforce this in the common code.
Assisted-by: OpenAI:ChatGPT-5.4
[Test cases written by an LLM ]
Signed-off-by: Wei Liu <liuwe@microsoft.com>
There is no reason for most of the Request struct to be writable from
anywhere in the codebase. Encapsulate it.
Use getter functions for access outside the request module. Replace the
trivial setter for the writeback field with direct assignment.
No functional change intended.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
The new_ prefix in Rust conventionally denotes constructors that return
Self (e.g. Vec::new(), File::new()). AsyncDiskFile::new_async_io does
not return Self. It is a factory method that constructs and returns a
Box<dyn AsyncIo> worker bound to the disk file descriptor and
metadata. The create_ prefix communicates this: the caller receives
a freshly constructed object of a different type.
This rename touches every format backend in block plus two external
callers in virtio-devices and performance-metrics. Every change is a
mechanical s/new_async_io/create_async_io/ substitution. No functional
change.
Ref: #7877 (task 3.2.8)
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
DeviceManager and VfioPciDevice both hold Arc<MmapRegion> for
each VFIO BAR mmap window. During VM shutdown, VfioPciDevice
drops after DeviceManager::Drop::drop (via device_tree
field drop). Without clearing DeviceManager's clones first,
VfioPciDevice::unmap_mmio_regions decrements the Arc but
does not reach zero, munmap never fires, the VFIO device
file VMAs survive, and VFIO_GROUP_UNSET_CONTAINER returns
EBUSY.
Clear DeviceManager's mmio_regions in Drop::drop so
VfioPciDevice is the sole Arc owner at drop time and ensure
VFIO_GROUP_UNSET_CONTAINER ioctl success.
Remove redundant .clone() on the mmio_regions() return value
in the eject_device() hot-unplug path.
Add detail comments
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Change RawFileAsync::new() from std::io::Result to BlockResult,
aligning it with RawFileAsyncAio::new(). Each fallible call inside
the constructor now maps to BlockErrorKind::Io explicitly.
FixedVhdAsync::new() follows the same change since its only
fallible operation is constructing a RawFileAsync. The intermediate
DiskFileError::NewAsyncIo wrapping in both new_async_io() call
sites is no longer needed and is removed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace the blanket BlockErrorKind::Io mapping with an explicit
match on all VhdxError variants:
NotVhdx, ParseVhdxHeader, ParseVhdxMetadata,
ParseVhdxRegionEntry => InvalidFormat
ReadBatEntry => CorruptImage
ReadFailed, WriteFailed => Io
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Vhdx::physical_size() can only return Error::GetFileMetadata.
Replace the catch-all arm with unreachable!() so future error
variants are not silently mapped to a generic Io classification.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace .unwrap() on FixedVhd::logical_size() with map_err in
DiskSize::logical_size() and new_async_io() for both FixedVhdDiskSync
and FixedVhdDiskAsync. The call is infallible today but unwrap hides
that assumption from callers and would panic if it ever changed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
FixedVhd::physical_size() can only return Error::GetFileMetadata.
Replace the catch-all arm with unreachable!() so future error
variants are not silently mapped to a generic Io classification.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write a known data pattern through QcowFile, compress all clusters
in place, reopen and read back via the seek based file_read path.
This covers the decompress_l2_cluster code path used by QcowFile
which is separate from the pread based path in QcowSync/QcowAsync.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write a known data pattern, compress all clusters in place, reopen
through QcowDiskAsync, and read back from four concurrent queues
on separate threads. Each queue independently decompresses and
returns the correct data, validating the Arc<dyn Decoder> sharing.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write a known data pattern to a QCOW2 image, convert all allocated
clusters to compressed format using compress_allocated_clusters,
reopen the image through QcowDiskSync, and verify that reading back
the full cluster returns the original data.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that decompress_cluster returns EIO when given invalid
compressed data that the decoder cannot process.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Compress a known 64K buffer with raw deflate, pass it through
decompress_cluster with ZlibDecoder, and verify the output matches
the original data.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that pread_alloc returns the correct data for a full read
from the start and a partial read at an arbitrary offset. Also
confirm that reading past the end of file produces an error.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a test utility that converts standard uncompressed clusters in
a QCOW2 image into compressed clusters in place. It walks the L1/L2
tables, compresses each allocated cluster with raw deflate, appends
the compressed payload at the end of the file, and rewrites the L2
entry with the compressed layout.
This enables end to end testing of the compressed read path without
external tools like qemu-img.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move decompression of compressed QCOW2 clusters out of the metadata
lock. Previously, reading a compressed cluster acquired a write lock
on metadata to perform in place decompression. Now, try_map_read
extracts the compressed layout (host offset, size) under a read lock
and returns it in the ClusterReadMapping::Compressed variant. Each
consumer (QcowSync, QcowAsync, Qcow2Backing, QcowFile) performs the
pread and decompression at the call site without holding any lock,
using the pread_alloc and decompress_cluster helpers.
Create the decoder once in QcowMetadata as Arc<dyn Decoder> and
share it via Arc::clone to QcowAsync, QcowSync, and Qcow2Backing
at construction time. This avoids per read RwLock acquisitions and
heap allocations. Add Send + Sync bounds to the Decoder trait.
This eliminates write lock contention on compressed reads, allowing
them to proceed concurrently with other read operations.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Cache the immutable cluster_size value at construction time in
QcowAsync, QcowSync, and Qcow2Backing. This avoids repeated RwLock
read acquisitions on the hot write and deallocation paths.
Replace QcowMetadata::cluster_offset() calls with inline bitmask
operations using the cached cluster_size. Remove the now unused
cluster_offset() method from QcowMetadata.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add two reusable helpers for the compressed cluster read path:
- pread_alloc(fd, offset, len) allocates a buffer and fills it with
pread_exact, returning the owned Vec.
- decompress_cluster(compressed, cluster_size, decoder) allocates the
output buffer, decodes via the Decoder trait, and validates that the
decoder produced exactly cluster_size bytes.
These will be used by QcowSync, QcowAsync, Qcow2Backing, and the
legacy QcowFile.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Spawn a process that exits immediately, then spawn another under
the same test name. Verify the stale group is detected and a fresh
group is created for the second child.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Spawn two processes under the same test name and verify they
have the same group PID. Cleanup kills both.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Spawn a sleep process through the registry, verify it is alive,
call cleanup and verify the process was killed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use thread::Builder to give the test thread a name matching the
test so Guest picks it up automatically. After every test, call
ProcessRegistry::cleanup() to kill the process group instead of
the old pkill based cleanup_stale_processes().
Remove cleanup_stale_processes() and its call sites.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Route GuestCommand::spawn(), iperf3, and ethr spawns through
ProcessRegistry::spawn() when the guest has a test_name. This
places every child process into the test's shared process group
so they can all be killed with a single killpg call.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a global registry that maps test names to process group IDs.
The first child spawned for a test creates a new process group
via setpgid(0, 0); subsequent children join it via setpgid(0, pgid).
A single killpg(pgid, SIGKILL) tears down all processes the test
spawned.
Also add Guest.test_name, populated automatically from the current
thread name at construction time.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The driver needs to be notified with the number of bytes written by the
device. Ensure that the correct number of bytes is reported.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The number of bytes written into descriptors should be reported for
`add_used()`. Here it is either just the status byte or also the size of
serial ID for the block device.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The virtio spec allows a chain of writable descriptors however the rng
device was assuming just a single writable descriptor. Instead fill in
all writable descriptors. There is no status byte (unlike e.g. block)
and instead 0 bytes used is used to indicate error.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The virtio spec requires that a status response is always written on
error. This was missing from the path where we had a valid request but
not for one we support.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The virtio spec allows the use of larger descriptors (for future
expansion). Relax the bounds check to only reject descriptors that are
too small.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The virtio spec allows the use of larger descriptors (for future
expansion). Relax the bounds check to only reject descriptors that are
too small.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The virtio spec says the used-ring length is bytes the device wrote to
device writable descriptors. The net TX descriptors are device readable
only (the device wrote nothing back) so the length needs to be 0. On the
ctrl queue the number of bytes reported was wrongly the size of the
status descriptor not the number of bytes written (the descriptor is
permitted to be larger).
Signed-off-by: Rob Bradford <rbradford@meta.com>
During development, it is common to cancel a running test and
rerun it after making changes. However, pressing Ctrl+C while
dev_cli.sh runs long-running container commands (wget, qemu-img,
cargo build, etc.) does not reliably terminate the process.
Bash defers signal handling while a foreground process is
running, so the trap only fires after the docker run command
returns. This makes it difficult to cancel and restart quickly.
Fix this by introducing a run_container() wrapper that runs
docker in the background and uses 'wait', which is immediately
interruptible by signals. A cleanup() trap handler is set for
SIGINT and SIGTERM that kills the named container, the tracked
background PID, and any remaining child processes.
Each docker run invocation is assigned a unique --name based
on the script PID (clh-dev-$$) to allow targeted cleanup.
The interactive shell (cmd_shell) is left unwrapped since it
needs foreground terminal I/O.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Fix test flakiness where the virtiofsd daemon was still running and
hotplugging was trying to reach the old version. Cleanup the socket so
that waiting for it actually waits for the new instance.
Signed-off-by: Rob Bradford <rbradford@meta.com>
QEMU supports passing inline string values to the guest via fw_cfg
(-fw_cfg name=...,string=...). Cloud Hypervisor previously only
supported file-backed fw_cfg items. This adds the 'string' option
so users can pass values like OVMF's X-PciMmio64Mb without creating
a temporary file on the host.
Each fw_cfg item now accepts exactly one of 'file' or 'string'.
The FwCfgInvalidItem invariant is validated in PayloadConfig::validate()
(via FwCfgConfig::validate()), covering both CLI and JSON API paths.
The populate_fw_cfg match arm uses unreachable!() since validation
guarantees the invariant holds at that point.
CLI syntax:
--fw-cfg-config items=[name=opt/ovmf/X-PciMmio64Mb,string=262144]
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Move FwCfgMissingKernel/Cmdline/Initramfs error variants from
ValidationError into PayloadConfigError. Change FwCfgConfig::validate()
to take &PayloadConfig instead of &VmConfig and return
PayloadConfigError. Wire the call through PayloadConfig::validate()
so both CLI and JSON API paths are covered.
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Live migration is not yet supported on mshv arm64. Annotate the
applicable integration tests with cfg_attr to ignore them for that
configuration.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Add build and clippy jobs for kvm+sev_snp+igvm+fw_cfg feature combination.
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Boot-time block devices on PCI segment 0 use 32-bit BARs so early
firmware can access them without additional identity mapping in the
firmware page tables. However, hot-plugged block devices are only ever
seen by the OS kernel which handles 64-bit BARs natively.
Switch hot-plugged block devices to 64-bit BARs to avoid exhausting the
scarce 32-bit MMIO window (typically 2-3 GB between RAM and 4 GB) when
many devices are hot-plugged.
Extract the BAR sizing decision into use_64bit_bar_for_virtio_device()
and thread an is_hotplug flag through add_virtio_pci_device(). Add unit
tests covering all relevant combinations.
Signed-off-by: Dylan Reid <dgreid@fb.com>
The Linux x86 boot protocol defines the setup area as
(setup_sects + 1) * 512 bytes. Previously we exported only the
boot_params buffer (4096 bytes), which is wrong for kernels with
setup_sects >= 8 where the actual setup area exceeds boot_params.
Truncate or extend the existing buffer to the correct setup_sects-
derived length, reading any extra bytes directly from the kernel file.
This avoids an extra allocation in the common case (setup_sects <= 7)
and matches QEMU's fw_cfg_add_kernel() behavior in
hw/i386/x86-common.c.
Signed-off-by: Dylan Reid <dgreid@fb.com>
A bootloader/firmware (e.g. stage0) and the VMSA page require dedicated
memory regions at fixed GPAs.
Add reserve_region_for_stage0() to allocate these regions before IGVM
loading begins:
- Stage0 at GPA 0xffc0_0000 (4 MB)
- VMSA page at GPA 0xffff_ffff_f000 (4 KB)
These reservations are KVM-only; MSHV handles stage0/VMSA placement
through its own isolated import path.
Also add fw_cfg device creation and SYS_statx to the vCPU seccomp
allowlist (needed by stage0's file access pattern).
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Adapt the IGVM loader to work with both MSHV and KVM backends, which
differ in page type constants, CPUID page layout, and VMSA handling.
Abstract page types into a PageTypeConfig struct populated at runtime
from the detected hypervisor, replacing hardcoded mshv_bindings constants.
Apply the VMSA register state to each vCPU via setup_sev_snp_regs(),
translating SevSelector attributes to KVM segment format using a bitfield
decoder.
KVM's SNP launch path sanitizes certain CPUID bits that could lead to
an insecure guest. If the VMM sets these bits, KVM rejects the CPUID
page import on the first attempt, requiring a retry with the
firmware-corrected values.
Pre-clear the known problematic bits before import to avoid the
reject-and-retry cycle:
- Leaf 0x1, ECX bit 24: TSC_DEADLINE (filtered by KVM)
- Leaf 0x7, EBX bit 1: SGX (filtered by KVM)
- Leaf 0x7, EDX: clear entirely (contains speculative features)
- Leaf 0x80000008, EBX bit 25: filtered by KVM
- Leaf 0x80000021, ECX: clear entirely
This keeps the CPUID page stable across launch updates and avoids
noisy error logs from the retry path.
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Co-authored-by: Dylan Reid <dgreid@fb.com>
Signed-off-by: Dylan Reid <dgreid@fb.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
During SNP boot all guest RAM is initially marked
KVM_MEMORY_ATTRIBUTE_PRIVATE. Pages imported via SNP_LAUNCH_UPDATE are
properly accepted by the guest, but generic RAM pages (e.g. the AP
trampoline at GPA 0xD000) are not. When stage0 on the BSP starts
secondary vCPUs via x2APIC, the APs try to execute from the trampoline
page through the shared mapping while KVM still has it marked private,
causing a KVM_EXIT_MEMORY_FAULT (flags=KVM_MEMORY_EXIT_FLAG_PRIVATE)
that previously fell through to the catch-all error, killing the VM.
Handle VcpuExit::MemoryFault by toggling the page's memory attribute
between private and shared based on the exit flags, allowing the vCPU
to retry the access.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
SEV-SNP guests will issue this hypercall to signal a change in the page
encryption status to the hypervisor.
Handle VcpuExit::Hypercall in the KVM vCPU run loop: decode the GPA,
page count, and private/shared attribute from the hypercall arguments,
then call KVM_SET_MEMORY_ATTRIBUTES to update the page state.
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Add the KVM_SEV_SNP_LAUNCH_FINISH ioctl, which finalizes the SNP
launch sequence and transitions the VM into a runnable encrypted
state.
Additionally, add KVM_SEV_SNP_LAUNCH_FINISH to the seccomp allowlist.
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Implement the KVM_SEV_SNP_LAUNCH_UPDATE ioctl.
Extend Vm::import_isolated_pages() with a uaddrs parameter carrying
host virtual addresses, which KVM needs, unlike MSHV. Compute uaddrs
from guest memory mappings in the IGVM loader.
Add KVM_SEV_SNP_LAUNCH_UPDATE to the seccomp allowlist.
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Introduce the SevFd abstraction that wraps /dev/sev and implements the
KVM_SEV_INIT2 and KVM_SEV_SNP_LAUNCH_START ioctls for SEV-SNP VM
initialization on KVM.
Key changes:
- Add sev.rs with KvmSevInit and KvmSevSnpLaunchStart ioctl structs
matching the kernel layout (linux/arch/x86/include/uapi/asm/kvm.h)
- Implement KVM_SEV_INIT2 and KVM_SEV_SNP_LAUNCH_START ioctls
- Set KVM_MEMORY_ATTRIBUTE_PRIVATE on newly created memory regions
when guest_memfd is supported
- Widen SevSnpPageAccessProxy cfg gates from mshv-only to all
sev_snp-enabled builds
- Make sev_snp_init a required trait method (remove default impl)
- Include KVM_SEV_SNP_LAUNCH_START in the seccomp allowlist
- Parse VMSA SEV features from IGVM and include them in the
KVM_SEV_INIT2 ioctl
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Co-authored-by: Rob Bradford <rbradford@meta.com>
Signed-off-by: Rob Bradford <rbradford@meta.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Move IGVM file parsing from load_igvm() into a dedicated parse_igvm()
helper in igvm/mod.rs, and parse the file upfront in Vm::new() so the
resulting IgvmFile struct is available throughout VM initialization.
This is a prerequisite for extracting VMSA SEV features from the parsed
IGVM before issuing KVM_SEV_INIT2, which needs sev_features.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
The load_payload and load_payload_async functions previously received a
sev_snp_enabled flag to decide whether to call load_igvm with or
without the host_data parameter. Replace this with a single code path
that always passes host_data behind a cfg(feature = "sev_snp") gate,
removing the runtime branch and the extra parameter threaded through
three call sites.
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Change configure_system to take an Option<GuestAddress>
since rsdp is wrapped into an option anyways (we use configure
system to setup the mptables).
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
The SNP guest policy (AMD SEV-SNP ABI bits controlling SMT, migration,
debug, etc.) was previously hardcoded inside the MSHV implementation.
Widen Vm::sev_snp_init() to accept an SnpPolicy parameter so each
hypervisor backend receives the policy at init time.
Add get_default_sev_snp_guest_policy() in the VMM to construct the
default policy.
Co-authored-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Previously, the payload validation rejected an IGVM file combined with
a kernel or firmware.
Relax this constraint to allow an IGVM carrying a firmware (e.g Oak
stage0) to be paired with a separate kernel image.
This enables fw_cfg-style boot where stage0 loads a kernel provided
through fw_cfg rather than embedded in the IGVM file itself.
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Add support for guest_memfd (available in Linux kernel v6.8+), which
enables private memory for confidential VMs.
Key changes:
- Introduce UserMemoryRegion abstraction with guest_memfd fields
- Add From impls between kvm_userspace_memory_region2 and UserMemoryRegion
- Convert all KVM memory region operations from kvm_userspace_memory_region
to kvm_userspace_memory_region2, with automatic fallback to v1 when
guest_memfd is not supported
- Add set_user_memory_region() wrapper that dispatches to v1/v2 based on
kvm_guest_memfd_supported capability
- Create guest_memfd via KVM_CREATE_GUEST_MEMFD ioctl when supported
- Extend KvmDirtyLogSlot to preserve region2 fields across dirty log
start/stop cycles
This is prerequisite infrastructure for KVM-based confidential computing
that requires private guest memory backed by guest_memfd.
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
Following the pattern used by the existing virtio devices make the
balloon device work with confidential VMs (e.g. SEV-SNP). This requires
advertising the VIRTIO_F_ACCESS_PLATFORM feature. Do not expose this to
the user as a controllable option and instead only enable in on the
"force" case.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This a clearer name for it's purpose and now matches more closely what
is used for the virtio devices themselves.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Rename from iommu to access_platform_enabled. The original name was
iommu as this feature was exposed for devices behind an IOMMU however
this feature is also now used for confidential VMs so adopt a more
general name.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Replace the stored AccessPlatform reference with one to the
VirtioDevice. By doing this not only does it allow the code to be
simplified but also now makes it virtio spec compliant by only
translating via the access platform if the feature is acknowledged.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This forwards through to the VirtioCommon implementation and can be used
to simplify the virtio PCI access code.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Adding this method to the trait will allow the virtio PCI code to access
a feature conditional version of the access platform and simplify the
logic.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use the new virtio feature gated accessor when creating the handlers for
the virtio devices. This now means that the translations via the
accessor will only be applied if the feature is acked in accordance with
the spec.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add VirtioCommon::access_platform() method. The virtio spec requires
that only if the feature is acked should the accesses be transformed via
the access platform implementation. This will enable that filtering.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use the ioctl based create_loop_device() helper instead of
shelling out to losetup in the file backed 4K alignment test.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Override AsyncIo::alignment() to report the actual device sector
size so that execute_async() correctly bounces misaligned guest
memory pointers.
Guard the io_uring fast path in resolve_read() with an alignment
check. When O_DIRECT is active, guest requests can have I/O sizes
smaller than the device sector size (e.g. 512 byte UEFI reads on
a 4096 byte sector device). The kernel rejects these with EINVAL.
Route such reads through scatter_read_sync() which uses AlignedBuf
and aligned_pread to satisfy O_DIRECT size and offset requirements.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write 128K of patterned data and read it back with O_DIRECT
active to verify the aligned I/O paths produce correct results.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that a 512 byte read from an allocated cluster succeeds
with O_DIRECT. This exercises the synchronous fallback path in
resolve_read() that is taken when alignment is nonzero.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that QcowAsync reports at least SECTOR_SIZE alignment
when O_DIRECT is active. Skipped on filesystems that do not
support O_DIRECT (e.g. tmpfs).
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that QcowAsync reports the default SECTOR_SIZE alignment
when O_DIRECT is not active.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Boot a UEFI guest from a QCOW2 image with direct=on to exercise
the aligned I/O write path during early firmware operations.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Block devices (LVM volumes, loop devices, RBD, etc.) cannot be resized
via ftruncate - they are resized externally. When vm.resize-disk is
called for a block device backend, verify the device size matches the
requested size instead of attempting ftruncate.
This enables the resize-disk API to work with block device backends by
validating the externally-resized device matches the expected size.
Signed-off-by: Vincent Thomas <vincent@v-thomas.com>
Previously, calling pause() when already paused would wait on a barrier
for worker threads that were already parked, causing a deadlock.
This situation occurs when the VMM thread holds a device mutex while
calling an operation that triggers pause(), and a vCPU thread
simultaneously needs that same mutex for MMIO access. With slow I/O
backends (like RBD/Ceph), the timing window for this race is larger,
making the deadlock more likely to occur, see [0].
Make pause() idempotent by checking the paused state atomically and
returning early if already paused, avoiding the barrier wait.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7948#discussion_r305052509
Signed-off-by: Vincent Thomas <vincent@v-thomas.com>
Our bus slots are now Reserved/Allocated/Free so change the method to
free it to free_device_id() and update error.
Also update to take u8 to match the other methods.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Adds a test that checks the correct error is returned on allocation of
an invalid device ID (one that is not in the range 0-31) and when trying
to allocate a reserved ID (such as that of the root bridge).
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Signed-off-by: Rob Bradford <rbradford@meta.com>
This integration test verifies that the same device ID cannot be
allocated twice. Moreover, we check that the returned error matches our
expectations.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit adds an integration test to verify that the guest sees the
correct BDF. Moreover, we check that we can allocate a random free BDF
and that freeing BDFs works.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Signed-off-by: Rob Bradford <rbradford@meta.com>
If we want to test for error cases, it can be useful to inspect the
`stderr` of a `Command` to analyze the errors. For example, this allows
us to ensure that a `Command` returns an `IoError` by parsing the
error trace, if an `IoError` is expected.
This commit prepares the implementation of negative integration tests
for the configurable BDFs.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Some of the documentation references PCI segment ID. For those documents
add a mention of the new PCI device ID.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use two passes to first reserve PCI device IDs and then allocate them
when adding the devices to the bus. This prevents a situation where an
anonymous PCI device allocation clashes with an explicitly allocated PCI
device ID.
Signed-off-by: Rob Bradford <rbradford@meta.com>
We pass the device ID from the config to the allocation routine, where
it is then used as the preferred device ID alongside the existing PCI
segment ID.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Signed-off-by: Rob Bradford <rbradford@meta.com>
Validate the PCI device ID are within range and not using the reserved
value. We need this option to ensure that invalid device IDs received
via an API call result in an error as soon as possible. In this case,
this would be after deserialization. On this code path, validation via
`parse` is skipped and must be invoked by calling `validate`.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Signed-off-by: Rob Bradford <rbradford@meta.com>
For those devices types that have the the ability to support specifying
the PCI device ID add it to their help syntax.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This can be used in a two pass approach where all configs that can hold
PCI devices are evaluated to reserve any specific PCI device IDs they
may need. Those device IDs will later be allocated when the devices are
added to the bus. The tri-state Free, Reserved, Allocated also catches
the problem of hotplugging a device with a specific, already used,
device ID.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Next to tests for `allocate_device_id`, we introduce a new constructor
`new_without_address_manager`, only available in the test build. As
there is no way to instantiate an `AddressManager` in the tests, we use
this constructor to work around this.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit refactors the PCI bus struct. It has two major focuses.
First, we change the type of `device_ids` in `PciBus` to an array. A
fixed-size array better reflects real PCI bus constraints, especially
its limited number of PCI devices. Moreover, it can't be grown
accidentally.
The second focus is changing the type of the key of `devices` in
`PciBus` to `u8`, since device IDs are not allowed to exceed 31. We
furthermore replace magic numbers with constants and make them publicly
available so we can use them in a follow-up change when parsing user
input.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Use `wait_until()` with the SSH command for detecting if the net device
is present/absent as part of hotplugging/unplugging.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use `wait_until()` with the SSH command for detecting if the block
device is present/absent as part of hotplugging/unplugging.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The vhost-user tests uses SSH and checking the RAM to test for the
liveness of the VM - replace the explicit sleep before them with
`wait_until()` allowing them to potentially finish earlier.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Rather than use a fixed time to wait for the socket to be opened instead
test for its existence using `wait_until()`.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Use new `wait_until()` and existing boot response mechanisms to remove
explicit sleeps from these tests.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Calling vm.add-user-device a second time with a socket path already
in use makes the VMM thread block indefinitely inside
vfio_user::Client::new(). libvfio-user servers (SPDK, the reference
libvfio-user daemon) accept a single active client per socket, so
the second connect(2) succeeds at the OS level but the handshake
recvmsg(2) waits for a response that never arrives.
All subsequent API requests queue behind the stuck VMM event loop
and also hang (vm.info, vmm.ping, vm.remove-device). The VM itself
keeps running on vcpu threads, making the symptom confusing: the
guest looks healthy, only the API is unreachable.
This is easy to hit from management software that uses an idempotent
reconcile / ensure pattern for user devices.
Reject the call up-front when another user_device already has the
same socket path, returning an HTTP 500 with a descriptive
UserDeviceSocketInUse error in milliseconds instead of hanging.
Signed-off-by: Max Makarov <maxpain@linux.com>
Several error mappings in vm.rs dropped the underlying error with
map_err(|_| ...), making failures harder to diagnose. Preserve the
source error by adding #[source] fields to InitramfsLoad and ErrorNmi.
- InitramfsLoad: now wraps std::io::Error from seek/rewind operations
- ErrorNmi: now wraps cpu::Error from the CPU manager nmi() call
Partially addresses #7563
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Add micro_bench_qcow_batch_write which builds a batch of num_ops
write requests and submits them all at once through
submit_batch_requests. Writes in QcowAsync are synchronous (COW
path), so this measures whether batching reduces per-request
overhead compared to individual write_vectored calls.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_async_l2_cache_miss which reads one cluster
from each of num_ops distinct L2 tables through the QcowAsync
io_uring path, forcing L2 cache eviction on nearly every read.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add sparse_qcow_async_tempfile which creates a sparse QCOW2 image
with one cluster per L2 table and opens it via QcowDiskAsync.
Mirrors the existing sparse_qcow_tempfile for io_uring benchmarks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_async_write which writes clusters into an
empty QCOW2 image through the QcowAsync io_uring path. Writes
in QcowAsync are synchronous due to COW metadata allocation, so
this measures the write path overhead through the async code path.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add empty_qcow_async_tempfile which creates an empty QCOW2 image
and opens it via QcowDiskAsync. Mirrors the existing
empty_qcow_tempfile for io_uring write benchmarks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_async_compressed_read which reads from a
zlib compressed QCOW2 image through the QcowAsync io_uring path.
Compressed clusters take the sync fallback since they require
decompression.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add compressed_qcow_async_tempfile which creates a zlib compressed
QCOW2 image via qemu-img and opens it via QcowDiskAsync. Mirrors
the existing compressed_qcow_tempfile for io_uring benchmarks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_async_backing_read which reads clusters from
a QCOW2 overlay through the QcowAsync io_uring path. All reads
fall through to the backing file, exercising the sync fallback
path in QcowAsync.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add qcow_async_overlay_tempfile which creates a QCOW2 overlay
backed by a RAW file and opens it via QcowDiskAsync. Mirrors
the existing qcow_overlay_tempfile for io_uring benchmarks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_async_multi_cluster_read which reads 8
contiguous clusters (512 KiB) per request through the QcowAsync
io_uring path. With coalesced mappings this can hit the io_uring
fast path for a single Readv SQE.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_async_random_read which reads clusters in
random order through the QcowAsync io_uring path. This mirrors
the existing sync random read benchmark and measures io_uring
completion handling under random access patterns.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_batch_read which builds a batch of num_ops
read requests and submits them all at once through
submit_batch_requests. This exercises the io_uring batch
submission path added in qcow_async, where multiple SQEs are
packed into a single io_uring_enter call.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_async_read which reads clusters through the
QcowDiskAsync io_uring backend. Single allocated cluster reads go
through io_uring for true asynchronous completion, unlike the sync
benchmarks which use QcowDiskSync with blocking I/O.
Workloads: 128 and 256 clusters.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_l2_cache_miss which reads one cluster from each
of num_ops distinct L2 tables in a sparsely allocated image. Clusters
are spaced L2_ENTRIES_PER_TABLE apart so every read touches a different
L2 table, forcing eviction when num_ops exceeds the cache capacity.
Workloads: 128 and 256 L2 tables.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add sparse_qcow_tempfile() which creates a QCOW2 image with one
allocated cluster per L2 table, spread across num_l2_tables distinct
L2 tables. Reading these clusters in sequence forces L2 cache misses
when the count exceeds the cache capacity.
Also add the L2_ENTRIES_PER_TABLE constant, 8192 for 64 KiB clusters.
To be used by the L2 cache cold miss benchmark.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_multi_cluster_read which issues large reads
spanning 8 contiguous clusters (512 KiB) per read_vectored call.
This exercises the mapping coalesce path where multiple L2 entries
are merged into fewer host I/O operations.
Workloads: 128 and 256 total clusters (16 and 32 reads).
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_compressed_read which reads clusters from a
zlib compressed QCOW2 image. Every cluster triggers decompression,
isolating the decompression overhead from the normal allocated cluster
read path.
Workloads: 128 and 256 clusters.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add compressed_qcow_tempfile() which creates a zlib compressed QCOW2
image by populating a RAW tempfile with data and converting it via
qemu-img convert -c. Every cluster in the resulting image is stored
compressed so reads exercise the decompression path.
To be used by the compressed read benchmark.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_cow_write which writes clusters into a QCOW2
overlay backed by a raw file. Each write triggers copy-on-write:
cluster allocation, L2 and refcount table updates, then the data
write. This measures COW allocation overhead compared to writing
into a plain empty image.
Workloads: 128 and 256 clusters.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_backing_read which reads clusters from a QCOW2
overlay where all data lives in a raw backing file. Every read falls
through the L2 lookup to the backing file, exercising the backing
chain read path.
Workloads: 128 and 256 clusters.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add qcow_overlay_tempfile() which creates a raw backing file with
pre-populated data and a QCOW2 overlay on top with no allocated
clusters. The overlay is opened with backing file support via
QcowDiskSync so reads fall through to the backing file.
To be used by backing file read and copy-on-write write
benchmarks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_random_read which reads clusters from a
prepopulated qcow2 image in a deterministic pseudo-random order.
Unlike the sequential read benchmark, this exercises L2 cache miss
and eviction behaviour under random access patterns.
Uses Fisher-Yates shuffle with DefaultHasher for reproducible
permutation across runs.
Two TEST_LIST entries: micro_block_qcow_random_read_128_us and
micro_block_qcow_random_read_256_us with 128 and 256 cluster
workloads.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add deterministic_permutation() which produces a reproducible
pseudo random permutation of [0, n) using a Fisher-Yates shuffle
seeded by DefaultHasher. This is used by the random read micro
benchmarks to generate a fixed access pattern that is identical
across runs.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_fsync which writes num_ops clusters into an
empty qcow2 image to dirty L2 and refcount metadata then times a
single fsync call that flushes all dirty tables to disk. This
isolates the metadata flush cost which scales with the number of
dirty L2 table entries and refcount blocks.
Two TEST_LIST entries: micro_block_qcow_fsync_64_us and
micro_block_qcow_fsync_256_us with 64 and 256 cluster workloads.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_punch_hole which times punch_hole calls through
QcowSync on a prepopulated qcow2 image. Each call deallocates one
cluster exercising deallocate_bytes with refcount decrement and
fallocate punch_hole on the host file.
Two TEST_LIST entries: micro_block_qcow_punch_hole_64_us and
micro_block_qcow_punch_hole_256_us with 64 and 256 cluster workloads.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_write which times write_vectored calls through
QcowSync on an empty QCOW2 image. Each write allocates a new cluster
exercising map_cluster_for_write with L2 entry allocation and refcount
updates followed by pwrite_all.
Two TEST_LIST entries: micro_block_qcow_write_128_us and
micro_block_qcow_write_256_us with 128 and 256 cluster workloads.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add empty_qcow_tempfile() which creates a QCOW2 v3 image with no
allocated clusters so every write triggers the full cluster allocation
path including L2 entry allocation and refcount updates.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add micro_bench_qcow_read which times read_vectored calls through
QcowSync on a prepopulated QCOW2 image. This exercises the hot
read path including L2 lookup, pread64 for allocated clusters and
iovec scatter.
Two TEST_LIST entries: micro_block_qcow_read_128_us and
micro_block_qcow_read_256_us with 128 and 256 cluster workloads.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add qcow_tempfile() which creates a QCOW2 v3 image with all clusters
allocated via QcowFile::new plus sequential writes, then reopens it
as QcowDiskSync. Add QCOW_CLUSTER_SIZE constant for the default
64 KiB cluster size.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Enable the io_uring feature so that QcowDiskAsync and QcowAsync are
available for async path micro benchmarks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Make it easier to chase down which vhost user socket failed and why in
systems that have many vhost user devices.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Remove the pinned cross-version commit hash from all
houseabsolute/actions-rust-cross usages. The pin was added as a
workaround for virtio-bindings build issues that have since been
resolved upstream.
Closes#7180
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Drop the -f flag from the process termination command in
cleanup_stale_processes() so it matches by process name only, not the
full command line. This prevents terminating unrelated processes whose
arguments happen to contain target strings (e.g., the test runner
invoked with --report-file /cloud-hypervisor/report.json).
Use the truncated name 'cloud-hyperviso' because Linux limits process
names to 15 characters.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Add a CLI-only --no-shutdown flag that keeps the VMM process alive
after a guest-triggered shutdown.
Management software may still need the Cloud Hypervisor process
after the guest has powered off. Exposing this separately lets
management software, for example libvirt, keep the VMM around in a
way that is closer to QEMU.
The flag only affects the GuestExit path. Fatal exits and other
existing VMM shutdown paths remain unchanged.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Plumb ACPI S5 shutdown through guest_exit_evt instead of the shared
exit path.
This keeps guest-triggered shutdown separate from fatal VMM exit
handling. Management software, for example libvirt, expects that
distinction, and making it explicit aligns Cloud Hypervisor more
closely with QEMU.
Only the guest shutdown path is moved here. Reboot handling stays on
reset_evt and non-guest exit paths are left unchanged.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Introduce a dedicated guest_exit_evt and a matching epoll dispatch
path for guest-triggered shutdowns.
This series is needed because managment software such as libvirt may
still need the Cloud Hypervisor process to stay alive after the guest
has shut down.
Today a guest-triggered shutdown can make the VMM disappear immediately,
which means the managment software can lose track of the VM run-state.
This must only apply to guest-triggered shutdowns. Fatal error paths
and other internal exit paths must keep using the existing VMM exit
handling.
For now GuestExit still calls vmm_shutdown(), so this commit only adds
the separate plumbing and keeps the current behavior unchanged.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Verify that AlignedBuf rounds the allocation size up to the
requested alignment. Passes under miri.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Test AlignedBuf with 512 and 4096 byte alignment. Verify pointer
alignment, zero initialization, and write/read round trip. Passes
under miri.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Boot a Windows guest from a qcow2 overlay with direct=on. After
boot, write 5 randomly filled files from 4MB to 20MB, copy each
file, and compare SHA256 hashes to verify data integrity through
the aligned bounce buffer path.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
WindowsDiskConfig now creates a qcow2 overlay backed by the raw
Windows image during prepare_files(). The overlay is placed under
~/workloads alongside the raw image. Writes go into the overlay
so the backing raw image stays unmodified, matching the CoW
semantics already provided by the dm snapshot for raw tests.
Drop removes the qcow2 file.
The DiskConfig trait gains a qcow2_disk() default method returning
None. WindowsDiskConfig overrides it to expose the overlay path.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Exercise both aligned_pread and aligned_pwrite with 4096 byte
alignment instead of 512. Verify written data and that surrounding
regions are preserved.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write at offset 100 with alignment 512 so the read modify write
path is exercised. Verify the written region and that surrounding
data is preserved.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write 4096 bytes via plain Vec<u8> whose address is not guaranteed
to be aligned. The bounce buffer path copies data into an aligned
allocation before the syscall. Read back with pread_exact to verify
data integrity.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write 4096 bytes of pattern data at offset 0 using AlignedBuf
and verify data integrity via plain pread_exact. All parameters
are naturally aligned to 512 so the fast path is exercised.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Test that aligned_pread handles a non aligned offset by
rounding down, reading an aligned region, and returning the
correct slice from within the bounce buffer.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Test that aligned_pread correctly uses a bounce buffer when
the caller buffer address is not aligned.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Test that aligned_pread takes the fast path when buffer
address, length, and offset are all properly aligned.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Exercise scatter/gather with multiple iovecs per operation,
covering both the standard and direct_io paths. Write uses
3 iovecs with distinct patterns, read uses 3 iovecs with
different sizes, then reassembles and compares.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add direct_io variants for suitable tests by extracting
test bodies into _impl(direct_io: bool) functions. Each
original test calls _impl(false) and a new _direct_io test
calls _impl(true).
When direct_io is true, RawFile probes alignment and QcowSync
exercises the AlignedBuf and bounce buffer paths in
read_vectored and write_vectored.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Store the alignment from the data file in QcowAsync. Use
aligned_pread in scatter_read_sync and aligned_pwrite with
gather_from_iovecs_into in cow_write_sync, matching the
QcowSync approach.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Store the alignment from the data file in QcowSync. Use AlignedBuf
directly in read_vectored and write_vectored as the intermediate
buffer so that aligned_pread/aligned_pwrite can skip the bounce
copy when offset and length are naturally aligned.
Use gather_from_iovecs_into to gather iovec data directly into the
aligned buffer.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When the data file is opened with O_DIRECT, buffer address, length,
and file offset must satisfy the device alignment.
Add AlignedBuf RAII wrapper and aligned_pread/aligned_pwrite helpers
in qcow_common that use bounce buffers when alignment constraints
are not met. For writes with misaligned offset, a read modify write
is performed on the aligned region.
gather_from_iovecs_into gathers iovec data directly into a caller
provided buffer, avoiding an intermediate Vec allocation.
Fixes: #8007
Signed-off-by: CMGS <ilskdw@gmail.com>
Co-authored-by: Anatol Belski <anbelski@linux.microsoft.com>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add pub fn alignment() to RawFile so that callers can
query the O_DIRECT buffer alignment requirement probed
at file open time.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The old name read as 'metadata for a QCOW2 backing file' rather
than what it actually is: a QCOW2 backing file reader. Rename to
Qcow2Backing to parallel RawBacking and clarify intent.
Suggested-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Extract AcpiCpuHotplugController from CpuManager and move the BusDevice
implementation to the new type. This separates VMM-internal vCPU
management from the guest-visible ACPI CPU hotplug MMIO interface.
Besides clarifying responsibilities and reducing technical debt, this
fixes a rare deadlock involving pause handling and MMIO access.
New responsibilities:
- CpuManager manages VMM-internal vCPU lifecycle and coordination
- AcpiCpuHotplugController implements the guest-visible ACPI CPU hotplug
MMIO interface
A vCPU thread may exit KVM_RUN to perform an MMIO access previously
handled by CpuManager. If the VMM thread begins processing a `pause`
event before that MMIO operation acquires access to CpuManager,
CpuManager::pause() will block waiting for the vCPU thread to ACK
the pause, while the vCPU thread is blocked waiting to complete the MMIO
operation through the same CpuManager - which it can never lock - the
VMM is deadlocked.
This can occur during early boot or CPU hotplug when pause events race
with MMIO accesses. The issue is rare and timing-dependent, but real.
For reproducing: run `ch-remote pause|resume` in a loop while booting
a Linux VM (via direct kernel boot).
With the new design, these MMIO operations no longer depend on
CpuManager, which removes the deadlock path entirely.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
The address that is passed from the guest should be treated as
untrusted. Currently an invalid address will panic the VMM. This only
allows the guest to hurt itself, but we shouldn't have the VMM crashing.
Instead let's return an error if possible or invalidate the queue if it
happen during setup.
The data flow from guest to translate_gva/translate_gpa is:
1. Guest writes a raw u64 address into a virtio descriptor in the
shared descriptor table (guest memory).
2. The virtio-queue crate reads this descriptor via read_obj() and
returns the addr field as-is in a GuestAddress — no validation.
3. Device code calls .translate_gva(access_platform, len) on the
GuestAddress.
4. With IOMMU (access_platform is Some): the address is an IOVA that
must be translated to a GPA via the IOMMU mapping table. If the
guest provides an unmapped IOVA, translation returns Err.
Previously, .unwrap() here panicked the VMM.
5. Without IOMMU (access_platform is None): translate_gva is a no-op
(returns self). The raw address flows to GuestMemory::read_obj()
which validates it — out-of-range addresses return
Err(InvalidGuestAddress), so no host memory corruption is possible.
Signed-off-by: Dylan Reid <dgreid@fb.com>
The unit test container runs with Docker default seccomp
profile which blocks io_uring_setup, io_uring_enter and
io_uring_register. This causes all qcow_async unit tests to
fail with EPERM when creating an io_uring instance.
Add --security-opt seccomp=unconfined to the unit test docker
run invocation. The container already has --device access and
cap_net_admin, so this does not materially change the security
posture.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write a distinct byte pattern into each of eight consecutive
clusters in a single operation, then read the full range back
and verify per cluster contents.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write data, punch hole to deallocate, then rewrite the same
range and verify the new contents read back correctly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that writes 4K into the middle of a
cluster, then reads the entire cluster back. Verifies that the
written region matches and surrounding bytes remain zero. This
exercises the COW path where unwritten parts of a newly allocated
cluster must be zero filled.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that reads from a range that was never
written. Verifies the fundamental QCOW contract that unallocated
clusters return zeroes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that submits a batch of interleaved
write and read requests via submit_batch_requests. Verifies that
all completions arrive with the correct user_data and that the
read back data matches the written data.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that writes distinct patterns into two
adjacent clusters, then issues a single read spanning the cluster
boundary. Verifies that multi mapping read resolution returns the
correct data from both clusters.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that writes a byte pattern through
write_vectored, reads it back through read_vectored, and verifies
the data matches. This exercises the core async write and read
paths end to end.
Also add an async_write helper for future tests.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test for write zeroes completion. The test
verifies that a write zeroes request reports successful completion
and that the zeroed range reads back as zeroes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test for punch hole completion. The test
verifies that a punch hole request reports successful completion
and that the deallocated range reads back as zeroes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement batch_requests_enabled() and submit_batch_requests() for
QcowAsync. Without batching, each read_vectored call performs its own
io_uring submit() syscall. With batching, the virtio queue handler
collects all pending requests and submits them in a single call,
pushing multiple SQEs before one submit() syscall.
Each request in the batch is classified through the metadata layer.
Requests that hit the fast path (single allocated cluster mapping)
are pushed to the io_uring submission queue. Requests that require
the slow path (compressed, backing, zero fill, or mixed mappings)
are completed synchronously and queued as synthetic completions.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When io_uring is available and not disabled, open QCOW2 images
with QcowDiskAsync for asynchronous reads. Falls back to
QcowDiskSync otherwise.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
try_clone shares the Arc wrapped metadata and backing file.
new_async_io creates a QcowAsync worker with its own io_uring
instance for the given ring depth.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Deallocate clusters through QcowMetadata::deallocate_bytes, then
apply the resulting DeallocAction list (punch hole or write zeroes
at host offsets). write_zeroes delegates to punch_hole since
unallocated QCOW2 clusters inherently read as zero.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Flush dirty metadata caches and sync the underlying file via
QcowMetadata::flush, then signal synthetic completion.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Synchronous per cluster write path - gather guest data from iovecs,
map each cluster through QcowMetadata, and pwrite to the allocated
host offset. Partial cluster writes with a backing file read the
backing data first so map_cluster_for_write can perform COW.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Single allocated cluster reads are submitted to io_uring for true
async completion. Mixed mapping reads (zero, compressed, backing,
multi cluster) fall back to synchronous pread64 with synthetic
completions.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add the AsyncIo trait impl with notifier and next_completed_request
filled in. The remaining methods are stubbed with unimplemented
and will be filled in by subsequent commits.
next_completed_request drains io_uring completions first, then
falls back to the synthetic completion list.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Per queue I/O worker that uses io_uring for asynchronous reads
against fully allocated clusters. The struct holds the shared
metadata, data file, optional backing reader, the io_uring
instance and a synthetic completion list.
Feature gated on io_uring in lib.rs.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Marker supertrait combining all composable capability traits.
QcowDiskAsync now satisfies the full DiskFile contract.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delegates to QcowMetadata::resize. Rejects resize when a backing
file is present, same as the sync backend.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce the device level handle for the async QCOW2 backend.
QcowDiskAsync mirrors QcowDiskSync. It parses the image, resolves
the backing chain and wraps QcowMetadata in an Arc for sharing
across virtio queues. No trait impls yet, just the struct,
constructor, Drop and Debug.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move the backing file constructor into qcow/backing alongside the
types it creates. Both qcow_sync and qcow_async can now import
shared_backing_from directly from qcow/backing.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move the raw backing file reader into the new qcow/backing module
so it can be shared between qcow_sync and the upcoming qcow_async
backend.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move scatter_to_iovecs, zero_fill_iovecs and gather_from_iovecs into
qcow_common so they can be shared with the upcoming qcow_async backend.
These helpers treat an iovec array as a flat byte stream and are used by
both read_vectored and write_vectored code paths.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
These position independent I/O helpers use pread64/pwrite64 to avoid
races on the shared file position when multiple queues operate on
duplicated file descriptors. Extracting them prepares for reuse by
the upcoming qcow_async backend.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The updated image is configured in a same way as the
previously used 2022.
SAC, SSH, and RDP are configured.
All Windows updates to the curent date are installed.
Includes latest stable virtio-win 0.1.285 drivers.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
After memory hotplug, it may happen that it takes a few seconds until a
VFIO device is available again (IOMMU/DMA mappings need update).
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This struct has the same members and it can be reused to reduce
complexity now and if other common PCI related fields need to be
added in the future.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This can then be used with the OptionParser::add_all() API to reduce the
number of locations the same options are added to the parser. The only
quirk is that some devices do not support an IOMMU (because they are
vhost-user / vfio-user based). There are two different versions of the
array to support that.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The IommuNotSupportedOnSegment variant is no longer needed as the common
PciDeviceCommonConfig::validate() handles this case with the
OnIommuSegment variant along with more use of the IommuNotSupported
error variant.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch VsockConfig over to using the newly extracted struct members as
used by all PCI based devices. The use of #[serde(flatten)] means that
this change has no impact on the JSON format that the data is stored as.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch VdpaConfig over to using the newly extracted struct members as
used by all PCI based devices. The use of #[serde(flatten)] means that
this change has no impact on the JSON format that the data is stored as.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch UserDeviceConfig over to using the newly extracted struct members
as used by all PCI based devices. The use of #[serde(flatten)] means
that this change has no impact on the JSON format that the data is
stored as.
As VFIO user devices do not support being placed behind an IOMMU an
error is now raised if iommu is set. This can't happen via the CLI but
could via the JSON/API.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch DeviceConfig over to using the newly extracted struct members as
used by all PCI based devices. The use of #[serde(flatten)] means that
this change has no impact on the JSON format that the data is stored as.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch PmemConfig over to using the newly extracted struct members as
used by all PCI based devices. The use of #[serde(flatten)] means that
this change has no impact on the JSON format that the data is stored as.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch GenericVhostUserConfig over to using the newly extracted struct
members as used by all PCI based devices. The use of #[serde(flatten)]
means that this change has no impact on the JSON format that the data is
stored as.
As generic vhost-user devices do not support being placed behind an
IOMMU an error is now raised if iommu is set. This can't happen via the
CLI but could via the JSON/API.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch FsConfig over to using the newly extracted struct members as used
by all PCI based devices. The use of #[serde(flatten)] means that this
change has no impact on the JSON format that the data is stored as.
As virtio-fs does not support being placed behind an IOMMU an error is
now raised if iommu is set. This option is not exposed via the CLI but
could happen with a miscontructed JSON/API call.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch NetConfig over to using the newly extracted struct members as
used by all PCI based devices. The use of #[serde(flatten)] means that
this change has no impact on the JSON format that the data is stored as.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Switch DiskConfig over to using the newly extracted struct members as
used by all PCI based devices. The use of #[serde(flatten)] means that
this change has no impact on the JSON format that the data is stored as.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Implement some common PCI segment validation. This can be used to reduce
duplication across the different validation methods.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Introduce a common struct that can encompass all the config fields
used by devices that are PCI based. The use of `skip_serializing_if`
means that the iommu field will only be included if set (otherwise
falling back to default false). This neatly handles the devices that
don't support an iommu.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This unit test was trying to test with extra "="s in the input but was
instead testing using an unknown option. Add the option to the parser to
not hit that incorrect error.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The error message for the InvalidSyntax was copied from UnknownOption.
Correct it to "invalid syntax".
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add an OptionParser::add_all method that takes a slice of option names
and use that to add to the set of parameters that the parser works on.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Refactor parse() into a version that can control whether to tolerate
unknown options. This can then be used to then parse a subset of the
options.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Previously the UNIX socket file was only removed on the success path
(start_vmm returned Ok(Some(path))). If start_vmm failed after the
HTTP API had bound a path-based socket, the file could be left on disk.
Parse --api-socket in parse_api_socket(), call start_vmm with the
result, then unlink the path in main after start_vmm returns for both
success and failure (fd= mode unchanged: no path to remove).
Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
Cross-check each UFFDIO_* constant against the Linux _IOC(dir, type,
nr, size) encoding formula at compile time so that transposed direction
bits or struct sizes are caught immediately rather than silently
producing wrong ioctl numbers at runtime.
Signed-off-by: Shayon Mukherjee <shayonj@gmail.com>
Now on the generic restore path the worker thread is notified on the
events and also the guest is notified via the interrupt. This avoids the
same "livelock" situation that required this "driver_awake" workaround
when restoring the net device.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This will wake up the guest and avoid a livelock situation by ensuring
that it will process any pending queues on its side.
Signed-off-by: Rob Bradford <rbradford@meta.com>
A restored virtqueue can already contain pending descriptors when the VM
resumes. Before this change, the worker thread was unparked and then
waited for a fresh queue eventfd signal. That is normally fine, but not
when the queue was already non-empty at snapshot time. The virtqueue
state lives in guest memory and is restored, but the original host-side
queue eventfd signal is not persistent snapshot state. If the guest
already notified the queue before the snapshot, it may not notify it
again after resume.
That can leave the worker idle while the guest is still waiting for the
pending request to complete. In one observed case, this stalled a
virtio-blk flush during early boot after snapshot/restore.
We mitigate this in the shared `VirtioCommon` resume path.
`VirtioCommon` retains cloned queue eventfds for activated virtqueues
and signals each of them once on resume after unparking the worker
threads.
Keep virtio-net on its existing special-case path: it resumes worker
threads without signaling queue eventfds so the `driver_awake`
workaround remains intact until the guest performs a real notify.
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
UFFDIO_WAKE was 0x4010_aa02 (_IOW) but should be 0x8010_aa02,
causing every wake call to silently fail with -EINVAL.
UFFD_FEATURE_MISSING_HUGETLBFS was (1<<6) but should be (1<<4),
colliding with UFFD_FEATURE_EVENT_UNMAP.
Signed-off-by: Zhiheng Tao <junchuan.tzh@antgroup.com>
This reduces pressure on CI and enables to run more tests locally on
developer machines (with 16GB of RAM or less).
No functional changes.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Replace fixed sleeps in Windows integration tests with polling
helpers that wait for boot, snapshot readiness, and device
enumeration.
This keeps the same test intent while avoiding long fixed delays on
the fast path.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Replace fixed sleeps in Linux snapshot and restore integration tests
with event monitor and API readiness checks.
This updates ivshmem and common_sequential snapshot paths to wait for
concrete restore and snapshot completion signals instead of sleeping
for an assumed amount of time.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Use polling helpers in common integration tests instead of fixed
sleeps where the tests already know the expected ready state.
This updates CPU and memory hotplug checks as well as a few
device- and restore-related waits in common_parallel to stop
oversleeping on the fast path while keeping the same assertions.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Treat missing or still-short event monitor files as a retryable state
in integration test helpers.
This keeps polling-based restore and snapshot checks from failing early
with file-not-found or short-file assertions while the monitor output
is still being written.
In the following, we can gracefully wait for the corresponding
conditions to become true.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Allow one-shot SSH commands to install a libssh2 session timeout and
use that path from wait_for_ssh.
This keeps SSH readiness probes from blocking far beyond their caller
provided timeout when the guest network is slow or broken.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Split the SSH helpers into a one-shot execution path and a retrying
wrapper with linear backoff.
This makes it possible to use a single bounded SSH attempt when tests
need a direct readiness probe while preserving the existing retrying
behavior for callers that expect it.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
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>
This gate behaves like a barrier, but it can be opened, meaning that
threads can be released before all threads arrived at the gate. This
lets us release waiting threads in case of an error, which will be
important for the sender side of a live migration with multiple
TCP connections.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
For sending memory over multiple connections, we need a way to split up
the work. With these changes, we can chop a memory table into same-sized
chunks for transmit
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Adds the functionality to accept multiple connections on the receiver
side of a live migration. A thread listens for incoming connections and
creates a worker for each new connection.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
With this, the receiver side of a migration can wait for incoming
connections, while also being able to abort the accept when the
migration is done.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
That way we avoid having to grab a lock when receiving a chunk of memory
over the migration socket. This is a necessary prerequisite for having
multiple memory receiving threads.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
The memory manager is guarded by a mutex, thus parallel accesses to it
and its members are not possible. But we have to execute this function
in parallel when we introduce multiple TCP connections. Otherwise, the
workers who receive the data and write it into guest memory will block
on each other, and thus slow down the migration.
Also rename the function to receive_memory_ranges for better naming
consistency.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
When doing a local migration using a UNIX socket, we removed the UNIX
socket file after accepting the connection. The VMM does not own this
socket file, which makes this an unsafe operation. Thus, we stop doing
that.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Remove the local remote_command() function from
performance_tests.rs. The identical function is now
available from test_infra via the existing glob import.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move remote_command() and remote_command_w_output() from
tests/common/utils.rs into test_infra/src/lib.rs to allow
reuse across crates.
The cloud-hypervisor integration tests already use
'use test_infra::*', so the functions are available
without any caller changes.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Remove the local x86_64 FOCAL_IMAGE_NAME constant from
performance_tests.rs. The identical public constant from
test_infra is already available via wildcard import.
The aarch64 definition is kept as it differs from test_infra:
performance-metrics uses a specific image with the
'-update-tool' suffix.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Remove the local DIRECT_KERNEL_BOOT_CMDLINE constant from
performance_tests.rs. The identical public constant from
test_infra is already available via wildcard import.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Remove the local direct_kernel_boot_path() function and unused
PathBuf import from performance_tests.rs. The identical public
function from test_infra is already available via wildcard
import.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Virtio v1.2 says that if CONFIG_WCE is negotiated
but FLUSH is not, the device must initialize writeback to 0.
It also says that if CONFIG_WCE was not negotiated but FLUSH
was, the driver should assume presence of a writeback cache.
Introduce a pure is_writeback_enabled helper and a
set_writeback_mode helper. This makes the two call flows
explicit:
* write_config resolves the guest requested mode against the
negotiated features before storing it back
* activate starts from the default writeback preference and then
resolves it against the negotiated features
* reset restores the initial writeback state
This keeps the config space value and the runtime writeback flag
in sync and makes the spec driven fallback easier to follow.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Refactor PciDevice::allocate_bars trait and all implementations
to take &mut SystemAllocator instead of &Arc<Mutex<SystemAllocator>>,
removing double indirection.
The caller in device_manager.rs now acquires the lock before
calling allocate_bars.
Signed-off-by: Chinmoy <daschinmoyy21@gmail.com>
The control queue handler passed the total length of all
descriptors (header + data + status) as used_len to add_used.
Per virtio spec section 2.6.8, used_len must only count bytes
written to device-writable descriptors. The device only writes
the 1-byte status/ack field.
Windows NetKVM >= 0.1.285 strictly checks this value and calls
NdisMRemoveMiniport when len != sizeof(virtio_net_ctrl_ack),
removing the network adapter immediately after activation.
Signed-off-by: CMGS <ilskdw@gmail.com>
Windows NetKVM driver (>= 0.1.271) issues unsupported command classes
even when they are not even advertised.
According to the Virtio 1.2 specification:
RX, VLAN, and ANNOUNCE control paths are only meaningful when their
corresponding features are negotiated in sections 5.1.3.1, 5.1.6.5.1.2,
5.1.6.5.2.2, and 5.1.6.5.4.1.
RX and VLAN are explicitly described as best-effort in sections
5.1.6.5.1 and 5.1.6.5.3.
Instead of returning an error to the guest, return success to the guest.
Fixes: #7925
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Change the return type of RawFileAsyncAio::new() from
std::io::Result<Self> to BlockResult<Self>, wrapping
internal errors from EventFd::new() and IoContext::new()
in BlockError with DiskFileError::NewAsyncIo.
This simplifies the caller in AsyncDiskFile::new_async_io()
which no longer needs its own error mapping.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Remove the old async_io::DiskFile trait implementation from
RawFileDiskAio, now that the new disk_file trait hierarchy
is fully implemented.
Clean up unused imports: DiskFile and DiskFileResult from
crate::async_io.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::AsyncDiskFile trait implementation for
RawFileDiskAio with try_clone() and new_async_io() methods.
try_clone() duplicates the underlying file descriptor and
wraps it in a new RawFileDiskAio. new_async_io() creates a
RawFileAsyncAio (Linux AIO) backend, wrapping errors in
BlockError instead of DiskFileError.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add empty disk_file::DiskFile impl for RawFileDiskAio.
This marker supertrait requires DiskSize + Geometry + Sync,
all of which are now satisfied.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Resizable trait implementation for
RawFileDiskAio. Calls file.set_len(size) and wraps the
I/O error in BlockError on failure.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::SparseCapable trait implementation for
RawFileDiskAio. Delegates to probe_sparse_support() to
detect whether the underlying file supports hole-punching.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Geometry trait implementation for
RawFileDiskAio. Probes disk topology from the file,
falling back to defaults on failure. Takes &self instead
of &mut self and uses unwrap_or_else for cleaner error
handling.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskFd trait implementation for
RawFileDiskAio. Delegates to file.as_raw_fd() via
BorrowedDiskFd, taking &self instead of &mut self.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::PhysicalSize trait implementation for
RawFileDiskAio. Returns the physical size from
query_device_size wrapped in BlockError on failure,
consistent with the DiskSize impl.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskSize trait implementation for
RawFileDiskAio using BlockError and BlockResult. Takes
&self instead of &mut self.
Add BlockError, BlockErrorKind, BlockResult, and disk_file
imports needed by this and subsequent trait impls.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add #[derive(Debug)] to RawFileDiskAio. This is required
by the new disk_file traits which have Send + Debug bounds.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a ramp time before measuring the block rate limiter tests so
both the single device and group workloads are measured after
warm up to make the measurements less sensitive to startup
transients.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Increase the group block refill time from 100 ms to 1000 ms and
scale the shared bucket sizes to preserve the target rate.
Set the one time burst to 0 to avoid transient overshoot and use
the shared block runtime constant directly in the group path.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The rate limiter token bucket has a fixed 100 ms cool down time
that pauses I/O whenever the bucket empties. With a 100 ms refill
time, the actual throughput drops to roughly half of the target
rate and causes the tests to miss their target.
Increase the net and single block refill time from 100 ms to
1000 ms and scale the bucket sizes by 10x to preserve the target
rate. Set the one time burst to 0 to avoid overshooting the upper
bound, and raise the runtime constants from 10 s to 20 s for
steadier measurements.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce named constants for the net and single block rate limiter
test runtimes and use them directly at the call sites.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Unfortunately with a single ARM64 machine this has now become a
bottleneck for landing PRs. Copy the methodology we use for existing
jobs that we only run on the MQ by creating dummy jobs that run on the
GH hosted runner (ubuntu-latest) allowing the PR to transition into
the MQ by passing the required checks.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Now that the VhostUserCommon::shutdown implementation has been filled
out to support migration it can also be used for the drop
implementations in the vhost-user devices.
It's worth noting that the call to wait_for_epoll_threads() was a no-op
as those threads are only configured on conventional virtio devices.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Advertising support for this virtio feature is required to enable
support for migration. (Along with the LOG_SHMFD protocol feature.)
Signed-off-by: Rob Bradford <rbradford@meta.com>
If the epoll thread is paused, which would be expected as a part of live
migration/snapshot-restore unpause the thread so that it can receive the
kill event. This mirrors the reset() behaviour of virtio devices. It is
important here so as to close the connection with the vhost-user-backend
to allow same host and --local migration and since after getting the
device state the vhost-user backend should no longer be used.
As a result of this change we can do --local and same-host migration
with virtio-fs.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This is used by all devices so it can be part of the common state.
Moving it simplifies the code and simplifies some future improvements
around shutdown for migration.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Since vhost-user devices are always virtio devices it makes sense to
structure this struct inside the VhostUserCommon struct. This then also
makes some of the methods on VhostUserCommon cleaner since they can now
act directly on the common virtio bits (e.g. for kill_evt)
Signed-off-by: Rob Bradford <rbradford@meta.com>
OVMF can reprogram PCI BARs while memory space decoding is disabled.
Cloud Hypervisor defers the corresponding BAR move in
`pending_bar_reprogram` until the PCI command register enables Memory
Space again.
That deferred state was not part of `PciConfigurationState`. A
snapshot taken in that window restored the new BAR values in PCI
config space, but lost the pending BAR relocation needed to update the
VMM-side BAR mapping.
The restore logs show guest MMIO accesses to the reprogrammed BAR
addresses `0xc0000000`, `0x100000000`, and `0x100080000` hitting
unregistered addresses. The firmware serial output shows OVMF
assigning those same BAR addresses during PCI resource allocation,
then reaching BDS, finding the mass-storage device, and failing to
boot from it.
Serialize and restore `pending_bar_reprogram` so deferred BAR moves
survive snapshot and restore.
Co-authored-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
Co-authored-by: Julian Schindel <julian.schindel@cyberus-technology.de>
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Previously, GSIs were eagerly allocated for all MSI-X vectors a device
advertises (i.e. the maximum the device can support). This can easily
exhaust KVM_MAX_IRQ_ROUTES (4096) with modern NVMe devices that support
up to 2048 MSI-X vectors.
Defer GSI allocation to the first time an interrupt vector is
unmasked. The EventFd is still created eagerly since external
components (e.g. VFIO) need it at device init time.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Introduce ExecuteError::UnsupportedFlags to carry both the
request type and the rejected flags value, replacing the
generic ExecuteError::Unsupported at discard and write zeroes
flag validation sites. This provides structured context for
debugging without changing the returned VIRTIO_BLK_S_UNSUPP
status.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
PR #7852 fixed the missing VirtioBlockConfig fields but did not
change the feature advertisement logic. The condition
`sparse || disk_image.supports_zero_flag()` causes qcow2 to
advertise DISCARD even with sparse=false, because qcow2 can
mark clusters as zero (supports_zero_flag() returns true).
Windows viostor BSODs (DRIVER_IRQL_NOT_LESS_OR_EQUAL) when
DISCARD is advertised on qcow2 backends, making sparse=off
ineffective as a workaround for qcow2 images.
Restrict DISCARD to explicit sparse=true only. WRITE_ZEROES
remains available for all sparse-capable backends.
Fixes#7849
Signed-off-by: CMGS <ilskdw@gmail.com>
The virtio spec v1.2 in 5.2.6.2 requires that the device
MUST return VIRTIO_BLK_S_UNSUPP for write zeroes commands
if any unknown flag is set.
Add an early check that rejects requests with reserved flag
bits set by returning VIRTIO_BLK_S_UNSUPP via the existing
ExecuteError::Unsupported variant.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The virtio spec v1.2 in 5.2.6.2 requires that the device
MUST return VIRTIO_BLK_S_UNSUPP for discard commands if the
unmap flag is set or if any unknown flag is set.
The discard handler was not reading the flags field at all,
silently accepting requests with arbitrary flags. Read and
validate the flags, rejecting any non-zero value with
VIRTIO_BLK_S_UNSUPP.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Previously, KVM_KVMCLOCK_CTRL was skipped when kvm_hyperv=on because
Windows does not use pvclock directly. However, KVM internally uses
pvclock data structures as the basis for computing the Hyper-V
Reference TSC page parameters. Not calling KVM_KVMCLOCK_CTRL means
there is no mechanism to signal time discontinuity to Windows guests
after pause/resume, contributing to multi-minute hangs.
Remove the kvm_hyperv guard so all guests receive the clock-paused
notification.
Signed-off-by: CMGS <ilskdw@gmail.com>
The queue_msix_vector register (offset 0x1a in virtio PCI common
config) was indexed into the msix_queues Vec using the guest-controlled
queue_select value without bounds checking. A malicious guest can set
queue_select to any u16 value via offset 0x16, then read or write
offset 0x1a to trigger an out-of-bounds panic, crashing the VMM.
Replace direct Vec indexing with .get()/.get_mut() for bounds-checked
access, returning VIRTQ_MSI_NO_VECTOR (0xFFFF) on OOB reads to match
the virtio "no vector" sentinel. Add a regression test that sets
queue_select to 0xFFFF and exercises both the read and write paths.
AI/LLM disclosure: this patch was co-authored with Claude Code.
Fixes#7917
Signed-off-by: Tobias Kässer <t.kaesser@gmail.com>
When booting an SEV-SNP guest VM using IGVM with -pvalidate_opt 1 (lazy
page acceptance), the guest kernel's #VC exception handler may issue
VMGEXIT with SVM_EXIT_CPUID (0x72) or SVM_EXIT_MSR (0x7c) exit codes
via the GHCB page protocol. The hypervisor had no handlers for these
exit codes, causing the guest's #VC handler to fail and trigger
sev_es_terminate(), which sends GHCB_MSR_TERM_REQ (0x100). The
hypervisor then panicked on the unhandled 0x100 operation.
Add the following handlers to the GHCB VMGEXIT processing:
- SVM_EXIT_CPUID (0x72): Read function/index/xcr0/xss from the GHCB
page and return CPUID results via get_cpuid_values().
- SVM_EXIT_MSR (0x7c): Handle MSR read (RDMSR) and write (WRMSR)
requests from the guest via the GHCB page protocol.
- GHCB_MSR_TERM_REQ (0x100): Decode reason_set and reason_val from the
GHCB MSR and return an error instead of panicking, allowing graceful
error propagation.
Testing:
Reproducer (on Azure DC16as_cc_v5, /dev/mshv):
cloud-hypervisor --cpus boot=1,nested=off --memory size=512M \
--disk path=osdisk.img path=cloudinit \
--net "tap=,mac=12:34:56:78:90:06,ip=192.168.6.1,mask=255.255.255.128" \
--serial null --console pty \
--api-socket /tmp/ch.sock \
--igvm /igvm_files/linux-ttyS0.bin \
--host-data <hash> --platform sev_snp=on -v
Before fix:
thread 'vcpu0' panicked at hypervisor/src/mshv/mod.rs:1207:30:
Unsupported VMGEXIT operation: 100
After fix: VM boots successfully to login prompt with no panics.
All virtio devices (console, rng, disks) activate normally.
No regression risk for non-SEV-SNP: all new code is within the
HVMSG_X64_SEV_VMGEXIT_INTERCEPT handler which is only reached for
SEV-SNP guests.
Signed-off-by: Souradeep Chakrabarti <schakrabarti@microsoft.com>
Reorder resume() to: set_clock, device_manager.resume,
cpu_manager.resume. This matches the inverse of pause()
which correctly saves the clock before pausing vCPUs.
Signed-off-by: CMGS <ilskdw@gmail.com>
This gives the community more time to react to possible security chain
compromises.
We have high confidence that rust-vmm crates are trusted, and the
community is fully capable of spotting any issues. There is no need to
delay that group.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Delegate try_clone() to FixedVhd::clone() and new_async_io() to
FixedVhdSync, preserving DiskFileError::NewAsyncIo.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delegate to FixedVhd::physical_size() which calls file.metadata().
Preserve the crate::Error::GetFileMetadata variant as the BlockError
source for diagnostic chain traversal.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delegate to FixedVhd::logical_size() which returns the guest
visible capacity parsed from the VHD footer at construction.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Classify the io::Error as BlockErrorKind::Io with ErrorOp::Open.
Update vmm CreateFixedVhdDiskSync to take BlockError.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
try_clone() shares the Arc<Mutex<Vhdx>>. new_async_io() creates
VhdxSync with a cloned Arc (no error path, infallible).
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delegate try_clone() to FixedVhd::clone() and new_async_io() to
FixedVhdAsync, preserving DiskFileError::NewAsyncIo.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Remove the legacy async_io::DiskFile implementation from
RawFileDiskSync now that the new disk_file trait impls are
in place.
Remove unused imports: Seek, SeekFrom, DiskFile, and
DiskFileResult.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Update device_manager.rs to construct DiskBackend::Next
instead of DiskBackend::Legacy for the synchronous raw
backend.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Update fuzz/block.rs to construct DiskBackend::Next instead
of DiskBackend::Legacy for the synchronous raw backend.
Remove the unused async_io::DiskFile import.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::AsyncDiskFile trait implementation for
RawFileDiskSync with try_clone() and new_async_io() methods.
try_clone() duplicates the underlying file descriptor and
wraps it in a new RawFileDiskSync. new_async_io() creates a
RawFileSync (synchronous fallback) backend, wrapping errors
in BlockError instead of DiskFileError.
Add DiskFileError::Clone variant in async_io.rs for the
try_clone() error path.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add empty disk_file::DiskFile impl for RawFileDiskSync.
This marker supertrait requires DiskSize + Geometry + Sync,
all of which are now satisfied.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Resizable trait implementation for
RawFileDiskSync. Calls file.set_len(size) and wraps the
I/O error in BlockError on failure.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::SparseCapable trait implementation for
RawFileDiskSync. Delegates to probe_sparse_support() to
detect whether the underlying file supports hole-punching.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Geometry trait implementation for
RawFileDiskSync. Probes disk topology from the file,
falling back to defaults on failure. Takes &self instead
of &mut self and uses unwrap_or_else for cleaner error
handling.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskFd trait implementation for
RawFileDiskSync. Delegates to file.as_raw_fd() via
BorrowedDiskFd, taking &self instead of &mut self.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::PhysicalSize trait implementation for
RawFileDiskSync. Returns metadata().len() wrapped in
BlockError on failure, consistent with the DiskSize impl.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskSize trait implementation for
RawFileDiskSync using BlockError and BlockResult. Uses
metadata().len() instead of seek(SeekFrom::End(0)), taking
&self instead of &mut self.
Add BlockError, BlockErrorKind, BlockResult, and disk_file
imports needed by this and subsequent trait impls.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add #[derive(Debug)] to RawFileDiskSync. This is required
by the new disk_file traits which have Send + Debug bounds.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Update device_manager.rs to construct DiskBackend::Next
instead of DiskBackend::Legacy for the io_uring raw backend.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::AsyncDiskFile trait implementation for
RawFileDisk with try_clone() and new_async_io() methods.
try_clone() duplicates the underlying file descriptor and
wraps it in a new RawFileDisk. new_async_io() creates a
RawFileAsync (io_uring) backend, wrapping errors in
BlockError instead of DiskFileError.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add empty disk_file::DiskFile impl for RawFileDisk. This
marker supertrait requires DiskSize + Geometry + Sync, all
of which are now satisfied.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Resizable trait implementation for
RawFileDisk. Calls file.set_len(size) and wraps the I/O
error in BlockError on failure.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::SparseCapable trait implementation for
RawFileDisk. Delegates to probe_sparse_support() to detect
whether the underlying file supports hole-punching.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Geometry trait implementation for RawFileDisk.
Probes disk topology from the file, falling back to defaults
on failure. Takes &self instead of &mut self and uses
unwrap_or_else for cleaner error handling.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskFd trait implementation for RawFileDisk.
Delegates to file.as_raw_fd() via BorrowedDiskFd, taking
&self instead of &mut self.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::PhysicalSize trait implementation for
RawFileDisk. Returns metadata().len() wrapped in BlockError
on failure, consistent with the DiskSize impl.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskSize trait implementation for RawFileDisk
using BlockError and BlockResult. Uses metadata().len()
instead of seek(SeekFrom::End(0)), taking &self instead of
&mut self.
Add BlockError, BlockErrorKind, BlockResult, and disk_file
imports needed by this and subsequent trait impls.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add #[derive(Debug)] to RawFileDisk. This is required by the
new disk_file traits which have Send + Debug bounds.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a Clone variant to DiskFileError for error handling in
the upcoming AsyncDiskFile::try_clone() implementations.
This variant will be used by RawFileDisk and RawFileDiskSync
when cloning the underlying file descriptor fails.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The sync fallback path in process_queue_submit() hardcoded
VIRTIO_BLK_S_IOERR for all errors. This caused unsupported
request errors to report IOERR to the guest instead of the
correct VIRTIO_BLK_S_UNSUPP.
Use ExecuteError::status() to return the appropriate status
code for each error variant.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Fix broken URL reported by Lychee. The binutils-gdb github repo no
longer exists. Use the equivalent sourceware.org link.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
The MSHV tests need access to secrets so that they can run workloads in
Azure. It does not need privileged access to GitHub. Ensure its
GITHUB_TOKEN has no permissions.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Switch the workspace ownership fix from 'runner' to 'github-runner'
to match the new dedicated service account used on the self-hosted
VFIO runner.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
This version is identical but with a new version number as the old
version is yanked due to a semver break.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This test has failed at least once in upstream CI. With the applied
stress workload, reducing the downtime to 1 ms makes it virtually
impossible for CI runners with various speeds to complete VM migration.
In other words: we will always be able to cancel.
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Add test_snapshot_restore_virtio_fs which validates that virtio-fs
continues to work correctly across a snapshot/restore cycle.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Enable the DEVICE_STATE protocol feature negotiation for all vhost-user
devices (block, fs, net, and generic). Restoring the state (including
the backend state if present) and vrings.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add a common method for validating the state (checking vrings &
device_state) and then restoring the backend state if present.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Fetch the opaque device state from the backend and store it along with
the last vring used in the state used for the snapshot.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The vhost-user protocol now has support for the backend to provide an
opaque blob of data (read or written through a pipe) that the VMM can
use to save/restore state after snapshot/restore or live migration.
It also adds a command for checking the backend accepts the uploaded
device state. One quirk of saving the state is that GET_VRING_BASE must
be used first to quiesce the state of the backend and flush any
in-flight requests. This then also requires saving that index for use on
the restore.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Rename update_supports_migration() to update_supported_features() as
this method will be extended to track additional capability flags beyond
just migration support (e.g. DEVICE_STATE for snapshot/restore.)
Signed-off-by: Rob Bradford <rbradford@meta.com>
This is a refactoring step in preparation for fetching backend device
state via SET_DEVICE_STATE_FD which can fail.
Signed-off-by: Rob Bradford <rbradford@meta.com>
In GenericVhostUser's read_config and write_config, access
vu_common.acked_protocol_features directly instead of going through
the state() method which creates a struct. This removes creating the
struct just to access two fields that are already directly accessible.
Signed-off-by: Rob Bradford <rbradford@meta.com>
With a common state structure for all vhost-user devices the state()
methods can also be refactored for reuse. This will make it easier to
add new common fields in the future for snapshot/restore.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Each vhost-user device type had near identical State structs.
Deduplicate those by introducing a new common struct (and parameterising
it when it needs to embed a config member.) This will make it easier to
reuse more code in the future and to add more struct members to handle
the requirements of snapshot/restore.
These changes have been designed to have no impact on the existing
snapshot/restore state.
Signed-off-by: Rob Bradford <rbradford@meta.com>
When landlock support was added, creation of file descriptors was
moved out into a function called pre_create_console_devices, with the
idea being that this could be run before Landlock rules are applied
and access to all the necessary paths are dropped.
This idea didn't take reboots into account, though. When a VM is
rebooted, pre_create_console_devices is called again, but now the
Landlock rules have been applied, so they need to allow access to all
those paths anyway.
I imagine the way this was intended to work was that file descriptors
would be preserved across reboot, but that's not currently the case,
and it's not a trivial change to make because they get dropped when
the VM is destroyed. Longer term it would be ideal if Cloud
Hypervisor's implementation was more focused on file descriptors than
paths[1], and if created VMs only took references to file descriptors,
so they were easily preserved across reboots.
Fixes: b3e5738b4 ("vmm: Introduce ApplyLandlock trait")
Closes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7547
Link: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7704 [1]
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Use logical_size() instead of physical_size() for the byte-range
advisory lock. physical_size() returns st_blocks*512 which is the
actual host allocation and can be smaller than the guest visible
extent on sparse files, leaving part of the range unprotected.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use query_device_size() instead of metadata().len() to correctly
handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use query_device_size() instead of seek(End(0)) and metadata().len()
to correctly handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use query_device_size() instead of seek(End(0)) and metadata().len()
to correctly handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use query_device_size() instead of seek(End(0)) and metadata().len()
to correctly handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a shared helper that returns the logical size in bytes for both
regular files and block devices using an immutable &File reference.
Regular files use metadata().len(). Block devices use the BLKGETSIZE64
ioctl. Any other file type returns an InvalidInput error.
This avoids seek(SeekFrom::End(0)) which requires &mut self and can
return incorrect results for block devices when the file position is
in an unexpected state.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add BLKGETSIZE64 0x80081272 to the VMM seccomp ioctl allow list
alongside the existing BLK* ioctls. This is needed for querying
block device size without seeking.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
For VFIO devices with non page aligned MSI-X offsets,
fixup_msix_region() relocates MSI-X table and PBA offsets
into an enlarged virtual BAR by mutating msix.cap in place.
generate_sparse_areas() later reads those relocated offsets
to carve mmap holes, but receives the physical BAR size as
region_size. The relocated offsets exceed the physical BAR
boundary, and the kernel rejects the mmap with EINVAL.
Guard inter_ranges insertion with an offset < region_size
check so relocated entries are skipped. The full physical
BAR is mmapped as a single region. The relocated MSI-X in
the upper half of the virtual BAR remains trapped because
it has no mmap backing.
Linux kernel commit a32295c612c5 ("vfio-pci: Allow mapping
MSIX BAR") allows mmapping the entire BAR including the
MSI-X region when VFIO_REGION_INFO_CAP_MSIX_MAPPABLE is
advertised. The actual security guarantees come from IOMMU
isolation and interrupt remapping, not from filtering
MSI-X table accesses. QEMU follows the same pattern,
mmapping the entire physical BAR when MsixMappable is
present.
Fixes: #7898
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Following the `VfioContainer` to `VfioOps` trait switch, update the
remaining field names, method names, comments, and log messages to use
`vfio_ops` and "host IOMMU address space" consistently.
No fucntional changes.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Replace the concrete `VfioContainer` type with the `VfioOps` trait
object for device passthrough. This decouples the VFIO DMA mapping
interface from the legacy VFIO container/group implementation, allowing
it to be extended to support VFIO cdev and iommufd in the future.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Use IFS-based splitting instead of parameter expansion to
correctly separate '#'-delimited volume paths in
process_volumes_args(). The previous approach placed all
volumes into a single array element, causing Docker to
receive malformed --volume arguments.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Previously this code could lead to the device being trying to be
activated multiple times as the code to trigger the activation was based
on the state of the device (not yet activated and device being ready).
This could occur if anothe vCPU wrote to a PCI BAR on this device before
the device activation was completed by the VMM thread. Now we only
trigger the activation if the device readiness has changed as a result
of this BAR write (by checking that the readiness was originally
unready.)
Signed-off-by: Rob Bradford <rbradford@meta.com>
The actual size of the balloon is taken directly from the guest. A
misbehaving guest can set it to an arbitrary value and cause underflow
on the next vm.info call. Use a saturation_sub instead to avoid a panic
in a debug build or a crazy number in a release build.
Signed-off-by: Dylan Reid <dgreid@dylanreid.com>
As far as I can tell, PIDTYPE_PID is a kernel-internal name, and
PR_SCHED_CORE_SCOPE_THREAD is the UAPI name. There's no PIDTYPE_PID
in the UAPI headers, and the core scheduling documentation says that
the fourth prctl argument should be a "PR_SCHED_CORE_SCOPE_-prefixed
macro constant".
Link: https://www.kernel.org/doc/html/v6.19/admin-guide/hw-vuln/core-scheduling.html#usage
Fixes: 3f800d2bb ("vmm: Add core scheduling support for vCPU threads")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Switch to a git hash of virtiofsd as unfortunately the last release is
some time ago and does not incorporate a dependency bump that enables it
to work with snapshot-restore.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add a CVM integration test for vdpa_block that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro and with_cpu(2).
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for macvtap_hotplug that validates
the same functionality using a confidential guest with the
basic_cvm_guest macro and with_cpu(2).
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for macvtap that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro and with_cpu(2).
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for tap_from_fd that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro and with_cpu(2).
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for pvpanic that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for watchdog that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro and FOCAL_IMAGE_NAME.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for counters that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for net_hotplug that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for disk_hotplug that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for landlock that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for memory_overhead that validates
the same functionality using a confidential guest with the
basic_cvm_guest macro and custom memory size.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for pci_bar_reprogramming that
validates the same functionality using a confidential guest
with the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for direct_kernel_boot_noacpi
that validates the same functionality using a confidential
guest with the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for console_file that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for virtio_console that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for serial_off that validates
the same functionality using a confidential guest with
the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM integration test for multiple_network_interfaces
that validates the same functionality using a confidential
guest with the basic_cvm_guest macro.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_vdpa_block into a shared
_test_vdpa_block wrapper function in tests_wrappers.rs.
The vdpa module check is kept in the parent test case.
Update the parent to use basic_regular_guest macro with
with_cpu(2). The wrapper uses default_kernel_cmdline()
for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from _test_macvtap into a shared wrapper
function in tests_wrappers.rs. Update both test_macvtap and
test_macvtap_hotplug to use the basic_regular_guest macro
with with_cpu(2). The wrapper uses default_kernel_cmdline()
for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_tap_from_fd into a shared
_test_tap_from_fd wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro with with_cpu(2). The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_pvpanic into a shared
_test_pvpanic wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro. The wrapper uses default_kernel_cmdline() for
kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_watchdog into a shared
_test_watchdog wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro with FOCAL_IMAGE_NAME. The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_counters into a shared
_test_counters wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro. The wrapper uses default_kernel_cmdline() for
kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from _test_net_hotplug into a shared
wrapper function in tests_wrappers.rs. Update both
test_net_hotplug and test_net_multi_segment_hotplug to
use the basic_regular_guest macro. The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_virtio_block_topology into
a shared _test_virtio_block_topology wrapper function in
tests_wrappers.rs. The loop device creation and cleanup
are kept in the parent test case. The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from _test_disk_hotplug into a shared
wrapper function in tests_wrappers.rs. Update both
test_disk_hotplug and test_disk_hotplug_with_landlock
to use the basic_regular_guest macro. The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_landlock into a shared
_test_landlock wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro. The wrapper uses default_kernel_cmdline() for
kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_memory_overhead into a shared
_test_memory_overhead wrapper function in tests_wrappers.rs.
The custom memory size is set in the parent test case via
with_memory(). The wrapper uses default_kernel_cmdline()
and default_memory() for setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_pci_bar_reprogramming into
a shared _test_pci_bar_reprogramming wrapper function in
tests_wrappers.rs. The kernel_path selection for aarch64
(edk2) is kept in the parent test case. The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_direct_kernel_boot_noacpi into
a shared _test_direct_kernel_boot_noacpi wrapper function in
tests_wrappers.rs. The kernel cmdline modification (acpi=off)
is kept in the parent test case. The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_console_file into a shared
_test_console_file wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro. The wrapper uses default_kernel_cmdline() for
kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_virtio_console into a shared
_test_virtio_console wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro. The wrapper uses default_kernel_cmdline() for
kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_multiple_network_interfaces into
a shared _test_multiple_network_interfaces wrapper function in
tests_wrappers.rs. Update the parent test case to use the
basic_regular_guest macro. The wrapper uses
default_kernel_cmdline() for kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract test logic from test_serial_off into a shared
_test_serial_off wrapper function in tests_wrappers.rs.
Update the parent test case to use the basic_regular_guest
macro. The wrapper uses default_kernel_cmdline() for
kernel/cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM variant of the DMI OEM strings test in
integration_cvm.rs. This test creates a confidential
guest using the basic_cvm_guest! macro and invokes the
shared _test_dmi_oem_strings() wrapper to validate DMI
OEM strings behavior under CVM.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move the DMI OEM strings test logic from integration.rs
into a shared _test_dmi_oem_strings() function in
tests_wrappers.rs. The original test in integration.rs
now uses the basic_regular_guest! macro and delegates to
this shared function, enabling reuse by CVM tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM variant of the DMI UUID test in
integration_cvm.rs. This test creates a confidential
guest using the basic_cvm_guest! macro and invokes the
shared _test_dmi_uuid() wrapper to validate DMI UUID
behavior under CVM.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move the DMI UUID test logic from integration.rs into a
shared _test_dmi_uuid() function in tests_wrappers.rs.
The original test in integration.rs now uses the
basic_regular_guest macro and delegates to this shared
function, enabling reuse by CVM tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_api_http_create_boot, chaining with_cpu(4) for the
required CPU count configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_api_http_pause_resume, chaining with_cpu(4) for the
required CPU count configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_api_http_delete, chaining with_cpu(4) for the
required CPU count configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_api_http_shutdown, chaining with_cpu(4) for the
required CPU count configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_virtio_vsock_hotplug. The aarch64 variant chains
with_kernel_path for EDK2 firmware support.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_virtio_vsock for consistency and reduced boilerplate.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_direct_kernel_boot for consistency and reduced
boilerplate.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_pci_multiple_segments for consistency and reduced
boilerplate.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_virtio_net_ctrl_queue for consistency and reduced
boilerplate.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_pci_msi for consistency and reduced boilerplate.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_power_button for consistency and reduced boilerplate.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_virtio_queue_affinity, chaining with_cpu(4) for the
required CPU count configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_cpu_affinity, chaining with_cpu(2) for the required
CPU count configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual UbuntuDiskConfig and GuestFactory guest
creation with the basic_regular_guest! macro in
test_multi_cpu for consistency and reduced boilerplate.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move the DMI serial number test logic from integration.rs
into a shared _test_dmi_serial_number() function in
tests_wrappers.rs. The original test now delegates to
this shared function, enabling reuse by CVM tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM variant of the split IRQ chip test in
integration_cvm.rs. This test creates a confidential
guest and invokes the shared _test_split_irqchip()
wrapper to validate split IRQ chip behavior under CVM.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move the split IRQ chip test logic from integration.rs
into a shared _test_split_irqchip() function in
tests_wrappers.rs. The original test now delegates to
this shared function, enabling reuse by CVM tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a CVM variant of the virtio block dynamic VHDX expand
test in integration_cvm.rs. This test creates a
confidential guest and invokes the shared
_test_virtio_block_dynamic_vhdx_expand() wrapper to
validate VHDX expansion under CVM.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move the virtio block dynamic VHDX expand test logic from
integration.rs into a shared _test_virtio_block_dynamic_
vhdx_expand() function in tests_wrappers.rs. The original
test in integration.rs now calls this shared function,
enabling reuse by CVM tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Refactor test_focal_ovmf to use the basic_regular_guest!
macro with the with_kernel() builder instead of manually
constructing UbuntuDiskConfig and setting kernel_path.
This also removes leftover unused disk_config in
test_focal_hypervisor_fw.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Introduce a basic_regular_guest! macro in integration.rs
to reduce boilerplate when creating regular (non-CVM)
guest instances. Also add a with_kernel() builder method
to Guest in test_infra, allowing fluent configuration of
the kernel path.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Introduce a basic_cvm_guest! macro in integration_cvm.rs
to reduce boilerplate when creating confidential VM guest
instances. This replaces repetitive UbuntuDiskConfig and
GuestFactory::new_confidential_guest_factory() calls
across multiple CVM test functions.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move all CVM (Confidential VM) integration tests from
integration.rs into a dedicated integration_cvm.rs file.
This separation improves code organization and makes it
easier to manage CVM-specific test cases independently
from regular integration tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This summarizes the latest state all relevant parties have agreed on
in the last meeting.
This commit was rephrased and improved with the help of Claude Code
using the Sonnet 4.6 model.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Mosts tests used 4GB of RAM, although the VM is mostly idling. In CI, we
experienced OOM issues on the ARM runners. If we reduce the VM memory of
the parallel live migration tests to 1.5GB RAM, we still have enough
capacity in the VM so that everything succeeds while reducing resource
usage.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This adds two new integration tests for the new functionality:
- VM under load, downtime=1ms, timeout=1s, timeout_strategy=cancel
- VM under load, downtime=1ms, timeout=1s, timeout_strategy=force
By using a short downtime and timeout plus adding a stress worker in the
guest, we can prevent quick migration. Therefore, we can nicely test the
timeout_strategy.
Testing for a specific downtime is cumbersome to do and highly depends
on CPU/host utilization. To prevent flakiness, there is no such test
integration test. I did, however, manual testing of that functionality.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Wire the new `downtime_ms`, `timeout_s`, and `timeout_strategy` fields
from `VmSendMigrationData` into the precopy loop, replacing the previous
hard-coded 5-iteration cap.
Each iteration now evaluates three convergence criteria in order:
- no dirty pages remain;
- the estimated final-iteration downtime is within the configured budget
- or the overall migration timeout has elapsed.
On timeout, `TimeoutStrategy::Cancel` aborts and keeps the VM live on
the source, while `TimeoutStrategy::Force` proceeds regardless of the
downtime target. The convergence callback is updated to return a Result
to propagate the cancel error cleanly up the call stack.
With the recent changes [0], it is fairly easy to implement the new
checks and operate on actual metrics.
These changes are inspired by [1] but differ significantly in details.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7799
[1] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7033
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Management software needs fine-grained control over live migration to
meet QoS requirements for VM guests. Add `downtime_ms`, `timeout_s`, and
`timeout_strategy` fields to `VmSendMigrationData`, exposed via API.
This commit contains the API changes only; the VMM does not yet act on
these values. This follows in the next commit.
For the JSON API, downtime and timeout are represented as plain integers
(downtime_ms and timeout_s) to make the units explicit. Using Duration
directly would require custom (de)serialization logic, so instead the
internal raw integers are exposed as Duration via getters. This
introduces minor conversion overhead but keeps the Rust API clear and
unambiguous.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This change prepares upcoming options (following commit) that are added
to VmSendMigrationData.
VmSendMigrationData is a special case as it is currently the only
"rich configuration" type that lives outside `config.rs`, as it is
purely API-facing. Therefore, it isn't integrated into the existing
OptionParser infrastructure. We therefore introduce a `parse()` method
to use that in `ch-remote` in the following.
In `ch-remote`, we remove `--local` for `send-migration` and switch to
the new option string parsing constructor (breaking change!). This
prepares the addition of downtime and timeout options in the following
and streamlines the `ch-remote` command line interface with other
commands, such as `ch-remote add-net`.
Lastly, this commit updates the integration tests.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
When configuring multiple queues for a virtio device, the guest can
activate between 1 and the configured amount of queues. The firmware,
for example, may activate only one queue, while a Linux guest would
likely activate all available queues.
The constructor of virtio-blk initializes the `paused_sync` barrier
using the configured queue count (plus one for the main thread). This
can be wrong if the guest enable a different number of queues at
activation time, which can make pause hang. Thus, we now recompute the
barrier size from the queues that are actually activated.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
When configuring multiple queues for a virtio device, the guest can
activate between 1 and the configured amout of queues. The firmware,
for example, may activate only one queue, while a Linux guest would
likely activate all available queues.
The constructor of virtio-net initializes the `paused_sync` barrier
using the configured queue count (plus one for the main thread). This
can be wrong if the guest enables a different number of queues at
activation time, which can make pause hang. Thus, we now recompute the
barrier size from the queues that are actually activated.
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
Include the number of segments found in the request payload in
the TooManySegments error variant so the logged message shows
both the actual and maximum values.
Suggested-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce DISCARD_WZ_MAX_PAYLOAD as the precomputed product of
DISCARD_WZ_SEG_SIZE and MAX_DISCARD_WRITE_ZEROES_SEG. Use it in the
DISCARD and WRITE_ZEROES segment count checks instead of repeating
the multiplication inline.
Suggested-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The libc crate provides all functionality provided by the net_gen crate.
Removing the net_gen crate reduces the maintenance burden.
The switch to libc required some fixes, most notably the switch from a
`Vec<u8>` to a `CString` for the `net_util::Tap.if_name` field.
On-behalf-of: SAP julian.schindel@sap.com
Signed-off-by: Julian Schindel <julian.schindel@cyberus-technology.de>
Bump to the released versions that are compatible wherever possible but
for the vhost and vfio crates they are git hashes as no releases with
compatible versions have yet been made.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This now required after Rust-VMM crate bumps. Also reorder some syscalls
so that they are now in alphabetical order.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add range validation for DISCARD and WRITE_ZEROES, matching the
existing check in the read/write path. Per virtio spec section
5.2.6.1, a driver must not submit a request which would cause a
read or write beyond capacity. Use checked_add to guard against
overflow, then compare against disk_nsectors.
Without this, requests beyond device capacity pass through to the
host punch_hole/write_zeroes calls, relying on backend specific
behavior rather than returning VIRTIO_BLK_S_IOERR consistently.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Split the data length check into two conditions:
- reject descriptors shorter than one
virtio_blk_discard_write_zeroes segment, and
- reject payloads exceeding MAX_DISCARD_WRITE_ZEROES_SEG segments
Previously only the minimum length was checked and extra segments
were silently dropped.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
All public qcow functions now return BlockResult with explicit error
classification at every site. The temporary From impl introduced in
the first commit of this series is no longer needed and is removed.
Internal functions in header.rs and the rebuild_refcounts helpers
stay on qcow::Result. Classification happens at the call site
boundary where qcow::Result meets BlockResult.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch detect_image_type from qcow::Result to BlockResult with
explicit error classification at every I/O site. This is the last
function migrated before the From scaffolding can be removed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch rebuild_refcounts from qcow::Result to BlockResult. The
inner helper functions remain on qcow::Result since they are purely
internal, and are wrapped with map_err at each call site where they
cross the BlockResult boundary.
InvalidRefcountTableSize errors are classified as CorruptImage since
they indicate inconsistent internal refcount structures rather than
a format violation.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch resize and grow_l1_table from qcow::Result to BlockResult.
All I/O error sites use explicit BlockError::new with the Io kind.
The write_to call in grow_l1_table rewraps WritingHeader as
ResizeIo to preserve the existing error semantics.
The two resize tests that check for ShrinkNotSupported and
ResizeWithBackingFile are updated to match on BlockErrorKind with
downcast to inspect the underlying variant.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace remaining automatic From conversions in parse_qcow and
BackingFile::new with explicit BlockError::new calls carrying the
appropriate BlockErrorKind at every error site.
Internal functions that still return qcow::Result (QcowHeader::new,
offset_is_cluster_boundary, clear_autoclear_features and others) are
wrapped with map_err at the boundary. These functions stay on
qcow::Result as they are internal to the qcow module and the
classification belongs at the call site rather than inside the
function itself.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch parse_qcow and BackingFile::new from qcow::Result to
BlockResult. Every early return site now produces an explicit
BlockError with the appropriate kind. Remaining internal calls to
functions still on qcow::Result rely on the From scaffolding and
will be converted in subsequent commits.
Two helpers are added to BlockError. with_kind replaces the
classification on an existing error, used in QcowDiskSync::new to
avoid double wrapping when the caller needs a different kind.
into_source consumes the error and returns the boxed source, used
at the recursive BackingFile open to extract the qcow::Error for
BackingFileOpen without letting qcow::Error hold a BlockError.
The qcow_sync boundary is simplified to a single closure that
operates on the BlockError already returned by parse_qcow.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch the public QcowFile constructors (new, new_from_backing,
new_from_header, from, from_backing, from_file_and_header) from
qcow::Result to BlockResult. Internal calls to header functions
that still return qcow::Result are wrapped with explicit error
classification at each call site.
Test assertions are updated to match on BlockErrorKind and use
downcast to inspect the underlying qcow::Error variant.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Temporary From impl that classifies each qcow::Error variant into
the appropriate BlockErrorKind. This enables an incremental migration
of qcow functions from qcow::Result to BlockResult, where each
subsequent commit replaces bare ? sites with explicit BlockError::new
calls until this impl can be removed.
The mapping assigns InvalidFormat for structural header violations,
UnsupportedFeature for version and feature mismatches, CorruptImage
for internal inconsistencies, Overflow for nesting depth and Io for
everything else.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move shared integration test logic out of tests/integration.rs.
Add tests/common/{mod.rs,tests_wrappers.rs,utils.rs} and migrate
API, VM lifecycle, disk/net, and utility helpers.
Update integration.rs to import common modules and keep test
entrypoints thin.
Benefits:
Reduces integration.rs size and duplication
Groups reusable helpers by role
Improves readability and future maintenance
Fixes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7808
Signed-off-by: Muminul Islam <muislam@microsoft.com>
We only verify devices are under some group but not which one.
With the change, the acpi variable is only needed for aarch64. Add an
underscore prefix to avoid a compilation warning on x86_64.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Linux kernel's behavior changes overtime. The grouping can be different
across different versions and different architectures.
We only cares about the exact SBDF exists somewhere. It doesn't matter
which group it is under.
Change the check so that this test case is no longer tied to the
grouping behavior of a particular kernel.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
QcowDiskSync now exclusively uses disk_file::DiskFile and
disk_file::AsyncDiskFile. The old async_io::DiskFile impl is removed
along with its unused imports (DiskFile, DiskFileError, DiskFileResult).
Tests are updated to import the new traits.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Change Block to hold DiskBackend instead of
Box<dyn async_io::DiskFile>. In device_manager, existing formats
(raw, vhd, vhdx) are wrapped in DiskBackend::Legacy while
QcowDiskSync uses DiskBackend::Next. The fuzz target is updated
accordingly.
The Error::DiskResize variant now carries BlockError instead of
DiskFileError, matching the BlockResult return type of
DiskBackend::resize().
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce DiskBackend with two variants:
- Legacy: wraps Box<dyn async_io::DiskFile> for existing formats
- Next: wraps Box<dyn disk_file::AsyncFullDiskFile>
Methods return BlockResult, with DiskFileError converted up to
BlockError on the Legacy path. The Next path passes through
directly with zero conversion overhead.
This is a transitional type. Once all formats implement
AsyncFullDiskFile, DiskBackend and Legacy are removed and
callers hold Box<dyn AsyncFullDiskFile> directly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement try_clone by sharing the metadata Arc and cloning the data
file descriptor. The new_async_io method creates a QcowSync worker
identical to the async_io::DiskFile version.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add ErrorOp::Resize variant and implement the Resizable trait.
Resize is rejected when a backing file is present.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Advertise support for sparse operations and the zero flag. QCOW2
inherently supports both through cluster deallocation.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Uses the default DiskTopology (512B logical/physical) since
QCOW2 does not probe the underlying device geometry.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Borrows the raw file descriptor from the underlying QcowRawFile
for fcntl() operations. Uses &self for shared access.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delegate to QcowRawFile::physical_size() which returns the actual
host allocation size of the QCOW2 container file.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delegate to QcowMetadata::virtual_size() which returns the guest
visible capacity stored in the QCOW2 header.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The new composable traits require Debug. Implement it manually since
QcowMetadata contains RwLock state that cannot auto derive.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Marker trait combining FullDiskFile and AsyncDiskFile. Blanket impl
covers any type implementing both supertraits.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Marker trait bundling all optional capabilities (PhysicalSize, DiskFd,
SparseCapable, Resizable) on top of DiskFile. Blanket impl covers any
type implementing all constituent traits.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Extend DiskFile with async I/O construction for virtio queue workers.
AsyncDiskFile adds try_clone() for creating independent handles to
the same backing storage, and new_async_io() for constructing an
async I/O engine at the given ring depth.
Bounds: DiskFile + Unpin. Unpin ensures trait objects can be moved
freely (all concrete disk file types are naturally Unpin since they
hold no self referential state).
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Bundles DiskSize and Geometry as the universal disk
capabilities every format must implement. Adds Sync so
that Arc<dyn DiskFile> can be shared across threads for
concurrent readonly access.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Live disk resize support. Single method resize() taking
&mut self and the new size in bytes. Implementations may
return an error if the backend does not support resizing.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Sparse and zero flag support for thin provisioned disk
images. Two methods with false defaults: sparse operations
(punch hole, write zeroes, discard) and zero flag
optimization in WRITE_ZEROES.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Sector and cluster geometry of a disk image. Returns
DiskTopology with a default implementation providing
512B logical and physical block sizes. Formats that
probe the underlying device override this.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Backing file descriptor access for disk images backed by
a file. Returns a BorrowedDiskFd that wraps the raw fd
with lifetime tracking. Not available for network or
memory backed disk formats.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Host allocation size for file-backed disk images. Reports
actual bytes occupied on the host filesystem. Not every
format supports this, e.g. network or memory backed disks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Reported capacity of a disk image. Every format, be it
file backed, network, memory, exposes a logical size.
Single method logical_size() returning the virtual size
in bytes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Composable disk capability traits with DiskFile as a supertrait
bundling DiskSize and Geometry. Optional capabilities are
separate traits: PhysicalSize, DiskFd, SparseCapable, Resizable.
AsyncDiskFile extends DiskFile with async I/O construction.
Empty module with doc comment, trait definitions follow.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a full suite of test_virtio_block_* tests to the common_cvm
integration test module to verify virtio block functionality in
confidential guest environments.
The following tests are added, all using 4-vCPU confidential
VMs created via GuestFactory:
- test_virtio_block_io_uring (Raw image, io_uring backend)
- test_virtio_block_aio (Raw image, AIO backend)
- test_virtio_block_sync (Raw image, sync backend)
- test_virtio_block_qcow2 (QCOW2 image)
- test_virtio_block_qcow2_zlib (QCOW2 with zlib compression)
- test_virtio_block_qcow2_zstd (QCOW2 with zstd compression)
- test_virtio_block_qcow2_backing_zstd_file
- test_virtio_block_qcow2_backing_uncompressed_file
- test_virtio_block_qcow2_backing_raw_file
This extends CVM test coverage to all virtio block I/O backends
and disk image formats.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move _test_virtio_block to module-level scope, accepting a
Guest reference instead of an image name string. Replace
hardcoded CPU, kernel, and cmdline arguments with default_cpus
and default_kernel_cmdline.
Promote all supporting disk utilities to module-level scope:
compute_backing_checksum, disk_check_consistency, run_qemu_img,
get_image_info, get_qcow2_v3_info, check_dirty_flag,
check_corrupt_flag, set_corrupt_flag, resolve_disk_path, and
compute_file_checksum.
Update all test_virtio_block_* call sites in common_parallel
to create guests via GuestFactory::new_regular_guest_factory()
with 4 vCPUs and pass them to the helper. This enables reuse
with different guest types such as confidential VMs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_direct_kernel_boot to the common_cvm integration test
module to verify that boot, CPU, memory, and MSI interrupt
functionality work correctly in confidential guest environments.
The test creates an Ubuntu Jammy-based confidential VM using
GuestFactory and delegates to the existing
_test_direct_kernel_boot helper.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract direct kernel boot test logic into a standalone
_test_direct_kernel_boot helper that accepts a Guest reference.
The helper boots a VM, validates CPU count and memory using
generic validate_cpu_count and validate_memory methods, and
asserts 12 MSI interrupts in /proc/interrupts.
Replace hardcoded kernel and cmdline arguments with
default_kernel_cmdline(). Update the test call site in
common_parallel to use GuestFactory and delegate to the new
helper, enabling reuse with different guest types.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_pci_multiple_segments to the common_cvm integration
test module to verify multiple PCI segment support in
confidential guest environments.
The test uses 8 PCI segments, which exceeds the Linux default
of 6 and matches the maximum supported by the IGVM file for
SEV-SNP guests. A test disk is placed on segment 5 to validate
cross-segment device functionality.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract common PCI multiple segment disk test logic into
_test_pci_multiple_segments() and reuse it from the test case.
Switch guest creation to GuestFactory in test_pci_multiple_segments
and pass segment values through helper parameters.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Introduce default_kernel_cmdline_with_platform() in GuestCommand
that accepts an optional platform parameter. For confidential
VMs, the platform arg is prepended to sev_snp=on. For regular
VMs, it is passed via --platform if provided.
Retain default_kernel_cmdline() as a convenience wrapper that
calls the new method with None, preserving backward
compatibility.
This enables tests to pass additional platform configuration
such as num_pci_segments alongside the default kernel and
cmdline setup.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_virtio_net_ctrl_queue to the common_cvm integration
test module to verify that virtio net control queue functionality
works correctly in confidential guest environments.
The test creates an Ubuntu Jammy-based confidential VM using
GuestFactory and delegates to the existing
_test_virtio_net_ctrl_queue helper to validate MTU configuration
and ethtool offload settings.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract virtio net control queue test logic into a standalone
_test_virtio_net_ctrl_queue helper that accepts a Guest
reference. The helper boots a VM with MTU 3000, verifies
ethtool can disable rx-gro-hw, and asserts the guest interface
MTU is correctly set.
Replace hardcoded kernel and cmdline arguments with
default_kernel_cmdline(). Update the test call site in
common_parallel to use GuestFactory and delegate to the new
helper, enabling reuse with different guest types.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_pci_msi to the common_cvm integration test module to
verify that PCI MSI interrupt functionality works correctly in
confidential guest environments.
The test creates an Ubuntu Jammy-based confidential VM using
GuestFactory and delegates to the existing _test_pci_msi helper
to validate MSI interrupts.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract PCI MSI interrupt test logic from test_pci_msi into a
standalone _test_pci_msi helper that accepts a Guest reference.
The helper boots a VM, waits for boot, and asserts that 12 MSI
interrupts are present in /proc/interrupts.
Replace hardcoded kernel and cmdline arguments with
default_kernel_cmdline(). Update the test call site in
common_parallel to use GuestFactory and delegate to the new
helper, enabling reuse with different guest types.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_virtio_queue_affinity to the common_cvm integration
test module to verify that per-queue CPU pinning works correctly
in confidential guest environments.
The test creates a 4-vCPU Ubuntu Jammy-based confidential VM
using GuestFactory and delegates to the existing
_test_virtio_queue_affinity helper to validate queue-to-core
affinity settings.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract virtio queue affinity test logic into a standalone
_test_virtio_queue_affinity helper that accepts a Guest
reference. The helper verifies the host has at least 4 CPUs,
boots a VM with per-queue affinity on the cloud-init disk,
and asserts each disk queue thread is pinned to the expected
cores.
Replace hardcoded kernel and cmdline arguments with
default_cpus() and default_kernel_cmdline(). Update the
test call site in common_parallel to use GuestFactory and
delegate to the new helper, enabling reuse with different
guest types.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_cpu_affinity to the common_cvm integration test module
to verify that CPU pinning works correctly in confidential
guest environments.
The test creates a 2-vCPU Ubuntu Jammy-based confidential VM
using GuestFactory and delegates to the existing
_test_cpu_affinity helper to validate vCPU-to-core affinity.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract CPU affinity test logic from test_cpu_affinity into a
standalone _test_cpu_affinity helper that accepts a Guest
reference. The helper verifies the host has at least 4 CPUs,
boots a VM with affinity settings, and asserts vcpu0 is pinned
to cores 0,2 and vcpu1 to cores 1,3.
Add default_cpus_with_affinity_string() to Guest and
default_cpus_with_affinity() to GuestCommand in test_infra
to generate CPU arguments with affinity configuration.
Update the test_cpu_affinity call site in common_parallel to
use GuestFactory and delegate to the new helper, enabling
reuse with different guest types.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_multi_cpu to the common_cvm integration test module
to verify that multi-CPU functionality works correctly in
confidential guest environments.
The test creates an Ubuntu Jammy-based confidential VM using
GuestFactory and delegates to the existing _test_multi_cpu
helper to validate SMP boot with multiple vCPUs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract the multi-CPU test logic from the test_multi_cpu test
into a standalone _test_multi_cpu helper that accepts a Guest
reference as a parameter.
Update the test_multi_cpu call site in common_parallel to
create the guest via GuestFactory::new_regular_guest_factory()
and delegate to the new helper. This enables reuse of the test
logic with different guest types such as confidential VMs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_virtio_vsock to the common_cvm integration test module
to verify that virtio vsock functionality works correctly in
confidential guest environments.
The test creates an Ubuntu Jammy-based confidential VM using
GuestFactory and delegates to the existing _test_virtio_vsock
helper with hotplug disabled.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Extract guest and kernel setup out of _test_virtio_vsock and
pass a Guest reference as a parameter instead. Replace explicit
kernel and cmdline arguments with default_kernel_cmdline().
Move guest creation to the test call sites using
GuestFactory::new_regular_guest_factory(), enabling reuse of
the helper with different guest types such as confidential VMs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_power_button to the common_cvm integration test module
to verify that power button functionality works correctly in
confidential guest environments.
The test creates an Ubuntu Jammy-based confidential VM using
GuestFactory and delegates to the existing _test_power_button
helper to validate the power button signal handling.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Remove the acpi bool parameter and internal guest and kernel
setup from _test_power_button. The function now accepts a Guest
reference and uses default_kernel_cmdline() instead of
hardcoded kernel paths.
Update test_power_button in common_parallel to create a regular
guest via GuestFactory. Update test_power_button_acpi in
aarch64_acpi to use with_kernel_path(edk2_path()) for ACPI
firmware support.
Add with_kernel_path() builder method on Guest in test_infra
to allow overriding the kernel path after guest creation.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Collect up to 32 completions per io_getevents call instead of one
at a time, buffering them in the existing VecDeque. This reduces
syscalls from 128 to 4 per drain cycle at the default queue depth.
The stack cost is 1 KB per call.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Set discard_sector_alignment from the logical block size
reported by the backend topology instead of hardcoding it
to 1 sector. This gives the guest accurate alignment hints
so it can avoid sub block discards that the filesystem
might silently ignore.
For example, on a 4K block filesystem the alignment is now
8 sectors (4096/512) instead of 1.
For image formats with their own allocation units (QCOW2
clusters, VHD/VHDX block sizes), the ideal alignment would
be derived from the format cluster/block size. This is
left for a followup that surfaces allocation granularity
through DiskTopology.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace magic numeric offsets with mem::offset_of!() referencing the
virtio_blk_discard_write_zeroes struct from the virtio-bindings crate
when reading the sector, num_sectors and flags fields in the DISCARD
and WRITE_ZEROES request handlers.
No functional change.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add an option that can be used when restoring to resume the VM. This is
particularly useful when restoring the VM via the direct VMM command
line, when you might not want/have an API socket configured.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Skip micro_ prefixed tests in the metrics CI workflow to avoid
dashboard pollution. They can still be run on demand via
--test-filter micro_.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add --test-exclude to process_common_args in test-util.sh and forward
it to the performance-metrics binary from run_metrics.sh.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a --test-exclude flag that excludes tests matching the provided
keywords. Both --test-filter and --test-exclude are now applied before
--list-tests, so listing respects the active filters.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add test_virtio_block_write_zeroes_unmap_raw to verify that the
VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP code path works correctly with
raw disk images.
The test creates a 128M raw disk and writes 64M of random data,
then uses fallocate --punch-hole on the guest block device, which
the Linux virtio-blk driver translates to VIRTIO_BLK_T_WRITE_ZEROES
with VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP set. It then verifies:
- the zeroed region reads back as zero from the guest
- the host file became sparse (punch_hole succeeded)
- FIEMAP confirms the file has holes
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The write zeroes segment descriptor (struct
virtio_blk_discard_write_zeroes, virtio spec v1.2 section 5.2.6)
includes a flags field with an unmap bit. Per section 5.2.6.2, if
unmap is set, the device MAY deallocate the specified range of
sectors in the device backend storage, as if the discard command
had been sent.
Read the flags field and when the unmap bit is set, use punch_hole
to deallocate the range. Otherwise continue using write_zeroes via
ZERO_RANGE which preserves allocation.
This allows the guest to reclaim host disk space through write
zeroes requests on thin provisioned images.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The virtio vhost-user device backend prefers to use externally-provided
eventfds as irqfds. This allows the frontend VM to notify the backend
VM directly, without the need for a userspace proxy process. Since the
frontend can provide irqfds at any time, the backend needs to register
and unregister irqfds dynamically.
This is tricky because the functions that access the irqfd table all
take `&self`, not `&mut self`. The obvious solution to this problem is
to wrap the table in a mutex. Most of these functions are not called on
hot paths, but `.notifier()` is called whenever Cloud Hypervisor needs
to inject an interrupt into a guest. Most devices don't need to
register irqfds at runtime, and for them, slowing down interrupt
injection would be wasteful.
Instead, require devices to opt-in to irqfd registration. The irqfd
table now comes in two forms: one that contains a mutex and one that
does not. The one containing a mutex can be mutated freely, while
attempting to mutate the one that does not will panic.
Right now, no code registeres irqfds at runtime, but this will change in
subsequent commits.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
This allows creating an InterruptSourceGroup with an externally provided
file descriptor. It also allows changing the file descriptor
afterwards.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
It is currently left as unimplemented!().
No functional change intended as there are no callers.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
The InterruptRoute code tried to be thread-safe, but it wasn't. In
particular, concurrently enabling and disabling an InterruptRoute could
result in the route thinking it was enabled (when it was disabled) or
visa versa.
Wrap all operations in a mutex and drop the attempt at being lock-free.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Add micro_block_raw_aio_drain_128_us and
micro_block_raw_aio_drain_256_us tests that submit N AIO writes
to a temporary file, wait for the eventfd signal, then time how
long it takes to drain all completions via next_completed_request().
This measures per completion syscall overhead and provides a
baseline before any batching optimizations.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
These factor out common setup and synchronization patterns used by block
layer micro benchmarks.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add an optional num_ops parameter for micro benchmarks to configure
workload size (e.g. number of AIO operations to submit). A warning
is emitted if it is accidentally set on a non micro test where it
has no effect.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce support for in process micro benchmarks alongside the
existing VM level performance tests. Micro benchmarks are
integrated into the same PerformanceTest/TEST_LIST infrastructure
and follow the same iteration, timeout, and reporting pipeline.
They are distinguished by a micro_* name prefix.
The test dispatch loop is refactored to pre filter the test list
and gate init/cleanup behind a flag, so that pure micro benchmark
runs skip the expensive VM lifecycle entirely. Mixed runs
(VM + micro) continue to work correctly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Trigger the interrupts in the guest for the virtio device queues behind
the vhost-user devices when resuming. This avoids a situation where
interrupts from the backend get lost when they are dispatched from the
backend when then guest is paused leading to the guest/backend
effectively waiting for each other to move forward. This is more
reproducible with longer durations between pause and resume as there is
more opportunity for the backend to completely process it's queue and
fire all the interrupts.
It's perfectly safe and allowed by the virtio spec to generate these
interrupts and the performance impact is negligible and is a safe way to
ensure forward progress after a resume.
See: #7850
Signed-off-by: Rob Bradford <rbradford@meta.com>
The config space fix in the previous commit correctly populates
the discard and write zeroes fields, so the sparse=off
workaround is no longer needed for Windows guests.
Replace default_disks_sparse_off() with default_disks() in all
Windows test cases and remove the explicit sparse=off from the
multi queue test.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When VIRTIO_BLK_F_DISCARD or VIRTIO_BLK_F_WRITE_ZEROES features
are advertised, the virtio spec v1.2, sections 5.2.4 and
5.2.6.1, requires the corresponding VirtioBlockConfig fields
to contain valid, non zero values. Leaving them at zero causes
strictly behaved drivers to either reject the features or crash.
Populate max_discard_sectors, max_discard_seg,
discard_sector_alignment, max_write_zeroes_sectors,
max_write_zeroes_seg and write_zeroes_may_unmap after
feature advertisement so drivers can safely negotiate
these features.
Fixes: #7849
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This device is not called virtio-vhost-user; that's something else.
I don't think the comment really clarifies anything anyway, so just
remove it.
Fixes: 8c618ff5e ("virtio-devices: generic-vhost-user: implement device")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Rename the aarch64 sha1sums file to sha1sums-aarch64-common to follow
the same naming convention as sha1sums-x86_64-common. This allows
run_metrics.sh to use the generic sha1sums-${TEST_ARCH}-common
pattern for all architectures, removing the need for aarch64-specific
conditionals.
Update run_integration_tests_aarch64.sh to reference the renamed file.
Signed-off-by: Souradeep <schakrabarti@microsoft.com>
warning: this argument is passed by value, but not consumed in the function body
--> cloud-hypervisor/tests/integration.rs:3785:51
|
3785 | fn run_multiqueue_qcow2_test<F>(image_config: QcowTestImageConfig, test_fn: F)
| ^^^^^^^^^^^^^^^^^^^
|
help: or consider marking this type as `Copy`
--> cloud-hypervisor/tests/integration.rs:3774:5
|
3774 | enum QcowTestImageConfig {
| ^^^^^^^^^^^^^^^^^^^^^^^^
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
= note: requested on the command line with `-D clippy::needless-pass-by-value`
Signed-off-by: Rob Bradford <rbradford@meta.com>
error: the borrowed expression implements the required traits
--> cloud-hypervisor/tests/integration.rs:8510:32
|
8510 | disk_check_consistency(&test_disk_path, None);
| ^^^^^^^^^^^^^^^ help: change this to: `test_disk_path`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args
= note: `-D clippy::needless-borrows-for-generic-args` implied by `-D clippy::all`
= help: to override `-D clippy::all` add `#[allow(clippy::needless_borrows_for_generic_args)]`
error: could not compile `cloud-hypervisor` (test "integration") due to 7 previous errors
Signed-off-by: Rob Bradford <rbradford@meta.com>
error: you seem to use `.enumerate()` and immediately discard the index
--> cloud-hypervisor/tests/integration.rs:7675:72
|
7675 | for (_i, (offset, length)) in discard_operations.iter().enumerate() {
| ^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_enumerate_index
= note: `-D clippy::unused-enumerate-index` implied by `-D clippy::all`
= help: to override `-D clippy::all` add `#[allow(clippy::unused_enumerate_index)]`
help: remove the `.enumerate()` call
|
7675 - for (_i, (offset, length)) in discard_operations.iter().enumerate() {
7675 + for (offset, length) in discard_operations.iter() {
|
Signed-off-by: Rob Bradford <rbradford@meta.com>
error: consider adding a `;` to the last statement for consistent formatting
--> cloud-hypervisor/tests/integration.rs:2516:9
|
2516 | _test_simple_launch(&guest)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `_test_simple_launch(&guest);`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
Signed-off-by: Rob Bradford <rbradford@meta.com>
error: variables can be used directly in the `format!` string
--> cloud-hypervisor/tests/integration.rs:12770:27
|
12770 | let driver_path = format!("{}/driver", NVIDIA_VFIO_DEVICE);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
help: change this to
|
12770 - let driver_path = format!("{}/driver", NVIDIA_VFIO_DEVICE);
12770 + let driver_path = format!("{NVIDIA_VFIO_DEVICE}/driver");
Signed-off-by: Rob Bradford <rbradford@meta.com>
error: this argument is passed by value, but not consumed in the function body
--> net_util/src/tap.rs:685:17
|
685 | ifname: String,
| ^^^^^^ help: consider changing the type to: `&str`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
= note: requested on the command line with `-D clippy::needless-pass-by-value`
Signed-off-by: Rob Bradford <rbradford@meta.com>
Write down our policy for git commit hygiene, especially when it comes
to the history, i.e., multiple git commits in a PR.
TL;DR: Commits must be revieable units guiding reviewers how the
developer got from A to B.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
raw_sync, raw_async, and raw_async_aio each defined
FALLOC_FL_PUNCH_HOLE, FALLOC_FL_KEEP_SIZE, and FALLOC_FL_ZERO_RANGE as
local constants in their punch_hole() and write_zeroes()
implementations. These are available from the libc crate directly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
probe_file_sparse_support() defined FALLOC_FL_KEEP_SIZE,
FALLOC_FL_PUNCH_HOLE, and FALLOC_FL_ZERO_RANGE as local constants.
These are available from the libc crate directly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Replace duplicated test bodies with thin wrappers that construct
the backend-specific AsyncIo instance and delegate to the shared
raw_async_io_tests helpers.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add raw_async_io_tests.rs with punch_hole, write_zeroes, and
multiple_operations helpers that take &mut dyn AsyncIo + &mut File.
These are raw-backend-specific. They verify data by reading the
underlying file directly, which only works for plain file backends
without container format metadata.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Split the vDPA preparation flow into helper functions for
building modules, validating availability, loading modules,
and creating devices.
Build the vdpa_sim modules only on Ubuntu, where the script
installs dependencies and compiles them from the matching
kernel source. On other distributions, reuse the installed
kernel modules and verify that they are available before
continuing.
This makes the script easier to follow and supports systems
such as Azure Linux, where the modules are provided by the
kernel package.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
A buggy or malicious guest may write an inappropriate value into
virtqueue's next_avail field. This will result in an error
when iterating over the queue:
863837ef86/virtio-queue/src/queue.rs (L708)
but this error is (logged and) ignored if pop_descriptor_chain()
is used:
863837ef86/virtio-queue/src/queue.rs (L583)
A reasonable approach, implemented here, is to mark the device as
NEEDS_RESET and ignore further queue events until the guest
reinitializes the device.
How this patch was tested:
Linux kernel was patched to trigger a bad next_avail when the
virtqueue queue counter reaches 5000:
--------------- START OF LINUX KERNEL PATCH ----------
$ git diff
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b784aab668670..989f2a0c64a77 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -15,6 +15,9 @@
#include <linux/spinlock.h>
#include <xen/xen.h>
+
+void virtqueue_kick_always(struct virtqueue *vq);
+
#ifdef DEBUG
/* For development, we want to crash whenever the ring is screwed. */
#define BAD_RING(_vq, fmt, args...) \
@@ -677,6 +680,12 @@ static inline int virtqueue_add_split(
struct virtqueue *_vq,
* new available array entries. */
virtio_wmb(vq->weak_barriers);
vq->split.avail_idx_shadow++;
+ {
+ if ((vq->split.avail_idx_shadow % 100) == 0)
+ printk(KERN_ERR "avail idx: %d",
+ (int)vq->split.avail_idx_shadow);
+ if (vq->split.avail_idx_shadow == 5000)
+ vq->split.avail_idx_shadow = 0;
+ }
vq->split.vring.avail->idx = cpu_to_virtio16(_vq->vdev,
vq->split.avail_idx_shadow);
vq->num_added++;
@@ -689,6 +698,11 @@ static inline int virtqueue_add_split(
struct virtqueue *_vq,
if (unlikely(vq->num_added == (1 << 16) - 1))
virtqueue_kick(_vq);
+ {
+ if (unlikely(vq->split.avail_idx_shadow == 0))
+ virtqueue_kick_always(_vq);
+ }
+
return 0;
unmap_release:
@@ -2515,6 +2529,11 @@ bool virtqueue_kick(struct virtqueue *vq)
}
EXPORT_SYMBOL_GPL(virtqueue_kick);
+void virtqueue_kick_always(struct virtqueue *vq)
+{
+ virtqueue_kick_prepare(vq);
+ virtqueue_notify(vq);
+}
/**
* virtqueue_get_buf_ctx - get the next used buffer
* @_vq: the struct virtqueue we're talking about.
--------------- END OF LINUX KERNEL PATCH ----------
Then the kernel was booted, and the host pinged until the
nic became unresponsive:
ping -i 0.002 192.168.4.1
Device status was confirmed using
cat /sys/class/net/eth0/device/status
(it was 0x4f).
Then the device was re-initialized:
DEV_NAME=$(basename $(readlink -f /sys/class/net/eth0/device))
echo $DEV_NAME | tee /sys/bus/virtio/drivers/virtio_net/unbind
echo $DEV_NAME | tee /sys/bus/virtio/drivers/virtio_net/bind
ip link set eth0 up
At this point networking became healthly again.
Signed-off-by: Peter Oskolkov <posk@google.com>
Add UFFD restore tests to common_sequential: basic anonymous RAM,
shared memory, and hugepage-backed zone memory. Each exercises the
full snapshot/restore cycle with memory_restore_mode=ondemand and
verifies CPU count, memory size, and device health after resume.
Signed-off-by: Shayon Mukherjee <shayonj@gmail.com>
When memory_restore_mode=ondemand is specified on the restore command,
the memory manager creates a userfaultfd descriptor, registers each
guest RAM range for missing-page fault interception, and spawns a
handler thread that serves page faults from the snapshot file using
UFFDIO_COPY. This avoids reading the entire memory-ranges file into
guest RAM before restore completes.
The handler uses epoll to multiplex the userfaultfd and a stop eventfd
for clean shutdown. Concurrent faults from multiple vCPUs are handled
by treating EEXIST as a benign race and waking blocked threads with
UFFDIO_WAKE. Once all pages have been served the handler exits
automatically. If the handler thread panics the VMM is signalled to
exit since the VM cannot continue without page fault service.
MemoryZone gains a backing_page_size field so the handler resolves
fault granularity from the zone rather than the top-level config.
Errors from the UFFD setup path use a structured UffdError enum
and a new MigratableError::OnDemandRestore variant, with a From
impl to keep call sites concise.
The seccomp filter is updated to allow the userfaultfd syscall and
the four uffd ioctls (UFFDIO_API, UFFDIO_COPY, UFFDIO_REGISTER,
UFFDIO_WAKE) under the VMM thread profile.
Signed-off-by: Shayon Mukherjee <shayonj@gmail.com>
Add a MemoryRestoreMode enum (Copy | OnDemand) to RestoreConfig so
the restore path can be selected at restore time. Copy preserves the
existing eager read-copy behavior. OnDemand enables userfaultfd-based
demand paging and fails restore if the kernel does not support it.
Validate that prefault=on is not combined with OnDemand mode.
Update the OpenAPI spec with the new enum field.
Signed-off-by: Shayon Mukherjee <shayonj@gmail.com>
Add safe Rust wrappers around the raw userfaultfd ioctls: create
(syscall + API handshake), register (missing-page mode), copy
(resolve fault), and wake (unblock threads after EEXIST race).
These are used by the demand-paged snapshot restore handler in a
subsequent commit.
Signed-off-by: Shayon Mukherjee <shayonj@gmail.com>
Add a small constants module with the ioctl numbers and protocol
constants needed for userfaultfd-based demand-paged snapshot restore.
These are derived from the kernel's include/uapi/linux/userfaultfd.h.
Signed-off-by: Shayon Mukherjee <shayonj@gmail.com>
Emit a "vm.migration-memory-iteration" event after every precopy memory
iteration to allow management software to observe forward progress
during migration.
This event is primarily intended for integration with management
software such as libvirt, where it maps to
VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION.
The event is intentionally independent of any upcoming migration
metrics endpoint. Detailed migration statistics will be exposed via
that endpoint, while this event provides a lightweight progress signal
expected by external management layers.
With this event, management software can detect forward progress during
migration without being blocked on any upcoming migration metrics
endpoint.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Add infrastructure to collect metrics during precopy memory migration
iterations.
For each iteration we now track transferred bytes, duration, bandwidth,
and estimate the expected downtime based on the remaining memory of the
current iteration and measured bandwidth. These metrics are logged and
used to decide when to stop the precopy phase.
This also introduces basic termination conditions such as:
- maximum number of iterations
- reaching a target downtime
- maximum migration duration
This is the fundament for an upcoming API call to publicly export
statistics about an ongoing live migration. The changes are, however,
self-contained and helpful by themselves.
The new log now looks somewhat as in the following, providing lots of
helpful insights (especially the bandwidth and estimated downtime are
helpful). The metrics were measured with CHV build with `--release`, a
VM under heavy load (lots of memory writes), same-host TCP
migration and prefault=on:
```
cloud-hypervisor: 12.702682s: <vmm> DEBUG:vmm/src/lib.rs:1313 -- Precopy: iter=0 total=6144MiB curr=6144MiB bw=1986.83MiB/s transfer=3.09s overhead=0ms est_downtime=0ms elapsed=3.11s avg_bw=1975.41MiB/s
cloud-hypervisor: 15.728419s: <vmm> DEBUG:vmm/src/lib.rs:1313 -- Precopy: iter=1 total=11562MiB curr=5418MiB bw=1824.44MiB/s transfer=2.97s overhead=56ms est_downtime=2726ms elapsed=6.14s avg_bw=1884.21MiB/s
cloud-hypervisor: 18.710428s: <vmm> DEBUG:vmm/src/lib.rs:1313 -- Precopy: iter=2 total=16980MiB curr=5418MiB bw=1854.25MiB/s transfer=2.92s overhead=59ms est_downtime=2969ms elapsed=9.12s avg_bw=1862.17MiB/s
cloud-hypervisor: 21.783699s: <vmm> DEBUG:vmm/src/lib.rs:1313 -- Precopy: iter=3 total=22407MiB curr=5428MiB bw=1799.43MiB/s transfer=3.02s overhead=56ms est_downtime=2926ms elapsed=12.19s avg_bw=1837.92MiB/s
cloud-hypervisor: 25.785696s: <vmm> DEBUG:vmm/src/lib.rs:1313 -- Precopy: iter=4 total=27825MiB curr=5418MiB bw=1375.53MiB/s transfer=3.94s overhead=62ms est_downtime=3010ms elapsed=16.19s avg_bw=1718.26MiB/s
cloud-hypervisor: 29.000349s: <vmm> DEBUG:vmm/src/lib.rs:1313 -- Precopy: iter=5 total=33243MiB curr=5418MiB bw=1727.60MiB/s transfer=3.14s overhead=78ms est_downtime=3938ms elapsed=19.41s avg_bw=1712.82MiB/s
cloud-hypervisor: 32.215805s: <vmm> DEBUG:vmm/src/lib.rs:1313 -- Precopy: iter=6 total=38671MiB curr=5429MiB bw=1724.03MiB/s transfer=3.15s overhead=66ms est_downtime=3142ms elapsed=22.62s avg_bw=1709.33MiB/s
cloud-hypervisor: 32.275215s: <vmm> DEBUG:vmm/src/lib.rs:1286 -- Precopy converged: iter=7 total=38671MiB curr=5418MiB bw=1720.46MiB/s transfer=3.15s overhead=66ms est_downtime=3142ms elapsed=22.68s avg_bw=1704.85MiB/s
...
cloud-hypervisor: 33.411682s: <vmm> INFO:vmm/src/lib.rs:1365 -- Precopy complete: iter=8 total=44339MiB curr=5668MiB bw=1799.98MiB/s transfer=3.15s overhead=66ms est_downtime=3142ms elapsed=23.82s avg_bw=1861.45MiB/s
```
# Outlook
We can add user-configurable downtimes and migration downtimes next.
These changes are inspired by [0] but differ significantly in details.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7033
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Introduce MemoryMigrationContext to track internal metrics of an ongoing
precopy memory migration.
The context aggregates information such as iteration count, transferred
bytes, durations, bandwidth, and estimated downtime. This enables
migration logic to make decisions based on runtime characteristics,
such as terminating iterations once the expected downtime is below a
target threshold.
The type is used in the next commit to implement iteration-based
migration metrics.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Refactor the precopy memory migration path into dedicated helpers that
handle the different migration phases:
- initial full memory transfer
- repeated dirty-page iterations while the VM is running
- final iteration after the VM is paused
This separates concerns in the migration code and provides the
infrastructure needed for collecting migration metrics in the following
changes.
These changes are inspired by [0] but differ significantly in details.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7033
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Lower several informational messages in the dirty logging path to
debug level.
These messages are noisy in practice and provide little value since
dirty logging is known to work reliably. More useful migration metrics
(e.g., dirty size per iteration) is logged per iteration in subsequent
commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Emit migration lifecycle events via the event monitor.
This aligns migration with other VM lifecycle operations such as boot,
pause, and resume, allowing external management software to observe
migration progress consistently.
Events emitted:
src:
vm.migration-started
vm.migration-finished
vm.migration-failed
dst:
vm.migration-receive-started
vm.migration-receive-finished
vm.migration-receive-failed
Please note that these features are independent of an upcoming new
endpoint to fetch migration statistics.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Currently, it is not possible to migrate a paused VM. It fails with
the following error:
```
[2026-03-09T14:43:42Z ERROR cloud_hypervisor] Fatal error: HttpApiClient(ServerResponse(InternalServerError, Some("[\"Error from API\",\"Error starting migration sender\",\"Failed to pause migratable component\",\"Invalid transition: InvalidStateTransition(Paused, Paused)\"]")))
Error: ch-remote exited with the following chain of errors:
0: http client error
1: Server responded with InternalServerError
2: Error from API
3: Error starting migration sender
4: Failed to pause migratable component
5: Invalid transition: InvalidStateTransition(Paused, Paused)
```
and even worse, after that, the VM is resumed on the source!
Make the behavior explicit by only allowing migration of VMs in the
Running state. This avoids unintended state transitions during
migration and clarifies the current expected semantics.
Future work could extend the migration protocol to work with paused VMs
and preserve the VM runtime state, allowing paused VMs to be migrated
without altering their state.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Move the error branch to the top and remove unnecessary nesting in
send_migration().
This change is purely mechanical and introduces no functional changes.
It simplifies the control flow and prepares the code for the following
migration-related improvements in this series.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
The rate limiter tests create raw block images with dd but do not
specify image_type=raw. Without it the VMM autodetects the format
and enables sector 0 write protection for unknown image types,
causing I/O errors when fio writes to sector 0 and making the
test hang until timeout.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Confidential VMs require additional time during boot to load the IGVM
image, complete page measurements, and perform Reverse Map Table (RMP)
validation. In addition, PSP latency can further delay the boot
process. Extend the test timeout to accommodate these additional
initialization steps.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
- Modified the integration test script to support CVM test threads
- Add more parameters to cargo nextest to match other files
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Moves the MSRV requirement to the workspace and expands it to all
cloud-hypervisor dependencies and dev-dependencies.
This improves discoverability for new contributors working on crates
other than the cloud-hypervisor itself and creates consistency regarding
the MSRV of cloud-hypervisor dependencies.
Functionally, this doesn't change anything for dependencies of the
cloud-hypervisor crate as the MSRV requirement is already enforced by CI
when building the cloud-hypervisor with the MSRV versioned compiler.
On-behalf-of: SAP julian.schindel@sap.com
Signed-off-by: Julian Schindel <julian.schindel@cyberus-technology.de>
Remove the architecture check that prevented nested virtualization
control on arm64 and riscv64. This allows nested virtualization to
be disabled where supported, particularly when using MSHV.
Note that on arm64 disabling nested virtualization may not fully
disable the capability depending on the underlying platform.
Use of this functionality is left to the user's discretion.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
With `.num_args(1..)`, multiple values can be specified for a CLI
option, but the option cannot be specified more than once. In my
experience, it’s more common to specify flags with a single argument
multiple times to specify multiple arguments. One might thus expect to
call cloud-hypervisor with e.g. `--disk path=foo --disk path==bar`.
With this commit, both `--disk path=foo path=bar path=baz` and
`--disk path=foo -disk path=bar path=baz` (note: combinations as well)
are allowed.
Signed-off-by: Sebastian Walz <sebastian.walz@secunet.com>
The pointer created by `Vec::as_ptr` may not be used for mutation of the
underlying data [0].
This PR switches to `Vec::as_mut_ptr` and uses `cast` to avoid
mutability changes when casting.
Also improves safety reasoning, separates the unsafe call from the
call to `read_exact` to improve clarity and simplifies the vector
creation.
[0]: https://doc.rust-lang.org/alloc/vec/struct.Vec.html#method.as_ptr
On-behalf-of: SAP julian.schindel@sap.com
Signed-off-by: Julian Schindel <julian.schindel@cyberus-technology.de>
Switch l2_table(), refcount_block(), and first_zero_refcount()
to BlockResult. These are public inspection helpers with no
callers within the crate.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch the public convert() entry point to BlockResult. Inner
calls to functions already returning BlockResult propagate
naturally; those still returning qcow::Error get map_err
bridges.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch convert_reader() to BlockResult, preserving the original
qcow::Error variants as the BlockError source. The inner
convert_reader_writer() call now propagates naturally. Callers
get map_err bridges where they still return qcow::Error.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch convert_reader_writer() to BlockResult, preserving the
original qcow::Error variants as the BlockError source. The
inner convert_copy() call now propagates BlockResult naturally.
Callers get map_err bridges where they still return qcow::Error.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch convert_copy() to BlockResult, preserving the original
qcow::Error variants as the BlockError source for diagnostics.
A map_err bridge at the caller converts back where needed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Switch the header dirty and corrupt bit helpers from
qcow::Result to BlockResult. Their callers either discard
the result or unwrap in tests, so no caller signatures change.
A map_err bridge in parse_qcow() converts back where needed.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a small helper in the block crate that opens a disk image
file and wraps any failure in a BlockError carrying the file
path and operation context. Use it from the vmm device manager
so that a failed open now reports which path couldn't be opened.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Extend the BackingFileIo and BackingFileOpen variants of
qcow::Error with a path field so that backing file failures
report which file was involved. The path is populated from
the backing file configuration.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Convert detect_image_type() from io::Result to BlockResult so
that I/O failures carry the operation name in the error context.
Update the corresponding vmm error variant to wrap BlockError.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Change QcowDiskSync::new() to return BlockResult instead of
qcow::Result, mapping format specific errors to the appropriate
BlockErrorKind at the crate boundary. The vmm caller attaches
the disk image path to the error so failures identify which
file was being opened.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement AsFd for both RawFile and QcowRawFile by delegating to
the inner File handle. This enables safe fd borrowing through the
standard AsFd trait, which is a prerequisite for replacing unsafe
libc::dup calls with BorrowedFd::try_clone_to_owned().
Suggested-by: Rob Bradford <rbradford@rivosinc.com>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add the public BlockResult type alias and a From<io::Error>
impl so that bare I/O errors automatically convert into
BlockError with BlockErrorKind::Io via the ? operator.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add the construction and inspection API for BlockError,
consisting on constructors that accept a kind and optional
source, builder methods that attach context after
the fact, and accessors for retrieving the kind, context,
and typed source references. The builder pattern allows
callers to enrich errors at each level of the call stack.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add the single public crate error type. It combines a
BlockErrorKind for classification, an optional boxed source
for the underlying cause, and an optional ErrorContext for
diagnostics. Display renders the kind and context only,
leaving source traversal to error reporters so the cause
chain is not duplicated in human readable output.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a struct that carries optional diagnostic metadata - file
path, byte offset, and operation name that can be attached
to any BlockError. This lets errors report *where* and *during
what* a failure occurred, which is especially useful when the
same I/O kind shows up at multiple call sites.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a small, stable enum that classifies block errors into
broad categories - I/O, invalid format, unsupported feature,
corrupt image, out of bounds, not found, overflow. Callers
match on this for control flow rather than on format specific
error variants.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce error.rs as the home for a unified error hierarchy that
will replace the per format error types at the public crate
boundary. This commit is intentionally empty beyond the copyright
header and module declaration in lib.rs.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The AIO block backend advertises VIRTIO_BLK_F_WRITE_ZEROES
and VIRTIO_BLK_F_DISCARD to guests because the filesystem
probe (supports_sparse_operations) returns true on ext4/XFS.
However, RawFileAsyncAio::write_zeroes() and punch_hole()
return errors because Linux AIO (io_submit) has no IOCB
command for fallocate.
When io_uring is unavailable (e.g. io_uring_disabled=2, a
common security hardening on enterprise Linux), Cloud
Hypervisor falls back to the AIO backend. The guest
negotiates the feature, issues WRITE_ZEROES requests, and
gets I/O errors.
Implement write_zeroes and punch_hole using synchronous
libc::fallocate() calls, matching the pattern used by the
sync backend (RawFileSync). A VecDeque-based completion
list signals results to the caller via the existing eventfd
mechanism.
Unit tests mirror the existing raw_sync.rs test suite.
Integration tests add AIO-specific variants of the discard
and fstrim tests using _disable_io_uring=on.
Signed-off-by: Emir Beganovic <beganovic.emir@gmail.com>
Without it the VMM autodetects the format and logs
warnings that specifying image_type will become mandatory
for non raw images in the future.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Without explicit image_type fio first sequential write hits
sector 0 and gets VIRTIO_BLK_S_IOERR. fio then hangs, causing
block_write_MiBps and all other write tests using
BLK_IO_TEST_IMG to time out.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Flush host writeback queues, drop the page cache and sleep 1s
for kernel housekeeping before each test run.
The cloud-hypervisor block backend does buffered I/O on the host
side, so dirty pages from prior write tests can accumulate and
compete for I/O bandwidth with subsequent tests. Dropping caches
ensures cold read tests get a consistent baseline rather than
benefiting from data cached by prior tests. The brief cooldown
lets the kernel finish tearing down KVM state and freeing pages
from the previous VM before the next one starts.
Requires root, which the metrics container provides. Silently
fails otherwise.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When a test times out, the spawned thread containing the
cloud-hypervisor child process, iperf3/ethr sub processes,
and all associated resources (TAP devices, file descriptors,
hugepage reservations) is abandoned without cleanup. This
attaches a cleanup routine that kills cloud-hypervisor,
iperf3, and ethr processes on timeout, then waits
briefly for the kernel to reclaim their resources. This
prevents leaked processes from interfering with subsequent
tests.
Removes the existing TODO comment.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
We ran the Microsoft Windows installer in CHV (via network + VNC) and
the installation always failed when the installer wanted to write the
partition table. Since recently, for very good reason, sector 0 writes
are disabled if the image type is not set explicitly and only
implicitly auto-detected as raw [0].
To ease troubleshooting, I've added a descriptive log message. It is a
little spammy, but it is what is required to help users to troubleshoot.
[0] 6ecdf90e22
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This makes it clearer that these are enums that can be reused and also
helps generation by providing names for those types.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Signal the guest before processing queue submissions to enable
earlier guest side completion event handling, reducing end-to-end
latency for block device operations.
FIO benchmarks show up to 7.4% bandwidth improvement at 16
iodepth and 4k block size with NVMe devices.
Signed-off-by: wuxinyue <wuxinyue.wxy@antgroup.com>
Since the project claims to follow Linux's process, update the link to
point to Linux's process, instead of relying on an archived page which
contains outdated information.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Replace the clone based BackingFileOps trait with a BackingKind enum
so backing files can be decomposed into their concrete owned types.
BackingFile::new() for QCOW2 backings now calls parse_qcow() directly
instead of building a full QcowFile. Remove Clone for BackingFile and
QcowFile.
Prerequisite for the qcow_sync rewrite which decomposes a BackingFile
into a raw fd or QcowMetadata for lock free I/O.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add resize() and grow_l1_table() so the metadata layer can grow
the virtual disk size. Only grow is supported.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce QcowMetadata, a thread safe wrapper around QCOW2 metadata
tables and caches using RwLock.
Provides cluster resolution for reads and writes, and deallocate
operations for discard.
Extract parse_qcow() from QcowFile so both QcowFile and QcowDiskSync
can share the parsing and validation logic.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move L1 and L2 table entry helpers, division utilities and related
constants from mod.rs into a dedicated util.rs submodule. Both
mod.rs and metadata.rs import from util.
No functional changes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move QcowHeader, associated types, constants and helper functions
into a new header.rs submodule. Public types are re-exported from
mod.rs.
No functional changes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Both process_input_queue and process_output_queue were only processing
the first descriptor of a chain, leading to data loss if the driver used
chained descriptors.
This change iterates through all descriptors in a chain. It also moves
the flush call out of the descriptor loops to improve performance.
Signed-off-by: Andrei Vagin <avagin@google.com>
For a transmit queue (guest to host), the host only reads from the
guest-provided buffers and does not write to them. According to the
virtio specification (e.g., Section 2.6.8 in Virtio 1.1), the 'len'
field in the used ring has to be set to the number of bytes written to
the buffers. Therefore, it should be 0 for the console transmit queue.
Signed-off-by: Andrei Vagin <avagin@google.com>
The update_console_size method was using fetch_and on the acked_features
atomic, which modified the atomic and cleared other feature bits.
Changed it to use a non-destructive load and bitwise AND.
Signed-off-by: Andrei Vagin <avagin@google.com>
Add docs/disk_locking.md explaining advisory OFD locking, the
lock_granularity parameter, byte-range vs whole-file semantics,
and fallback behavior.
Signed-off-by: Victor Vieux <vieux@repl.it>
Add a per-disk lock_granularity parameter that lets users choose
between byte-range OFD locks and whole-file OFD locks:
--disk path=/foo.img,lock_granularity=byte-range
--disk path=/bar.img,lock_granularity=full
Byte-range is the default and matches QEMU behavior, working
best with storage backends where whole-file OFD locks are treated
as mandatory. The full option restores the original whole-file
locking for environments that depend on it.
The LockGranularityChoice enum and its FromStr impl live in the
block crate alongside the existing LockGranularity type. The
Block device converts the user-facing choice to the internal
LockGranularity at lock time, keeping device_manager.rs simple.
Closes: #7553
Signed-off-by: Victor Vieux <vieux@repl.it>
Rename the transport feature bit constant from
VIRTIO_F_IOMMU_PLATFORM to VIRTIO_F_ACCESS_PLATFORM across
the entire virtio-devices crate.
The virtio specification as of v1.1 carries bit 33 as
VIRTIO_F_ACCESS_PLATFORM. The Linux kernel UAPI header
<linux/virtio_config.h> carries VIRTIO_F_IOMMU_PLATFORM
only as a backward-compatible alias.
This is a pure rename with no functional or behavioral
change.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Device ID 35 for virtio watchdog was officially allocated and
merged into the Linux kernel UAPI headers as VIRTIO_ID_WATCHDOG
in kernel 5.15. The virtio specification v1.2 also lists device
ID 35 for the watchdog device type. Leaving the comment is
therefore misleading.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Fix the _reserved field in VirtioIommuConfig from [u8; 7] to
[u8; 3], correcting the struct size from 44 bytes to the
spec-mandated 40 bytes.
The virtio specification v1.2, Section 5.13.4 defines struct
virtio_iommu_config as 40 bytes total.
The kernel UAPI header linux/virtio_iommu.h matches this
layout with __u8 reserved[3] since kernel 5.17. Prior to that,
the struct was 36 bytes with no bypass field at all.
The incorrect [u8; 7] made the packed struct 44 bytes. Since
the struct is exposed to the guest, the guest saw a 44 byte
device specific configuration region instead of 40 bytes.
While well behaved guest drivers only access fields at known
offsets and would not observe data corruption from the extra
4 zero bytes at the tail, the oversized config region is a
spec violation.
The write_config path is not affected because it validates
the exact offset of the bypass field before allowing writes,
and the bypass field sits at offset 36 regardless of the
trailing reserved size.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
It makes most sense to create the epoll FD and add the kill event before
identifying the transport specific fd.
Signed-off-by: Rob Bradford <rbradford@meta.com>
This is not just used for determine the output but also the input to the
console where this can be bidirectional.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The nightly compiler used by cargo fuzz no longer requires unsafe
for __cpuid intrinsics, but stable still does.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The variant has been unused since commit 12e20effd which
replaced direct QcowFile creation with QcowDiskSync.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Since we run integration tests on Intel & AMD this should test the
behaviour of `--cpus nested={on|off}` correctly.
Signed-off-by: Rob Bradford <rbradford@meta.com>
The loop that is for programming the APIC ID and disabling nested
virtualization was prematurely breaking out on AMD platforms as the 0x1
leaf is also valid on AMD. This lead to the code attempting to disable
SVM in the 0x8000_0001 leaf never being reached.
Now only break out early if the CPU vendor is Intel.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add test_api_http_shutdown and test_api_http_delete to the
common_cvm module using GuestFactory with 4 CPUs. Both tests
reuse existing _test_api_shutdown and _test_api_delete helpers
to extend API coverage to confidential VMs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace manual Guest field assignments with
GuestFactory::new_confidential_guest_factory() in
test_focal_simple_launch for consistent CVM guest creation.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add test_api_http_create_boot to the common_cvm module using
GuestFactory::new_confidential_guest_factory() with 4 CPUs.
This extends API create/boot coverage to confidential VMs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Refactor api_create_body() to read cpu_count, kernel_path,
and kernel_cmdline from Guest fields instead of taking them
as parameters. This makes Guest the single source of truth
for VM configuration.
Update all call sites in HTTP and DBus API tests to use the
new parameterless signature. Switch guest creation to use
GuestFactory for consistent 4-CPU configuration.
Replace manual CPU and memory assertions with
validate_cpu_count() and validate_memory() helpers.
Replace thread::sleep with wait_vm_boot() in
_test_api_create_boot for proper boot synchronization.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Refactor api_create_body() to branch based on GuestVmType.
For confidential VMs, the JSON body now includes:
- platform config with sev_snp enabled
- IGVM payload with host_data instead of kernel
- nested virtualization disabled in CPU config
Replace the monolithic format! macro with incremental
push_str calls for clearer JSON construction.
Also improve error handling in GuestCommand by replacing
an unwrap() with a descriptive expect() on the IGVM path.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Introduce GuestFactory struct that encapsulates GuestVmType,
boot timeout, and nested virtualization defaults. This avoids
repeatedly specifying VM type and associated defaults when
constructing Guest instances in integration tests.
Two factory constructors are provided:
- new_regular_guest_factory: default timeout, nested enabled
- new_confidential_guest_factory: CVM timeout, nested disabled
Multiple create_guest variants allow customizing CPU count,
memory size, and nested virtualization while inheriting the
factory's VM type and timeout settings.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Initialize kernel_path and kernel_cmdline with standard
direct boot defaults in the Guest constructor instead of
None. This removes boilerplate from individual tests that
use the common direct kernel boot configuration.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move test constants (MAX_NUM_PCI_SEGMENTS,
DIRECT_KERNEL_BOOT_CMDLINE, CONSOLE_TEST_STRING),
arch-specific image name modules (x86_64, aarch64),
and helper functions (direct_kernel_boot_path, edk2_path)
from integration.rs to test_infra/src/lib.rs.
This centralizes shared test definitions so they can be
reused across multiple test crates instead of being
confined to integration.rs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Boot a VM with a 4k sector loop device passed with direct=on and
image_type=raw. Assert that the guest sees a 4096 byte logical
sector and that a DIO write/read roundtrip at 4096 byte alignment
succeeds.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that DiskTopology::probe() returns the correct DIO alignment
for a regular file on a 4k sector filesystem. The test creates a
loop device with --sector-size 4096, formats ext4, places a raw disk
image on it, and boots a VM with direct=on. Asserts that the guest
sees a 4096 byte logical sector and that a DIO write/read roundtrip
succeeds.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Move LOOP_CTL_GET_FREE + open + LOOP_CONFIGURE into the retry loop
so each attempt requests a fresh free device number. Previously, a
parallel test could claim the same device between GET_FREE and
CONFIGURE, and retrying the same stale number would always fail with
EBUSY.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Test valid power of two alignment, layout compatibility,
direct helper coverage, and O_DIRECT write/read roundtrip.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
DiskTopology::probe() returned a hardcoded 512 for regular files,
causing O_DIRECT failures on volumes with larger block sizes
(e.g. 4K).
Use statx(STATX_DIOALIGN) (Linux >= 6.1) to query the real per file
DIO memory and offset alignment. Unlike fstatvfs().f_bsize, which
only returns the filesystem preferred I/O block size,
STATX_DIOALIGN reports the true DIO constraints accounting for the
filesystem, underlying block device, and any stacking (loop, dm,
etc.).
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Nightly rustfmt now prefers `self` re-exports inline rather
than a separate 'pub use {kvm_bindings, kvm_ioctls}' line.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Avoid a potential infinite loop where if the leader fails to create a
cookie due to an unexpected error (not one of the SMT/no kernel support
errors) then the other vcpu threads will continue around their
spinloops.
This change also clarifies the state machine for the leader election
with an explicit enum.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Drop an unused vm_memory::GuestAddress import from common_cvm
in integration tests to keep the module clean.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace hard-coded --memory size=512M args with default_memory()
across integration tests to centralize default memory settings.
This reduces duplicated CLI fragments and keeps behavior consistent.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace hard-coded --cpus boot=<n> arguments in integration tests
with GuestCommand::default_cpus() for shared, centralized defaults.
This removes duplicated CLI fragments and keeps CPU setup consistent.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace the hard-coded memory threshold check in the simple launch
integration test with Guest::validate_memory(None).
Add Guest::get_expected_memory() to derive thresholds from mem_size_str
and vm_type, and reuse this through validate_memory().
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace hard-coded --memory args in simple launch tests
with GuestCommand defaults driven by Guest state.
Add Guest.mem_size_str with a default of 512M and introduce
default_memory_string() and GuestCommand::default_memory().
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Instead of validating number of CPU in the test case itself,
moving the checking of the CPU count to Guest struct with a
new function as The Guest already has the Default CPU number.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Replace the hard-coded .args(["--cpus", "boot=1"]) in the simple
launch integration test with a shared helper (default_cpus) from test
infrastructure.
Extend Guest with explicit CPU-related defaults (num_cpu, nested)
and add default_cpus_string() so CPU configuration is derived from
guest state instead of being duplicated at call sites.
This refactor improves consistency and makes CPU defaults easier to
maintain across integration tests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Move MetaEvent from the integration test into shared test infrastructure
and expose it for reuse. Add a Guest helper that returns the expected
sequential events for simple launch, and update the integration test to
consume this helper instead of maintaining a local event list.
Adjust expected behavior for confidential VMs by omitting the disk reset
event, which is not guaranteed to be emitted in that mode. Preserve the
existing expected sequence for non-confidential VMs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The SYNTAX help string for --net was missing a comma between
pci_segment and offload_tso parameters, making the help output
show them as a single run-on token.
Signed-off-by: Victor Vieux <vieux@repl.it>
O_DIRECT requires buffer addresses to be aligned to the backend
device's logical block size. The existing bounce buffer logic in
execute_async() hardcodes SECTOR_SIZE (512) for the alignment check
and bounce buffer allocation. This is insufficient for devices with
a 4096-byte logical block size, where misaligned buffers cause
-EINVAL from the host kernel.
Add an alignment() method to the AsyncIo trait that returns the
backend's logical block size, defaulting to SECTOR_SIZE. The three
raw I/O backends (io_uring, AIO, synchronous) probe the device
topology via DiskTopology::probe() at creation time and return the
actual logical block size. All image format backends would simply
use the default value of 512 bytes since their underlying are
not block devices.
execute_async() now queries disk_image.alignment() instead of using
the hardcoded SECTOR_SIZE
Fixes: #7720
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Add a core_scheduling option to --cpus with three modes of operation.
This feature takes advantage of a kernel feature that restricts
scheduling of processes on the SMT threads on the same core. This is
useful for mitigating certain classes of side-channel attacks and has
better performance that disabling SMT on the CPU.
- vm (default): All vCPU threads share one core scheduling cookie.
They may be co-scheduled on SMT siblings while host threads are
excluded - this has minimal performance impact and can even
potentially improve performance from co-location.
- vcpu: Each vCPU gets a unique cookie preventing any two vCPUs from
sharing SMT siblings. This has the strongest isolation but at some
compromise of performance.
- off: No core scheduling applied (old behaviour).
This isolation is done by the kernel maintaining a "cookie" - threads
with the same cookie can share the same core.
In vCPU mode each vCPU thread the cookie is created when the thread
starts and each gets a unique cookie. For VM mode the first vCPU thread
(the leader) will create the cookie. All other vCPU threads started (via
hotplug or during boot) will have that cookie shared to it.
EINVAL/ENODEV from prctl is silently ignored so this works transparently
on kernels older than 5.14 that lack PR_SCHED_CORE or when SMT disabled.
Full details of this kernel feature can be found at:
https://docs.kernel.org/admin-guide/hw-vuln/core-scheduling.html
This implementation was inspired by crosvm's implementation - in
particular the enable_core_scheduling() function.
This is challenging to test via integration testing but the logging of
the received cookie shows it working:
VM case:
cloud-hypervisor: 0.243102s: <vcpu1> INFO:vmm/src/cpu.rs:1247 -- vCPU 1: core scheduling cookie = 0x33e4c167
cloud-hypervisor: 0.243102s: <vcpu0> INFO:vmm/src/cpu.rs:1247 -- vCPU 0: core scheduling cookie = 0x33e4c167
vCPU case:
cloud-hypervisor: 0.089356s: <vcpu0> INFO:vmm/src/cpu.rs:1247 -- vCPU 0: core scheduling cookie = 0x13993ad6
cloud-hypervisor: 0.089380s: <vcpu1> INFO:vmm/src/cpu.rs:1247 -- vCPU 1: core scheduling cookie = 0xd48e86e
Signed-off-by: Rob Bradford <rbradford@meta.com>
The current implementation performs multiple operations on allocators in
a row, with the single goal of updating the allocator. For each of these
operations, the `Mutex` guarding the respective allocator is locked anew
which introduces room for race conditions.
Instead of locking the mutex multiple times, we should lock it once to
perform the whole move.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
Vm::create_device_manager accepted both config and _vm_config, but
both represented the same VM configuration source. Remove _vm_config
from the function signature and from its call site, and use config
for the TDX dynamic check.
This is a cleanup-only refactor with no intended functional change.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
There is no non destructive readonly ioctl to query block device
discard or write zeroes capabilities. BLKZEROOUT is guaranteed to
succeed via kernel software fallback. BLKDISCARD may fail at runtime
with EOPNOTSUPP on devices that lack trim support, but the error
propagates to the guest as VIRTIO_BLK_S_IOERR and well behaved
guests handle it gracefully.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The Windows tests use a DM snapshot device for the OS disk.
DM snapshot targets do not support BLKDISCARD, so the VMM returns
IOERR for every TRIM attempt. viostor.sys may BSOD when the host
returns an error for negotiated discard/write-zeroes operations.
Add a default_disks_sparse_off() helper to GuestCommand and use it
in all Windows tests.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that the guest remains stable when BLKDISCARD fails on the
host backend. DM snapshot targets do not support discard, so the
VMM returns VIRTIO_BLK_S_IOERR. The test retries blkdiscard several
times, checking guest responsiveness after each attempt, then
confirms normal I/O still works.
The DM topology follows the same pattern used by WindowsDiskConfig.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify that a loopback block device advertises
VIRTIO_BLK_F_DISCARD to the guest and that blkdiscard succeeds.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Extend run_qemu_img() with an optional trailing_args parameter
for arguments that follow the image path, such as the size in
'qemu-img create -f raw <path> 128M'.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Some virtio devices cannot be implemented via vhost-user because they
require tight integration with the VMM. This includes the IOMMU and
watchdog devices.
An attempt to create a generic vhost-user device with one of these IDs
is always either a bug or human error. To aid debugging, return a
helpful error message rather than silently continuing.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
This implements a generic vhost-user device. All information about this
device must be provided to Cloud Hypervisor via the command-line or API.
The main use-case is types of vhost-user devices Cloud Hypervisor
doesn't know about, but it can also be used for types it does know
about.
The generic device delegates all configuration space handling to the
backend. This means that the vhost-user backend must support
configuration space access. It also means that the backend has control
of configuration space. For instance, this means that setting the tag
of a virtio-fs device on the virtiofsd command line works as expected.
If the VM is snapshotted or migrated, the backend must write the
configuration space to a separate save file or migration stream.
Similarly, if the VM is restored or migrated, the backend must read the
configuration space from a separate save file or migration stream.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Wrap the Vhdx instance in Arc<Mutex<>> so that all queues share
a single mutex-protected backend, matching the approach already
used for QCOW2.
Vhdx::clone() uses dup() which shares the kernel file description
including the file offset. With multiple queues performing
concurrent seek+read/write on the shared offset, I/O operations
race and corrupt data.
Fixes: #7665
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Accept arguments after -- in 'dev_cli.sh shell' and forward them
to 'bash -c' inside the container. When no arguments are given,
an interactive shell is started as before. This enables running
one-off commands in the CI container without an interactive session,
for example:
./scripts/dev_cli.sh shell -- rustup toolchain install nightly \&\& cargo +nightly fmt --all -- --check
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
As well as rejecting writes to sector 0 in the case of raw files where
the user hasn't specified the image_type also reject virtio requests of
type discard and write_zeroes.
Signed-off-by: Rob Bradford <rbradford@meta.com>
If the disk image was autodetected to raw (not specified with image_type
= 0) then in the virtio-block subsystem generate errors for writes to
block 0 (treat as if read-only). This gives an immediate error vs using
the image implementations in the block subsystem.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Add an image_type to DiskConfig to specify the image type. If none is
specified autodetect the image type but disable potentially unsafe
behaviour in the QCOW2 backend by disabling the backing file support.
If the image type is autodetected then fix it in the config so that it
will be persistant across reboots and migrations/snapshot & restores.
This also handles the case where the image type was not specified as
part of the disk configuration.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Verify that opening a QCOW2 image with a backing file reference
through QcowDiskSync with backing_files=off produces the user-facing
BackingFilesDisabled error rather than MaxNestingDepthExceeded.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When a QCOW2 image has a backing file but backing_files=on is not set,
the error was MaxNestingDepthExceeded which gives no indication that
this is a policy decision or how to resolve it.
Add a BackingFilesDisabled error variant whose message indicates that
backing file support is disabled and references the backing_files
option. The translation from MaxNestingDepthExceeded to
BackingFilesDisabled happens at the QcowDiskSync boundary where the
policy decision is made, preserving the original error for genuine
recursive depth exhaustion.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The 0.6.7 version of the mshv crates introduced a new version of
make_default_partition_create_arg inside `struct Mshv`. This version
queries the available processor features on the host and gives the same
feature set to the guests.
Move Cloud Hypervisor to this new function.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
test_guest_numa_generic_initiator was missing the #[test] attribute and
did not match the VFIO CI filter pattern "vfio::test_nvidia"
Add #[test] and rename to test_nvidia_guest_numa_generic_initiator so
the existing CI infrastructure picks it up on the vfio-nvidia runner.
Fixes: #7718
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
The device_id field was added to both NumaConfig and NumaNode as part
of the Generic Initiator support, but create_numa_nodes() change
was missed when the commits were reorganized.
As a result, node.device_id is never propogated from the config to
the runtime node and the ACPI SRAT Type 5 (Generic Initiator Affinity)
entries were never emitted.
Add the missing propogation so that create_srat_table() can resolve
the device and emit the correct affinity structure
Fixes: #7717
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Add performance tests for standalone qcow2 images without backing
files - uncompressed, zlib and zstd compressed. Each variant
includes single queue and multiqueue tests for sequential
read, random read and warmed up sequential read.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add multiqueue num_queues=4 performance tests for qcow2 overlay
images with both qcow2 and raw backing files - sequential read,
random read, and warm read variants.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The backing_files option defaults to false, so qcow2 overlay
tests fail with MaxNestingDepthExceeded. Pass backing_files=on
when the test file is an overlay.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The focal image checksums have been moved in the -common
sha1sums file. Use the correct file for metrics.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Unlike most virtio feature bits, VIRTIO_BLK_F_RO is not optional.
It indicates that the host is refusing to permit write operations, and
the guest must not be allowed to override it.
However, the block device currently does not enforce this. If the guest
does not negotiate VIRTIO_BLK_F_RO, the block device will think the
device is writable and forward write requests to the backend.
This is not a security problem right now because the backing device of a
read-only device is always opened read-only. The kernel will thus
reject the write operations with EBADF. If support is added for
receiving the backing device file descriptor via SCM_RIGHTS (#7704),
it will be possible to have a read-only block device backed by a
writable file descriptor. This would make the bug a genuine security
vulnerability.
Fix the bug by explicitly checking if VIRTIO_BLK_F_RO was offered but
not negotiated. In this case, log a warning and proceed as if the guest
did acknowledge the feature. This always indicates a guest driver bug.
Fixes: #7697
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
OVMF sends FLUSH requests to read-only virtio-block devices. Refusing
these requests prevents OVMF from accessing the EFI System Partition and
therefore makes VMs unable to boot. Accept these requests instead.
them.
Ignoring these requests is possible, but inconsistent with fsync(2)
which honors them.
Fixes: #7698
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Add handling for GHCB_INFO_SPECIAL_DBGPRINT VMG exit in the SEV-SNP
guest exit handler. This exit occurs when the guest sends debug print
requests through the GHCB interface.
Without this handler, SEV-SNP guests fail to boot when debug output
is triggered, such as when a debugger is attached to the guest image.
The handler acknowledges the exit without printing to avoid performance
degradation from frequent debug print requests.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The --net help text documented fd as fd=<fd1,fd2...>, but
comma-separated FD lists in option values must be bracketed to avoid
top-level option splitting.
Update NetConfig::SYNTAX to use fd=<[fd1,fd2,...]>, matching parser
behavior and existing net parsing tests:
`cargo test -p vmm test_net_parsing`
On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
Add comprehensive integration tests for DISCARD and WRITE_ZEROES:
Multiqueue stress tests verify concurrent operations across queues,
testing scattered writes with simultaneous fstrim, and write/discard
races that stress refcount table locking.
Format specific tests verify QCOW2 deallocates clusters after DISCARD,
raw files create holes using fallocate, and unsupported formats VHD
and VHDX correctly reject DISCARD requests.
Tests for sparse=off verify raw files preallocate full disk size and
QCOW2 uses zero flag instead of deallocating clusters.
Add helper functions to verify sparse files, count QCOW2 zero flagged
regions using qemu-img map, and verify guest reads zeros from
discarded regions.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add comprehensive tests for DISCARD and WRITE_ZEROES operations:
QCOW2 zero flag test validates the complete workflow: allocate
cluster, DISCARD it, verify reads return zeros, write new data,
verify cluster reallocated.
QcowSync tests verify punch_hole and write_zeroes with Arc<Mutex<>>
sharing, including tests for cache consistency with multiple async
I/O operations.
RawFileSync tests verify punch_hole and write_zeroes using
fallocate.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement punch_hole() and write_zeroes() for raw file backends using
io_uring and fallocate.
punch_hole() uses FALLOC_FL_PUNCH_HOLE to deallocate storage.
write_zeroes() uses FALLOC_FL_ZERO_RANGE to write zeros efficiently.
Both use FALLOC_FL_KEEP_SIZE to maintain file size.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement punch_hole and write_zeroes for QcowSync backend by
delegating to QcowFile::punch_hole which triggers cluster
deallocation. write_zeroes delegates to punch_hole as unallocated
clusters read as zeros in QCOW2.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES request types.
Parse discard/write_zeroes descriptors (sector, num_sectors, flags),
convert to byte offsets, and call punch_hole/write_zeroes on the disk
backend. Mark as unsupported in sync mode.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement DISCARD using QCOW2 zero flag (bit 0 of L2 entries) with
sparse aware behavior.
When sparse=true - fully deallocate clusters by decrementing
refcount, clearing L2 entry, and reclaiming storage via punch_hole
when refcount reaches zero.
When sparse=false - use zero flag to keep storage allocated while
marking as reading zeros. Only works when cluster is not shared.
Shared clusters are fully deallocated.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When sparse=false is configured, preallocate the entire raw disk file
at startup using fallocate(). This provides space reservation and
reduces fragmentation.
Only applies to raw disks. QCOW2/VHD/VHDX formats manage their own
allocation.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add sparse parameter to QcowFile constructors and propagate it from
device_manager through QcowDiskSync. This makes the sparse configuration
available throughout the QCOW2 implementation for controlling allocation
and deallocation behavior.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add supports_zero_flag() to DiskFile trait to indicate whether a disk
format can mark clusters/blocks as reading zeros without deallocating
storage.
QCOW2 supports this via the zero flag in L2 entries. VHDX also has
PAYLOAD_BLOCK_ZERO state for this, though it's not yet implemented in
cloud-hypervisor.
This enables DISCARD to be advertised even with sparse=false for formats
with zero-flag support, since they can mark regions as zeros (keeps
storage allocated) instead of requiring full deallocation.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add sparse boolean configuration option to DiskConfig with a default
value of true to control disk space allocation behavior.
When sparse is true, the disk uses sparse allocation where deallocated
blocks are returned to the filesystem, and the DISCARD feature is
advertised to the guest.
When sparse is false, disk space is kept fully allocated and DISCARD
is not advertised.
WRITE_ZEROES is always advertised when the backend supports it,
regardless of the sparse setting.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add capability query to DiskFile trait to check backend
support for sparse operations (punch hole, write zeroes,
discard). Only advertise VIRTIO_BLK_F_DISCARD and
VIRTIO_BLK_F_WRITE_ZEROES when the backend supports these
operations.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add functions to probe whether a file or block device actually
supports PUNCH_HOLE and ZERO_RANGE operations at runtime. The
probe is performed at file open time by testing the operations
at EOF with a zero-length range, which is a safe no-op.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add punch_hole() and write_zeroes() methods to the AsyncIo trait
with stub implementations for all backends. These will be used to
support DISCARD and WRITE_ZEROES operations.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Decompose the monolithic `new_from_memory_manager` function into
smaller, focused helper methods to improve code readability,
maintainability, and testability.
Changes:
- Extract `should_force_iommu()` to determine IOMMU requirements for
confidential computing (TDX/SEV-SNP)
- Extract `should_stop_on_boot()` to check debug pause configuration
- Extract `create_cpu_manager()` to encapsulate CPU manager creation
and CPUID population
- Extract `init_tdx_if_enabled()` for TDX-specific VM initialization
- Extract `create_device_manager()` to encapsulate device manager setup
- Extract `hypervisor_specific_init()` to orchestrate initialization
sequences for different hypervisors (KVM, MSHV, SEV-SNP)
- Extract `init_sev_snp()` for SEV-SNP confidential VM setup
- Extract `init_mshv()` for MSHV hypervisor initialization
- Extract `init_kvm()` for KVM hypervisor initialization
- Extract `create_fw_cfg_if_enabled()` for fw_cfg device creation
This refactoring replaces complex nested `cfg_if!` blocks with cleaner
conditional method calls, providing clear separation between hypervisor-
specific initialization paths while preserving existing functionality.
No functional changes intended.
Issue: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7598
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Update .lychee.toml to exclude the following patterns:
- ARM domains (developer.arm.com, infocenter.arm.com) which return 403
Forbidden due to anti-bot protections in CI.
- Local TCP addresses (192.168.1.10) which are unsupported by the
link-checker tool.
- The .lychee.toml file itself, to prevent the tool from recursively
checking its own regex exclusion patterns as valid URLs.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Document device_id parameter in NumaConfig, automatic
guest_numa_id assignment, default NUMA distances and
restrictions on Generoc Initiator NUMA nodes
Add numa configuration examples with GPU device and distance
relationships.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Add test_guest_numa_generic_initiator to validate ACPI Generic
Initiator Affinity (SRAT Type 5) support for VFIO device.
The test verifies the following :
- Guest VM boots with a VFIO device associated with a {cpu,
memort}-less NUMA node
- Guest Kernel correctly detects Generic Initiator through
ACPI tables SRAT, SLIT
- NUMA topology in the guest includes the device-only node
with correct distances
Invoked via :
./scripts/dev_cli.sh tests --integration -- --hypervisor kvm \
--test-filter test_guest_numa_generic_initiator
The test requires a real VFIO device bound to vfio-pci driver and
skips gracefully if hardware is unavailable.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Update FDT generation to skip NUMA properties when Generic Initiator
nodes are present, preventing conflicts between FDT and ACPI NUMA
information. FDT cannot represent Generic Initiator nodes, so ACPI
(via SRAT Type 5) becomes the authoritative source for the entire
NUMA topology when Generic Initiators exist.
Skip FDT numa-node-id properties in CPU and memory nodes
when Generic Initiator is present
Distance map bug fix : iterate over actual NUMA node IDs instead
of 0..len()
Use distance symmetry to derive distance when forward config is
missing
Default to distance cost 20 when neither direction specified
Only create memory nodes if NUMA node has memory region
Added unit tests
ARM64 boot protocol:
https://docs.kernel.org/arch/arm64/booting.html
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Support ACPI Generic Initiator Affinity to associate
PCI devices with NUMA proximity domains
Add GenericInitiatorAffinity struct
Add from_pci_bdf() to encode PCI Segment:Bus:Device.Function
Add from_acpi_device() for ACPI device handles (future use)
Generate SRAT Type 5 entries for nodes with device_id
Improve create_slit_table() to check distance symmetry when
forward distance is missing
Track device ID to BDF mappings in DeviceManager
Includes comprehensive unit tests
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Validate device_id in numa config is mutually
exclusive with cpus and memory_zones
Add NumaConfig::validate() and modify NumaConfig::parse()
Add ValidationError::InvalidNumaConfig for detailed error
messages
Include unit tests covering valid and invalid configs
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Add an optional device_id string field to NumaConfig for identifying
PCI devices associated with a NUMA node. This is used by the Generic
Initiator support to map devices to their proximity domain.
Update OpenAPI spec (cloud-hypervisor.yaml) to include the
new device_id field in the NumaConfig schema.
The device_id is optional and parsed from the --numa parameter:
--numa "device_id=<device_id>,distances=[...],..."
The optional field is accepted but not used.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
The documentation says guest_numa_id is required to be unique and
therefore the parser() giving default value for non-existing
guest_numa_id with .unwrap_or(0) is dangerous.
Return a validation error if guest_numa_id is not provided instead
of silently defaulting to 0.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Verify live resize of QCOW2 disks works via the API, including
resizing that requires L1 table growth.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add support for live resizing QCOW2 images. This enables growing
the virtual size of a QCOW2 disk while the VM is running.
Key features:
- Growing the image automatically expands the L1 table if needed
- Shrinking is not supported
- Resizing for images with backing files is not supported
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Provide a stub implementation for save_data_tables() to unblock pause
functionality. Without this, pausing a VM causes Cloud Hypervisor to
panic due to the unimplemented!() macro. This unblocks the
test_api_http_pause_resume testcase. We don't need to save any state
just to pause and resume.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Instead of closing a file descriptor that belongs to the vhost-user
frontend, drop the vu_common_ctrl::VhostUserHandle and the
vhost::vhost_user::Frontend it contains. This causes the destructor to
drop the file descriptor.
This breaks the last DPDK test, so disable it. See #7689.
Fixes: #7163
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
When a VFIO device with multiple MMIO regions is hot-unplugged, each
region must be individually matched and removed from the DeviceManager's
mmio_regions list. Compare per-region rather than building an aggregate
across all regions, which would never match any individual entry.
Also remove the now-unused HashSet import.
Signed-off-by: Damian Barabonkov <dbctl@pm.me>
Change has_matching_slots() to compare two MmioRegion instances
directly rather than requiring callers to construct an intermediate
HashSet of slot numbers. Remove the now-unused
user_memory_region_slots() method and HashSet import.
Signed-off-by: Damian Barabonkov <dbctl@pm.me>
Replace `clone()` with `take()` when retrieving device configurations
from `DeviceManager.config`.
This avoids unnecessarily copying the device configuration lists (e.g.,
`disks`, `net`, `fs`) when they are being processed and subsequently
moved out of the configuration. This optimization improves performance
by reducing memory allocations and cloning overhead.
Signed-off-by: Changyuan Lyu <changyuanl@google.com>
Since kernel commit 6693731487a8 ("vsock/virtio: Allocate nonlinear SKBs
for handling large transmit buffers"), a large vsock packet can be split
into multiple descriptors.
If we encounter such TX packets, pull the content into an owned buffer.
Fixes: #7672
Signed-off-by: Wei Liu <liuwe@microsoft.com>
When running manual tests locally, it is sometimes necessary to
generate a cloud-init file at a custom path instead of defaulting
to /tmp. This is useful for developers and higher-level management
layers where files in /tmp may be cleaned up automatically.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Backing files (e.g. for QCOW2) interact badly with landlock since they
are not obvious from the initial VM configuration. Only enable their use
with an explicit option.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Test reading from overlay at offsets beyond backing file returns
zeros. Covers reads within backing range, beyond backing, and
boundary spanning.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When an overlay QCOW2 image is larger than its backing file, reads
from offsets beyond the backing file virtual size would previously
fail with an I/O error.
The backing file virtual size is determined at open time and stored
for bounds checking during read operations:
- If the entire read is beyond the backing size, return all zeros
- If the read spans the boundary, read available data from backing and
fill the remainder with zeros
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Set HV_PARTITION_CREATION_FLAG_SMT_ENABLED_GUEST when the guest
topology has more than one thread per core. This allows the
hypervisor to schedule guest VPs correctly on SMT-enabled hosts.
Without this flag, the hypervisor schedules guest VPs incorrectly,
causing SMT unusable.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The kernel allows madvise on shared memory if
/sys/kernel/mm/transparent_hugepage/shmem_enabled is set.
Always try and configure THP via madvise when
the user requests THP be enabled.
If this fails, only a warning log is emitted and THP won't be enabled.
Signed-off-by: Champ-Goblem <cameron@northflank.com>
When restoring from snapshot with shared=false, write access to the
backing file is not required. Opening it read-only allows restore to
succeed on read-only media and overlay lower layers while preserving
MAP_PRIVATE semantics.
Signed-off-by: Rowen-Ye <rowenye1@gmail.com>
This patch adds the skeleton of the CVM test
support and modify existing scripts and test framework
to enable such scenario. Split the sha1sum to support both
regular and CVM guest. Add one test case for CVM. Will further
add more test cases.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
X64_64 image download steps is being used for both
regular and CVM guest. Keeping the steps withing a function
in the test-util.sh
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Now Guest struct has an option to set timeout.
No need to pass timeout while booting the guest.
If no timeout is set, default is used.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Modify Guest struct to keep some test specific
data so that test cases could be shared between
regular guest and CVM.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Testing generic vhost-user devices will require virtiofsd to support the
--tag option, which v1.8.0 does not support.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Replace generic WritingHeader error with specific SyncingHeader
error for header fsync operations. This provides more precise
error reporting when syncing QCOW2 header changes to disk fails.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Wrap QcowFile in Arc<Mutex<>> to ensure thread safety when multiple
virtio queues access the same QCOW2 image concurrently.
Previously, each queue received its own QcowSync instance via
new_async_io() that shared the underlying QcowFile through Clone.
However, cloned QcowFile instances share internal mutable state
(L2 cache, reference counts, file seek position) without
synchronization, leading to data corruption under concurrent I/O.
This change serializes all QCOW2 operations through a mutex, which
ensures correctness at the cost of parallelism. A more performant
solution would require separating metadata locking from actual I/O
operations, tracked in #7560.
Related: #7560
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
TL;DR: Would reduce CI pressure by cancelling more "unnecessary" runs
but I can't verify without running a merge queue.
A common development pattern is to push a change and then immediately
check CI results. Follow-up fix pushes are quite common, which leads to
multiple CI runs being queued for the same pull request.
In Cloud Hypervisor, the size and cost of the CI matrix means that
several consecutive pushes (for example 3-4 in a short time) put
significant pressure on CI runners and noticeably increase feedback
latency.
In practice, concurrency handling is especially tricky for the merge
queue. From personal experience: If one does not take special care, CI
runs triggered by a `merge_group` can cancel each other, as in a merge
queue there are two runs for each job by default: one for the normal PR
and one for the merge commit. This is easy to run into, also because the
available documentation and best practices for this feature are not very
good.
At the same time, our workflows do not run on `push` events, but only
on `pull_request` and `merge_group`. Because of this, using
`${{ github.ref }}` alone as a concurrency key is not very meaningful,
and in practice only few runs are actually cancelled for successive PR
updates. Therefore, we should improve the usage of this feature.
This change tries to improve the situation by refining the concurrency
group key. The goal is to keep cancellation for multiple PR pushes,
while at the same time preventing unintended cancellations in the merge
queue by separating `merge_group` runs from regular PR runs.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
In kata-containers we use the api_client crate, but it's currently
failing our cargo deny check due to missing license, and there aren't
any license files within the crate, so I haven't found a good way to
work around this.
Alternatively I'd be happy to add the license to the workspace crate
and then reference it here, but that seems to clash with the direction
of the project in #7525.
Signed-off-by: stevenhorsman <steven@uk.ibm.com>
QCOW2 v3 autoclear_features field contains bits for features whose
metadata becomes invalid when the image is modified by software that
doesn't understand them. Defined bits:
- Bit 0: Bitmaps extension
- Bit 1: Raw external data
Cloud-hypervisor doesn't support bitmaps or external data files, so
all autoclear bits are cleared on writable open. This signals other
tools that these features' data may be stale.
Readonly opens preserve autoclear bits unchanged.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This adds some missing features that are useful. In particular it adds
VIRTIO_F_RING_INDIRECT_DESC which gives a performance improvement.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Reported-by: Daniel Farina <daniel@ubicloud.com>
TDX builds its own ACPI tables in `create_acpi_tables_tdx` so it will
return None in the standard `create_acpi_tables` function and the
assertion for `rsdp_addr` will fail.
Signed-off-by: Zhibin Li <banlu.lzb@antgroup.com>
Add tests for corrupt bit behavior during I/O operations.
- Unaligned L2 table address triggers corrupt bit on read
- Unaligned cluster address triggers corrupt bit on read and write
- Normal operations do not set the corrupt bit
- V2 images work correctly without feature bits
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
MSHV doesn't present an ITS to guests. So, /proc/interrupts would never
have "ITS-PCI-MSIX".
Instead, a Gicv2m frame is presented to guests. So expect
"GICv2m-PCI-MSIX" in testcases.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Add integration tests for QCOW2 corrupt bit handling. Verify that
images with the corrupt bit set are rejected for writable access but
allowed for read-only access with a warning.
Helper functions are added to read and modify the corrupt flag in the
QCOW2 v3 header.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Validate that L2 table offsets and refcount block offsets are cluster
aligned. Set the corrupt bit when unaligned offsets are detected, as
this indicates corrupted L1 or refcount table entries.
Validate that data cluster offsets from L2 entries are cluster aligned
during both reads and writes to existing clusters. Set the corrupt bit
when unaligned data cluster offsets are detected.
Prevent allocation of clusters at offset 0, which contains the QCOW2
header and should never be allocated. This catches corruption in the
available clusters list. Set the corrupt bit when this condition is
detected.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Set the QCOW2 corrupt bit when internal inconsistencies are detected
that indicate image metadata may be corrupted:
- Decompression decode failure, meaning compressed cluster data is
invalid
- Decompression size mismatch, where decompressed data doesn't match
expected cluster size
- Partial write after decompression, where L2 table was updated but
data cluster not fully written, leaving metadata inconsistent
- Invalid refcount index, where cluster address is outside valid
refcount table range, indicating a corrupted L2 entry
- Dirty L2 with zero L1 address, where L2 table is marked dirty but
L1 has no address for it
Note: Marking decompression failures as corrupt is more conservative
than QEMU, which returns EIO without setting the corrupt bit. This is
debatable since corrupted compressed data doesn't necessarily indicate
metadata corruption, but it provides a stronger safety guarantee by
preventing further writes to potentially damaged images.
Once set, the image can only be opened read-only until repaired with
qemu-img check -r.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add comprehensive tests for the corrupt bit handling. Cover writable
rejection, read-only access, persistence, and dirty bit
coexistence.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement proper handling of the QCOW2 corrupt bit (incompatible feature
bit 1) according to the specification:
- Add Error::CorruptImage for rejecting writable opens of corrupt images
- Add CORRUPT to SUPPORTED features (handled specially, not rejected)
- Add QcowHeader::set_corrupt_bit() to mark images as corrupt
- Add QcowHeader::is_corrupt() helper method
- Reject writable opens of corrupt images with Error::CorruptImage
- Allow readonly opens of corrupt images with a warning
The corrupt bit indicates that image metadata may be inconsistent. Per
spec, such images must not be written to until repaired by external
tools like qemu-img. Read-only access is permitted to allow data
recovery.
Users can open corrupt images read-only using:
--disk path=/path/to/image.qcow2,readonly=on
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
VsockPacket::hdr holds a raw pointer to the address of the VSock packet
header, which is in guest memory. It opens the door to double-fetch
(or TOCTOU) race conditions. Therefore, VSockPacket::hdr content can't
be trusted since it can be arbitrarily changed by the guest, at any
time.
To mitigate this, we can copy the header content to an array in VMM's
memory that the guest can't modify.
Signed-off-by: Thomas Leroy <thomas.leroy.mp@gmail.com>
Update QcowHeader and other related places to use BeUint methods
internally for reading/writing header fields.
This removes the byteorder dependency from mod.rs and consolidates
all big-endian file I/O through the shared BeUint trait.
Suggested-by: Rob Bradford <rbradford@rivosinc.com>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a read_be() method to the BeUint trait and make it pub(super)
so it can be used across the qcow module. Change BeUint::write_be()
to take Self instead of u64, providing type safety through TryFrom
conversion.
Suggested-by: Rob Bradford <rbradford@rivosinc.com>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add tests to verify dirty bit is set while VM runs and cleared on
clean shutdown. As part of it, ensure graceful shutdown when OS
disk verification requires consistent image state.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Verify dirty bit is set on open and cleared on close for v3 images.
Ensure v2 and read-only files are not affected. Update existing
tests.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add support for the dirty bit (bit 0 of incompatible_features) which
indicates the image was not closed cleanly. This improves data
integrity by allowing detection of potentially corrupted images.
On open:
- If dirty bit is already set, log a warning and trigger
refcount rebuild
- Set the dirty bit and write it to disk immediately
- Sync to ensure persistence before any writes
- Skip dirty bit and refcount rebuild for readonly files
On clean close:
- Clear the dirty bit in the header
- Write it to disk and sync
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Test all refcount_order values (0-6):
- Basic open for each width
- Write/read roundtrip
- Overwrite and multi-cluster allocation
- L2 cache eviction under memory pressure
- Sub-byte and byte-aligned max value handling
- Overflow error detection
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Reject refcount values exceeding the maximum for the image's
refcount_order. This prevents silent truncation when storing
refcounts in narrow widths (e.g., 1-bit max is 1, 4-bit max is 15,
etc.).
Returns RefcountOverflow error with the attempted value, maximum,
and bit width. Propagates as EINVAL to the guest.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
QCOW2 v3 specifies refcount_order 0-6 with
refcount_bits = 1 << refcount_order. Previously only 16-bit (order 4)
was supported.
Changes:
- RefcountBytes trait handles byte-aligned types (8/16/32/64-bit)
- Generic pack/unpack for sub-byte widths (1/2/4-bit)
- Function pointers for read/write selected at open time
- Internal refcount type widened from u16 to u64
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Parse the feature name table header extension to provide descriptive
error messages when unsupported incompatible features are detected.
Currently only the compression bit (bit 3, zstd) is supported.
This prevents opening qcow2 images with features that would cause
incorrect behavior or data corruption (e.g., dirty bit, corrupt bit,
external data file, extended L2 entries).
Feature names are defined as follows:
1. The image's feature name table header extension (if present)
2. Hardcoded fallback names for known features
3. Generic "unknown feature bit N" for undefined features
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Co-developed-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Implement read support for bit 0 in QCOW2 L2 table entries.
When this flag is set, the cluster reads as zeros without accessing
disk. This improves compatibility with QCOW2 images that use this
optimization.
According to the QCOW2 specification, bit 0 of the standard cluster
descriptor indicates that the cluster reads as zeros. Unlike
l2_entry == 0 indicating a completely unallocated entry, bit 0 can
be set on an allocated cluster.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
build_edk2 was leaving behind .built markers
even when compilation failed.
Gate creation of.built marker to occur only on
successful build
Modify build_edk2() to exit with error code
when arm64 firmware artifact : CLOUDHV_EFI.fd
is not produced
Fixes#7608
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
build_edk2() module in scripts/common-aarch64.sh
does not produce the UEFI firmware for aarch64 as
the commits used to assemble sources for acpica,
edk2-platforms and edk2 do not compile after GCC
version upgraded from 11.4.0 to 13.3.0 in the
developer container (ubuntu 22.04 to 24.04)
Apply minimum upgrade to EDK2_REPO and ACPICA_REPO
required to compile with GCC 13.3.0
while still assuring guest VM boot for all
integration tests
BaseTools: Brotli compression submodule that was
previously failing has been fixed following commit
bump
Developers can now produce UEFI firmware for
aarch64 using the following commands
```
./scripts/dev_cli.sh shell
source scripts/test-util.sh
source scripts/common-aarch64.sh
build_edk2
```
Update docs/uefi.md
Fixes#7608
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
Recent changes related to arm64 support in MSHV exposed
inconsistencies in the VM initialization and CVM boot paths.
The VM creation flow currently diverges across multiple scenarios,
including regular MSHV, CVM, and arm64, with each path performing
guest initialization steps in a different order.
Certain platform-specific requirements further constrain the ordering
of operations, such as the timing of address space creation,
IGVM loading, interrupt controller setup, and payload loading. For
CVM case address-space creation must be done after IGVM loading, and
PSP measurement. For Regular and arm64 this memory initialization
must be done early. For MSHV, vm.init() and sev_snp.init() are called in
different order which is run time and build time conditionally checked.
Additionally, while the KVM initialization path differs slightly
from MSHV, it shares common logic that is currently split across
separate conditional and build-time code paths, contributing to
fragmentation of the overall flow.
This change restructures the VM creation and initialization sequence
to better align shared logic, enforce scenario-specific ordering
constraints, and ensure consistent and correct behavior across all
supported configurations. In doing so, it restores proper CVM boot
behavior and improves the maintainability of the initialization code.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The spec says simply that that an empty payload should be returned on
error. Be slightly more helpful by adding a warning.
Signed-off-by: Rob Bradford <rbradford@meta.com>
Based upon the discussion and in
https://github.com/rust-vmm/vhost/issues/29#issue-830820820 and the QEMU
behaviour the get_config offset should be zero. This was not caught by
our integration tests as the vhost-user-blk backend as implemented in
this repository does not use the offset.
Fixes: #7615
Signed-off-by: Rob Bradford <rbradford@meta.com>
Since the mshv integration workflow has been stable for a long time,
make the workflows no longer optional.
Signed-off-by: Aastha Rawat <aastharawat@microsoft.com>
Add warmup_iterations field to run iterations before measuring
performance. This complements existing cold start tests
by separating cache effects from steady state throughput.
New tests with 2 warmup iterations:
- block_qcow2_backing_qcow2_read_warm_MiBps
- block_qcow2_backing_raw_read_warm_MiBps
Results show warm cache is much faster and more consistent:
- QCOW2: 1766 MiB/s (4% variance) vs cold 960 MiB/s (73% variance)
- RAW: 1822 MiB/s (6% variance) vs cold 1300 MiB/s (55% variance)
RAW backing is 3% faster than QCOW2 in steady state.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The write_to() function is used by test code to create qcow2 files for
testing. For v3 headers with extended header_size (>104), it needs to:
1. Write the mandatory compression_type field at bytes 104-111
2. Write the header extension end marker at the header_size offset
3. Seek to backing_file_offset before writing the backing file path
Additionally, create_for_size_and_path() must set backing_file_offset
to account for the 8 byte extension end marker in v3 files, so the
backing file path doesn't overwrite the extension area.
Add unit tests for read_header_extensions() covering backing format
parsing (raw/qcow2), unknown extensions, and error cases (invalid
formats, invalid UTF-8). These tests depend on the header writing fixes
to create properly formatted v3 test files.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add support for parsing QCOW v3 header extensions to read the
backing file format. The QCOW v3 spec allows optional header
extensions between the fixed header and the backing file name.
Implement read_header_extensions() to parse the extension area,
which starts at the header_size offset. At the moment it is
used to read the backing file format. Further extension
processing is open in folow up implementations.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add support for raw backing files in addition to qcow2 backing
files. This enables QCOW2 overlays to use raw images as their
backing store.
The backing file format is auto-detected when not specified,
using the existing detect_image_type() function.
Add backing_file_format field to QcowHeader to store the format
type, which will be populated from header extensions by a
subsequent patch.
Modify new_from_backing() to accept a backing_format parameter,
consolidating support for both raw and qcow2 backing files in a
single function. The backing_file_size parameter allows overlay
creation without opening the backing file multiple times.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
In most of the cases, special registers don't change after emulations,
but current code sets them back unconditionally, and although some of
them are set over the register page, others require a system call and a
hypervisor to be updated, which is a waste it there were not changes.
Introduce and CPU update method for Microsoft Hypervisor emulator and
set special registers only when they were changed. This change reduces
guest boot time by 4% for a single VP guest boot (in L1VH partition) in
my experiments.
Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
This is a precursor change to overall ioctl and hypercall reduction
effort. The old (current) CPU state can be compared to the new to
determine what has changed and avoid unnecessary register updates.
Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Minor modifications were made to make the sentences sound more natural.
Also fixed some parameter usage issues in bash code block.
Signed-off-by: Yi Wang <foxywang@tencent.com>
There are some syntax and format issues in tdx/sev documents.
Make some modification to make the description more natural.
And the link of SEV-SNP is invalid, fix it.
Signed-off-by: Yi Wang <foxywang@tencent.com>
There are some minor syntax and command issues in debug-port document.
As commit 5febdec81a (vmm: Enable `gdbstub` on AArch64) supported
aarch64, the docs should keep consistent.
Signed-off-by: Yi Wang <foxywang@tencent.com>
Fix some minor syntax issues in api/building document to make
the sentences more fluent and easy to read.
Signed-off-by: Yi Wang <foxywang@tencent.com>
Some description in the device document were inconsistent with the
source code. Also fix some syntax issues to make the sentences more
fluent.
Signed-off-by: Yi Wang <foxywang@tencent.com>
CI reports:
In scripts/test-util.sh line 216:
cleanup() {
^-- SC2329 (info): This function is never invoked. Check usage (or ignored if invoked indirectly).
The shellcheck can't trace calling in trap, so we need add hint
to make it happy.
Signed-off-by: Yi Wang <foxywang@tencent.com>
The IORT table's ID mapping uses a 256-ID offset per PCI segment to
ensure unique device IDs across all segments. This partitioning scheme
(output_base = 256 * segment_id) must match the device ID encoding used
in KVM MSI routing configuration [1].
This mapping assumes one bus per PCI segment, and supports up to 256 PCI
segments in the system.
[1] c9374d87ac
Signed-off-by: Bo Chen <bchen@crusoe.ai>
The IORT specification (Revision E.b, Table 12) defines the ITS Group
Node structure with an ITS Identifiers array following the node header.
Although the IORT table is zero-initialized, this commit adds an
explicit write of the ITS identifier value (0) for clarity and spec
compliance.
This ITS identifier must match the `translation_id` field in the MADT
GIC ITS structure to ensure proper interrupt routing on ARM platforms.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
The current IORT table implementation is based on IORT Spec revision E.b
[1], as evidenced by:
* The PCI root complex node revision being set to `3`
* The code being updated in late 2021 [2] when revision E.b was the
latest version
This patch ensures the IORT table is properly generated according to
this specification revision, fixing three issues:
1. The IORT table revision should be `3` rather than `2` (see Table 2 in
the spec [1])
2. The GIC ITS group node revision should be `1` rather than `0`
(see Table 12 in the spec [1])
3. The "Memory access properties" and "ATS Attribute" fields of the PCI
root complex node was set incorrectly - specifically the MAF (Memory
Access Flags) including CPM and DACS bits (see Tables 14, 15, and 17
in the spec [1])
[1] https://developer.arm.com/documentation/den0049/eb/?lang=en
[2] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/3356
Signed-off-by: Bo Chen <bchen@crusoe.ai>
It should always succeed and is apparently implicitly called by libc or
some dependency somewhere.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
x86::__cpuid is safe on Rust ≥1.94 but unsafe on older versions. This
causes unused_unsafe warnings when compiling with Rust ≥1.94. However,
on earlier Rust versions, the code won’t compile if the unsafe blocks
are absent.
Work around this by adding #[allow(unused_unsafe)] where needed to
suppress the warnings.
See #7588 for more discussion.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
On MSHV, exposing multithreaded CPU topologies requires setting the
PROCESSORS_PER_SOCKET partition property so that CPUID.0xB reports
correct logical processor counts and topology levels to the guest.
This property must be set after all vCPUs are configured, as the
hypervisor uses the complete vCPU layout to derive and report CPU
topology information.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This change is a prerequisite for live disk resizing. Before this
commit, the epoll-handler threads just got a copy of the sector
size which we cannot update during runtime.
On-behalf-of: SAP thomas.prescher@sap.com
Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
Add sequential and random read performance tests for QCOW2 overlays
with QCOW2 backing files.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce a new BlockControl struct to encapsulate fio operation
parameters. This replaces the tuple-based fio_control with a more
extensible structure that includes:
- fio_ops: The FIO operation type
- bandwidth: Whether to measure bandwidth or IOPS
- test_file: The file path to test against
This refactoring enables reusing performance_block_io with different
test files.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Virtio PCI devices are created in a set of nested functions. In each
of this functions a vector is created to add created devices to, only
to be appended to the vector of the higher nesting level. Those nested
vectors are unnecessary as we can directly write to the member of
`DeviceManager`.
Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
The TILE data state of AMX may require 8KB+ space, calling the legacy
KVM_GET_XSAVE will encounter an error since KVM_GET_XSAVE only can get
4KB space. This patch adds KVM_GET_XSAVE2 support to allow snapping more
data.
Fixes: #7533
Signed-off-by: Songqian Li <sionli@tencent.com>
Refactor write_pointer_table to accept iterators instead of requiring
materialized vectors, eliminating temporary allocations in L1 table
sync operations.
Changes:
- Modified write_pointer_table() to take Iterator<Item = &T> and
dereference internally before passing owned values to the callback
- Added write_pointer_table_direct() convenience wrapper for cases
without value transformation
- Updated sync_caches() to use l1_table.iter() directly instead of
.get_values().iter().copied()
- Implemented Deref<Target = [T]> for VecCache to enable direct .iter()
Performance impact:
- Eliminates L1 table allocation during sync (~2KB per 100GB disk)
- L2 and refcount table writes already used slices, no change there
- Zero performance overhead: iterator dereferencing is equivalent to
.copied() and optimizes identically
The L1 sync previously collected entries into a Vec to apply the
OFLAG_COPIED flag. The new iterator+callback pattern computes this
on-the-fly, avoiding the allocation entirely.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add Deref<Target = [T]> implementation for VecCache<T> to allow direct
slice operations without explicitly calling get_values(). This enables
cleaner code patterns like cache.iter() instead
of cache.get_values().iter().
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add fcntl to virtio_block_thread_rules to allow try_clone() on file
descriptors. The try_clone() method uses fcntl(fd, F_DUPFD_CLOEXEC)
to duplicate file descriptors, which is needed for efficient QCOW2
L1 table sync that avoids temporary allocations.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Creating a vdpa_net with an associated MAC address and setting the right
amount of queues in order to fix the integration test related to
vdpa_net.
Fixes: #5756
Signed-off-by: Sebastien Boeuf <seb@rivosinc.com>
In [0] we refactored some Arc<Mutex<T>> parameters to &Mutex<T>> to
satisfy clippy's needless_pass_by_value lint. Nevertheless, this is also
not so idiomatic, so as a follow-up, we put the responsibility to lock
objects to the caller side (only where this is not strictly needed by
the callee).
While on it, I also tried to pass vm_config directly into
pre_create_console_devices() which would clean up some code, but then
we have interleaving mutable and immutable borrows of the Vmm, which
are denied by the borrow checker.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Our CI test execution system finds some mergeable pages in the system
directly on boot since a recent update. Remove the broken assumption in
the test_memory_mergeable integration test and only check if the guest
VMs influence the shared pages count.
Signed-off-by: Stefan Nürnberger <stefan.nuernberger@cyberus-technology.de>
https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7294 adjusted
the checks for read-only requests made to virtio-blk devices and started
rejecting VIRTIO_BLK_T_GET_ID requests. These requests do not perform
any writes and are needed in order to access device serials from within
the guest.
Signed-off-by: Connor Brewster <cbrewster@hey.com>
`cargo rustc` is incompatible with virtual manifests, so the CI needs to
use cargo build instead. However, passing `RUSTFLAGS="-D warnings"` via
the environment would propagate to all dependencies, and some of them
currently fail to build under ``-D warnings` due to issues like [0]:
```
error: creating a mutable reference to mutable static
--> src/temp.rs:97:5
|
97 | DIRS.pop()
| ^^^^^^^^^^ mutable reference to mutable static
```
To resolve this, apply ``-D warnings` only to the `cargo clippy`
commands (which apply to our workspace only) and avoid enforcing it for
the entire cargo build.
[0]: https://github.com/cloud-hypervisor/cloud-hypervisor/actions/runs/19962283528/job/57245376263?pr=7525
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
TL;DR: cargo clippy|check|... now runs on whole workspace by default.
## Steps
- add new workspace member `cloud-hypervisor`
- move `./src` to new workspace member
- move `./tests` to new workspace member
- move relevant parts from Cargo.toml to new workspace member
- kept necessary parts in main Cargo.toml, such as profile
configurations
## About
The main Cargo.toml historically mixes workspace and crate definitions
for cloud-hypervisor and ch-remote. This makes it hard to read and
requires `--workspace` to run cargo clippy or cargo test on all
workspace members, which is counter-intuitive.
This patch separates the workspace from the crate definition in the main
Cargo.toml file. After this, cargo clippy, cargo test, etc., work on the
whole workspace naturally, giving a smoother developer experience. The
Cargo.toml without a package definition is also called a virtual
workspace or virtual manifest by Cargo [0].
Backporting is not a concern: CHV no longer backports, but the affected
files are rarely modified anyway.
[0] https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This will also prevent some useless rebuilds. Using `--verbose` we can
observe that the build.rs causes frequent useless rebuilds - having
less is a good thing. They come from the dependency of `build.rs` to
the local git repository.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
The BufWriter must be flushed explicitly to handle errors
properly. Without explicit flush, errors during the implicit
drop flush are ignored.
This is the same issue fixed for write_pointer_table
in commit 85556951a.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The MSR enumeration logic in MSHV does not accurately
account for the capabilities of the underlying
hardware and hypervisor. Previously, integration tests
passed because only the default MSRs—universally supported
across platforms—were involved. However, recent feature
additions in MSHV have introduced MSRs that are not
supported on Intel hardware, causing failures.
This patch retrieves the MSRs from the VM specific
API call that filters out the unsupported MSRs.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add set_cluster_refcount_track_freed() helper to consolidate the
common pattern of setting a cluster refcount and tracking freed
refblocks. This reduces code duplication and improves readability.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
The image passed for the guest construction is copied. Previously,
check-img has been checking the unchanged image from the workspace dir,
which is supposed to be error free.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Freed clusters correctly have refcount=0. Remove the assertion that
expected no clusters with zero refcount, as it was validating the
buggy behavior.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When converting a compressed cluster to standard during write
operations, the old compressed cluster's refcount was never
decremented, causing leak warnings by `qemu-img check ..`
`Leaked cluster X refcount=N reference=M`
Additionally, compressed data can span multiple physical clusters,
not just one. The compressed cluster address and size are encoded
in the L2 entry, and the data may cross cluster boundaries.
The proper handling is implemented as follows:
- Extract compressed cluster address and size before overwriting
L2 entry
- Identify all clusters occupied by the compressed data
- Decrement refcount for each cluster in the range
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
When a refcount block is evicted from cache and replaced with a new
one, the old refcount block cluster was added to unref_clusters but
its refcount was never decremented to 0 on disk. This left the cluster
with refcount=1 while no metadata referenced it, causing errors in
qemu-img check
`Leaked cluster X refcount=1 reference=0`
This fix recursively calls set_cluster_refcount(freed_cluster, 0) to
properly decrement the freed refcount block's refcount on disk. The
recursion handles cascading replacements where freeing one refcount
block may trigger the replacement of another.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
"Signed-off-by" is the only variant that is accepted. So we
should remove the inconsistency to prevent:
- user forgets this at all
- CI complains
- user adds "Signed-Off-By"
- CI still complains because of the wrong format
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
We enable AMX tile state components via the hypervisor (as introduced
in the previous commit) instead of doing this inline in the body of
`CpuManager::new`.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Currently when the user configures AMX the corresponding state
components get dynamically enabled directly inside the function body of
vmm::cpu::CpuManager::new.
With our ongoing work on CPU templates/profiles, there will (likely) be
one more binary crate for producing CPU profiles that also needs to do
this (without creating a CpuManager) and it may also be the case that
we will need to call this function prior to `CpuManager::new` during
live migrations.
We thus add a method for enabling the AMX tile state components on the
hypervisor trait that may be called wherever necessary. We argue that
this is beneficial for code clarity independently of the upcoming CPU
templates/profiles PR that we are working on.
The astute reader will notice that the logic introduced here is not 100%
the same as what is done inside the vmm::cpu::Cpumanager::new method. We
claim that our approach is more in-line with the official documentation.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
This patch updates the documentation to reflect the newly added
nested CPU feature option in the CLI.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add an option in the CLI to enable nested support.
Adding an option --cpu nested=on|off to the CPU
argument to enable nested support for Microsoft
Hypervisor. By default it is enabled for both KVM
and MSHV.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Create HypervisorVmConfig early and pass the
struct to VM creation API in the vmm crate. Getting
rid of multiple conditional parameter.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The OFLAG_COPIED bit (bit 63) indicates a cluster's refcount is exactly
1 and doesn't need copy-on-write. This bit must be set in L1 entries
when their referenced L2 clusters have refcount=1.
Previously, L1 entries were always written as raw addresses without the
OFLAG_COPIED bit, violating the QCOW2 specification and causing qemu-img
check to report errors like
`ERROR OFLAG_COPIED L2 cluster: l1_index=X .... refcount=1`
The implementation queries each L2 cluster's refcount in sync_caches()
and sets OFLAG_COPIED appropriately when writing the L1 table. This
ensures QCOW2 images are specification compliant and maintain correct
COW semantics to avoid data corruption.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Previously the code relies on the implicit flush when BufWriter is
dropped. That's not safe.
Per BufWriter's document:
```
It is critical to call flush before BufWriter<W> is dropped. Though
dropping will attempt to flush the contents of the buffer, any errors
that happen in the process of dropping will be ignored. Calling flush
ensures that the buffer is empty and thus dropping will not even attempt
file operations.
```
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The MSRs are constant at boot time so rather than creating a vector in
the boot_msr_entries() method instead reaturn a reference to static MSR
array data.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Previously, state that we accumulated during the migration process in
the receiver was kept in `mut Option` variables or HashMaps. The
problem is that it is unclear in the code when these variables can be
safely used. It's also difficult to add new state, such as the state
we need to handle the upcoming feature for performing the migration
using multiple connections.
To solve this, I've refactored the code to use the state machine
pattern. Each state carries the data it needs to. Any state that
didn't arrive yet (memory_files, memory_manager) cannot be accessed
until we are in the proper state.
Some benefits that fall out of this:
- We now respond to all requests, even invalid ones, at least with an
error message.
- Any error handling a request will result in an error message being
sent.
- There is only a single place where responses are sent and thus it's
very hard to mess this up in the code.
- The main protocol state machine fits on a screen.
I would argue that especially the error cases are now much more
consistent. There is still a lot to be done. There is still state
transfer via self.vm and similar. In an ideal world, this would also
be carried by the state machine. I also want to see better handling of
payloads, which are still handled all over the place, but this change
is already too big. :)
Co-authored-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP julian.stecklina@sap.com
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
... and nuke some Option<> while I was there. Given that HashMap has a
usable default and we end up passing an empty HashMap anyway, just get
rid of the Option.
On-behalf-of: SAP julian.stecklina@sap.com
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
During the lifecycle of a confidential VM, the guest may revoke
previously shared pages via an attribute-intercept VM exit.
When this happens, the host-side cache must be updated so that any
subsequent access by the VMM triggers a fresh request for the guest
to re-share the page.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This is a follow-up of [0].
# Advantages
- This saves dozens of unneeded clone()s across the whole code base
- Makes it much easier to reason about how parameters are used
(often we passed owned Arc/Rc versions without actually needing
ownership)
# Exceptions
For certain code paths, the alternatives would require awkward or overly
complex code, and in some cases the functions are the logical owners of
the values they take. In those cases, I've added
#[allow(clippy::needless_pass_by_value)].
This does not mean that one should not improve this in the future.
[0] 6a86c157af
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Fix the condition to correctly identify a new PTY connection.
Fixes: 287887c99 (vmm: fix console IO safety)
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Previously, `into_raw_fd()` transferred fd ownership to epoll while
keeping separate clones in `reader` and `writer`, causing leaks when
the stream was closed. Now, `reader` owns the fd and epoll borrows it.
When the FD is closed in the kernel, reader will be reset to None.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
The Intel Granite Rapids processors include more AMX related features
that are advertised in leaf 0x7 subleaf 0x1. If the VM is not
configured to support AMX (the default) then these feature bits need
to be masked out.
Furthermore Tile information and TMUL information
in leaves 0x1d and 0x1e respectively are also purely related to AMX
and should also be zeroed whenever AMX support is disabled.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP <oliver.anderson@sap.com>
When enabling amx feature, we should call arch_prctl to request
permission to use tile data for guest. The permission should be
requested before the first vcpu is created, so we need to call
arch_prctl in vmm thread. This patch adds the arch_prctl syscall for
vmm_thread_rules.
Fixes: #7516
Signed-off-by: Songqian Li <sionli@tencent.com>
This helps to uncover expensive and needless clones in the code base.
For example, I prevented extensive clones in the snapshot path where
(nested) BTreeMap's have been cloned over and over again. Further,
the lint helps devs to much better reason about the ownership of
parameters.
All of these changes have been done manually with the necessary
caution. A few structs that are cheap to clone are now `copy` so that
this lint won't trigger for them.
I didn't enable the lint so far as it is a massive rabbit hole and
needs much more fixes. Nevertheless, it is very useful.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
We've encountered issues that Cloud Hypervisor corrupts disk images
after use. Those issues may not be immediately obvious until the
corrupted images are used again.
Run consistency checks over the disk images in the test cases to catch
issues as early as possible.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
It is a common use case to run a subset of tests locally to verify
certain functionalities.
The default behaviour for nextest is to error out if no tests are run.
That causes the test scripts to return a non-zero value (failure). Pass
`--no-tests=pass` to nextest to match what `cargo test` does if no tests
are run.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This is continuing the work from [0]. Some places in CHV
"misuse" Result::map_err for side-effects. inspect_err is
a better suited alternative for exactly that use-case.
Unfortunately, there is no clippy lint for this yet.
[0] f02745a7ed
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This commit is the first in a series of similar commits to clean up
obsolete `extern crate` statements
Since Rust 1.30, normal macros can be imported via `use`, and with Rust
1.31 and edition 2018 this has become the preferred approach.
`extern crate` is only needed for `alloc` in `no_std` crates, which does
not apply here.
By dropping these (often redundant or odd) `extern crate` lines, we
expose the actual dependencies more clearly and reduce technical debt.
## Auto-generation of the series
Most of this series was produced automatically:
1. Removed all "extern crate" references
2. Run the script [0] to add missing `use` statements
3. Run `cargo +nightly fmt --all`
4. Fix the remaining problems manually
The treewide changes were then split into per-folder commits.
[0]
```python
import os
import re
# Mapping of macro/function usage to imports
MACRO_IMPORTS = {
"info!": "use log::info;\n",
"debug!": "use log::debug;\n",
"error!": "use log::error;\n",
"trace!": "use log::trace;\n",
"warn!": "use log::warn;\n",
"event!": "use event_monitor::event;\n",
"anyhow!(": "use anyhow::anyhow;\n",
"bitflags!(": "use bitflags::bitflags;\n",
"ioctl_ior_nr!": "use vmm_sys_util::{ioctl_ior_nr};\n",
"ioctl_iow_nr!": "use vmm_sys_util::{ioctl_iow_nr};\n",
}
# Regex for finding the first use statement
USE_REGEX = re.compile(r"^\s*(use|pub use) .+?;")
def process_file(path):
with open(path, "r", encoding="utf-8") as f:
lines = f.readlines()
content = "".join(lines)
existing_imports = set(lines)
needed_imports = set()
# Check macros/functions against mapping, only add if not already present
for key, import_stmt in MACRO_IMPORTS.items():
if key in content and import_stmt not in existing_imports:
needed_imports.add(import_stmt)
if not needed_imports:
print(f"Unmodified {path} (no new imports needed)")
return # Nothing to do
# Find first use or pub use statement
for i, line in enumerate(lines):
if USE_REGEX.match(line):
insertion_index = i + 1
break
else:
print(f"Unmodified {path} (no use or pub use statement found)")
return # No use statement found, skip file
# Insert imports
lines[insertion_index:insertion_index] = list(needed_imports)
# Write back file
with open(path, "w", encoding="utf-8") as f:
f.writelines(lines)
print(f"Modified {path}, added imports: {''.join(needed_imports).strip()}")
for root, _, files in os.walk("."):
for file in files:
if file.endswith(".rs"):
process_file(os.path.join(root, file))
```
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Add tests:
- zlib: test_virtio_block_qcow2_zlib()
- zstd: test_virtio_block_qcow2_zstd()
Both these tests use zlib- and zstd-compressed images as OS image.
Modify test_virtio_block_qcow2_backing_file() test: it is practical
to test qcow2 file-backing with compression, so use zlib-compressed
image as a backing file.
Signed-off-by: Eugene Korenevsky <ekorenevsky@aliyun.com>
Add support of reading and writing compressed clusters.
Support zlib and zstd compressions.
L2 cache: store entire L2 entries, not only standard cluster addresses.
Read path. Offsets of compressed clusters cannot be determined,
therefore replace QcowFile.file_offset_read() with QcowFile.file_read().
This method reads the cluster, decompresses it if necessary and returns
the data to the caller.
Write path. QcowFile.file_offset_write(): since writing to compressed
clusters is not generally possible, allocate a new standard
(non-compressed) cluster if compressed L2 entry is encountered; then
decompress compressed cluster into new cluster; then return offset
inside new cluster to the caller. Processing of standard clusters is
not changed.
Signed-off-by: Eugene Korenevsky <ekorenevsky@aliyun.com>
As well as saving the MSRs as it is currently does ensure that the KVM
capability is enabled along with keeping the internal state updated.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Co-authored-by: Chengyu Fu <chengyu.fu@linux.alibaba.com>
The granularity has significant implications in typical cloud
deployments with network storage. The Linux kernel will sync advisory
locks to network file systems, but these backends may have different
policies and handle locks differently. For example, Netapp speaks a NFS
API but will treat advisory OFD locks for the whole file as mandatory
locks, whereas byte-range locks for the whole file will remain
advisory [0].
As it is a valid use case to prevent multiple CHV instances from
accessing the same disk but disk management software (e.g., Cinder in
OpenStack) should be able to snapshot disks while VMs are running, we
need special control over the lock granularity. Therefore, it is a valid
use case to lock the whole byte range of a disk image without
technically locking the whole file - to get the best of both worlds.
This also brings CHVs behavior in line with QEMU [1].
Whole-file locks remain a valid use case and could be supported later.
This patch only provides the necessary groundwork; making it
configurable is out of scope for now.
[0] https://kb.netapp.com/on-prem/ontap/da/NAS/NAS-KBs/How_is_Mandatory_Locking_supported_for_NFSv4_on_ONTAP_9
[1] <qemu>/util/osdep.c::qemu_lock_fcntl()
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This should be guaranteed by GuestMemory and GuestMemoryRegion, but
those traits are currently safe, so add checks to guard against
incorrect implementations of them.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
It takes a pointer to a userspace address that it accesses, so it should
be marked unsafe. This was missed earlier.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Callers of get_host_address_range() rely on it returning a pointer to at
least size bytes of memory. mem.get_host_address() is an overrideable
method of a safe trait, so it is better for safe code to not rely on its
correctness for safety. Instead, use mem.get_slice(), which returns a
VolatileSlice whose invariants guarantee that it points to a sufficient
amount of memory. If mem.check_range() succeeds but mem.get_slice()
returns a slice that is too small, this means that there is either a
logic error or a situation the code cannot support yet, so panic.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
The kernel will validate that the size is page-aligned. The file offset
is always zero, so the kernel will also validate that the offset is
page-aligned.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
This API passes a u64 to a kernel API that treats the u64 as a userspace
address. Therefore, it should be marked unsafe, but it currently is not
[1]. Wrap the call in an unsafe block to document that invariants must
be upheld to avoid undefined behavior. This causes a compiler warning,
so suppress the warning with #[allow(unused_unsafe)].
[1]: https://github.com/rust-vmm/vfio/issues/100
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
I believe that its only caller used it safely, but it is still better to
mark the code as unsafe. Also add additional validity checks.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Also drop support for building the TDX code for 32-bit targets. All
CPUs with TDX support are 64-bit so supporting 32-bit targets is not
needed.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
To ensure that struct sizes are the same on 32-bit and 64-bit, various
kernel APIs use __u64 (Rust u64) to represent userspace pointers.
Userspace is expected to cast pointers to __u64 before passing them to
the kernel, and cast kernel-provided __u64 to a pointer before using
them. However, various safe APIs in Cloud Hypervisor took
caller-provided u64 values and passed them to syscalls that interpret
them as userspace addresses. Therefore, passing bad u64 values would
cause memory disclosure or corruption.
Fix the bug by using usize and pointer types as appropriate. To make
soundness of the code easier to reason about, the PCI code gains a new
MmapRegion abstraction that ensures the validity of pointers. The rest
of the code already has an MmapRegion abstraction it can use. To avoid
having to reason about whether something is keeping the MmapRegion
alive, reference counting is added. MmapRegion cannot hold references
to other objects, so the reference counting cannot introduce cycles.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
To ensure that struct sizes are the same on 32-bit and 64-bit, various
kernel APIs use __u64 (Rust u64) to represent userspace pointers.
Userspace is expected to cast pointers to __u64 before passing them to
the kernel, and cast kernel-provided __u64 to a pointer before using
them. However, various safe APIs in Cloud Hypervisor took
caller-provided u64 values and passed them to syscalls that treat them
as userspace addresses. Therefore, passing bad u64 values would cause
memory disclosure or corruption. The memory region APIs are one example
of this, so mark them as unsafe.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
When booting a Linux guest in SMP configuration, on sapphire rapids
and granite rapids the following kernel warning can be observed:
[Firmware Bug]: CPUID leaf 0x1f subleaf 1 APIC ID mismatch 1 != 0
[Firmware Bug]: CPUID leaf 0x1f subleaf 2 APIC ID mismatch 1 != 0
The reason is that we announce the presence of the extended topology
leaf, but fail to announce the x2apic ID in EDX for each subleaf.
Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
On-behalf-of: SAP thomas.prescher@sap.com
as of rust 1.90, writes to unix sockets use the sendto syscall. This
affects the vcpu threads when vfio_user devices are accessed.
Signed-off-by: Stefan Nürnberger <stefan.nuernberger@cyberus-technology.de>
This is the first commit in a series of commits to improve the Code
Quality in Cloud Hypervisor in a sustainable way. These are the
default rules from `clippy::all` but written here to be more explicit.
`clippy::all` refers to all "default sensible" lints, not all
existing lints.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This better aligns with the rest of the code and makes it clearer
that these tests can run "as is" in a normal hosted environments
without the special test environment.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
TL;DR: Massive quality of life improvement for devs
Cloud Hypervisor uses the Cargo test framework for multiple tests:
- normal unit tests
- unit tests requiring special environment (the Tap device tests)
- integration tests requiring a special environment
This prevented the execution of `cargo test --workspace`, which results
in a very poor developer experience. Although
`./scripts/run_unit_tests.sh` exists, there are valid reasons why devs
cannot or even don't want to use it.
By adding a new `chv_testenv` rustc config, we can conditionally only
activate tests when the `./scripts/` magic runs them. This improves
the general developer experience by a lot.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Commit 5ec47d4883 was intended to patch ebx bits 23-16 in cpuid leaf
0x1, but it was not working as expected, as in rust, operator << has a
stronger precedence than & [1]. Later commit b6667f948e fixed the
operator precedence clippy warning, but did not fix the actual issue. As
a result, the current code is not changing ebx,
```
cpu_ebx |= ((dies_per_package as u32) * (cores_per_die as u32) * (threads_per_core as u32))
& (0xff << 16);
```
Since the total number of logical processors is generally less than
65536, the right hand side of the expression is 0 in most cases.
[1] https://doc.rust-lang.org/reference/expressions.html#expression-precedence
Fixes: 5ec47d4883 ("arch: x86_64: enable HTT flag")
Signed-off-by: Changyuan Lyu <changyuanl@google.com>
A major improvement to the developer experience of clippy in
Cloud Hypervisor.
1. Make `cargo clippy` just work with the same lints we use in CI
2. Simplify adding new lints
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
... by just passing the iterator along. For large VMs this bitmap is
gigantic. A 12TB VM has 384MB of dirty bitmap.
With all these optimizations from the previous commits in place, we
see quite the improvement when it comes to scanning the dirty bitmap.
For a bitmap with 1% bits (randomly) set, dirty_log() takes:
Original code: 2166ms (100.0%)
New code: 382ms ( 17.6%)
on my system. The sparser the dirty bitmap the faster. Scanning an
empty bitmap is 100x faster. For a 5% populated bitmap we are still 3x
faster.
If someone wants to play with this, there is a benchmark harness here:
https://github.com/blitz/chv-bitmap-bench
On-behalf-of: SAP julian.stecklina@sap.com
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
This would be a good opportunity to optimize another pointless vector
away, but I don't have a good way to test this at the moment. But
maybe someone else gives it a shot.
On-behalf-of: SAP julian.stecklina@sap.com
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
Adding itertools as dependency improves the iteration code in the
following significantly.
With this change, we don't need a copy of the vector. Just something
that can be coerced into an iterator. We also use the bit position
iterator to make the code somewhat clearer. The new code is much
faster, because it will not iterate over every bit, just each 1 bit in
the input.
The next commit will complete this optimization and have some concrete
numbers.
On-behalf-of: SAP julian.stecklina@sap.com
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
Due to the fw_cfg test being disabled on MSHV this results in no tests
being runnable which results in an error in nextest. Reduce that error
to a warning use --no-tests=warn
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
cargo nextest is an improved test runner that allows retries as well a
reporting the times for the test runs.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
When using nextest for running tests each test is run in its own process
so the old solution of using a static variable for the guest ID (used to
determine the network segment) no longer works.
Instead use a text file on the filesystem protected with an exclusive
lock. The test process will read from it and then write back the next ID
that can be used. It wraps around at the limit of u8 and skips ID 0.
This function intentionally panics rather than propagate errors as it
should only be called for testing purposes and there the panic handler
will give a useful backtrace and cleanup.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This is required to support exclusive locking on files which is needed
for safe test ID generation when using nextest (since it runs each test
as a separate process.)
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
as of rust 1.90, writes to unix socket streams use send_with_flags
instead of write, so it uses a sendto syscall instead of write.
Signed-off-by: Matt Moriarity <matt@mattmoriarity.com>
To get that list, I've used
```
git log | grep --fixed-strings -- "-by:" | head -n 100000 | sort | less
```
on the Linux kernel's git repository.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
The set of extensions supported by a RISC-V system needs to be exposed
to the guest - currently that is a fixed, minimal set of extensions.
These extensions are not sufficient to boot Ubuntu 25.10 which now has a
mininimum requirement of RVA23S64 (which is a minimum set of extensions
that make sense for server use cases.)
The easiest way to convey the extensions that the guest should use is to
copy those that the host kernel understands (and thus includes in the
/proc/cpuinfo) data.
However since nested virtualisation is not currently possible - exclude
the "H" (Hypervisor) extension from the list of short (single letter)
extensions.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
After updating the Linux kernel to 6.19.6 the second segment (segment=1)
is now under the 2nd IOMMU group (which it a more logical setup) and as
such the added device which is on that segment is in that second IOMMU
group.
The same check is made in test_vdpa_block so also test there.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Resignal every 10ms the thread if it has not acknowledged the signal via
setting the atomic when the vCPU thread was acknowledged. Further, avoid
an infinite loop by generating an error if it takes more than 1000ms to
interrupt the thread.
The retry helps mitigate a race condition where the signal is received
between checking the pause atomic and entering KVM_RUN ioctl when
pausing. Hitting this race condition would leave the
wait_untial_signal_acknowledged() method spinning indefinitely.
The timeout error avoids the VMM process being blocked indefinitely.
See: #7427
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Dump kernel logs after running the tests in the MSHV workflow to help
debug failures.
In addition to getting the kernel logs using `dmesg` also use AzCli to
retrieve the serial console logs. If the VM is hung or panicked, the
workflow would be unable to SSH into it and execute `dmesg`. In this
case the serial console logs would be helpful.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Replace the use of `guestmount and `guestunmount` with standard tools
(losetup, mount) to modify cloud disk image. This eliminates
dependency on guestmount which requires /dev/kvm and is not available
in MSHV root partition.
Signed-off-by: Aastha Rawat <aastharawat@microsoft.com>
Refactor MSHV hypervisor selection logic to enable aarch64 support
instead of exiting. Use `--features mshv` to conditionally build &
test when hypervisor is mshv replacing hard exit for aarch64 on mshv.
Signed-off-by: Aastha Rawat <aastharawat@microsoft.com>
There are several copy-pasted code fragments in impl QcowFile. All of
them add L2 entry to the cache and one of them (in file_offset_write())
does also allocating new L2 entry if necessary.
Fold all these code fragments (except of one in l2_table() which does
error handling in special way) into cache_l2_cluster() method without
changing the logic.
This will make the code more compact and clean.
Signed-off-by: Eugene Korenevsky <ekorenevsky@aliyun.com>
With the current syntax docker gives 'docker: invalid reference format'
error. Also during parsing /xxx:/yyy in process_volumes_args
with \" inside variable i.e arr_vols=("${arg_vols//#/ }")
gives wrong output.
Example:
scripts/dev_cli.sh tests --integration --volumes /mshv:/mshv
Error: The volume /mshv /mshv does not exist.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The API documentation tells users to expect a message when Cloud
Hypervisor is launched, this message was removed in commit 13724db
This change updates the documentation to reflect how the program
actually functions, which is to say no message.
Signed-off-by: Ariel Chenet <achenet@fastmail.com>
Consuming `&Arc<T>` as argument is almost always an antipattern as it
hides whether the callee is going to take over (shared) ownership
(by .clone()) or not. Instead, it is better to consume `&dyn T` or
`Arc<dyn T>` to be more explicit. This commit cleans up the code.
The change is very mechanic and was very easy to implement across the
code base.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Disable test_snapshot_restore_hotplug_virtiomem for mshv. It is failing
frequently in the CI. It needs to be stabilized before enabling again.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
The ivshmem tests involving snapshot/restore & live migration are
failing in the MSHV CI with this error:
Could not get vCPU state GetMsrEntries(
Hypercall 80 failed with 0x5 : InvalidParameter ...<snip>)
This needs more investigation. It is worth noting that the general live
migration tests are also not run in the CI for MSHV.
Disable these tests for MSHV for the time being.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
The ivshmem tests are all failing in the CI for MSHV because Cloud
Hypervisor is built without the mshv feature.
Error: Cloud Hypervisor exited with the following chain of errors:
0: Failed to open hypervisor interface (is hypervisor interface
available?)
1: Failed to create the hypervisor
2: no supported hypervisor
Modify the build command to include the mshv feature.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
The existing concurrency configuration causes workflow runs for one Pull
Request to cancel in-progress runs for another Pull Request. When the
workflow is triggered by the `pull_request_target event`, `github.ref`
is always set to the base branch, regardless of which branch raised the
PR. This causes every new pull request to share the same concurrency key
and thus cancel the running CI of any other open pull request.
This commit updates the `concurrency.group` to use
`github.event.pull_request.number` for unique isolation when running on
PR, falling back to `github.ref` for non-PR push (e.g., merge group).
Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
Disable the following common parallel and common sequential tests for
mshv since these are failing consistently in the CI.
Common parallel:
- test_tpm
- test_cpu_topology_421
- test_cpu_topology_142
- test_cpu_topology_262
- test_cpu_hotplug
Common sequential:
- test_snapshot_restore_basic
- test_snapshot_restore_with_fd
- test_snapshot_restore_pvpanic
Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
test_fw_cfg is frequently failing in the CI for MSHV. Exclude it for
now. It needs further investigation. See issue #7434 for details.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Move the GICv2M MSI frame SPI base from 32 to 128 to avoid conflicts
with platform device interrupts.
While at it, rename the constants to make it explicit that they are
associated with the GICv2m MSI Frame.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
This was added in 7be69edf51 to deal with
changes to the KVM bindings that made run() and set_immediate_exit()
take &mut self. Instead adopt a Box<> value in Vcpu allowing the removal
of this internal Mutex.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The virtio spec defines the feature bit range and 4 x 32-bit pages.
However no features are currently defined with bits > 63. However Linux
has now started acking features in those higher pages. Since this is
harmless (we drop the acks to those feature pages) and quietly return 0
for available features in those higher pages this warning can be
removed.
Fixes: #7414
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Fix a race condition that happens in resume()-pause() cycles.
It is odd that for pause(), the CpuManager waited via `state.paused`
for the vCPU thread to ACK the state change but not for `resume()`.
In the `resume()` case, oddly CpuManager "owned" the state change
in `state.paused`. This commit changes this so that the vCPU ACKs
its state change itself in `state.paused` when it transitions from
pause->run. Further, `CpuManager::resume()` now gracefully waits for
the vCPU to be resumed.
More technical:
This change ensures proper synchronization and prevents situations
in that park() follows right after unpark(), causing deadlocks and
other weird behavior due to race conditions.
Calling resume() now takes slightly longer, very similar to pause().
This is, however, even for 254 vCPUs in the range of less than 10ms,
and ultimately we now have correct behaviour.
## Reproducer
Since [0] is merged, the underlying problem can be tested without this
commit by modifying the pause() API call to run `CpuManager::pause()`
and `CpuManager::resume()` in a loop a thousand times.
`ch-remote --api-socket ... pause`
```patch
diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs
index d7bba25cc..35557d58f 100644
--- a/vmm/src/vm.rs
+++ b/vmm/src/vm.rs
@@ -2687,6 +2687,10 @@ impl Pausable for Vm {
MigratableError::Pause(anyhow!("Error activating pending virtio devices: {:?}", e))
})?;
+ for _ in 0..1000 {
+ self.cpu_manager.lock().unwrap().pause()?;
+ self.cpu_manager.lock().unwrap().resume()?;
+ }
self.cpu_manager.lock().unwrap().pause()?;
self.device_manager.lock().unwrap().pause()?;
```
## Outlook
Decades of experience in VMM development showed us that using
many AtomicBools is a footgun. They are not synchronized with each
other at all. On the long term, we might want to refactor things to
have a single shared AtomicU64 with different bits having different
meanings.
[0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7290
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
These bindings actually refer to atomic bool shared across all
vCPUs to instruct single vCPUs with their next action. As there
are already enough Arc<AtomicBool>, this helps while debugging
things to see that different bindings refer to the same atomic
bool.
In other words: This naming really confused us while debugging.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This gives a reliable way of identifying if the VM has booted as well as
a reliable way to validate the addition of the network interface.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Add a second L1 network interface definition to the guest Cloud Init
configuration, including an additional host IP. Do this by splitting the
network range into two /25s. For clarity the network struct members have
also been renamed.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Previous RISC-V ACPI related change introduced MSIS which will be
rejected by typo check, let's extend the typos to accept it.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Add necessary definitions and RISC-V ACPI tables to enable ACPI feature.
More specifically, this commit add MADT definitions for RISC-V AIA
interrupt chips.
Signed-off-by: Can Zhang <icloud9957@gmail.com>
Rename the MSHV CI workflow to better align with the existing naming
scheme and also make the arch explicit.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Add step-level timeout for running integration tests so that the
workflow doesn't get stuck on any test.
Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
We are actually using v0.3.0 of vm-fdt since main branch of that crate
already includes everything. Let's pin vm-fdt to v0.3.0 instead.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Pull requests from forked repos cannot access GitHub secrets which
results in failure of MSHV CI. Switching to pull_request_target
resolves this. It allows the workflow to run with access to repo secrets
and ensures that code from the base branch is used instead of forked
code, preventing potential security risks.
Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
Add workflow to run integration tests on mshv. It calls the azure
infra setup workflow and executes integration tests in the
provisioned environment.
Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
Add workflow to setup Azure infra to validate MSHV.
This is used to provision the environment before executing tests
on it.
Signed-off-by: AASTHA RAWAT <aastharawat@microsoft.com>
This provides clearer life-cycle management of resources around vfio,
and aligns better with the kernel behavior as reported below with vfio
legacy mode (with vfio container/group).
Fixes: #7328
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Yi Wang <foxywang@tencent.com>
We recently moved many of our tests to use focal to jammy as the guest
images, including rate-limiter tests (#7367). We forgot to update the
rate-limiter scripts to reflect such change.
Our CI pipeline failed to report such error because our self-host runner
happened to be not working at the time we land the changes (see #7405).
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Only use 75% of the available threads - this will reduce dislk and
memory pressure. Reducing the chance of flaky tests.
See: #7405
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
While an IGVM is provided validation fails as there is
no kernel or firmware. This patch fixes the sev_snp boot
failure.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
MSHV (Microsoft Hypervisor) doesn't expose an ITS to guests. Instead it
exposes a GICv2m MSI Frame for mapping MSIs to SPIs.
Update the MADT generation code to create the GIC MSI Frame structure
instead of the ITS structure whenever the guest vGIC is using a GICv2m
frame. This allows booting guests via firmware on MSHV.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
In preparation for removing focal support - start by using a more
generic "disk_config" variable name for the DiskConfig struct vs
embedding the image type.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Rust's aliasing rules do not permit mutating a `usize` through a shared
reference. Unsafe blocks and FFI are no exception.
This PR fixes such a violation detected in the AMX support checks by
passing a raw mutable pointer instead of a shared reference in the
syscall.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP <oliver.anderson@sap.com>
For a graceful resource management of externally provided FDs in Cloud
Hypervisor, corresponding FDs need to be closed on a device removal.
This is the case for virtio-net devices using external FDs, for example.
With the fix introduced in this commit, we allow management software to
properly clean up resources, e.g., libvirt can clean up tap devices.
PS: CHV uses "added" and "removed", which has the same meaning as
hot device attach/hotplug and hot device detach/unplug.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Fix clippy warning `uninlined_format_args` reported by rustc rustc
1.89.0 (29483883e 2025-08-04).
```console
warning: variables can be used directly in the `format!` string
--> block/src/lib.rs:649:17
|
649 | info!("{} failed to create io_uring instance: {}", error_msg, e);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
= note: `#[warn(clippy::uninlined_format_args)]` on by default
help: change this to
|
649 - info!("{} failed to create io_uring instance: {}", error_msg, e);
649 + info!("{error_msg} failed to create io_uring instance: {e}");
|
```
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
"Update configs must have a unique combination of 'package-ecosystem',
'directory', and 'target-branch'. Ecosystem 'cargo' has overlapping
directories for target branch 'main'."
Drop `target-branch` in rust-vmm group to make those two unique.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
## TL;DR
This unifies error handling, implementation, and logging of config
objects that are populated with additional FDs received as part of
the HTTP API request from the management software. This prevents current
and future code in repetition.
In the future, if we want to support let's say virtio-blk with external
FDs, the AddBlk API handler simply needs a call to `attach_fds_to_cfg()`
and gets all the magic for free.
## Motivation
The motivation of the new abstraction is to provide a verbose, solid,
and bulletproof solution for a complex domain. The interaction between
- the management layer,
- the passing of file descriptors over UNIX domain sockets via
SCM_RIGHTS,
- the attachment of configurations to those FDs,
- and the ability to give new developers clear insights into what
happens under the hood
is not trivial. These factors justify encapsulating the complexity
behind a convenient and well-documented abstraction, making the system
both robust in production and approachable for new developers.
In addition, it allows us to perform unit testing. Further, We get rid
of existing partial code duplication and inconsistencies.
Finally, while this approach may initially result in more code, every
new handler that accepts FDs benefits from reduced duplication and a
correct implementation by relying on the shared abstraction. This will
also enable future functionality, such as virtio-blk devices backed by
FDs which can then be integrated with ease.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Deserializing values as `-1` makes sense to prevent errors, so let's
keep it. However, serializing them differently adds confusion. For
example, a `ch-remote info` call should not report `-1` but the actual
FDs.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
(1) The old messages are missing the "why" part. With this change, users
of Cloud Hypervisor have somehow more context and people looking at
the code perfectly know what's going on.
(2) Using warn! implies that the user should take action, but in this
case, there’s nothing the user can do. If the API is used correctly
and file descriptors are passed via an SCM_RIGHTS message over a
UNIX domain socket, everything works as intended. In that case,
there's no need to issue a warning — debug! is sufficient.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Live migration, state save/resume, and hotplug are not trivial when it
comes to virtio-net devices backed by externally provided FDs. As the
mechanism behind it can be considered as quite "multi-step magic" even
for experienced programmers, it makes sense to thoroughly document this
to ease debugging and to improve the mental model of developers working
on this in the future.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This change enables easier integration with third-party
tools by removing the requirement for a dummy IP address
when configuring tap devices. The modification applies to
both CLI and API interactions.
Previously, cloud-hypervisor would automatically set a
default static IP address (192.168.249.1) if none was provided.
This could lead to:
* multiple devices without explicit IP configurations
would end up with the same default IP
* unnecessary inclusion of this IP in firewall rules
* the IP address could clash with host networking and
routing
This introduces a new constraint:
When providing an IP, the mask must also be provided.
Removes warnings introduced in #7179.
Closes issue #7083.
Signed-off-by: Maximilian Güntner <code@mguentner.de>
The function `read_local_stream_port` had no proper handling for
unexpected or incomplete input.
When the control socket of the VSOCK device was closed without sending
the expected `CONNECT <PORT>\n` statement completely, the thread
got stuck in an infinite loop as it attempted to read from a closed
socket over and over again which never returned any data.
This resulted in the thread responsible for `epoll` being completely
blocked. New VSOCK connections could not be established and existing
ones became defunct, effectively leading to a Denial of Service of
the entire VSOCK device.
The issue can be reproduced by opening a socket and immediately
closing it.
```
socat - UNIX-CONNECT:/socket.vsock
<Ctrl-C>
```
Instead of applying a quick fix by handling the `EPOLLHUP` event before
reading, the function is refactored to remove the error-prone `while`
loop and multiple `read`s.
Notably, we now check if the number of bytes read is zero, which occurs
when `event_set == EPOLLHUP | EPOLLIN`, indicating that the socket has
been closed by the client.
Additionally, the actual parsing code is now extracted into a dedicated
function that is tested.
Fixes: #6798
Signed-off-by: Maximilian Güntner <code@mguentner.de>
For MSHV customers don't want to make everything
default during partition creation. For example
nested support, some synthetic features could be
controlled from CLI through platform argument.
Create_vm API getting messy after adding more flags.
This patch introduces common data struct to be passed
from vmm crate to hypervisor crate during partition creation.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Handle MSHV reset intercepts on arm64 such that guests can gracefully
shutdown/reboot instead of panicking due to unhandled intercept.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Reference link to set_device_attribut for aarch64
is invalid. Looks like the code browsing does not
have the reference anymore.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This message makes it easier to confirm a successful shutdown when
scanning logs during development and in production. If the message is
missing and the last log entry is not an error, the most likely cause
is a livelock (e.g. contention on a lock) introduced while developing
new Cloud Hypervisor features.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This commit includes all simple clippy fixes excluding the
collapsing of nested ifs using the let-chains feature. This
follows in the next commit.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Bump mshv-ioctls and mshv-bindings to 0.6.0. Most notably, this version
contains fixes and new bindings for arm64 guests.
Bump the vfio crates too so that they point to the latest mshv crates.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
Virtio console is activated much later in boot. The output it spits out
lacks the initial CPU configuration of the guest.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
These can differ between platforms, so it's better to use centralized
definitions of them. We can't currently do this for the KVM and VFIO
ioctls, because the corresponding crates don't publicly expose the
ioctl numbers.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
The previously linked file was converted to ReStructuredText, then
later removed from the kernel, with part of the justification being
"Most of what booting-without-of.rst contains is now in the DT
specification", so point to that instead.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Since the user has to explicitly ask for Landlock to be enabled in
Cloud Hypervisor, it's surprising that, even when they've done that,
Landlock will silently not be enabled if the kernel doesn't support
it.
To prevent accidental absence of a desired security protection, exit
with an error if Landlock, or the one feature of it we use in Cloud
Hypervisor (file access) is not supported.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
arch::aarch64::fdt::create_cpu_nodes will always look at this if it
exists. (If it doesn't exist, this is a no-op —
add_rule_with_access() won't add rules for paths that don't exist.)
Fixes: b3e5738b4 ("vmm: Introduce ApplyLandlock trait")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
MSHV now supports movable pages i.e VA backed guest.
Also with more features and stability in the MSHV
Kernel drives MSHV now supports more test scenario.
This patch enables more integration test cases.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Without write access to the directory the socket will go in, it's not
possible to create the socket.
I've tested outgoing connections from the VM, and they don't seem to
need read permissions on that directory to connect to a socket on the
host.
Fixes: b3e5738b4 ("vmm: Introduce ApplyLandlock trait")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
path_beneath_rules() just needs the paths given to it to be
AsRef<Path>, so there's no need to create new PathBufs for it.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Raise the max number of supported (v)CPUs on kvm x86_64 hosts
to 8192 (the max allowed value of CONFIG_NR_CPUS in the Linux kernel).
Other platfroms keep their existing CPU limits pending further
development and testing.
The change has been tested on Intel and AMD hosts.
Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
These are now used by Cloud Hypervisor when linked with Glibc 2.42.
These values should be correct for all currently supported Cloud
Hypervisor platforms, although they are not for all Linux platforms.
Closes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7276
Signed-off-by: Alyssa Ross <hi@alyssa.is>
This commit removes the SGX support from cloud hypervisor. SGX support
was deprecated in May as part of #7090.
Signed-off-by: Shubham Chakrawar <schakrawar@crusoe.ai>
This patch gives user an option to override the
default migratable version to any later release.
This option makes MSHV specific tests suitable for
tests since MSHV is stable after some breaking changes.
This patch is also necessary for MSHV CI.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This step was done manually by searching for "unsafe fn" in
the code base and adding corresponding Safety sections.
`clippy::missing_safety_doc` only works for public functions
but none of the corresponding functions is public.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Implement the batch submission function for raw disk, default it is
enabled. After parsing the requests this method is
called for better IO latency and bandwidth.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Cache and batch IO requests after parsing all
items in the queue, improving performance—especially
for small block sizes—by reducing per-request overhead.
Introduced two methods in the AsyncIo trait for batch
submission, with implementation in the raw disk backend.
This method should be called during/after parsing all block IO requests
in the available queue. If the batch submission is not enabled, by
default it does the old way of submitting requests.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Instead of returning boolean return an struct of completion status
so that it can be cached for batch submission.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This patch changes the read-only check using acked features bit, which
will help to check more features.
Signed-off-by: Songqian Li <sionli@tencent.com>
Also tweak extended interrupt handlings, as needed.
Most credit should go to Neel Natu, who figured out the magic
bits needed to make things work and provided detailed comments.
This patch is still NOOP, as VM config allows only up to
254 vCPUs on x86_64.
Note: changes in this and related previous patches/PRs have
only been tested on Linux hosts running on Intel x86_64 hardware.
Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
test_direct_kernel_boot_bzimage runs only on x86, so the cfg!() branch
for selecting grep_cmd is unnecessary. Remove it for clarity.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
One can call `to_vec()` anyway if one needs an owned copy. This change
further helps to prevent needless copies in upcoming changes.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
On aarch64 and RISC-V, calling load_firmware() through load_kernel()
provides no benefit and only duplicates checks already performed in
load_payload(). load_payload() now directly invokes load_firmware() or
load_kernel(), removing unnecessary indirection and redundancy.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Both functions are defined separately for the two architecture with
minor differences.
* `load_firmware()`: call `arch::uefi::load_uefi` which are available on
both architecture;
* `load_kernel()`: manually align to `arch::layout::KERNEL_START` 2MB
for both architecture (e.g. no-op for `aarch64`);
Signed-off-by: Bo Chen <bchen@crusoe.ai>
With 254 vCPUs, pausing now takes ~4ms instead of >254ms. This
improvement is visible when running `ch-remote pause` and is
particularly important for live migration, where every millisecond
of downtime matters.
For the wait logic, it is fine to stick to the approach of
sleeping 1ms on the first missed ACK as:
1) we have to wait anyway
2) we give time to the OS, enabling it to schedule a vCPU thread next
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Enable kvm build test and clippy test on RISC-V 64-bit platform to
ensure whole projects builds properly.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
MP table is a legacy device that is incompatible
with x2apic CPU IDs exceeding 254. The Linux kernel
is perfectly happy without MP table in these cases.
Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
Currently, the following scenarios are supported by Cloud Hypervisor to
bootstrap a VM:
1. provide firmware
2. provide kernel
3. provide kernel + cmdline
4. provide kernel + initrd
5. provide kernel + cmdline + initrd
As the difference between `--firmware` and `--kernel` is not very clear
currently, especially as both use/support a Xen PVH entry, adding this
helps to identify the cause of misconfiguration.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This is necessary to use the let-chains feature in a
follow-up. After upgrading to Rust edition 2024, clippy
wants to collapse various if's with let-chains.
Update image to 20250815-0 since MSRV in Dockerfile is updated.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This patch introduces the inter-vm shared memory(ivshmem) device
to share a memory region between multiple processes running
different guests and the host.
This patch supports the basic ivshmem functions like ivshmem-plain
in QEMU[1].
[1] https://www.qemu.org/docs/master/specs/ivshmem-spec.html
Signed-off-by: Yi Wang <foxywang@tencent.com>
Signed-off-by: Songqian Li <sionli@tencent.com>
Move UserspaceMapping to vm-device to avoid redefinition since
UserspaceMapping is used by both `virtio-devices` and `device`
crate.
Signed-off-by: Songqian Li <sionli@tencent.com>
It is always called with topology provided, so there is no
need to pass topology as an Option. Simplifying the signature
makes further topology-related changes to arc/src/x86_64 module
simpler.
Signed-off-by: Peter Oskolkov <posk@google.com>
This is the second patch in a series intended to let Cloud Hypervisor
support more than 255 vCPUs in guest VMs; the first patch/commit is
https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7231
At the moment, CPU topology in Cloud Hypervisor is using
u8 for components, and somewhat inconsistently:
- struct CpuTopology in vmm/src/vm_config.rs uses four components
(threads_per_core, cores_per_die, dies_per_package, packages);
- when passed around as a tuple, it is a 3-tuple of u8, with
some inconsistency:
- in get_x2apic_id in arch/src/x86_64/mod.rs the three u8
are assumed to be (correctly)
threads_per_core, cores_per_die, and dies_per_package, but
- in get_vcpu_topology() in vmm/src/cpu.rs the three-tuple is
threads_per_core, cores_per_die, and packages (dies_per_package
is assumed to always be one? not clear).
So for consistency, a 4-tuple is always passed around.
In addition, the types of the tuple components is changed from u8 to
u16, as on x86_64 subcomponents can consume up to 16 bits.
Again, config constraints have not been changed, so this patch
is mostly NOOP.
Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
This is the first change to Cloud Hypervisor in a series of changes
intended to increase the max number of supported vCPUs in guest VMs,
which is currently limited to 255 (254 on x86_64).
No user-visible/behavior changes are expected as a result of
applying this patch, as the type of boot_cpus and related
fields in config structs remains u8 for now, and all configuration
validations remain the same.
Signed-off-by: Barret Rhoden <brho@google.com>
Signed-off-by: Neel Natu <neelnatu@google.com>
Signed-off-by: Ofir Weisse <oweisse@google.com>
Signed-off-by: Peter Oskolkov <posk@google.com>
This allows us to enable/disable the fw_cfg device via the cli
We can also now upload files into the guest vm using fw_cfg_items
via the cli
Signed-off-by: Alex Orozco <alexorozco@google.com>
This allows the fw_cfg device to be recognized by the guest linux
kernel. This becomes more relavnt in the following cl where I add
the option to load files into the guest via fw_cfg. The Linux kernel
already has a fw_cfg driver that will automatically load these files
under /sys when CONFIG_FW_CFG_SYSFS is enabled in the kernel config
For arm we must add fw_cfg to the devices tree
Signed-off-by: Alex Orozco <alexorozco@google.com>
We pass a reference to the guest memory when we create the device
in DeviceManager. This allows us to access the guest memory for DMA.
Signed-off-by: Alex Orozco <alexorozco@google.com>
The acpi tables are created in the same place the acpi tables would be
created for the regular bootflow, except here we add them to the
fw_cfg device to be measured by the fw and then the fw will put the
acpi tables into memory.
Signed-off-by: Alex Orozco <alexorozco@google.com>
The kernel and initramfs are passed to the fw_cfg device as
file references. The cmdline is passed directly.
Signed-off-by: Alex Orozco <alexorozco@google.com>
Here we add the fw_cfg device as a legacy device to the device manager.
It is guarded behind a fw_cfg flag in vmm at creation of the
DeviceManager. In this cl we implement the fw_cfg device with one
function (signature).
Signed-off-by: Alex Orozco <alexorozco@google.com>
This partially reverts
ed8f347fe6 from #7183 and
6277d7d5f2 from #7201.
# Output how it was merged for v47 (#7066)
```
Error: Cloud Hypervisor exited with the following chain of errors:
0: Error booting VM
1: The VM could not boot
2: Error manipulating firmware file
3: No such file or directory (os error 2)
Debug Info: VmBoot(VmBoot(FirmwareFile(Os { code: 2, kind: NotFound, message: "No such file or directory" })))
```
# Output after #7183 and #7201
```
cloud-hypervisor: 31.385730ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:27 -- Error: Cloud Hypervisor exited with the following chain of errors:
cloud-hypervisor: 31.417961ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 -- 0: Error booting VM
cloud-hypervisor: 31.448078ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 -- 1: The VM could not boot
cloud-hypervisor: 31.486711ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 -- 2: Error manipulating firmware file
cloud-hypervisor: 31.513331ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:39 -- 3: No such file or directory (os error 2)
cloud-hypervisor: 31.548037ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:44 --
cloud-hypervisor: 31.568045ms: <main> ERROR:/home/pschuster/dev/cloud-hypervisor/src/lib.rs:45 -- Debug Info: VmBoot(VmBoot(FirmwareFile(Os { code: 2, kind: NotFound, message: "No such file or directory" })))
```
The "proper logger" has indeed the advantage that messages can
be gracefully redirected to log files etc. However, this makes the
error message hardly readable.
Therefore, I propose to use error!() only for runtime errors messages
but not a pretty-printed version of those.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Error::UefiLoad is required for load_firmware to propagate errors
encountered, define it for riscv64.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
uefi_flash field in memory_manager is required for uefi loading and
booting, enable it for riscv64 architecture.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
The option parser did not allow quoting any special characters, which
means that some strings could not be passed via command-line options.
Fix this by allowing double quotes to quote all the special characters,
such as '@', ',', '[', and ']'. '"' can be escaped by doubling it. The
implementation uses some tricks to stay modular.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
rustc 1.90.0-beta.1 (788da80fc 2025-08-04) suggests using library
feature `unsigned_is_multiple_of`. It is stabled in Rust 1.87.0.
Update image to 20250807-0 since MSRV in Dockerfile is updated.
Signed-off-by: Songqian Li <sionli@tencent.com>
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Now 'create_acpi_tables_internal()' can generate ACPI tables with
different dsdt offset, so that it can be reused for generating ACPI
tables for `fw_cfg`.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Alex Orozco <alexorozco@google.com>
Optimize lychee workflow to check only changed
files in pull requests, avoiding excessive API
calls to prevent rate limits.
Fixes#7056
Signed-off-by: Shubham Chakrawar <schakrawar@crusoe.ai>
In case of CVM guest rsdp is set to none. Unwrapping it
make the vmm crashed. Don't call configure system if the
rsdb address is none.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Many of the workspace members in the Cloud-hypervisor workspace share
common dependencies. Making these workspace dependencies reduces
duplication and improves maintainability.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
The current documentation only mentions Windows
server support. Since only minimal adjustments
are needed for Windows 11 support, these were
added where applicable.
Also contains whitespace fixes, adds missing `\`
in example code and adds more cross references.
Signed-off-by: Lucas Grosche <lucas.grosche@cyberus-technology.de>
The other workspace members in the Cloud-hypervisor workspace
currently declare log version 0.4.22, but the tpm crate
has an older version. This inconsistency is addressed by this PR
which opens the door for declaring log as a workspace dependency.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
Running one or two tests in a tight loop can cause the download
functions to quickly hit GitHub's API rate limit. That causes the test
script to fail for no apparent reason.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Generate the data disk under a temporary directory so that multiple
instances of the test suites can run at the same time.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The other workspace members in the Cloud-hypervisor workspace
currently declare libc crate version 0.2.167, but the tpm crate
has an older version. This inconsistency is addressed by this PR
which opens the door for declaring libc as a workspace dependency.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
The other workspace members in the Cloud-hypervisor workspace
currently declare anyhow version 1.0.94, but the tpm crate
has an older version. This inconsistency is addressed by this PR
which opens the door for declaring anyhow as a workspace dependency.
Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
It shouldn't be necessary to lock the file for the adaptor. This removes
two layers of indirection for QcowDiskSync and VhdxDiskSync.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The PL031 RTC provides two features: a real-time counter and an alarm
interrupt. To use the alarm, the driver normally writes a time value
into the match register RTCMR, and when the counter reaches that value
the device triggers the interrupt.
At the moment the implementation ignores programming of the alarm, as
the feature seems rarely used in VMs. However the interrupt is still
triggered arbitrarily when the guest writes to registers, and the line
is never cleared. This really confuses the Linux driver, which loops in
the interrupt handler until Linux realizes that no one is dealing with
the interrupt (200000 unanswered calls) and disables the handler.
One way to fix this would be implementing the alarm function properly,
which isn't too difficult but requires adding some async timer logic
which probably won't ever get used. In addition the device's interrupt
is level-triggered and we don't support level interrupts at the moment,
though we could probably get away with changing this interrupt to edge.
The simplest fix, though, is to just disable the interrupt logic
entirely, so that the alarm function still doesn't work but the guest
doesn't see spurious interrupts.
Add a default() implementation to satisfy clippy's new_without_default
check, since Rtc::new() doesn't take a parameter after this change.
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
The read_exact() call was introduced in 82ac114b8 ("virtio-devices:
vsock: handle short read in muxer") to solve a crash when a connection
disconnected without sending any data, but it introduced a problem of
its own: because the socket is non-blocking, read_exact() may read
some data, then return ErrorKind::WouldBlock. In that case, the data
it read will be discarded. So for example if it read "CONNECT ",
and then nothing else was available to read yet, "CONNECT " would be
discarded, and so the next time this function was called, when epoll
triggered again for the socket, only the following data would end up
in command.buf, causing an error due to just a port number being an
invalid command.
Contrary to that commit message, this code was actually designed to
handle short reads just fine — in the case of a short read, it stores
the data it has read in command, and returns
Error::UnixRead(ErrorKind::WouldBlock), which is ignored by the
caller, and the function gets called again when there is more data to
read, building up command potentially over the course of several
reads. The only thing it didn't handle correctly, as far as I can
tell, was a 0-byte read, which happens when a client disconnects from
the socket without writing anything. All that's needed to fix this is
to avoid an invalid subtraction in that case, so this change reverts
82ac114b8, fixing the issue with partial commands being discarded, and
instead handles the 0-byte read by using slice::get, and treating an
empty command as an incomplete command, which of course it is.
Fixes: 82ac114b8 ("virtio-devices: vsock: handle short read in muxer")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
This makes it possible to run cargo test just for the virtio-devices
crate (as long as either KVM or MSHV is specified).
Signed-off-by: Alyssa Ross <hi@alyssa.is>
`std::mem::offset_of` could be used for calculating nested fields, use
this feature to shorten aarch64 reg offset calculation.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`std::mem::offset_of` is stabilized since Rust 1.77, let's use
implementation provided by std instead of manual implementation.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Manually implemented `_offset_of` and `offset_of` in
`arch/riscv64/mod.rs` are not used now, remove them.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`std::mem::offset_of` supports calculating offset of nested structures,
let's use implementation provided by std instead of manual
implementation.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Other lines are already logged using `log::error!` and
`env_logger` is initialized before calling
`start_net_backend` in `main()`.
Signed-off-by: Maximilian Güntner <code@mguentner.de>
Unify log formatting and printing as `eprintln!` and `log::error!`
would be used alongside each other.
When using e.g. `env_logger` lines printed with `eprintln!` would
lack formatting / colors.
Currently only relevant in `ch-remote` + `cli_print_error_chain`.
Note that the replaced messages now also end up in the logfile of
`cloud-hypervisor` when configured and not any longer in stderr.
Signed-off-by: Maximilian Güntner <code@mguentner.de>
Until now all messages generated using `log::level!`
(e.g., `warn!`) have not been printed as `ch-remote` did not
register a logger.
Furthermore, replace all `eprintln!` with `error!`
to align formatting for consistency.
Signed-off-by: Maximilian Güntner <code@mguentner.de>
Recently vfio crates have moved to crates.io, thus we should start
consuming the crate from crates.io instead git url.
This results in better versioning instead of tracking some git commit
sha.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Since action-rs/cross is deprecrated, thus move to
houseabsolute/actions-rust-cross.
We should pin the cross-version to the latest version to fix the build
issues with virtio-bindings crate.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
When invoking the script chown shows a warning.
chown: warning: '.' should be ':': ‘1000.1000’
From `info coreutils 'chown invocation'`.
Some older scripts may still use ‘.’ in place of the ‘:’ separator.
POSIX 1003.1-2001 (*note Standards conformance::) does not require
support for that, but for backward compatibility GNU ‘chown’ supports
‘.’ so long as no ambiguity results, although it issues a warning and
support may be removed in future versions. New scripts should avoid the
use of ‘.’ because it is not portable, and because it has undesirable
results if the entire OWNER‘.’GROUP happens to identify a user whose
name contains ‘.’.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
That feature was dropped when consolidating the UUID dependency because
somehow building the whole project worked. The CI system was happy.
However, building the block crate alone is broken. The vhdx code uses
Uuid::new_v4, which requires `v4` to be enabled.
Add the feature back.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
When a proper Rust backtrace is printed, the Rust std wants to use the
SYS_getcwd(79) system call to prettify some paths while printing. In
Cloud Hypervisor, this is at least relevant for printing panics or if
a `anyhow::Error` value is printed using `{e:?}` (but not `{e:#?}`).
The syscall cause can be found in `impl fmt::Display for Backtrace {}`
in `library/std/src/backtrace.rs`.
Without this addition, the seccomp violation of the SYS_getcwd (79)
hinders the proper error message including a full backtrace from showing
up. This annoying behaviour already delayed many debugging efforts. With
this fix, things just work. The new syscall itself should be pretty
harmless for normal operation.
```
thread 'vmm' panicked at virtio-devices/src/rng.rs:224:9:
Yikes, things went horribly wrong!
==== Possible seccomp violation ====
Try running with `strace -ff` to identify the cause and open an issue: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/new
[1] 287683 invalid system call (core dumped) RUST_BACKTRACE=full cargo run --bin cloud-hypervisor -- --api-socket --kerne
```
```
thread 'vmm' panicked at virtio-devices/src/rng.rs:224:9:
Yikes, things went horribly wrong!
stack backtrace:
0: 0x557d91286b62 - std::backtrace_rs::backtrace::libunwind::trace::hc20b48b31ee52608
at /rustc/17067e9ac6d7ecb70e50f92c1944e545188d2359/library/std/src/../../backtrace/src/backtrace/libunwind.rs:117:9
1: 0x557d91286b62 - std::backtrace_rs::backtrace::trace_unsynchronized::h5d207cd20f193d88
at /rustc/17067e9ac6d7ecb70e50f92c1944e545188d2359/library/std/src/../../backtrace/src/backtrace/mod.rs:66:14
...
67: 0x0 - <unknown>
Error: Cloud Hypervisor exited with the following error:
Failed to join on VMM thread: Any { .. }
Debug Info: ThreadJoin(Any { .. })
```
- add any panic, for example into the create or drop function of a
device
- add --seccomp=true|log to analyze the situation
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
The virtio_features_to_tap_offload() defined in ctrl_queue.rs
is duplicated. Remove it and use the one defined in lib.rs
instead.
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
Checksumming a type that has padding would use the padding in the
checksum, which is definitely wrong and is often unsound.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
Cargo fuzz build report an error:
error: lifetime flowing from input to output with different syntax can be confusing
--> /home/runner/work/cloud-hypervisor/cloud-hypervisor/block/src/lib.rs:747:13
|
747 | fn file(&mut self) -> MutexGuard<F>;
| ^^^^^^^^^ ------------- the lifetime gets resolved as `'_`
| |
| this lifetime flows to the output
error: lifetime flowing from input to output with different syntax can be confusing
--> /home/runner/work/cloud-hypervisor/cloud-hypervisor/block/src/async_io.rs:68:11
|
68 | fn fd(&mut self) -> BorrowedDiskFd;
| ^^^^^^^^^ -------------- the lifetime gets resolved as `'_`
| |
| this lifetime flows to the output
Signed-off-by: Yi Wang <foxywang@tencent.com>
Remote server errors are transferred as raw HTTP body. This way,
we lose the nested structured error information.
This is an attempt to retrieve the errors from the HTTP response
and to align the output with the normal error output.
For example, this produces the following chain of errors. Note
that everything after level 0 was retrieved from the HTTP server
response:
```
Error: ch-remote exited with the following chain of errors:
0: http client error
1: Server responded with InternalServerError
2: Error from API
3: The disk could not be added to the VM
4: Failed to validate config
5: Identifier disk1 is not unique
Debug Info: HttpApiClient(ServerResponse(InternalServerError, Some("Error from API<br>The disk could not be added to the VM<br>Failed to validate config<br>Identifier disk1 is not unique")))
```
In case the JSON can't be parsed properly, ch-remote will print:
```
Error: ch-remote exited with the following chain of errors:
0: http client error
X: Can't get remote's error messages from JSON response: EOF while parsing a value at line 1 column 0: body=''
Debug Info: HttpApiClient(ServerResponse(InternalServerError, Some("")))
```
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
With the foundations of each error type implementing std::error::Error,
we can now nicely walk the `.source()` chain and print an error trace.
This commit introduces improved user-facing error printing when:
- Cloud Hypervisor fails with an error
- ch-remote fails (client error)
- ch-remote fails (remote error)
The additional context is a clear improvement in UX for both users and
developers. In the following example, the new behaviour is shown for
a direct invocation of Cloud Hypervisor leading to a failure. This
looks similar for ch-remote.
```
Old Style
`target/release/cloud-hypervisor --api-socket /tmp/chv2.sock --kernel /etc/bootitems/linux/kernel_minimal/stable.bzImage --cmdline console=ttyS0 --serial tty --console off --disk path=img.raw --initramfs /etc/bootitems/linux/initrd_minimal/default`
Error booting VM: VmBoot(LockingError(BlockError(LockDiskImage(AlreadyLocked)))
```
```
`target/release/cloud-hypervisor --api-socket /tmp/chv2.sock --kernel /etc/bootitems/linux/kernel_minimal/stable.bzImage --cmdline console=ttyS0 --serial tty --console off --disk path=img.raw --initramfs
/etc/bootitems/linux/initrd_minimal/default`
Error: Cloud Hypervisor exited with the following chain of errors:
0: Error booting VM
1: The VM could not boot
2: Error locking disk images: Another instance likely holds a lock
3: Cannot lock images of all block devices
4: Failed to get Write lock for disk image: ./img.raw
5: The file is already locked
Debug Info: VmBoot(VmBoot(LockingError(DiskLockError(LockDiskImage { error: AlreadyLocked, lock_type: Write, path: "./raw_disk.bin" })))
```
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
The changes were mostly automatically applied using the following
Python script:
```python
import os, re
for root, _, files in os.walk("."):
for f in files:
if not f.endswith(".rs"):
continue
p = os.path.join(root, f)
with open(p, "r", encoding="utf-8") as file:
lines = file.readlines()
changed = False
for i in range(len(lines) - 1):
if re.search(r'#\[error\(".*: \{0[^}]*\}"\)\]', lines[i]) and "#[source]" in lines[i + 1].strip():
lines[i] = re.sub(r': \{0[^}]*\}"\)\]', '")]', lines[i])
changed = True
if changed:
with open(p, "w", encoding="utf-8") as file:
file.writelines(lines)
print("Fixed:", p)
```
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
# Conflicts:
# vmm/src/api/http/mod.rs
Having them sorted alphabetically makes more sense since there are
already many, and the list is growing. This improves the UX for users
and developers.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Instead of exiting on IO errors, report the errors to the guest with
VIRTIO_BLK_S_IOERR. For example, the guest kernel will log something
similar to this if the nbd behind /dev/vdc is unexpectedly disconnected:
[ 166.033957] I/O error, dev vdc, sector 264 op 0x1:(WRITE) flags 0x9800 phys_seg 1 prio class 2
[ 166.035083] Aborting journal on device vdc-8.
[ 166.037307] Buffer I/O error on dev vdc, logical block 9, lost sync page write
[ 166.038471] JBD2: I/O error when updating journal superblock for vdc-8.
[...]
[ 174.234470] EXT4-fs (vdc): I/O error while writing superblock
In case the rootfs is not located on the affected block device, this
will not crash the guest.
Fixes: #6995
Signed-off-by: Gauthier Jolly <contact@gjolly.fr>
This was caught by the nightly compiler during cargo fuzz build.
error: lifetime flowing from input to output with different syntax can be confusing
--> /home/runner/work/cloud-hypervisor/cloud-hypervisor/hypervisor/src/arch/x86/emulator/mod.rs:493:26
|
493 | pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----------- the lifetime gets resolved as `'_`
| |
| this lifetime flows to the output
|
= note: `-D mismatched-lifetime-syntaxes` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(mismatched_lifetime_syntaxes)]`
help: one option is to remove the lifetime for references and use the anonymous lifetime for paths
|
493 | pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<'_, T> {
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
cargo fuzz build complaints about some un-used function in the
instruction emultator. Silence the warning by allowing dead code
generation.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Since it is used by multiple components at this point, it is better to
move it to workspace level dependency.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
There are a little many cpuid logs now. When starting a vm with
64 vcpu, we can get more than four thousand INFO messages:
cat vm1.log |grep 'arch/src/x86_64/mod.rs:891' |wc -l
4352
Signed-off-by: Yi Wang <foxywang@tencent.com>
This commit adds the warning to deprecate the SGX support with the
intention to remove the support from code base in two release cycles.
See: #6960
Signed-off-by: Bo Chen <bchen@crusoe.ai>
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
When booting a Linux guest in SMP configuration,
the following kernel warning can be observed:
[Firmware Bug]: CPUID leaf 0xb subleaf 1 APIC ID mismatch 1 != 0
The reason is that we announce the presence of the extended topology
leaf, but fail to announce the x2apic ID in EDX.
Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
On-behalf-of: SAP thomas.prescher@sap.com
No sane guest OS will allow hotplugging all cpus.
However, the REST API currently allows specifying
`ch-remote resize --cpus 0`.
On Linux, we can then observe the following error in the kernel log:
processor cpu0: Offline failed.
Subsequent resize commands via ch-remote will then fail with
VcpuPendingRemovedVcpu because the removal of cpu0 was never
successful.
Fix this by disallowing resizing to zero vCPUs.
Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
On-behalf-of: SAP thomas.prescher@sap.com
For use in QEMU, I would like GuestMemoryRegion to return a BitmapSlice
instead of a &Bitmap. This adds some flexibility that QEMU needs in
order to support a single global dirty bitmap that is sliced by the
various GuestMemoryRegions.
However, this removes access to the methods of AtomicBitmap, and in
particular reset() and get_and_reset(). Fortunately, cloud-hypervisor
always uses GuestMemoryMmap, and therefore `region` is known to be a
&GuestRegionMmap. Dereferencing it returns the MmapRegion to which the
bitmap is attached, thus calling MmapRegion::bitmap(); this has the
same effect as `<GuestRegionMmap as GuestRegion>::bitmap()`, and works
both with or without https://github.com/rust-vmm/vm-memory/pull/324.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.
This allows future work that nicely prints the error chains,
for example.
So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Allow tap interfaces to be configured with an IPv6 address. The change
is fairly straightforward: we need to update the API types and CLI
parsing to accept either an IPv6 or IPv4 and then match on the IP
address type when the tap device is configured.
For IPv6 addresses, the netmask (prefix) must be provided at the same
time as the address itself (in the SIOCSIFADDR ioctl). They cannot be
configured separately. So we remove the separate "set_netmask" function
and convert "set_ip_addr" to also accept a netmask. For IPv4 addresses,
the IP address and netmask were already always set together, so this
should have no functional impact for users of IPv4 addresses.
Signed-off-by: Gregory Anders <ganders@cloudflare.com>
The DeviceManagerError type is among the types missing the Error trait
so far. To streamline the code and to simplify usage on higher levels
of this error type, this type now implements Display and Error.
As not all variant values are Error yet, `#[source]` is not everywhere
where it could be. This is done in the next commits.
The high level goal is: Enable future work to improve the error output
of cloud hypervisor.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
The new locking behavior uncovered that unfortunate test situation:
Many tests running in parallel access the same disk image with
rw permissions. Luckily, none of the tests actually writes to
the disk. Therefore, we can set it to readonly=true. In case this
changes, the test needs to be moved to the sequential test module.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
# What
This commit introduces file-based advisory locking for the files backing
up the block devices by using the fcntl() syscall with OFD locks. The
per-open-file-descriptor (OFD) locks are more robust than traditional
POSIX locks (F_SETLK) as they are not tied to process IDs and avoid
common issues in multithreaded or multi-fd scenarios [1]. Therefore,
we don't use `std::fs::File::try_lock()`, which is backed by F_SETLKW.
The locking mechanism is aware of the `readonly` property and allows
`n` readers or `1` writer (exclusive mode).
As the locks are advisory, multiple cloud-hypervisor processes can
prevent themselves from writing to the same file. However, this is not
a system-wide file-system level locking mechanism preventing to open()
a file.
The introduced new locking mechanism does not cover vhost-user devices.
# Why
To prevent misconfiguration and improve safety, it is good practice to
protect disk image files with a locking mechanism. Experience and common
best practices suggest that advisory locks are preferable over mandatory
locks due to better compatibility and fewer pitfalls (in fs space).
The introduced functionality is aligned with the approach taken by
QEMU [0], and is also recommended in [1].
# Implementation Details
We need to ensure that not only normal operation keeps working but also
state save/resume and live-migration. Especially for live migration,
it is crucial that the sender VMM releases the locks when the VM stops
so the receiver VMM can acquire them right after that.
Therefore, the locking and releasing happen directly on the block
device struct. The device manager knows all block devices and can
forward requests to these types.
Last but not least, this commit uses on explicit lock acquiring
but implicit lock releasing (FD close). It only explicitly releases
the locks where this integrates more smoothly into the existing
code.
# Testing
I tested
- normal operation
- state save/resume,
- device hot plugging,
- and live-migration
with read/shared and write/exclusive locks.
One can use the `fcntl-tool` to test if locks are actually acquired
or released [2].
# Links
[0] 825b96dbce/util/osdep.c (L266)
[1] https://apenwarr.ca/log/20101213
[2] https://crates.io/crates/fcntl-tool
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
To support PCIe P2P between VFIO devices, we populate IOMMU mappings for
the non-emulated MMIO regions of all VFIO devices via
`VFIO_IOMMU_MAP_DMA` (f0c1f8d), but the patch did not properly update
the IOMMU mappings with BAR reprogramming.
Fixes: #7027
Signed-off-by: Bo Chen <bchen@crusoe.ai>
The way how we handle PCI configuration space for vfio and vfio-user
devices are different from the rest of PCI devices. Besides accesses to
BAR registers (trapped to access the shadowing PCI config space we
maintained), accesses to other registers (including the COMMAND
register) are handled directly by the underline vfio or vfio-user
device.
This patch adds the proper handling of pending BAR reprogramming for
vfio and vfio-user devices.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
The Memory Space Enable (MSE) bit from the COMMAND register in the
PCI configuration space controls whether a PCI device responds to memory
space accesses, e.g. read and write cycles to the device MMIO regions
defined by its BARs. The MSE bit is used by the device drivers to ensure
the correctness of BAR reprogramming. A common workflow is, the driver
first clears the MSE bit, then writes new values to the BAR registers,
and finally set the MSE bit to finish the BAR reprogramming.
This patch changes how we handle BAR reprogramming for all PCI
devices (e.g. virtio-pci, vfio, vfio-user, etc.), so that we follow the
same convention, e.g. moving PCI BARs when its MSE bit is set.
Note that some device drivers (such as edk2) only clear and set MSE once
while reprogramming multiple BARs of a single device. To support such
behavior, this patch adds support for multiple pending BAR reprogramming.
See: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7027#issuecomment-2853642959
Signed-off-by: Bo Chen <bchen@crusoe.ai>
A BAR reprogramming of a PCI device will only happen when the (guest)
kernel write to its PCI config space, e.g. the detection of bar
reprogramming (`detect_bar_repgraomming()`) can be embedded to the PCI
config space write (`write_config_register()`). It simplifies APIs
exposed by the `struct PciConfiguration` and `trait PciDevice`. It also
prepares for easier handling of pending bar reprogramming when the MSE
bit of the COMMAND register is not enabled at the time of changing BAR
registers.
See: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7027#issuecomment-2853642959
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Fixing the following clippy issue using `cargo clippy --fix`:
error: variables can be used directly in the `format!` string
--> build.rs:25:27
|
25 | version.push_str(&format!("-{}", extra_version));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Currently a lot of functions are stubbed out with unimplemented feature
tag. Add the missing implementation to successfully boot ARM64 guests on
MSHV.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Num SPI and Base SPI nodes should be added before the end node to be
included in the device tree generation.
Fixes: eac44e6 (arch: Extend FDT for GICv2M device for ARM64 on MSHV)
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
It seems like address allocation has been spread into different files
and different location for x86 vs ARM. This makes it hard to follow the
code. Thus, unify it a single location which satisfies all the
requirement.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
It just simplifies code and improves the code read-ability without much
affecting the boot performance.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
This will satisfy the requirement of MSHV i.e., setting the GICD base
address before initializing the VM.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
For MSHV guests, we would need interrupt controller to be initialized
before the VM gets initialized. This is because we are registering the
base address of GIC distributor with MSHV as part of interrupt
controller initialization workflow. And MSHV mandates that this property
is set before we initialize the VM.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
For ARM64 guests we need to set three important partition property:
1) PPI interrupt ID for timer interrupt
2) PPI interrupt ID for PMU interrupts.
3) Hiding LPI support from the guest because MSHV does emulate ITS for
the guest.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Since this would be used in other places inside the hypervisor and
hypervisor crate cannot take a dependency on arch crate, as that creates
cyclic dependency.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Currently PPI interrupt ID are hardcoded as numbers, it would be ideal
to define them as constants and could be reused in other parts of the
hypervisor crate.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Along with also bump the vfio-bindings crates to use the latest
mshv-bindings.
There is a breaking change in the new mshv crate which requires an
additional step to initialize vm after creating it.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
On x86 MSHV guests only used to support MSI based interrupts via IOAPIC
but ARM64 guests uses legacy interrupt for its functioning. Thus, extend
the logic to create routing entry to support legacy interrupts for ARM64
guests on MSHV.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
For MSHV arm64 guest, there is an in-hypervisor GICv2M emulation and for
that to work, it needs to be enlightened with the base address of GIC
redistributor exposed to guest via FDT.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
GICv2M requires two additional properties to be exposed via FDT:
1) Base SPI number and 2) Total number of SPIs. SPIs in general starts
from 32 and goes upto 1019. But currently we are limiting the range to
96 as that should be good enough for any normal Linux guest to function.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Since there are not a wide availability of RISC-V boards available at
the moment, it is easiest to develop with a QEMU virtual machine. I had
a hard time setting one up, but with the assistance of Ruoqing, I was
able to get one running. These are the steps I took to do so.
Signed-off-by: abm-77 <andrewmiller77@protonmail.com>
Ubuntu 24.04 LTS (Noble Numbat) is tested against cloud-hypervisor v45.0
release and it is working, document status in README.md.
Signed-off-by: Bingxin Li <bl497@cam.ac.uk>
ARM64 system register constants are not 1:1 mapped to MSHV definition of
those registers so we need a small helper function to translate that
mapping before retrieving those system registers.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
There are other potential users of these registers definitions in the
hypervisor crate. And hypervisor crate cannot use definitions from arch
crate because it creates cyclic dependency.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
In order to be on-pair with what's we're using from micro-http, let's
also add the proper status code here as well (as it will be used by
`ch-remote`).
Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
Although the CPU manager gives us a quite descriptive error, on the
application side (the part calling Cloud Hypervisor) we have absolutely
no way to distinguish such error from any other error that may happen
when resizing a VM.
With this in mind, let's be more specific and return a TooManyRequests
(429) error, allowing the caller to have a chance to decide whether they
want to retry the operation or not.
https://datatracker.ietf.org/doc/html/rfc6585#section-4
Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
As the coming patches in this series will take advantage of a status
code that was recently added there.
Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
New MSHV version updates the get_msr_list output as
vector instead of fam-wrapper. It avoids unnecessary
conversions.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Latest mshv crates contains some IOCTL changes that
enhances VM creation and configures the features in correct
way. Also adds some features that improves register access.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
MSHV allows VMM to map the VP register page into root.
This feature helps VMM to faster process most of the frequent
used registers. This patch uses the VP register page for port
handling in CPU run method.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
As part of this configure the program counter, pstate and X0 registers.
Program counter will point to the start address of the kernel/firmware
in the guest memory. X0 will point to start of the FDT.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
As part of this configuration, two things are being done:
1. Setting up the base address of GIC Distributor
2. Setting up the base address of GIC Interrupt Translator
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Initial PSTATE value would be same for both KVM and MSHV. Thus, move it
to common register definition pool.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
There are a lot of internal functions that are not and probably should
not be called from other places.
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
If a device returns 0xff as a capability pointer bad things happen.
The code before the previous commits would crash in debug builds due
to integer overflow. With the two lowest bits masked out, it sends the
code into an endless loop.
Be more robust by at least handling the case where the capability
appears to point to itself.
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
The PCI standard mandates that the lower bits of the capability
pointer are masked out before using the pointer. See PCI Local Bus
Specification 3.0 Chapter 6.7 "Capabilities List".
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
Currently, the code tries to follow the PCI capabilities list in
offset 0x34 in the config space regardless of whether the status
registers says this is valid. Fix by adding the appropriate check.
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
OSDev has cranked up its bot protection. The following link works for
me locally after clicking the "I'm a human" button. I guess the CI
fails this check...
Without this exception the CI fails the link check stage:
* [403] [https://wiki.osdev.org/IOAPIC](https://wiki.osdev.org/IOAPIC) | Network error: Forbidden
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
Use the context from Unmapped Gpa exit from the hypervisor to initialize
the MshvEmulatorContext and later call the emulator to decode the
instruction.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Currently it would be using the syndrome register for instruction
decoding which is what KVM has been using in-kernel to decode
instructions for ARM64 guests. In future, it could be extended with an
actual instruction emulator if required. But most Linux guests works
well with the instruction decoder using syndrome register.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
This helps in implementing an instruction decoder for MSVH which does
not support in-kernel instruction decoding like KVM.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Some tests are specifically designed for KVM hypervisor platform. Thus,
guard them using appropriate feature flags.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
There are a bunch of unused variables as of now on the MSHV side and
compiler warns about them. Thus, mark them as unused for the time being.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
MSHV does not emulate a GICv3-ITS for guests to support MSI interrupts,
instead it exposes a GICv2m device. Currently adding a skeleton code
which would be modified later on with complete implementation.
With this we can start compiling cloud-hypervisor for MSHV on ARM64.
This will make sure that we don't regress in future in terms of basic
compilation test.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
`zerocopy` is bumped to 0.8.x after 0.3.4 of igvm crates, bump to rev
d062818 to capture `zerocopy` upgrade, but we should bump to 0.3.5
later.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Manually bump zerocopy to 0.8.24 since our dependabot could not perform
the upgrade properly.
Manually bump acpi_tabls as well since it's depending on zerocopy.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
The dependency `bitfield-struct` 0.10.x of `igvm` 0.3.5 requires MSRV
1.83.0, bump to catch up.
Update image to 20250412-0 because MSRV in Dockerfile is updated.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
This aligns with our CLI syntax. The correctness of `DiskConfig` will be
ensured via `VmConfig::validate()`, e.g. `path` and `socket` are
mutually exclusive.
Fixes: #7016
Signed-off-by: Bo Chen <bchen@crusoe.ai>
Use the builtin function instead of using `==` operator.
Warning from the beta compiler:
error: use `std::ptr::eq` when comparing raw pointers
--> pci/src/vfio.rs:1616:24
if host_addr == libc::MAP_FAILED {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: try: `std::ptr::eq(host_addr, libc::MAP_FAILED)`
= help: for further information visit
= https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq
= note: `-D clippy::ptr-eq` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]`
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Use the builtin function to improve the readability of the code.
Warning from beta compiler:
error: manual arithmetic check found
--> vm-allocator/src/address.rs:151:30
|
|let adjust = if alignment > 1 { alignment - 1 } else { 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| help: replace it with: `alignment.saturating_sub(1)`
|
= help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub
= note: `-D clippy::implicit-saturating-sub` implied by `-D warnings`
= help: to override `-D warnings` add`#[allow(clippy::implicit_saturating_sub)]`
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Rust has a new way of constructing other error and clippy complains if
we are still using the older way to construct error message. Thus,
migrate to the new approach suggested by the clippy.
Warning from beta compiler:
error: this can be `std::io::Error::other(_)`
--> block/src/vhdx/mod.rs:142:17
|
| / std::io::Error::new(
| | std::io::ErrorKind::Other,
| | format!("Failed to update VHDx header: {e}"),
| | )
| |_________________^
|
= help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error
help: use `std::io::Error::other`
std::io::Error::other(
format!("Failed to update VHDx header: {e}"),
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
`serde_json` crate is referenced by multiple components, centralize it
to workspace to better manage this crate.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
KVM supports GICv3-ITS emulation and the current GicState is modelled
around the KVM implementation. We should refactor this to accomodate
other hypervisor requirements. For example, MSHV only support GICv2M
emulation for guests for delivering MSI interrupts instead of GICv3-ITS.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Add `riscv.md` to guide developers/users on preparing guest kernel,
image, and direct boot VM on riscv64 platforms; document support status
and known limitations.
Co-authored-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
The larger the VM memory, the greater the memory pressure, and the
greater the stop_dirty_log() overhead. Moving stop_dirty_log() outside
the downtime period can reduce downtime.
Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
`riscv64_set_one_reg_to_vcpu` macro is used to set value of specific
RISC-V `$reg_name` stored in `state` to KVM Vcpu.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`riscv64_get_one_reg_from_vcpu` macro is used to extract RISC-V register
data from KVM Vcpu according to `$reg_name` provided to `state`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`igvm` crates are referenced by multiple components, centralize them to
workspace to better manage those crates.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Certain MSHV ioctls are only available on x86 architecture. Thus,
conditionally compile seccomp filter for x86 and in general enable
seccomp filters when compiling for MSHV on aarch64.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
The CLI has grown to a big variety of options. clap prints them in the
help message (--help) in the order they were defined. We now are at a
point where grouping things logically together doesn't work well.
Further, there is no support by clap for logical grouping and the
current code base wasn't consistent. Therefore, this commit introduces
two changes:
- a new structure to define arguments (all in an array)
- an alphabetical ordering of the arguments
No other changes have been made. No options have been altered.
This significantly improves:
- code maintainability and extensibility
- readability of the --help output
A unit test ensures they stay sorted. A better approach to check if the
list of arguments (known at build time) is sorted would be a compile
time check (`const`), but this currently isn't possible in stable Rust.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Use the definitions from the rust-vmm/mshv crate for various
datastructures such as StandardRegisters, RegList, VcpuInit etc.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
We are moving the metrics and rate-limiter workers to a bare-metal
system, so that we can have more consistent results (particularly for
the block device metrics)
Signed-off-by: Bo Chen <bchen@crusoe.ai>
v0.5.0 of `seccompiler` has supported riscv64, let's bump from v0.4.0 to
v0.5.0 to capture that support.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
In addition to the BDF information on the guest, reporting the device
path of the VFIO device on the host is more useful when it comes to
debug DMA map/unmap errors particularly ones caused by failing hardware
on the host.
Signed-off-by: Bo Chen <bchen@crusoe.ai>
`test_snapshot_restore_with_fd` uses unsafe file descriptors and with
rust 1.82.0 it errors with:
```
fatal runtime error: IO Safety violation: owned file descriptor already
closed
```
so has been skipped for now.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
We are having complains from Rust 1.86.0-beta.1 (f0cb41030 2025-02-17)'
clippy, which suggests us to replace `repeat().take()` with
`repeat_n()`. While `repeat_n()` is stablized in Rust 1.82.0.
Update image to 20250307-2 because MSRV in Dockerfile is updated.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
While executing `rustup toolchain add --profile minimal
1.82.0-x86_64-unknown-linux-musl`, it errors out with:
```
error: toolchain '1.82.0-x86_64-unknown-linux-musl' may not be able to
run on this system
note: add the `--force-non-host` flag to install the toolchain anyway
```
Add `--force-non-host` to install minimal musl toolchain for x86_64.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Currently we are just storing the StandardRegisters in the Vcpu state
which would be required for saving and restoring the ARM64 guest on
MSHV.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
The reason `test_vfio_user` fails is as @likebreath pointed: our ARM
host does not support SVE, while the nvme_tgt binary built from the
container image requires it. As a result, we encountered a SIGILL when
running the nvme_tgt binary. This also explains why this is not
happening when the container is built on the same host itself.
And quote from @rbradford:
When a job is run on one of the workers it looks to see if there is a
container locally matching the name as specified in the dev_cli.sh
script - if there is then it uses it. Otherwise it will try and download
it from the container registry - if that fails then it will built
locally. For the x86-64 workers started dynamically it will never have a
local version as they are a fresh VM. But on the ARM64 builder is a
local container image cache.
This can lead to an issue where if the image is build with one version
(a handcrafted datestamp) and then the Dockerfile is changed without
changing the timestamp then an old version may be fetched from the cache
or server. It is there for essential to always bump the datestamp (there
is a number after the - that can be used for this.)
However there is also the added complexity that image that is build and
uploaded to the container registry is not the same as the built locally
and thus used for the initial testing of the Dockerfile change. This
leads to the issue we have seen where different CPU compiler flags (from
-march=native) from the QEMU cross build in the hosted GHA action and
the local ARM64 build. Resulting in a binary in the remotely built
container not working locally.
We end up specifying TARGET_ARCHITECTURE="armv8.2-a" for building spdk,
and put built `python/spdk/` folder into `/usr/local/bin/spdk-nvme`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`arm64` build in ubuntu:22.04 errors out with `error processing package
libc-bin`. This issue is a known issue between the binfmt (running
different architectures via QEMU) and the libc ldconfig binary running
in container. We're "suddenly" having issues as ubuntu-latest (which is
the OS version we run the GH action container with) was recently changed
from 22.04 to 24.04 and hence why upgrading the container userspace from
22.04 to 24.04 solves the problem.
Removed deprecated package `python3-distutils`.
Update image name from `20250111-0` to `20250222-0`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Currently a bunch of KVM specific interfaces are leaked into the vmm
crate which should ideally does not contain any hypervisor specific data
structures.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Use `lychee` to check availability of links in cloud-hypervisor.
The urls explictly excluded in config file are manually checked.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
We have lost track to releases before v27.0 since these projects no
longer exists. Delete links to those projects.
Update links to a detailed view specific to each group of release.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Previous repo hosts details of `Rust Style` is removed, point `Rust
Style` to `style-guide` in `rust-lang/rust` repo.
Link to provide illustration on `signed-off-by language` is also
removed, use a snapshot found in web archive [1] instead.
Format `CONTRIBUTING.md` using `mdformat` with GitHub Flavored Markdown
(GFM).
[1] https://web.archive.org
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
TDX homepage was moved to elsewhere, and `sgx` support is upstreamed
since v5.11 kernel.
Format `intel_sgx.md` using `mdformat` with GitHub Flavored Markdown
(GFM).
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
TDX homepage was moved to elsewhere, and `tdx-tools` repo was removed.
Provide a valid link of TDX homepage and change all reference to
`tdx-tools` to `tdx-linux`.
Format `intel_tdx.md` using `mdformat` with GitHub Flavored Markdown
(GFM).
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
There is a link referencing `rate-limiter` module of `firecracker`, but
that module no longer exsits.
Point the link to a commit with the same date in `firecracker` when this
commit was merged to `cloud-hypervisor`.
Format `io_throttling.md` using `mdformat` with GitHub Flavored Markdown
(GFM).
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`docs/arm64.md` was removed and splited into `README.md`, `building.md`
and `uefi.md` in #4991.
Let's point it to
`8ab15b9a98/docs/arm64.md`
the commit right before `docs/arm64.md` was removed in main branch.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Previous link `docs/logging` is not valid, replacing `docs/logging` with
`docs/logging.md`.
Format `logging.md` using `mdformat` with GitHub Flavored Markdown
(GFM).
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Use this to add any extra versioning information to the binary. It is
useful when packaging Cloud Hypervisor.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This is a typo here, `interrupt-controller` attribute of each CPU node
should not have a `#` prepended.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Replace the use of a reference kernel configuration file from this
repository with the use of a defconfig from the linux fork.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The IMSIC attr of RISC-V AIA is wrongly configured to start from 0, which
would error out with `os error 22` (invalid argument).
```console
Error booting VM: VmBoot(DeviceManager(CreateInterruptController(CreateAia(CreateVaia(Vaia error SetDeviceAttribute(SetDeviceAttribute(Invalid argument (os error 22))))))))
```
`riscv_imsic_attr_of` should shift `cpu_index` by 1 here to produce
correct IMSIC attr.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
For more control over updating the guest kernel use a fixed tag name
rather than fetching the latest.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Currently, Cloud Hypervisor does not set a VIRTIO_IOMMU_F_INPUT_RANGE
feature bit for the VirtIO IOMMU device, which, according to spec[1],
means that the guest may use the whole 64-bit address space is for
IOMMU purposes:
>If the feature is not offered, virtual mappings span over the whole
>64-bit address space (start = 0, end = 0xffffffff ffffffff)
As far as I am aware, there are currently no host platforms on
the market capable of addressing the whole 64-bit address space.
For example, I am currently working with a host platform that reports
39-bit address space for IOMMU purposes:
>DMAR: Host address width 39
When running a VFIO pass-through guest on such a platform, NVIDIA
driver in guest gets DMA mapping failures when working with large data,
and this results in Cloud Hypervisor exiting with the following error:
>cloud-hypervisor: 1501.220535s: <__iommu>
>ERROR:virtio-devices/src/thread_helper.rs:53 -- Error running worker:
>HandleEvent(Failed to process request queue : ExternalMapping(Custom
>{ kind: Other, error: "failed to map memory for VFIO container, iova
>0x7fff00000000, gpa 0x24ce25000, size 0x1000: IommuDmaMap(Error(22))"
>}))
Passing "--platform iommu_address_width=39" to Cloud Hypervisor built
with this change fixes this.
[1]: https://docs.oasis-open.org/virtio/virtio/v1.3/csd01/
virtio-v1.3-csd01.html#x1-5420006
Signed-off-by: Nikolay Edigaryev <edigaryev@gmail.com>
When VM restore fails, the VMM state is left with some side-effects,
such as a VM being created. It would prevent the VMM from creating and
booting a new VM or restoring from a VM snapshot.
To fix this issue, this patch explicitly handles the side effects to the
VMM state when VM restore fails, e.g. clear the VmConfig and shutdown
the VM being created.
Fixes: #6869
Signed-off-by: Bo Chen <bo.arvin.chen@gmail.com>
With VM restore, the VMM is always re-creating a VM based on the
restored `VmConfig`. We should always re-generate the 'console_info'
from the `Vmm` struct to stay consistent with the new VM being created.
Signed-off-by: Bo Chen <bo.arvin.chen@gmail.com>
Instead of reinventing this mock infrastructure in the upcoming fuzzer,
reuse the one that is already available.
However this change makes Clippy complain that TestBackend and
TestContext don't implement Default. This is just test code, we can
suppress Clippy in this case.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Updating the kernel to v6.12 has shown up a flaw in the workflow for our
binary kernel releases. The CI job that builds the binary kernel in the
cloud-hypervisor/linux repository fetches the config from the main
branch of the cloud-hypervisor/cloud-hypervisor repository. However the
CI job to update the kernel version to use is in the cloud-hypervisor
repository.
As a workaround - update the kernel config and version in the
cloud-hypervisor repository to point to v6.12 and use the ability to
build the kernel during the CI run. Once merged to main a new release
can be made in the linux respository which will build a binary asset
using the new config. After that release the CI jobs on the
cloud-hypervisor repository can changed back to using the binary kernel
assets.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Remove an erroneous optimisation that used the page size mask to reduce
the range to iterate through on the set of mappings. This doesn't work
as the virtio-iommu ranges are larger than a single page. This may have
worked in the past when the mappings were limited to a single page.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
No change to the Dockerfile but I observed that the 20251022-0 image was
not available in the repository.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
MSHV's SEV-SNP implementation calls ioeventfds whenever there is an
event.
This change removes the need frequent allocation and deallocation of a
vector, while at the same time makes sure other call sites are
unaffected.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This avoids ambiguity of parameters:
error: ambiguous reference to positional arguments by number in a tuple variant; change this to a named argument
--> block/src/qcow/mod.rs:48:48
|
48 | #[error("File larger than max of {}: {0}", MAX_QCOW_FILE_SIZE)]
| ^^^^^^^^^^^^^^^^^^
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This will become useful when we build the fuzzing target for the
instruction emulator, because there is no need to pull in the rest of
the hypervisor crate in that situation.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The fastfmt feature and VEX support use techniques that appear to leak
memory in the eye of LLVM's address sanitizer.
While at it, disable a bunch of instruction set decoding support we
never intend to support.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The size was set to one because without VIRTIO_BLK_F_SEG_MAX, the guest
only used one data descriptor per request.
The value 32 is empirically derived from booting a guest. This value
eliminates all SmallVec allocations observable by DHAT.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This allows the guest to put in more than one segment per request. It
can improve the throughput of the system.
Introduce a new check to make sure the queue size configured by the user
is large enough to hold at least one segment.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
When the main fuzzer function returns (), it is equivalent to
returning Corpus::Keep.
In some of the return paths, we want to reject the input so that the
libfuzzer won't spend more time mutating them.
The should make fuzzing more efficient. No functional change intended.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The checksum field in the original buffer should be zeroed.
The code was zeroing a temporary buffer. That's wrong.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The original code was buggy. It always attempted to update the header,
even when the file was opened as read-only. That led to an error.
The specification states that the headers should be updated when the
first user visible write happens. We can just drop the incorrect code.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The ASYNC flag forces requests to go to worker threads. Worker threads
are expensive. Let the kernel decide what to do.
With this change, I no longer see an excessive amount of io_uring worker
threads.
Quote from the manual for io_uring_sqe_set_flags(3):
```
IOSQE_ASYNC
Normal operation for io_uring is to try and issue an sqe
as non-blocking first, and if that fails, execute it in an
async manner. To support more efficient overlapped
operation of requests that the application knows/assumes
will always (or most of the time) block, the application
can ask for an sqe to be issued async from the start. Note
that this flag immediately causes the SQE to be offloaded
to an async helper thread with no initial non-blocking
attempt. This may be less efficient and should not be
used liberally or without understanding the performance
and efficiency tradeoffs.
```
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Instead of silently ignoring the error, return an error to the callers.
This in practice should never happen, because the submission queue size
(ring depth) is the same as the virtio queue size. Virtio queue won't
push more requests than there are submission queue entries.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The original code relied on the default `read_vectored` or
`write_vectored` implementations from the standard library.
The default implementation of those functions only uses the first
non-empty buffer. That's not correct when there are more than one
buffers.
Fixes: #6876
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This system is erroring out on jobs due to insufficient memory - reduce
parallelism to allow CI jobs to complete.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Updated the live migration documentation to include instructions for
performing cross-host live migrations over TCP connections.
Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
Add support for cross-host live migration over TCP, which
significantly improves performance in cross-host live migration
scenarios compared to the Unix socket forwarding method.
Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
Bump vm-memory from 0.16.0 to 0.16.1 to include the implementations of
ReadVolatile and WriteVolatile for TcpStream.
Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
While non-Intel CPU architectures don't have a special concept of IO
address space, support for PCI I/O regions is still needed to be able
to handle PCI devices that use them.
With this change, I'm able to pass through an e1000e device from QEMU
to a cloud-hypervisor VM on aarch64 and use it in the cloud-hypervisor
guest. Previously, it would hit the unimplemented!().
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Add a bitmap to MshvVM struct for caching the pages
that the VMM got shared access from the guest.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Pass memory size from vmm crate to hypervisor VM
creation API so use for creating Bitmap for SEV-SNP
guest.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
For SEV-SNP VM on MSHV we need to request page access during
IO, we want to avoid such request for the page that have already
been requested. In order to maintain the bitmap we need the memory size
during bitmap creation.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
VMM needs to handle VMG exit for guest request. This patch
removes the old method that uses gpa_read/write(IOCTL and hypercall),
which is expensive and update the GHCB page using
mapped(root partition) struct.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
VMM needs to handle VMG exit for MMIO. This patch
removes the old method that uses gpa_read/write(IOCTL and hypercall),
which is expensive and update the GHCB page using
mapped(root partition) struct.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
VMM needs to handle VMG exit for IO Port. This patch
removes the old method that uses gpa_read/write(IOCTL and hypercall),
which is expensive and update the GHCB page using
mapped(root partition) struct.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
VMM needs to handle VMG exit for doorbell page. This patch
removes the old method that uses gpa_read/write(IOCTL and hypercall),
which is expensive and update the GHCB page using
mapped(root partition) struct.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
After handling the VMG exit vmm needs to clear the exitinfo1
into the GHCB page. This patch replaces the old
method(gpa_write) and clear the exitinfo1 using mapped GHCB struct.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
For confidential VM on MSHV, GHCB page is the communication
method between guest and host. All the CVM exits, VMM
needs to read and write to the GHCB page. MSHV provides
an option to remap the page to the root partition. This
way VMM could directly read and write to the page and
skip extra IOCTL and hypercall. This improvement makes
the IO 10% faster.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
TPM support on RISC-V is not scheduled in this stage, we will come back
when it's ready and we have workloads to verify it on RISC-V.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Currently `devices` module cannot be solely built, by specifying
`arch/kvm` to turn on the features required for its dependency - `arch`
crate to build. Thus enabling `devices` crate to be built and tested
with command:
```sh
cargo build -p devices --features kvm
```
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`arch` module are required for devices module to build. Enabling `arch`
module in target specific dependencies section.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Provide implementation for GSI allocator to work on riscv64
architecture, and doc comment for riscv64 as well.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Currently `vm-allocator` module cannot be solely built, by add
`features` section and specifying `arch/kvm` to turn on the features
required for its dependency - `arch` module to build. Thus enabling
`vm-allocator` crate to be built and tested with command:
```sh
cargo build -p vm-allocator --features kvm
```
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`arch` module are required to provide definitions for riscv64 system irq
and memroy allocation, enabling `arch` module in target specific
dependencies section.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Integrate fdt setup and layout for `riscv64` to `arch` crate, provide
definitions of `riscv64` platform specific error and reuse
`MmioDeviceInfo`, `PciSpaceInfo` structures and `DeviceInfoForFdt` impl
block for `riscv64`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Reused layout set for `aarch64` as much as possible to provide a concise
and compatible (for devices) layout for RISC-V 64-bit.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`fdt_parser` and `vm-fdt` crates are required to setup fdt used to boot
riscv64 virtual machines, enabling the two crates in target specific
dependencies section.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
It turns out we need to setup `a0`, `pc` and `a1` for all vcpus before
we run them, remove predicates used to set `pc` and `a1` for `vcpu0`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Previous `Vaia` implementation uses types as it is, thus the property
string generated for fdt setup requires additional type conversion.
Change the types used in the methods of `Vaia` trait to provide a
concise fdt setup process.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
The rate-limiter worker was moved to use small Azure VMs (#6731) and now
requires more time to complete.
Increasing its timeout to stablize this worker.
Signed-off-by: Bo Chen <bo.arvin.chen@gmail.com>
With 0.5.0 release of `rust-hypervisor-firmware`, `aarch64` binary were
added to assets, which causes the `FW_URL` to have multiple download url
separated by a white space, thus our integration tests would fail.
Constrain `FW_URL` to `hypervisor-fw` to resolve this.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
The previous docs were very developer centric and have led several
people to believe that cross-machine migration is not supported at
all.
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
I've added newlines between paragraphs and code blocks for easier
reading. I've also changed the code blocks to use the correct
highlighting.
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
Replace `map_or()` on false condition with `is_some_and` to provide
better readability, as suggestted by v1.84.0-beta.1 `cargo clippy`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Adapt the existing code to transparently the MemorySlotAllocator. The
MemoryManager is the canonical holder of the these values with them
turned into a MemoryAllocator on demand.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Add an allocator for KVM memory slots, a finite resource in the kernel
- these need to be manipulated across different crates with a common
dependency on this crate.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
`prepare_linux` is capable of determining whether we need to invoke
`build_custom_linux` for building linux from source or `download_linux`
for downloading pre-built.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`prepare_linux` checks if a `--build-guest-kernel` option is present,
and build kernel from `cloud-hypervisor/linux.git`. Otherwise, it will
invoke `download_linux` to use pre-built kernel.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
If any VM argument (e.g. --disk) is provided require some payload (e.g.
--kernel or --firmware) when parsing the command line arguments.
See: #6831
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Add unit-test to make sure get_regs and set_regs on riscv64 architecture
work as expected, effectively avoiding typos in register names.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Complement `create_standard_regs` implementation on RISC-V platform to
work with `From` trait of `kvm_riscv_core`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Incorporates riscv64 register interaction and AIA creation to kvm
module. Complete `Vcpu` trait on RISC-V platform.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Integrate `aia` module into `riscv64` module, and enable `riscv64`
module if target architecture is RISC-V 64-bit.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`fuzz` is a separate workspace, enable consistency check on rust-vmm
crates in `fuzz` to keep stuffs in sync with root workspace.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
`get_device_attr` in 0.19.0 kvm-ioctls is marked as unsafe, wrap
invokation of `get_device_attr` with `unsafe` block.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
- Bump kvm-bindings from 0.9.1 to 0.10.0
- Bump kvm-ioctls from 0.18.0 to 0.19.0
- Bump vm-memory from 0.15.0 to 0.16.0
- Bump linux-loader from 0.12.0 to 0.13.0
- Bump virtio-bindings from 0.2.1 to 0.2.4
- Bump virtio-queue from 0.13.0 to 0.14.0
- Pin mshv-bindings to 0.3.1
- Pin mshv-ioctls to 0.3.1
- Pin vhost to rev "d983ae0"
- Pin vhost-user-backend to rev "d983ae0"
Since vhost 0.12.0 and vhost-user-backend 0.16.0 are going to be yanked,
temporarily pin these two to "d983ae0", which are expected to be
replaced by 0.13.0 vhost and 0.17.0 vhost-user-backend after released.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Add `package-consistency-check.py` script to prevent #6809 and #6815
from happening. This script takes a string present in the repository
field of packages to identify pacakges from a specific source.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
This reverts commit b264aebcde.
Pulls in new vm-memory so should be done as part of a global bump of
Rust-VMM crates.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
warning: the following explicit lifetimes could be elided: 'a
--> hypervisor/src/arch/x86/emulator/mod.rs:492:6
|
492 | impl<'a, T: CpuStateManager> Emulator<'a, T> {
| ^^ ^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
= note: `#[warn(clippy::needless_lifetimes)]` on by default
help: elide the lifetimes
|
492 - impl<'a, T: CpuStateManager> Emulator<'a, T> {
492 + impl<T: CpuStateManager> Emulator<'_, T> {
|
warning: the following explicit lifetimes could be elided: 'a
--> hypervisor/src/mshv/x86_64/emulator.rs:19:6
|
19 | impl<'a> MshvEmulatorContext<'a> {
| ^^ ^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
help: elide the lifetimes
|
19 - impl<'a> MshvEmulatorContext<'a> {
19 + impl MshvEmulatorContext<'_> {
|
warning: the following explicit lifetimes could be elided: 'a
--> hypervisor/src/mshv/x86_64/emulator.rs:65:6
|
65 | impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
| ^^ ^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
help: elide the lifetimes
|
65 - impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
65 + impl PlatformEmulator for MshvEmulatorContext<'_> {
|
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
--> test_infra/src/lib.rs:1307:25
|
1307 | let child = self
| _________________________^
1308 | | .command
1309 | | .stderr(Stdio::piped())
1310 | | .stdout(Stdio::piped())
1311 | | .spawn()
1312 | | .unwrap();
| |_________________________^
|
= note: consider calling `.wait()`
= note: not doing so might leave behind zombie processes
= note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#zombie_processes
= note: `#[warn(clippy::zombie_processes)]` on by default
The API caller should ensure that they call .wait() or equivalent on the
spawned child to reap it.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The snapshot/restore test didn't wait on the child being spawned:
warning: spawned process is never `wait()`ed on
--> performance-metrics/src/performance_tests.rs:495:25
|
495 | let mut child = GuestCommand::new(&guest)
| _________________________^
496 | | .args(["--api-socket", &api_socket_source])
497 | | .args([
498 | | "--cpus",
... |
507 | | .spawn()
508 | | .unwrap();
| |_____________________^
|
= note: consider calling `.wait()`
= note: not doing so might leave behind zombie processes
= note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#zombie_processes
= note: `#[warn(clippy::zombie_processes)]` on by default
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
We know what we are doing within `tracer` crate, disable lint on these
shared reference to mutable static.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Functions marked as `pub` in test module need to be documented. Since
these are literally helper functions and there is no need to be `pub`,
remove these `pub` keywords.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
As clippy of rust-toolchain version 1.83.0-beta.1 suggests, remove
redundant `return` statement to keep code clean.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
As clippy of rust-toolchain version 1.83.0-beta.1 suggests, use `c""` to
construct nul-terminated `CStr`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
As clippy of rust-toolchain version 1.83.0-beta.1 suggests, remove
manual implementation of `is_power_of_two` to improve readability.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
As clippy of rust-toolchain version 1.83.0-beta.1 suggests, replace
manually implemented `div_round_up!` and the like with `div_ceil` from
std.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
This system has a lot of cores (80) resulting in all the tests being
spawned simultaneously and leading to exhaustion of the available
memory. Instead limit the number of threads.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
After updating the OS image to the latest jammy version this test now
requires more memory to run
Fixes: #6782
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
When running with the newer jammy OS image error messages from Rust
Hypervisor Firmware about lack of ram when rebooting where observed.
Increase the RAM allocation to allow it to boot after a reboot.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Currently `arch` crate cannot be built, by specifying `hypervisor/kvm`
to turn on the features required for its dependency - `hypervisor` crate
to build. Thus enabling `arch` crate to be built with command:
```sh
cargo build -p arch --features kvm
```
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
AddressManager::move_bar() acquires the device_tree mutex.
The function is called from PciConfigIo::config_space_write()/
PciConfigMmio::config_space_write() while the pci_bus mutex
is acquired.
The functions DeviceManager::pci_resources()/eject_device()
acquire these mutexes in reverse order, which leads to a deadlock.
Fixes: #6775
Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
This lint disallows asserttions on is_ok()/is_err() in favor of either
using unwrap (so that at least if the test fails, we the failure message
will contain the actual failure reason instead of just "was not
ok/err"), or actually matching the specific variant.
Inspired by and quoted from @roypat.
Enable this lint for `build.yaml` and `quality.yaml`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Asserting on .is_ok()/.is_err() leads to hard to debug failures (as if
the test fails, it will only say "assertion failed: false". We replace
these with `.unwrap()`, which also prints the exact error variant that
was unexpectedly encountered (we can to this these days thanks to
efforts to implement Display and Debug for our error types). If the
assert!((...).is_ok()) was followed by an .unwrap() anyway, we just drop
the assert.
Inspired by and quoted from @roypat.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
This is based on a revert of commit
ce49a6f4b8 with some modifications for a
different worker configuration.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Only download the kernel binaries from the github release if the remote
file is newer (avoids multiple copies accumulating in the download
directory.)
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Cargo's features are additive. Disabling default features in individual
packages but not on the workspace level makes no sense.
This fixes the several build warnings.
Fixes: 5a70d7ec69 (build: Centralize rust-vmm crates to workspace)
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Since cloning Option<Arc<T>> will clone for Arc<T>, this patch fixes the
follow warning:
warning: this call to `as_ref.map(...)` does nothing
--> vmm/src/lib.rs:872:13
|
872 | self.console_resize_pipe.as_ref().map(Arc::clone),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `self.console_resize_pipe.clone()`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref
= note: `#[warn(clippy::useless_asref)]` on by default
Signed-off-by: Songqian Li <sionli@tencent.com>
This patch removes pub import vm_config in config.rs to eliminate
the ambiguity of vm_comfig reference.
Signed-off-by: Songqian Li <sionli@tencent.com>
By introducing `imports_granularity="Module"` format strategy,
effectively groups imports from the same module into one line or block,
improving maintainability and readability.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Enforcing group_imports="StdExternalCrate" requires using cargo fmt from
the nightly toolchain. Create a new workflow that runs on nightly to run
cargo fmt.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Historically the Cloud Hypervisor coding style has been to ensure that
all imports are ordered and placed in a single group. Unfortunately
cargo fmt has no support for ensuring that all imports are in a single
group so if whitespace lines were added as part of the import statements
then they would only be odered correctly in the group.
By adopting "group_imports="StdExternalCrate" we can enforce a style
where imports are placed in at most three groups for std, external
crates and the crate itself. Choosing a style enforceable by the tooling
reduces the reviewer burden.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Serial device doesnt support resize semantics. Setting up the
console resize pipe in the Serial device setup path, overwrites
the setup done as part of virtio-console.
Signed-off-by: BharatNarasimman <bharatn@microsoft.com>
This patch removes locks in VmCreate request and VmInfo response
since we needn't use a lock here and should ensure that internal
implementation is transparent to the runtime.
Signed-off-by: Songqian Li <sionli@tencent.com>
Killing process with SIGKILL will miss the information since CLH process
needs to end normally to export code coverage information.
Signed-off-by: Songqian Li <sionli@tencent.com>
Add release and target params to `cargo test` since we collect
the code coverage reports from `xx/$BUILD_TARGET/release/`.
Signed-off-by: Songqian Li <sionli@tencent.com>
The construction of `FilePair` in `virtio_devices` component has changed
in 287887c, wrapping the parameters with `Arc` to fix fuzz build.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Modify `Cargo.toml` in each member crate to follow the dependencies
specified in root `Cargo.toml` file.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
For a VM with virt-console enabled, when a reboot is requested, the
console devices are closed during the shutdown path. As part of this
the sigwinch listener process and the console resizer pipe are closed.
For the new incarnation of the VM, fresh set of console devices are
setup and a new console resizer pipe is created. The new VM should
be setup to use the newly created console devices including the console
resizer pipe.
Reading from the older console resizer pipe results in unexpected eof
error and terminates the cloud hypervisor process.
Signed-off-by: BharatNarasimman <bharatn@microsoft.com>
Rebooting a VM fails with the following error when debug assertions
are enabled:
fatal runtime error: IO Safety violation: owned file descriptor already closed
This happens because FromRawFd::from_raw_fd is used on RawFds stored
in ConsoleInfo every time a VM begins to boot, so the second
time (after a reboot, or if the first attempt to boot via the API
failed), the fd will be closed. Until this assertion is hit, the code
is operating on either closed file descriptors, or new file
descriptors for something completely different. If debug assertions
are disabled, it will just continue doing this with unpredictable
results.
To fix this, and prevent the problem reocurring, ownership of the
console file descriptors needs to be properly tracked, using Rust's
type system, so this commit refactors the console code to do that.
The file descriptors are now passed around with reference counts, so
they won't be closed prematurely. The obvious way to do this would be
to just have each member of ConsoleInfo be an Arc<File>, but we need
to accomodate that serial console file descriptors can also be
sockets. We can't just store an OwnedFd and convert it when it's
used, because we only get a reference from the Arc, so we need to
store the descriptors as their concrete types in an enum. Since this
basically duplicates the ConsoleOutputMode enum from the config, the
ConsoleOutputMode enum is now not used past constructing the
ConsoleInfo.
So that ownership can be represented consistently, the debug console's
tty mode now uses its own stdout descriptor.
I'm still using .try_clone().unwrap() (i.e. dup()) to clone file
descriptors for Endpoint::FilePair and Endpoint::TtyPair, because I
assume there's a reason for them not just to hold a single file
descriptor.
I've also retained the existing behaviour of having serial manager
ignore the tty file descriptor passed to it (which is stdout), and
instead using stdin. It looks a lot weirder now, because it has to
explicitly indicate it's ignoring the fd with an underscore binding.
Fixes: 52eebaf6 ("vmm: refactor DeviceManager to use console_info")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
The assignment of console_resize_pipe in the TTY case seems to have
been accidentally deleted. I've put it back, but since this is adding
code, I used the new safe API for checking whether a file is a
terminal, introduced in Rust 1.70.0. We should probably use that
everywhere, but that's out of scope of this bug fix.
Fixes: 52eebaf6 ("vmm: refactor DeviceManager to use console_info")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
I've moved this so that it's just after the enum definition, which
will hopefully make it less easy to miss if events are added/removed
again in future.
Fixes: 6d1077fc ("vmm: Unix socket backend for serial port")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Complete the removal of the DAX support by removing the use of
non-standard messages. These messages have since been removed from the
vhost_user crate (rust-vmm/vhost#246) and so need to be removed from our
implementation since that would otherwise block updating to a newer
version of the crate.
The ability to enable DAX support in Cloud Hypervisor has been disabled
some time ago but this code was residual with no way to enable it.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
And modify to code to use the updated interfaces.
Arguments for map_guest_memory, get_dirty_bitmap, vp.run(),
import_isolated_pages, modify_gpa_host_access have changed.
Update these to use the new interfaces, including new MSHV_*
definitions, and remove some redundant arguments.
Update seccomp IOCTLs to reflect interface changes.
Fix irq-related definitions naming.
Bump vfio-ioctls to support mshv v0.3.0.
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
`GetRegList` variant will be referenced on both Aarch and RISC-V. Fixed
comment to generalize this error variant.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Since RISC-V has its own definition of `CoreRegister`, expand the Aarch
variant to avoid collision of `HypervisorCpuError`.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
The error message of `SetRegister` and `GetRegister` fail to describe
the reason as the error variant suggests. Fixed error message
accordingly.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
The rate-limiter worker now is running on Azure VMs whose performance
are more prone to be fluctuate, particularly on block performances. This
commit relaxes the limit check for group rate limiter tests to make them
less flaky.
Signed-off-by: Bo Chen <chen.bo@intel.com>
Port I/O is only supported on x86_64 - use inverted conditional logic to
match the other architectures rather than calling them out specifically.
This will be relevant when RISC-V support is added.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The steps with predicates of `x86_64` targets would never turn on
`use-cross`, removing them from quality check.
Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
Bound checks for virtio-mem and ACPI memory hotplug are off by
one and two, respectively. This prevents users to fully use the reserved
memory hotplug size.
For ACPI, if we specific `--memory size=2G,hotplug_size=4G` and run
`ch-remote resize --memory 6G`, cloud-hypervisor will report the
following error because of the incorrect bound check:
`<vmm> ERROR:vmm/src/lib.rs:1631 -- Error when resizing VM:
MemoryManager(InsufficientHotplugRam)`
Similarly, for virtio-mem, cloud-hypervisor will fail the incorrect
bound check and abort the resize. The VM will see the following error
in dmesg:
`virtio_mem virtio3: unknown error, marking device broken: -22`
This patch has fixed both bound checks and ensure that users can
hot add memory up to the reserved hotplug size.
Signed-off-by: Yuhong Zhong <yz@cs.columbia.edu>
Since the underline bare-metal system is going to retire, we are moving
the metrics and rate-limiter workers to use Azure VMs.
Signed-off-by: Bo Chen <chen.bo@intel.com>
Otherwise, you just see output like "Error running command: Server
responded with an error: InternalServerError", which isn't very
helpful. The response body used to be include with the message, but
was removed when the Error enum was converted to thiserror.
Fixes: 5d0d56f5 ("api_client: Use thiserror for errors")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
With cd0cdac ("virtio-devices: Fix seccomp rules for SevSnp guest"), the
sys_ioctl rule that was applied in virtio_thread_common, would override
previously specified sys_ioctl rules for individual thread type. This
causes the SevSnp guest to crash with seccomp violation.
Fixes: cd0cdac ("virtio-devices: Fix seccomp rules for SevSnp guest")
Signed-off-by: Purna Pavan Chandra <paekkaladevi@microsoft.com>
The Linux kernel fork repository for Cloud Hypervisor now produces
prebuilt x86-64 and aarch64 binaries. Speed up the CI by using those
binaries.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
An example warning output is:
error: first doc comment paragraph is too long
--> virtio-devices/src/lib.rs:158:1
|
158 | / /// Convert an absolute address into an address space (GuestMemory)
159 | | /// to a host pointer and verify that the provided size define a valid
160 | | /// range within a single memory region.
161 | | /// Return None if it is out of bounds or if addr+size overlaps a single region.
| |_
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_long_first_doc_paragraph
= note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
Signed-off-by: Bo Chen <chen.bo@intel.com>
In case of SEV-SNP guests on MSHV, any host component including VMM
trying to access any guest memory region, needs to call gain_access API
to acquire access to that particular memory region. This applies to all
the virtqueue buffers as well which the VMM is using to use to perform
DMA into the guest and in order to facilitate device emulation.
While creating various virtqueues we are already using access platform
hook to translate the addresses but currently we are missing the size
arguments which would be required by the SevSnpAccessPlatformProxy to
gain access to the memory of these queues.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
This would be used in case of SEV-SNP guest because we need to accquire
access to these virtqueue segments before accessing them.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
DeviceManager::add_virtio_console_device used to create the console
resize pipe and assign it to self.console_resize_pipe, but when this
was changed to use console_info, that was deleted without replacement.
This meant that, even though the console resize pipe was created by
pre_create_console_devices, the DeviceManager never found out about
it, so console resize didn't work (at least for pty consoles).
To fix this, the console resize pipe needs to be passed to the Vm
initializer, which is already supported, it was just previously not
used for new VMs.
Since DeviceManager already stores the console resize pipe in an Arc,
and Vmm also needs a copy of it, the sensible thing to do is change
DeviceManager::new to take Arc, and then we don't need to dup the file
descriptor, which could fail.
Fixes: 52eebaf6 ("vmm: refactor DeviceManager to use console_info")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
When the rate limit was reached it was possible for the notification to
the guest to be lost since the logic to handle the notification was
tightly coupled with processing the queue. The notification would
eventually be triggered when the rate limit pool was refilled but this
could add significant latency.
Address this by refactoring the code to separate processing queue and
signalling - the processing of the queue is suspended when the rate
limit is reached but the signalling will still be attempted if needed
(i.e. VIRTIO_F_EVENT_IDX is still considered.)
Signed-off-by: wuxinyue <wuxinyue.wxy@antgroup.com>
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Previously we didn't handle extended guest requests at all and always
returned an error. This lead to issues with some guests that expected
extended requests to succeed. Instead, handle extended requests like
normal requests and write zeros to the extended area to signal to the
guest that we don't want to supply any additional certificate data.
Signed-off-by: Tom Dohrmann <erbse.13@gmx.de>
In case of ARM64 kvm_regs are considered as StandardRegister which is no
longer required since we have defined architecture independent
StandardRegisters in hypervisor crate.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Use the StandardRegisters defined in the hypervisor crate instead of
re-defining it from MSHV/KVM crate.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
This change is along the lines of x86 platform which defined similar
convinence macros to access the StandardRegisters.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
With commit 1e967697c ("vmm: pass AccessPlatform implementation for
SEV-SNP guest"), we started performing one additional ioctl to gain
access to the guest memory before accessing those regions inside
virtio-device emulation code path. This additional ioctl is not part of
the current seccomp filter, which is causing the SevSnp guest to crash
in this scenario with seccomp violation.
Fixes: 1e967697c ("vmm: pass AccessPlatform implementation for SEV-SNP
guest")
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
This fixes a issue of running vm compiled in debug with Rust
1.80.0 or later, where this check was introduced.
Signed-off-by: Wenyu Huang <huangwenyuu@outlook.com>
Implement get_guest_debug_hw_bps() for mshv and simply return 0 for now.
This unblocks the usage of the crashdump feature with mshv. If left
unimplemented, Cloud Hypervisor built with mshv and guest_debug features
crashes immediately upon start due to unimplemented!() macro.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
With this we are removing the CloudHypervisor definition of
StandardRegisters instead using an enum which contains different
variants of StandardRegisters coming from their bindigs crate.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Currently we are redefining StandardRegisters instead of using the ones
coming from bindings. With this we can remove the unnecessary
construction of global structure which contains fields from different
hypervisor dependent structs.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
The index is derived from the access offset, so it is controlled by the
guest. Check it before accessing internal data structures.
Since Rust enforces strict bound check even in release builds, the VMM
process will crash if the guest misbehaves. There is no security issue
since the guest can only DoS itself.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Use the IOCTL numbers directly from mshv-ioctls instead of hardcoding
them in the seccomp filters.
Remove seccomp rules for unused ioctls:
MSHV_GET_VERSION_INFO,
MSHV_ASSERT_INTERRUPT.
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
CVM guests can configure GHCB page multiple times during it's
lifetime depending on it's requirement. For example a Linux CVM guest
configures a different GHCB page during compressed kernel boot and sets
up a new one after decompressing the kernel. As a cleanup step, VMM
should unset the previous GHCB page before registering a new one for
a particular vcpu thread.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
DeviceFd::get_device_attr should be marked as unsafe, because it
allows writing to an arbitrary address. I have opened a kvm-ioctls
PR[1] to fix this. The hypervisor crate was using the function
unsafely by passing it addresses of immutable variables. I noticed
this because an optimisation change[2] in Rust 1.80.0 caused the
kvm::aarch64::gic::tests::test_get_set_icc_regs test to start failing
when built in release mode.
To fix this, I've broken up the _access functions into _set and _get
variants, with the _get variant using a pointer to a mutable variable.
This has the side effect of making these functions a bit nicer to use,
because the caller now has no need to use references at all, for
either getting or setting.
[1]: https://github.com/rust-vmm/kvm-ioctls/pull/273
[2]: d2d24e395a
Signed-off-by: Alyssa Ross <hi@alyssa.is>
This fixes the vsock::device::tests::test_virtio_device test with Rust
1.80.0 or later, where this check was introduced.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Passing AccessPlatform trait to virtio-device for requesting
restricting page access during IO for SEV-SNP guest.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Implement AccessPlatform for SEV-SNP guest to access
restricted page using IO. VMM calls MSHV api to get access
of the pages, MSHV requests guest to release the access.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a structure to hold the reference of the Vm trait
from Hypervisor crate to access of restricted page
from SEV-SNP guest.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Pvmemcontrol provides a way for the guest to control its physical memory
properties, and enables optimizations and security features. For
example, the guest can provide information to the host where parts of a
hugepage may be unbacked, or sensitive data may not be swapped out, etc.
Pvmemcontrol allows guests to manipulate its gPTE entries in the SLAT,
and also some other properties of the memory map the back's host memory.
This is achieved by using the KVM_CAP_SYNC_MMU capability. When this
capability is available, the changes in the backing of the memory region
on the host are automatically reflected into the guest. For example, an
mmap() or madvise() that affects the region will be made visible
immediately.
There are two components of the implementation: the guest Linux driver
and Virtual Machine Monitor (VMM) device. A guest-allocated shared
buffer is negotiated per-cpu through a few PCI MMIO registers, the VMM
device assigns a unique command for each per-cpu buffer. The guest
writes its pvmemcontrol request in the per-cpu buffer, then writes the
corresponding command into the command register, calling into the VMM
device to perform the pvmemcontrol request.
The synchronous per-cpu shared buffer approach avoids the kick and busy
waiting that the guest would have to do with virtio virtqueue transport.
The Cloud Hypervisor component can be enabled with --pvmemcontrol.
Co-developed-by: Stanko Novakovic <stanko@google.com>
Co-developed-by: Pasha Tatashin <tatashin@google.com>
Signed-off-by: Yuanchu Xie <yuanchu@google.com>
BusDevice trait functions currently holds a mutable reference to self,
and exclusive access is guaranteed by taking a Mutex when dispatched by
the Bus object. However, this prevents individual devices from serving
accesses that do not require an mutable reference or is better served
with different synchronization primitives. We switch Bus to dispatch via
BusDeviceSync, which holds a shared reference, and delegate locking to
the BusDeviceSync trait implementation for Mutex<BusDevice>.
Other changes are made to make use of the dyn BusDeviceSync
trait object.
Signed-off-by: Yuanchu Xie <yuanchu@google.com>
After moving landlock config to VMConfig, there is no need to start
destination VM with landlock cmdline options in
test_live_migration_with_landlock test.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
There were some scenarios where we are not clearing SW_EXIT_INFO1 to
indicate that there were no error while handling the GHCB exit.
Recently, new Linux guests got stricter with checking the value of
SW_EXIT_INFO1 after coming back from VMGEXIT and started crashing. Fix
this behavior by clearing out SW_EXIT_INFO1 in case of no error.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Support event idx feature for virtio-blk device.
This feature could improve disk IO performance by suppressing
notifications from guest to host and interrupts from host to
guest, which has been already supported in virtio-net and
vhost-user devices.
To achieve this, virtqueue's event-idx-related API is
leveraged for avail_event field update and needs_notification
check.
Fixes: #6580
Signed-off-by: wuxinyue <wuxinyue.wxy@antgroup.com>
HV APIC(i.e., synthetic APIC controller exposed by Microsoft Hypervisor)
does not support one-shot operation using a TSC deadline value. Due to
which we see the following backtrace inside the guest when running with
hypervisor-fw/OVMF:
[ 0.560765] unchecked MSR access error: WRMSR to 0x832 (tried to
write 0x00000000000400ec) at rIP: 0xffffffff8f473594
(native_write_msr+0x4/0x30)
[ 0.560765] Call Trace:
[ 0.560765] ? native_apic_msr_write+0x2b/0x30
[ 0.560765] __setup_APIC_LVTT+0xbc/0xe0
[ 0.560765] lapic_timer_set_oneshot+0x27/0x30
[ 0.560765] clockevents_switch_state+0xaf/0xf0
[ 0.560765] tick_setup_periodic+0x47/0x90
[ 0.560765] tick_setup_device.isra.0+0x7c/0x110
[ 0.560765] tick_check_new_device+0xce/0xf0
[ 0.560765] clockevents_register_device+0x82/0x170
[ 0.560765] clockevents_config_and_register+0x2f/0x40
[ 0.560765] setup_APIC_timer+0xe1/0xf0
[ 0.560765] setup_boot_APIC_clock+0x5f/0x66
[ 0.560765] native_smp_prepare_cpus+0x1d6/0x286
[ 0.560765] kernel_init_freeable+0xcf/0x255
[ 0.560765] ? rest_init+0xb0/0xb0
[ 0.560765] kernel_init+0xe/0x110
[ 0.560765] ret_from_fork+0x22/0x40
Also, if this feature is exposed guest would not finish booting and get
stuck right before unpacking the root filesystem.
Fixes: 06e8d1c40 ("hypervisor: mshv: fix topology for Intel HW on MSHV")
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
This is a preparatory work to make space for ARM64 emulator.
There is no functional change in this commit, just moving code from one
file to another.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
As per VirtIO spec 1.2 section 5.2.6, the `status` field is a byte, not
u32. cloud-hypervisor writes an `u32` to guest memory, which
accidentally zeros out the following 3 bytes, and may corrupt guest OS
internal state.
Signed-off-by: Changyuan Lyu <changyuanl@google.com>
The assertion that only code emulation requires GVA to GPA translation
is wrong.
Allow the caller of `translate` to pass in permission flags directly.
Provide a new method `read_memory_flags` so that we can add the EXECUTE
permission flag where necessary.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This method will return the existing Response if the status is
successful (Status::Ok) otherwise issue a command to abandon the
migration and return the desired error.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This requires stashing the config values in `struct Vmm`. The configs
should be validated before before creating the VMM thread. Refactor the
code and update documentation where necessary.
The place where the rules are applied remain the same.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Add file/dir paths from landlock-rules arguments to ruleset. Invoke
apply_landlock on VmConfig to apply config specific rules to ruleset.
Once done, any threads spawned by vmm thread will be automatically
sandboxed with the ruleset in vmm thread.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Introduce ApplyLandlock trait and add implementations to VmConfig
elements with PathBufs. This trait adds config specific rules to
landlock ruleset.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Users can use this parameter to pass extra paths that 'vmm' and its
child threads can use at runtime. Hotplug is the primary usecase for
this parameter.
In order to hotplug devices that use local files: disks, memory zones,
pmem devices etc, users can use this option to pass the path/s that will
be used during hotplug while starting cloud-hypervisor. Doing this will
allow landlock to add required rules to grant access to these paths when
cloud-hypervisor process starts.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Users can use this cmdline option to enable/disable Landlock based
sandboxing while running cloud-hypervisor.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
landlock syscalls are required by event_monitor, signal_handler,
http-server and vmm threads. Rest of the threads are spawned by the vmm
thread and they automatically inherit the ruleset from the vmm thread.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
We will start receiving GPA intercepts. For our use cases they are
handled the same way as UNMAPPED GPA intercepts.
Put in some logging to distinguish the two cases.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Previously we required the hypervisor to give us a valid instruction
stream. That worked well enough because we never hit any edge conditions
(such as when the instruction stream crosses page boundary).
Now that MSHV can deal with partial or empty instruction stream, we can
remove that requirement.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Original we checked for R and W, but that code path never got executed.
It is now understood that we can only get here when we execute code. Fix
the permission flags.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The default value of IP is zero. If the decoder's state not set
properly, then the guest state is going to be wrong.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
TIOCGWINSZ modifies its argument, so it needs to mutably borrow it.
Unfortunately, ioctl()'s signature is not able to enforce this, and
the write happens in the kernel, so I don't think anything like miri,
valgrind, UBSan, etc. would have been able to catch this.
The UB passing an immutable reference caused resulted, for me, in
get_win_size() returning (0, 0) since LLVM commit
9a09c737a052 ("[BasicAA] Make isNotCapturedBeforeOrAt() check for
calls more precise (#69931)").
I've had a look through the other ioctl() calls in Cloud Hypervisor,
and I don't think any others have the same problem.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Comparing RAX with RIP makes no logical sense other than RIP happens to
be the correct value. Use `target_rax` instead.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
cargo-cyclonedx rejects the current license key in Cargo.toml, because
it doesn't comply with the SPDX standard:
Package cloud-hypervisor has an invalid license expression (LICENSE-APACHE & LICENSE-BSD-3-Clause), using as named license: Invalid Lax SPDX expression: unknown term
Fix by using the names from the SPDX list:
https://spdx.github.io/license-list-data/
Signed-off-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>
In 42e9632c53 a fix was made to address a
typo in the taplo configuration file. Fixing this typo indicated that
many Cargo.toml files were no longer adhering to the formatting rules.
Fix the formatting by running `taplo fmt`.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Killing CLH by SIGKILL will cause inaccurate code coverage
information. This patch changes the signal to SIGTERM.
Fixes: #6507
Signed-off-by: Songqian Li <sionli@tencent.com>
Since vdpa device does not support pause/resume [1], it does not make
sense to restore on paused state.
[1] 099cdd2af8
Signed-off-by: Bo Chen <chen.bo@intel.com>
Impose a limit on the maximum nesting of file formats that can open more
files. For example, a qcow2 file can have a backing file, which could be
another qcow2 file with a backing file (or even the same file as the
original), potentially causing unbounded recursion.
This commit is based on crosvm implementation:
eb1640e301Fixes: #6472
Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
While checking if the console device is a tty use the cloned fd instead
of libc::STDOUT_FILENO.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Console devices are created after vm_config is received and the created
devices are passed Vm during vm_receive_state.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
During vm_shutdown or vm_snapshot, all the console devices will be
closed. When this happens stdout (FD #2) will also be closed as the
console device using these FD is closed. If the VM were to be started
later, FD#2 can be assigned to a different file. But
pre_create_console_devices looks for FD#2 while opening tty device,
which could point to any file.
To avoid this problem, the STDOUT FD is duplicated when being
assigned to a console device. Even if the console devices were to be
closed, the duplicated FD will be closed and FD#2 will continue to
point to STDOUT.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
While adding console devices, DeviceManager will now use the FDs in
console_info instead of creating them.
To reduce the size of this commit, I marked some variables are unused
with '_' prefix. All those variables are cleaned up in next commit.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Use pre_create_console_devices method to create and populate console
device FDs into console_info in Vmm Object.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
With this change all the information to manage console devices is now
available within Vmm Object.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Introduce ConsoleInfo struct. This struct will be used to store FDs of
console devices created in pre_create_console_devices and passed to
vm_boot.
Move set_raw_mode, create_pty methods to console_devices.rs to
consolidate console management methods into a single module.
Lastly, copy the logic to create and configure console devices into
pre_create_console_devices method.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
If the KVM version is older than v6.6, KVM_GET_SUPPORTED_CPUID will omit
the L1 cache information in CPUID function 0x8000_0005. Fall back to
the host L1 cache information if it is omitted by KVM.
Signed-off-by: Sean Banko <sbanko@crusoe.ai>
Currently by default each core is allocated it's own socket. Basically
it is n socket 1 core 1 thread/core kind of a structure as witnessed
from within the guest.
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 1
Core(s) per socket: 1
Socket(s): 8
NUMA node(s): 1
This is not a good default topology because resources are distributed
across multiple sockets. For example, a Linux guest with multi socket
configuration will have to calibrate TSC per socket due to which it
might observe a higher amount of boot time than usual.
A better idea for default topology would be 1 socket n core 1
thread/core which ensure better resource locality.
After this change topology would change to:
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 1
Core(s) per socket: 8
Socket(s): 1
NUMA node(s): 1
Fixes: #6497
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Populating these cpuid with default values so that
CLH can patch with topology information. Otherwise it gets
skipped while setting some topology information.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Rather than calling cpuid and then updating the APIC ID field - use the
existing common CPUID data which already includes CPUID data for eax=1
(aka function = 1). This removes the need to call cpuid per vCPU thread
created. This has a positive impact on boot time with multiple vCPUs as
the cpuid instruction is serialising.
Fixes: #5646
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The cloud-hypervisor package does not have a lib target, so it is
invalid. Cargo just ignores that line.
Dropping it removes a warning.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The original code gave an owned fd to UnixListener. That made the same
fd wrapped into two owned files.
When the files were dropped, the same fd would be closed more than once.
A newly introduced check in Rust's stdlib caught that error.
A newly cloned fd should be given to UnixListener.
Fixes: #6485
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Whenever the file descriptor table is full, Linux expands it by doubling
it's size.
The filesystem code that does this uses RCU synchronization to ensure
all pre-existing RCU read-side critical sections have completed. The
latency induced by this synchronization is a big part of the total time
required to restore a snapshot.
The kernel has an optimization in code, where it doesn't call
synchronize_rcu() if there is only one thread in the process. We can
take advantage of this optimization by expanding the descriptor table at
the application start, when it has only one thread.
This commit tries to expand the table to 4096 entries, this way we avoid
any expansion that could take place later.
Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
Certain VMEXITs can only happen for x86 guests, thus reduce the scope to
x86_64 at the compilation stage.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
For MSHV we always create frozen partition, so we
resume the VM during boot. Also during pause and resume
VM events we call hypervisor specific API.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Create a partition frozen always, then unfreeze the partition
during boot phase or resume phase. We also freeze the
partition during pause event. Time is freeze during the
time between freeze and unfreeze.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add Pause/Resume functions for VM trait. For KVM it
will be empty implementations. For MSHV it needs to freeze
and unfreeze the partition.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Currently, the watchdog configuration in systemd is reloaded by
reboot. We can cancel this reboot operation by restarting the
systemd daemon process.
Signed-off-by: Songqian Li <sionli@tencent.com>
tests_snapshot_restore* have been earlier removed from common_parallel
due to the falkiness they add testsuite. Running them sequentially would
eliminate the flakiness. Hence, add the tests back to testsuite but into
common_sequential module.
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
test_snapshot_restore_* tests often have transient failures and add to
overall flakiness of the integration testsuite. Hence, remove them from
common_parallel. However, these tests need to be added back to
common_sequential
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
VM is created with FDs explicitly passed to CH via --net parameter
and snapshotted. New net FDs are passed in turn during restore.
Boilerplate code from _test_snapshot_restore().
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
Add a section about restoring VM with new Net FDs explicitly passed to
ch-remote via 'net_fds' parameter
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
Enable restore command the ability to send file descriptors along with
HTTP request. This is useful when restoring a VM with explicit FDs
passed to NetConfig(s).
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
Consume FDs passed via SCM_RIGHTs to VmRestore API and assign them
appropriately to RestoredNetConfig's fds field.
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
'NetConfig' FDs, when explicitly passed via SCM_RIGHTS during VM
creation, are marked as invalid during snapshot. See: #6332.
So, Restore should support input for the new net FDs. This patch adds
new field 'net_fds' to 'RestoreConfig'. The FDs passed using this new
field are replaced into the 'fds' field of NetConfig appropriately.
The 'validate()' function ensures all net devices from 'VmConfig' backed
by FDs have a corresponding 'RestoreNetConfig' with a matched 'id' and
expected number of FDs.
The unit tests provide different inputs to parse and validate functions
to make sure parsing and error handling is as per expectation.
Fixes#6286
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
Co-authored-by: Bo Chen <chen.bo@intel.com>
The list is gathered from going through various code paths in the code
base.
No functional change intended.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Per the KVM API document, that capability is only valid with in-kernel
irqchip that handles MSIs.
Through out the code base, there is no call to KVM_IOCTL_SIGNAL_MSI.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The compiler is now able to warn if an invalid attribute (e.g like a
feature) is not available.
See https://blog.rust-lang.org/2024/05/06/check-cfg.html for more
details.
Add build.rs files in the crates that use #cfg(fuzzing) to add fuzzing
to the list of valid cfg attributes.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The ability to control the rustc flags (required for adding new
attributes to the allowed list of #[cfg(..)]) requires bumping the MSRV
to 1.77.0
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Code in this crate is conditional on this feature so it necessary to
expose as a new feature and use that feature as a dependency when the
feature is enabled on the vmm crate.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Enable the use of the vmm crate with the "guest_debug" feature and make
the code that exercises that in the fuzzer unconditional on
"guest_debug" as a feature (as that is not specified as a feature in the
fuzz workspace itself.)
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The "dhat-heap" feature needs to be enabled inside the vmm crate as a
depenency from the top-level as there is build time check for that
feature inside the vmm crate.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
These tests use relatively large memory allocations and if they are
allowed to run in parallel can result in the container encountering an
OOM situation.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Update the vhost-user-backend crate version used along with related
crates (vhost and virtio-queue.) This requires minor changes to the
types used for the memory in the backends with the use of the
BitmapMmapRegion type for the Bitmap implementation.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Replace the specific Bitmap implementation from the type signature used
for functions that take memory. This allows more flexibility when using
these functions in particular when these functions are used by the
vhost-user-block backend. An updated vhost-user-backend crate requires
extra constraints on the Bitmap implementation used (it must support
BitmapReplace which AtomicBitmap does not.)
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Replace the specific Bitmap implementation from the type signature used
for functions that take memory. This allows more flexibility when using
these functions in particular when these functions are used by the
vhost-user-net backend. An updated vhost-user-backend crate requires
extra constraints on the Bitmap implementation used (it must support
BitmapReplace which AtomicBitmap does not.)
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This is to resolve the inconsistencies from our openapi specification,
as default values do not make sense for required fields.
Reported-by: James O. D. Hunt <james.o.hunt@intel.com>
Signed-off-by: Bo Chen <chen.bo@intel.com>
Change from default 4G to 2G to reduce the memory usage. This will help
avoid "No disk space left" errors when all snapshot tests run at once.
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
The snapshot_dir is not needed anymore fter the guest is restored.
Hence, remove it. This will potentially avoid transient failures caused
due to insufficient disk space.
Signed-off-by: Purna Pavan Chandra <paekkaladevi@linux.microsoft.com>
The mem_size field is not needed in TestContext. Drop it.
Make sure guest_evvq is read once. Clippy cannot figured out that it was
used.
While at it, add an extra assert for the spurious rxvq event test, too.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Clippy complained one use of the char_array macro.
Instead of fixing that use case, the observation is that the macro was
needed only because MP table types mixed c_char and c_uchar for no
particular reason.
Only use c_uchar in those types, and drop char_array.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
The maintainer can then replace the plaintext body (derived from the
tag) with a markdown version and then publish.
As part of 6c4144e943 creating a draft
release was accidentally dropped.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
As MSHV also implements set/get_clock data, this patch
removes the KVM feature guard and make it x86_64 only and
both for KVM and MSHV.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The contents of this crate may change and cause conflicts - re-exporting
the contents is unnecessary.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This is required as the VcpuFd::run and VcpuFd::set_immediate_exit
methods now take a &mut self. I explored alternative solutions:
1. Using RefCell for runtime interior mutability - the Vcpu trait is
Sync and it's not possible to use RefCell with types that are Sync.
2. Using UnsafeCell - the mutable reference nature of ::run and and
::set_kvm_immediate_exit was added for a reason so it unwise to
bypass this.
3. Adjusting the trait interface to expose the &mut self - this requires
an Arc<Mutex<>> around the hypervisor::vcpu::Vcpu object and was very
intrusive.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The members for {Io, Mmio}{Read, Write} are unused as instead exits of
those types are handled through the VmOps interface. Removing these is
also a prerequisite due to changes in the mutability of the
VcpuFd::run() method.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
On Microsoft Hypervisor, we need to save/restore five
VP state components which are as follows:
1. Local APIC
2. Xsave
3. Synthetic Message Page
4. Synthetic Event Flags Page
5. Synthetic Timers
In the MSHV crate we created a single struct for all the
components and API to get/set the states.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
When using multiple PCI segments, the 32-bit and 64-bit mmio
aperture is split equally between each segment. Add an option
to configure the 'weight'. For example, a PCI segment with a
`mmio32_aperture_weight` of 2 will be allocated twice as much
32-bit mmio space as a normal PCI segment.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
In accordance with reuse requirements:
- Place each license file in the LICENSES/ directory
- Add missing SPDX-License-Identifier to files.
- Add .reuse/dep5 to bulk-license files
Fixes: #5887
Signed-off-by: Ruslan Mstoi <ruslan.mstoi@intel.com>
Replace actions: actions-rs/toolchain, upload-release-asset.
actions-rs/toolchain is unmaintained, for cross-compilation replace it
with houseabsolute/actions-rust-cross
Action upload-release-asset is unmaintained and has been archived since
Mar 4, 2021. An issue with upload-release-asset is that it creates
separate release for each job of matrix strategy. Thus, to solve these
issues, replace unmaintained upload-release-asset with upload-artifact
See: #5929
Signed-off-by: Ruslan Mstoi <ruslan.mstoi@intel.com>
This removes the requirement to ensure that we land PRs that update the
Dockerfile (and the appropraite dev_cli.sh change) in a specific time
frame.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Assigning KVM_IRQFD (when unmasking a guest IRQ) after
KVM_SET_GSI_ROUTING can avoid kernel panic on the guest that is not
patched with commit a80ced6ea514 (KVM: SVM: fix panic on out-of-bounds
guest IRQ) on AMD systems.
Meanwhile, it is required to deassign KVM_IRQFD (when masking a guest
IRQ) before KVM_SET_GSI_ROUTING (see #3827).
Fixes: #6353
Signed-off-by: Yi Wang <foxywang@tencent.com>
Signed-off-by: Bo Chen <chen.bo@intel.com>
The caller shouldn't pass in an &str that's too long. This is a
precaution if something goes wrong in the caller.
Signed-off-by: Wei Liu <liuwe@microsoft.com>
Properly detach a device from a domain if that device is already
attached to another domain on an attach request (following section
5.13.6.3.2 of the virtio-iommu spec). Resolves nested virtualization
reboot.
Signed-off-by: Andrew Carp <acarp@crusoeenergy.com>
Ensures that any endpoints already attached to the domain are properly
mapped to a new endpoint on said endpoint's attach request. This is done
by search for all previous mappings in the domain and then issuing map
requests for the newly attached endpoint.
Signed-off-by: Andrew Carp <acarp@crusoeenergy.com>
Add infrastructure to lookup the host address for mmio regions on
external dma mapping requests. This specifically resolves vfio
passthrough for virtio-iommu, allowing for nested virtualization to pass
external devices through.
Fixes#6110
Signed-off-by: Andrew Carp <acarp@crusoeenergy.com>
VfioUserDmaMapping is already in the pci crate, this moves
VfioDmaMapping to match the behavior. This is a necessary change to
allow the VfioDmaMapping trait to have access to MmioRegion memory
without creating a circular dependency. The VfioDmaMapping trait
needs to have access to mmio regions to map external devices over
mmio (a follow-up commit).
Signed-off-by: Andrew Carp <acarp@crusoeenergy.com>
The memory region that is associated with the hotpluggable part of
a virtio-mem zone isn't backed by the file specified in the
MemoryZoneConfig. The file is used only for the fixed part of the
zone. When you try to restore a snapshot with virtio-mem, the
backing file is used for all its regions. This results in the
following error:
VmRestore(MemoryManager(GuestMemoryRegion(MappingPastEof)))
This patch sets backing_file only for the fixed part of a virtio-mem
zone.
Fixes: #6337
Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
HV_PAGE_SIZE is defined as a usize in mshv_bindings.
Remove the redefinition, and perform casts where necessary.
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
Add IOCTL number for generic hypercall ioctl (MSHV_ROOT_HVCALL).
Update IOCTL numbers for set/get vp state.
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
This reverts commit fcf229a33a.
The virtio-queue version needs to stay the same as the rest of the
source tree.
Signed-off-by: Bo Chen <chen.bo@intel.com>
The 'NetConfig' may contain FDs which can't be serialized correctly, as
FDs can only be donated from another process via a Unix domain socket
with `SCM_RIGHTS`. To avoid false use of the serialized FDs, this patch
explicitly set 'NetConfig' FDs as invalid for (de)serialization.
See: #6286
Signed-off-by: Bo Chen <chen.bo@intel.com>
Prefix field with an _ to indicate that this is intentionally unused.
This resolved a nightly compiler check issue due to the unusued field.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
When restoring a VM, the VirtioPciCfgCapInfo struct is not properly
initialized. All fields are 0, including the offset where the
capabibility starts. Hence, when you read a PCI configuration register
in the range [0..length(VirtioPciCfgCap)] you get the value 0 instead of
the actual register contents.
Linux rescans the whole PCI bus when adding a new device. It reads the
values vendor_id and device_id for every device. Because these are
stored at offset 0 in pci configuration space, their value is 0 for
existing devices. As such, Linux considers that the devices have been
unplugged and it removes them from the system.
Fixes: #6265
Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
Current MSHV emulator only works for x86 instruction decoder. So, let's
restrict its usage to x86.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
According to the virtio iommu spec (section 5.13.6.6), all mappings
within the entire range from virt_start to virt_end in an unmap
request must be removed. This change adds this functionality,
iterating through all mappings that fall within an unmap request
for that domain and removing them.
Signed-off-by: Andrew Carp <acarp@crusoeenergy.com>
Current instruction emulator can only decode x86 instructions. Thus,
restrict the exit handling for just x86 guests.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
APIC controller is only available on x86 machine. ARM uses a different
interrupt controller so those exit messages won't happen for ARM guests.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
MSR and CPUID are limited to x86 architecture so, reduce the visbility
of these two members inside struct MshvVcpu to just x86 architecture.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
error: the item `io` is imported redundantly
Error: --> devices/src/legacy/uart_pl011.rs:468:9
|
467 | use super::*;
| -------- the item `io` is already imported here
468 | use std::io;
| ^^^^^^^
error: the item `Arc` is imported redundantly
Error: --> devices/src/legacy/uart_pl011.rs:469:21
|
467 | use super::*;
| -------- the item `Arc` is already imported here
468 | use std::io;
469 | use std::sync::{Arc, Mutex};
| ^^^
error: could not compile `devices` (lib test) due to 8 previous errors
Error: warning: build failed, waiting for other jobs to finish...
Error: The process 'cross' failed with exit code 101
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
error: the item `read_le_u32` is imported redundantly
Error: --> devices/src/legacy/gpio_pl061.rs:342:17
|
341 | use super::*;
| -------- the item `read_le_u32` is already imported here
342 | use crate::{read_le_u32, write_le_u32};
| ^^^^^^^^^^^
|
= note: `-D unused-imports` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(unused_imports)]`
error: the item `write_le_u32` is imported redundantly
Error: --> devices/src/legacy/gpio_pl061.rs:342:30
|
341 | use super::*;
| -------- the item `write_le_u32` is already imported here
342 | use crate::{read_le_u32, write_le_u32};
| ^^^^^^^^^^^^
error: the item `Arc` is imported redundantly
Error: --> devices/src/legacy/gpio_pl061.rs:343:9
|
341 | use super::*;
| -------- the item `Arc` is already imported here
342 | use crate::{read_le_u32, write_le_u32};
343 | use std::sync::Arc;
| ^^^^^^^^^^^^^^
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
clippy was flagging this up as a mixture of mixed attributes but that
attribute is no longer necessary
warning: item has both inner and outer attributes
--> hypervisor/src/arch/x86/emulator/mod.rs:769:1
|
769 | / #[cfg(test)]
770 | | mod tests {
771 | | #![allow(unused_mut)]
| |_________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style
= note: `#[warn(clippy::mixed_attributes_style)]` on by default
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
error: the item `kvm_bindings` is imported redundantly
Error: --> hypervisor/src/kvm/aarch64/gic/mod.rs:9:18
|
9 | use crate::kvm::{kvm_bindings, KvmVm};
| ^^^^^^^^^^^^ the item `kvm_bindings` is already defined by prelude
|
= note: `-D unused-imports` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(unused_imports)]`
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
warning: assigning the result of `Clone::clone()` may be inefficient
--> vmm/src/device_manager.rs:4188:17
|
4188 | id = child_id.clone();
| ^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `id.clone_from(child_id)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones
= note: `#[warn(clippy::assigning_clones)]` on by default
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
warning: `devices` (lib) generated 1 warning (run `cargo clippy --fix --lib -p devices` to apply 1 suggestion)
warning: assigning the result of `Clone::clone()` may be inefficient
--> virtio-devices/src/transport/pci_device.rs:1073:9
|
1073 | self.bar_regions = bars.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `self.bar_regions.clone_from(&bars)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
warning: assigning the result of `Clone::clone()` may be inefficient
--> devices/src/pvpanic.rs:213:9
|
213 | self.bar_regions = bars.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `self.bar_regions.clone_from(&bars)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones
= note: `#[warn(clippy::assigning_clones)]` on by default
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Model Specific Registers (MSRs) are usually available on x86
architecture. So, let's reduce the visibility of MSRs to just x86
architecture.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
A deadlock can happen from the destination VM of live upgrade or
migration due to waiting on paused device worker threads. For example,
when a serialization error happens after the `DeviceManager` struct is
restored (where all virtio device worker threads are spawned but in
paused/parked state), a deadlock will happen from
`DeviceManager::drop()`, as it blocks for waiting worker threads to
join.
This patch ensures that we wake up all device (mostly virtio) worker
threads before we block for them to join.
Signed-off-by: Bo Chen <chen.bo@intel.com>
Current version can't boot a SNP guest while using
more than one VCPU. It turns out that there is an
issue in the Snp AP creation process. We should be writing
to Software exitinfo1 instead of exitinfo2. This patch fixes
the issue and we can boot multi vcpu SNP guest.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Currently, we only support injecting NMI for KVM guests but we can do
the same for MSHV guests as well to have feature parity.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Microsoft Hypervisor raises this request to change the guest page
visibility in case of SEV-SNP guest.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Nuno Das Neves <nudasnev@microsoft.com>
Kernel can panic when get a unknown nmi when set unknown_nmi_panic,
we can use this feature to test if nmi injected to guest.
Signed-off-by: Yi Wang <foxywang@tencent.com>
When running on the merge group this workflow is run twice - once for
the create event (merge queue creates a new branch) and once for the
merge_group event. Unfortunately the second event would cause the first
to be cancelled - unfortunately sometimes that second event is the
create event where the job in the workflow only runs if it is also a
tag.
By creating distinct concurrency groups for each event type then the
cross cancellation can be avoided.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The workers share a common public IP address and often GitHub will
reject attempts to access the API due to exceeding the anonymous rate
limit threshold.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
When a bare-metal worker is canceled, its workspace can be left with
files owned by the root user as a result of running tests from our
container. This patch add a step to fix workspace permissions for such
case before checking out code.
Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit ensures that the HttpApi thread flushes all the responses
before the application shuts down. Without this step, in case of a
VmmShutdown request the application might terminate before the
thread sends a response.
Fixes: #6247
Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
Because of double quotes the current value is passed
as a single argument with a space in it to cargo.
This commit changes it to an array so each element
is passed as a different arguments.
Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
On platforms where PCIe P2P is supported, inject a PCI capability into
NVIDIA GPU to indicate support.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
The DCO tool doesn't understand merge_groups but we still need to have a
valid status check to allow the merge group to proceed.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
And clean up some of the whitespace formatting so that the "name" and
"on" are grouped away from the "jobs".
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Most of our CI workers are now running form GitHub actions, so we are
ready to disable Jenkins CI workers.
See: #6231
Signed-off-by: Bo Chen <chen.bo@intel.com>
cloud-hypervisor, ch-remote, vhost-user-block and vhost-user-net all
need at least one argument to do anything useful, so printing command
help is helpful when they are run without arguments or a subcommand.
Use clap::Command::arg_required_else_help(true) to do this.
Signed-off-by: Chris Webb <chris@arachsys.com>
ch-remote crashes when run with --api-socket but no subcommand:
$ target/release/ch-remote --api-socket /tmp/api
thread 'main' panicked at src/bin/ch-remote.rs:509:14:
internal error: entered unreachable code
Use clap::Command::subcommand_required(true) to yield a more friendly
error in this case.
Signed-off-by: Chris Webb <chris@arachsys.com>
Host data that is passed to the hypervisor. Then
the firmware includes the data in the attestation report.
The data might include any key or secret that the SevSnp guest
might need later.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
The host data provided at launch. Data is passed
to the hypervisor during the completion of the
isolated import.
Host Data provided by the hypervisor during guest launch.
The firmware includes this value in all attestation
reports for the guest.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
To reduce issues caused by flaky tests split the musl and glibc jobs
into separate jobs. This means fewer jobs will need to be restarted for
flaky tests. This will also increase CI throughput since the musl builds
account for ~40% of the total CI time when run together with glibc.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Since we don't register ioevents in case of SEV-SNP guests. Thus, we
should not unregister it as well.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
With the nightly toolchain (2024-02-18) cargo check will flag up
redundant imports either because they are pulled in by the prelude on
earlier match.
Remove those redundant imports.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
When a guest running on a terminal reboots, the sigwinch_listener
subprocess exits and a new one restarts. The parent never wait()s
for children, so the old subprocess remains as a zombie. With further
reboots, more and more zombies build up.
As there are no other children for which we want the exit status,
the easiest fix is to take advantage of the implicit reaping specified
by POSIX when we set the disposition of SIGCHLD to SIG_IGN.
For this to work, we also need to set the correct default exit signal
of SIGCHLD when using clone3() CLONE_CLEAR_SIGHAND. Unlike the fallback
fork() path, clone_args::default() initialises the exit signal to zero,
which results in a child with non-standard reaping behaviour.
Signed-off-by: Chris Webb <chris@arachsys.com>
Allow cloud-hypervisor to direct boot the bzImage kernel format using
the regular 32 bit entry point. This can share the memory and vcpu
setup with the regular PVH boot code, but requires the setup of the
'zero page'.
Signed-off-by: Stefan Nuernberger <stefan.nuernberger@cyberus-technology.de>
For SevSnp guest IO events are handled by GHCB protocol.
While we get the notification we have to notify via eventfd.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
In case of SEV-SNP guest devices use sw-iotlb to gain access guest
memory for DMA. For that F_IOMMU/F_ACCESS_PLATFORM must be exposed in
the feature set of virtio devices.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
According to PCIe specification, a 64-bit MMIO BAR should be
naturally aligned. In addition to being more compliant with
the specification, natural aligned BARs are mapped with
the largest possible page size by the host iommu driver, which
should speed up boot time and reduce IOTLB thrashing for virtual
machines with VFIO devices.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
The 'generate_ram_ranges' function currently hardcodes the assumption
that there are only 2 E820 RAM entries. This is not flexible enough to
handle vendor specific memory holes. Returning a Vec is also more
convenient for users of this function.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
Since the ACPI tables are generated inside the IGVM file in case of
SEV-SNP guest. So, we don't need to generate it inside the cloud
hypervisor.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
... enabled VMs. IOEvents are not supported in case of SEV-SNP VMs. All
the IO events are delievered via GHCB protocol.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This will help in identify whether a VM supports sev-snp and based on
that disable/enable certain features.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Implement workflow to to run static analysis and linting of all shell
scripts by using shfmt and shellcheck.
Fixes: #5396
Signed-off-by: Ruslan Mstoi <ruslan.mstoi@intel.com>
We occasionally saw cloud-hypervisor crashed due to seccomp violations. The
coredumps showed the HTTP API thread crashing after it attempted to call
sched_yield(). The call came from rust stdlib's mpmc module, which calls
sched_yield() if several attempts to busy-wait for a condition to fulfil fall
short.
Since the system call is harmless and it comes from the stdlib, I opted to allow
all threads to call it.
Signed-off-by: Peteris Rudzusiks <rye@stripe.com>
Currently the only way to set the affinity for virtio block threads is
to boot the VM, search for the tid of each of the virtio block threads,
then set the affinity manually. This commit adds an option to pin virtio
block queues to specific host cpus (similar to pinning vcpus to host
cpus). A queue_affinity option has been added to the disk flag in
the cli to specify a mapping of queue indices to host cpus.
Signed-off-by: acarp <acarp@crusoeenergy.com>
Traditional way to configure vcpu don't work for sev-snp guests. All the
vCPU configuration for SEV-SNP guest is provided via VMSA.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This also fixes the following clippy warning on nightly build from cargo
fuzz:
warning: struct `RegionEntry` is never constructed
--> /home/chenb/project/cloud-hypervisor/cloud-hypervisor/block/src/vhdx/vhdx_header.rs:357:8
|
357 | struct RegionEntry {
| ^^^^^^^^^^^
|
= note: `RegionEntry` has derived impls for the traits `Debug` and `Clone`, but these are intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` on by default
Signed-off-by: Bo Chen <chen.bo@intel.com>
For all VFIO devices, map all non-emulated MMIO regions to
the vfio container to allow PCIe P2P between all VFIO devices
on the virtual machine. This is required for a wide variety of
advanced GPU workloads such as GPUDirect P2P (DMA between two
GPUs), GPUDirect RDMA (DMA between a GPU and an IB device).
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
Currently kernel and firmware are checked as a payload.
IGVM should be checked as well. Otherwise, it hangs indefinitely.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Unaccepted GPA is usually thrown by Microsoft hypervisor in case of
mismatch between GPA and GVA mappings. This is a fatal message from the
hypervisor perspective so we would need to error out from the vcpu run
loop. Along with add some debug message to identify the broken mapping
between GVA and GPA.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
On guests with large amounts of memory, using the `prefault` option can
lead to a very long boot time. This commit implements the strategy
taken by QEMU to prefault memory in parallel using multiple threads,
decreasing the time to allocate memory for large guests by
an order of magnitude or more.
For example, this commit reduces the time to allocate memory for a
guest configured with 704 GiB of memory on 1 NUMA node using 1 GiB
hugepages from 81.44134669s to just 6.865287881s.
Signed-off-by: Sean Banko <sbanko@crusoeenergy.com>
The `ByteValued` trait implementations for the data structures from the
'linux_loader' crate are no longer needed, and hence their wrappers can
be removed.
Signed-off-by: Bo Chen <chen.bo@intel.com>
Fix beta clippy issue:
error: file opened with `create`, but `truncate` behavior not defined
--> src/main.rs:624:26
|
624 | .create(true)
| ^^^^^^^^^^^^- help: add: `.truncate(true)`
|
= help: if you intend to overwrite an existing file entirely, call `.truncate(true)`
= help: if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`
= help: alternatively, use `.append(true)` to append to the file instead of overwriting it
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_open_options
= note: `-D clippy::suspicious-open-options` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]`
Signed-off-by: Bo Chen <chen.bo@intel.com>
The embedded error in the enum will be read on debug output of the
error.
Fixes beta clippy issue:
warning: field `0` is never read
--> vhost_user_block/src/lib.rs:64:23
|
64 | CreateKillEventFd(io::Error),
| ----------------- ^^^^^^^^^
| |
| field in this variant
|
= note: `#[warn(dead_code)]` on by default
help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
|
64 | CreateKillEventFd(()),
| ~~
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
The embedded error in the enum will be read on debug output of the
error.
Fixes beta clippy issue:
warning: field `0` is never read
--> performance-metrics/src/performance_tests.rs:25:11
|
25 | Infra(InfraError),
| ----- ^^^^^^^^^^
| |
| field in this variant
|
= note: `#[warn(dead_code)]` on by default
help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
|
25 | Infra(()),
| ~~
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
warning: field `0` is never read
--> block/src/qcow/vec_cache.rs:139:21
|
139 | struct NumCache(pub u64);
| -------- ^^^^^^^
| |
| field in this struct
|
= note: `#[warn(dead_code)]` on by default
help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
|
139 | struct NumCache(());
| ~~
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
These structs directly embed another struct and then implement
ByteValued on that struct to implement ByteValued for the inner struct.
As such the inner struct is never directly accessed so to avoid the dead
code analysis mark this as allowed.
Beta clippy fix:
warning: field `0` is never read
--> arch/src/x86_64/mod.rs:129:32
|
129 | struct MemmapTableEntryWrapper(hvm_memmap_table_entry);
| ----------------------- ^^^^^^^^^^^^^^^^^^^^^^
| |
| field in this struct
|
= note: `MemmapTableEntryWrapper` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` on by default
help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
|
129 | struct MemmapTableEntryWrapper(());
|
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Beta clippy fix
warning: useless use of `vec!`
--> tests/integration.rs:5845:23
|
5845 | let kernels = vec![direct_kernel_boot_path()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[direct_kernel_boot_path()]`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec
= note: `#[warn(clippy::useless_vec)]` on by default
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Beta clippy fix:
warning: initializer for `thread_local` value can be made `const`
--> vmm/src/sigwinch_listener.rs:27:40
|
27 | static TX: RefCell<Option<File>> = RefCell::new(None);
| ^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(None) }`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#thread_local_initializer_can_be_made_const
= note: `#[warn(clippy::thread_local_initializer_can_be_made_const)]` on by default
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Beta clippy fix:
warning: this call to `as_ref.map(...)` does nothing
--> vmm/src/device_manager.rs:1234:9
|
1234 | self.console_resize_pipe.as_ref().map(Arc::clone)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `self.console_resize_pipe.clone()`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref
= note: `#[warn(clippy::useless_asref)]` on by default
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
According to crates.io the crc-any crate is actively maintained which
avoids issues with the crc32c crate and the nightly compiler.
Fixes: #6168
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
When we import a page, we have a page with
some data or empty, empty does not mean there is no data,
it rather means it's full of zeros. We can skip writing the
data as guest memory of the page is already zeroed.
A page could be partially filled and the rest of the content is zero.
Our IGVM generation tool only fills data here if there is some data
without zeros. Rest of them are padded. We only write data
without padding and compare whether we complete writing
the buffer content. Still it's a full page and update the variable
with length of the full page.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
When the HTT flag CPUID.1.EDX[HTT] is 0, it indicates that there is
only a single logical processor in the package. When HTT is 1, it
indicates that CPUID.1.EBX[23:16] contains the number of logical
processors in the package.
When this information is not included in CPUID leaf 0x1, some cpu
topology enumeration software such as hwloc are known to crash.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
This commit adds the debug-console (or debugcon) device to CHV. It is a
very simple device on I/O port 0xe9 supported by QEMU and BOCHS. It is
meant for printing information as easy as possible, without any
necessary configuration from the guest at all.
It is primarily interesting to OS/kernel and firmware developers as they
can produce output as soon as the guest starts without any configuration
of a serial device or similar. Furthermore, a kernel hacker might use
this device for information of type B whereas information of type A are
printed to the serial device.
This device is not used by default by Linux, Windows, or any other
"real" OS, but only by toy kernels and during firmware development.
In the CLI, it can be configured similar to --console or --serial with
the --debug-console parameter.
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Set the SEV control register so we know where to
start running. This register configures the
SEV feature control state on a virtual processor.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
This register configures the SEV feature control
state on a virtual processor.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Consistent with the other data structures and constants used in TDX
support code import the necessary structures from the kernel for
accessing the vmcall structure.
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
These Default implementations either don't produce valid configs, are
no longer used outside of tests, or both.
For the tests, we can define our own local "default" values that make
the most sense for the tests, without worrying about what's
a (somewhat) sensible "global" default value.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Bumping anyhow crate from 1.0.75 to 1.0.79 will cause seccomp
failures through integration tests. Newly added backtrace support
relies on readlink and many other syscalls.
Issue noticed with test_api_http_pause_resume test, where second time
of VM PAUSE or VM RESUME prints error and causes panic.
Noticed that panic message in a thread which is not allowed to write
output triggered the issue.
So implementing Display trait for HttpError and ApiError enums to avoid
adding many syscalls to seccomp filter section.
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
On hosts with >256 cpus, setting the cpu affinity to a host cpu index
>255 will return an error because type of `host_cpu` is `u8`.
This commit changes the type of `host_cpu` to `usize` to remove this
limitation.
Signed-off-by: Sean Banko <sbanko@crusoeenergy.com>
Move the duplicated logic to download OVMF into a helper function.
Explicitly specify the OVMF_FW_TAG instead of downloading the latest
so that new OVMF versions can be easily tested.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
Testing instructions are very old and type=dpdkvhostuser is
deprecated from DPDK.
logs from /var/log/openvswitch/ovs-vswitchd.log
|netdev_dpdk|WARN|dpdkvhostuser ports are considered deprecated;
please migrate to dpdkvhostuserclient ports
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
Uses of the old ApiRequest enum conflated two different concerns:
identifying an API request endpoint, and storing data for an API
request. This led to ApiRequest values being passed around with junk
data just to communicate a request type, which forced all API request
body types to implement Default, which in some cases doesn't make any
sense — what's the "default" path for a vhost-user socket? The
nonsensical Default values have led to tests relying on being able to
use nonsensical data, which is an impediment to adding better
validation for these types.
Rather than having API request types be represented by an enum, which
has to carry associated body data everywhere it's used, it makes more
sense to represent API request types as trait objects. These can have
an associated type for the type of the request body, and this makes it
possible to pass API request types and data around as siblings in a
type-safe way without forcing them into a single value even where it
doesn't make sense. Trait objects also give us dynamic dispatch,
which lets us get rid of several large match blocks.
To keep it possible to fuzz the HTTP API, all the Vmm methods called
by the HTTP API are pulled out into a trait, so the fuzzer can provide
its own stub implementation of the VMM.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
With the change in 7bc764d to expose the SVM bit for nested
virtualisation test_vfio can be re-enabled on the AMD workers.
Fixes: #5895
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
When using amd topology, the svm feature flag on cpuid leaf
0x8000_0001.ecx is overwritten. We update the amd cpu topology
logic to use the flag values that originated in
KVM_GET_SUPPORTED_CPUID ioctl and override as necessary.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
warning: this URL is not a hyperlink
--> arch/src/aarch64/layout.rs:114:58
|
114 | ...in https://www.kernel.org/doc/Documentation/arm64/booting.txt.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://www.kernel.org/doc/Documentation/arm64/booting.txt.>`
|
= note: bare URLs are not automatically turned into clickable links
= note: `#[warn(rustdoc::bare_urls)]` on by default
I also noticed that it looks like this comment was supposed to be
applied to FDT_MAX_SIZE, not FDT_START, so I moved it.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
The VIRTIO specification[1] says:
> The upper 32 bits of the CID are reserved and zeroed.
We should therefore not allow the user to supply a VSOCK CID with
those bits set. To accomplish this, limit the public API of the
virtio-vsock device to only accept 32-bit CIDs, while still using
64-bit CIDs internally since that's how virtio-vsock works.
[1]: https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-4400004
Signed-off-by: Alyssa Ross <hi@alyssa.is>
I accidentally ran a VM with CID 2 (VMADDR_CID_HOST), and very strange
and difficult to debug behavior ensued. I don't think a virtio-vsock
device should be allowed to have any of the special CIDs
(VMADDR_CID_ANY, VMADDR_CID_HYPERVISOR, VMADDR_CID_LOCAL, VMADDR_CID_HOST).
Signed-off-by: Alyssa Ross <hi@alyssa.is>
The socket is nonblocking, so it's not guaranteed that it will be
possible to read the whole connect command in a single iteration of
the event loop. To reproduce:
(echo -n 'CONNECT '; sleep 1; echo 1234; cat) | socat STDIO UNIX-CONNECT:vsock.sock
This would produce the error:
cloud-hypervisor: 5.509209s: <_vsock4> INFO:virtio-devices/src/vsock/unix/muxer.rs:446 -- vsock: error adding local-init connection: UnixRead(Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" })
To fix this, if we only get a partial command, we need to save it for
future iterations of the event loop, and only proceed once we've read
a complete command.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Complete the isolated import, telling the
Microsoft hypervisor that import is done so that
MSHV can issue SNP_LAUNCH_FINISH command.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Use right and exact size 32 bytes for host data field
for completing the isolated import. This way OOB
can be avoided during a function call.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Import all the isolated pages after parsing is
done on the iGVM file. Hypervisor adds those
pages for PSP measurement(part of the hashing).
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Current instructions are incorrect and there is now a new profile called
dev-opt to build the debug version of TD-SHIM.
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
Under the fuzzer this code appears dead:
error: field `0` is never read
--> /home/rob/src/cloud-hypervisor/arch/src/x86_64/mod.rs:128:32
|
128 | struct MemmapTableEntryWrapper(hvm_memmap_table_entry);
| ----------------------- ^^^^^^^^^^^^^^^^^^^^^^
| |
| field in this struct
|
= note: `MemmapTableEntryWrapper` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis
= note: `-D dead-code` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(dead_code)]`
help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
|
128 | struct MemmapTableEntryWrapper(());
| ~~
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
Add a 'rate_limit_groups' field to VmConfig that defines a set of
named RateLimiterGroups.
When the 'rate_limit_group' field of DiskConfig is defined, all
virtio-blk queues will be rate-limited by a shared RateLimiterGroup.
The lifecycle of all RateLimiterGroups is tied to the Vm.
A RateLimiterGroup may exist even if no Disks are configured to use
the RateLimiterGroup. Disks may be hot-added or hot-removed from the
RateLimiterGroup.
When the 'rate_limiter' field of DiskConfig is defined, we construct
an anonymous RateLimiterGroup whose lifecycle is tied to the Disk.
This is primarily done for api backwards compatability. Importantly,
the behavior is not the same! This implementation rate_limits the
aggregate bandwidth / iops of an individual disk rather than the
bandwidth / iops of an individual queue of a disk.
When neither the 'rate_limit_group' or the 'rate_limiter' fields of
DiskConfig is defined, the Disk is not rate-limited.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
Add a 'rate_limiter/group' module that defines the RateLimiterGroup
and a RateLimiterGroupHandle types.
The RateLimiterGroupHandle can be used in place of a RateLimiter to
limit the aggregate bandwidth and/or ops of multiple virtio-blk or
virtio-net queues.
Each RateLimiterGroup has an associated worker thread that broadcasts
an event to each RateLimiterGroupHandle when a RateLimiter is unblocked.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
CI reports errors:
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
--> arch/src/x86_64/mod.rs:1351:19
|
1351 | epc_sections: &Vec<SgxEpcSection>,
| ^^^^^^^^^^^^^^^^^^^ help: change this to: `&[SgxEpcSection]`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
= note: `-D clippy::ptr-arg` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::ptr_arg)]`
Signed-off-by: Yi Wang <foxywang@tencent.com>
CI reports clippy errors:
error: argument to `Path::join` starts with a path separator
--> tests/integration.rs:4076:58
|
4076 | let serial_socket = guest.tmp_dir.as_path().join("/tmp/serial.socket");
| ^^^^^^^^^^^^^^^^^^^^
|
= note: joining a path starting with separator will replace the path instead
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#join_absolute_paths
Signed-off-by: Yi Wang <foxywang@tencent.com>
CI reports clippy errors:
error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
--> test_infra/src/lib.rs:93:51
|
93 | match (|| -> Result<(), WaitForBootError> {
| ___________________________________________________^
94 | | let listener =
95 | | TcpListener::bind(listen_addr.as_str()).map_err(WaitForBootError::Listen)?;
96 | | listener
... |
145 | | }
146 | | })() {
| |_________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_conditions
= note: `-D clippy::blocks-in-conditions` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]`
Signed-off-by: Yi Wang <foxywang@tencent.com>
This PR addresses a bug in which the cpu topology of a guest
with non power-of-two number of cores is incorrect. For example,
in some contexts, a virtual machine with 2-sockets and 12-cores
will incorrectly believe that 16 cores are on socket 1 and 8
cores are on socket 2. In other cases, common topology enumeration
software such as hwloc will crash.
The root of the problem was the way that cloud-hypervisor generates
apic_id. On x86_64, the (x2) apic_id embeds information about cpu
topology. The cpuid instruction is primarily used to discover the
number of sockets, dies, cores, threads, etc. Using this information,
the (x2) apic_id is masked to determine which {core, die, socket} the
cpu is on. When the cpu topology is not a power of two
(e.g. a 12-core machine), this requires non-contiguous (x2) apic_id.
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
The following tests have been temporarily disabled:
1. Live upgrade/migration test with ovs-dpdk (#5532);
2. Disk hotplug tests on windows guests (#6037);
This patch has been tested with PR #6048.
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
Tested-by: Bo Chen <chen.bo@intel.com>
For SEV-SNP guests we need to provide the extended memory. It follows a
very simple layout and very similar to other x86 guests.
First segment: [HIGH_RAM_START - MEM_32BIT_RESERVED_START]
PCI hole: [MEM_32BIT_RESERVED_START - RAM_64BIT_START]
Second segment: [RAM_64BIT_START - RAM_END]
Fixes#5993
Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
You will need to `chmod +x .git/hooks/pre-commit` to have it run on every
@@ -36,42 +93,65 @@ commit you make.
## Certificate of Origin
In order to get a clear contribution chain of trust we use the [signed-off-by language](https://01.org/community/signed-process)
In order to get a clear contribution chain of trust we use the [signed-off-by language](https://www.kernel.org/doc/Documentation/process/submitting-patches.rst)
used by the Linux kernel project.
## Patch format
## Patch format & Git Commit Hygiene
Beside the signed-off-by footer, we expect each patch to comply with the following format:
_We use **Patch** as synonym for **Commit**._
```
<component>: Change summary
We require patches to:
More detailed explanation of your changes: Why and how.
Wrap it to 72 characters.
See http://chris.beams.io/posts/git-commit/
for some more good pieces of advice.
- Have a `Signed-off-by: Name <email>` footer
- Follow the pattern: \
```
<component>: Change summary
Signed-off-by: <contributor@foo.com>
```
More detailed explanation of your changes: Why and how.
Wrap it to 72 characters.
See http://chris.beams.io/posts/git-commit/
for some more good pieces of advice.
For example:
Signed-off-by: <contributor@foo.com>
```
Valid components are listed in `TitleStartsWithComponent.py`. In short, each
cargo workspace member is a valid component as well as `build`, `ci`, `docs` and
`misc`.
Example patch:
```
vm-virtio: Reset underlying device on driver request
If the driver triggers a reset by writing zero into the status register
then reset the underlying device if supported. A device reset also
requires resetting various aspects of the queue.
In order to be able to do a subsequent reactivate it is required to
reclaim certain resources (interrupt and queue EventFDs.) If a device
reset is requested by the driver but the underlying device does not
support it then generate an error as the driver would not be able to
configure it anyway.
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
```
### Git Commit History
We value a clean, **reviewable** commit history. Each commit should represent
a self-contained, logical step that guides reviewers clearly from A to B.
Avoid patterns like `init A -> init B -> fix A` or \
`init design A -> revert A -> use design B`. Commits must be independently
reviewable - don't leave "fix previous commit" or earlier design attempts in
the history.
Intermediate work-in-progress changes are acceptable only if a subsequent
commit in the same series cleans them up (e.g. a temporary `#[allow(unused)]`
removed in the next commit).
## Pull requests
Cloud Hypervisor uses the “fork-and-pull” development model. Follow these steps if
@@ -79,12 +159,16 @@ you want to merge your changes to `cloud-hypervisor`:
1. Fork the [cloud-hypervisor](https://github.com/cloud-hypervisor/cloud-hypervisor) project
into your github organization.
2. Within your fork, create a branch for your contribution.
3. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
1. Within your fork, create a branch for your contribution.
1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)
against the main branch of the Cloud Hypervisor repository.
4. To update your pull request amend existing commits whenever applicable and
then push the new changes to your pull request branch.
5. Once the pull request is approved it can be integrated.
1. Each commit must comply with the Commit Hygiene guidelines above.
1. A pull request should address a single component or concern to keep review
focused and approvals straightforward.
1. Once the pull request is approved it can be integrated.
Please squash any changes done during review already into the corresponding
commits instead of pushing `<component>: addressing review for A`-style commits.
## Issue tracking
@@ -101,16 +185,83 @@ comments or by adding the `Fixes` keyword to your commit message:
```
serial: Set terminal in raw mode
In order to have proper output from the serial, we need to setup the
terminal in raw mode. When the VM is shutting down, it is also the
VMM responsibility to set the terminal back into canonical mode if we
don't want to get any weird behavior from the shell.
sh 'scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json'
}
}
stage('Upload metrics report') {
steps {
sh 'curl -X PUT https://cloud-hypervisor-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'
}
}
}
}
stage('Worker build - Rate Limiter') {
agent { node { label 'focal-metrics' } }
when {
branch 'main'
beforeAgent true
expression {
return runWorkers
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Run rate-limiter integration tests') {
options {
timeout(time: 10, unit: 'MINUTES')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-rate-limiter'
The following scenarios are supported by Cloud Hypervisor to bootstrap a VM, i.e.,
to load a payload/bootitem(s):
- Provide firmware
- Provide kernel \[+ cmdline\]\ [+ initrd\]
Please note that our Cloud Hypervisor firmware (`hypervisor-fw`) has a Xen PVH
boot entry, therefore it can also be booted via the `--kernel` parameter, as
seen in some examples.
### Custom Kernel and Disk Image
#### Building your Kernel
Cloud Hypervisor also supports direct kernel boot. For x86-64, a `vmlinux` ELF kernel (compiled with PVH support) is needed. In order to support development there is a custom branch; however provided the required options are enabled any recent kernel will suffice.
Cloud Hypervisor also supports direct kernel boot. For x86-64, a `vmlinux` ELF kernel (compiled with PVH support) or a regular bzImage are supported. In order to support development there is a custom branch; however provided the required options are enabled any recent kernel will suffice.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.