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