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>