Repository navigation
[DO NOT REVIEW] state_unit: record unit contracts and re-create hot-plugged PCIe devices - #5014
Closed
Pedro Henrique Penna (ppenna) wants to merge 3 commits into
Closed
Pedro Henrique Penna (ppenna) wants to merge 3 commits into
Pedro Henrique Penna (ppenna) wants to merge 3 commits into
Conversation
A snapshot's inventory held only the names of the state units, so it could not say what each unit was to the guest, whether the VM's configuration had created it or it had been hot-plugged, or that a destination's device differed from the saved one behind the same name. Give each unit a contract, which it declares when it is added: a stable, guest-visible identity, such as the PCIe port of its device; its kind; its lifetime, static, dynamic, or derived; and descriptors of what the guest sees of it. vmotherboard derives a chipset device's descriptors from its static regions, interrupt lines, PCI placement, and the identity that its PCI configuration space reports, and records a dynamically added device as dynamic. A PCIe device takes its port as its stable identity, whether configured or hot-plugged. StateUnits::save_with_inventory records the contracts of the units that it saved from the same snapshot of the unit set as their saved state, so a unit removed while the save runs appears in both or in neither. StateUnits::check_inventory matches a saved inventory against the units by name, whatever their registration order, reports missing, unexpected, and changed units, duplicate records, and saved state without a record in a typed InventoryMismatch, and returns the recorded dynamic units that the destination lacks, which the VM worker refuses until it can re-create them. The VM worker's saved state records the contracts in field 3 instead of the names of field 2, which version 2 of the saved-state schema retires. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A device hot-added to a PCIe port records a dynamic state-unit contract whose stable identity is its port, but a restore into a new process had no such device, so it could only fail. Re-create such devices. On --restore-snapshot, the controller reads the ports that the saved state records as hot-plugged and hands the devices that the command line places on those ports to the VM worker instead of building them with the machine. Before it applies saved state, the worker re-creates each recorded hot-plugged device on its port from the supplied device, without a hotplug notification, since the root complex's saved state restores what the guest saw of the port, and then requires the inventory, which now includes the re-created devices' PCI identities, to match exactly. A recorded device without a supplied device, a supplied device of another kind, and a supplied device on a port that records none fail the restore. The runtime hot-add and the re-creation build the device with the same code. Add the add-pcie-device and rm-pcie-device console commands, so that a command-line VM can hot-plug a virtio-rng device and remove it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hot-add a virtio-rng device to a PCIe root port, pulse save/restore, and check that the guest still enumerates the device, that it still produces entropy, and that it can still be hot-removed. The save records the device's dynamic state-unit contract for its port, and the restore checks it. The test is unstable for the reason that pcie_save_restore is: pulse save/restore of PCIe on Linux direct is flaky in CI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Nov 10, 2026
Contributor
Author
|
Closing as not planned, together with microsoft/nvx#1450, which pinned this head. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Records in saved state, for each state unit, the part of the VM's contract that the unit owns, in place of the flat list of state-unit names that position 017 (#4624) records, so that a restore can tell what each unit is to the guest and can re-create the devices that were hot-plugged onto PCIe ports. This is an alternative to #4624, and #5015 proposes the same change to
main.Three commits on
6ddd6ca50, the head offeature/microvm/dev. microsoft/nvx#1450 pins this head, as roadmap positions 243-245.Record a contract for each state unit (
021d269b8)state_unit: each unit declares a contract when it is added (UnitBuilder::stable_id,kind,lifetime,descriptor,descriptors): its name; a stable, guest-visible identity, the name unless declared; its kind; its lifetime,Static,Dynamic, orDerived; and sorted, deduplicatedkey=valuedescriptors.StateUnits::inventoryreturns the contracts by name.save_with_inventorysaves the units and returns the contracts of exactly the units that answered, from the same snapshot of the unit set (run_op_tracked), and, assavedoes since78e752de1, fails without sending a request while a unit is in a terminal state.check_inventorymatches a saved inventory against the units by name, whatever their registration order, and either reports missing, unexpected, and changed units, duplicate records, and saved state without a record in a typedInventoryMismatch, or returns anInventoryPlanwhoserecreatelists the recorded dynamic units that the VM lacks.vmotherboard: derives a chipset device's descriptors from what it registers, without device-specific code:mmioandpiofor each static region (<label>@<base>+<length>),lineandline.target,pci.bdf,pcie.port, orpcie.rciep, and thepci.id,pci.class,pci.revision, andpci.subsystemthat its configuration space reports. Itschipsetunit and line sets are derived, andadd_dyn_devicetakes aDynamicDeviceContractand records the device as dynamic. A PCIe device's stable identity is its port,pcie-port:<port>, whethervmm_core::device_builderconfigures it or it is hot-plugged; VPCI and VPCI relay devices record their kinds.openvmm_core,openvmm_defs,openvmm_helpers: the worker'sSavedStaterecords the contracts in field 3. Field 2, position 017's names, is retired, andSAVED_STATE_SCHEMA_VERSIONmoves to 2, so a restore refuses version 1 snapshots by their manifest.vmtimeandinputare derived. A restore refuses saved state whose check plans to re-create units, until the next commit. The microVM manifest takes its state-unit names from the contracts.state_unit/src/tests/inventory.rs: the contracts' order, each kind of mismatch and its message, the dynamic plan, a save, re-creation, and restore, and a unit removed while the save runs, answered or not.tests/terminal.rs:save_with_inventoryfails likesaveon a terminal unit.vmotherboard:chipset/contract.rsand a static device's registrations.openvmm_core's time ABI tests read the contracts.Re-create hot-plugged PCIe devices on restore (
07b4281df)--restore-snapshot, the controller reads the ports that the saved state records as hot-plugged (SavedState::hotplugged_pcie_ports) and hands the devices that the command line places on those ports to the VM worker (VmWorkerParameters::restore_pcie_devices) instead of building them with the machine. Before it applies saved state, the worker re-creates each on its port (dispatch/pcie_hotplug.rs) with the code that the runtime hot-add uses, attaches it without a hotplug notification, since the root complex's saved state restores what the guest saw of the port, and then requires the inventory to match exactly. A recorded device without a supplied device, a supplied device of another kind, and a supplied device on a port that records none fail the restore. Adds theadd-pcie-device <PORT> virtio-rngandrm-pcie-device <PORT>console commands, and documents the restore rules and that a guest should release a device before its hot-remove.openvmm_defs(hotplugged_pcie_ports) andopenvmm_entry(take_hotplugged_pcie_devices).Test a hot-plugged device across save and restore (
3e7809ba4)pcie_hotplug_save_restorehot-adds a virtio-rng device to a root port, pulses save and restore, and checks that the guest still enumerates it, that it still produces entropy, and that it can be hot-removed once the guest releases it. It is unstable for the reason thatpcie_save_restoreis.Validation
At this head,
3e7809ba4, on Windows with Rust 1.97.1:cargo checkandcargo clippy --all-targetsforstate_unit,vmotherboard,vmm_core,openvmm_defs,openvmm_helpers,openvmm_core,openvmm_entry,petri,vpci_relay, andvmm_tests, andcargo doc --no-depsfor all butvmm_tests, without warnings;cargo nextest run --profile agentfor all butvmm_tests, 699 passed;cargo xtask fmt --fix, clean.At this head, on NVX's KVM, MSHV, and WHP test VMs, through microsoft/nvx#1450's head,
6905c055a, with OpenVMM built from this head:KVM:
cargo xflowey vmm-tests-run --filter 'test(/openvmm_linux_x64_/)', 40 passed, includingpcie_hotplug_save_restore,pcie_hotplug, andpcie_save_restore.All three: NVX's default microVM suite, and the runtime adapter's 161 scenarios.
A cross-process check through the console: hot-add a virtio-rng device to a root port,
save-snapshot, and restore in a new process with--virtio-rng --virtio-rng-pcie-port.All 9 cases passed on KVM and MSHV. On WHP they passed once
save-snapshotopened its RAM file writable:vm_controller'sFile::open(...).sync_all()fails there with "Access is denied", a separate, existing bug that this pull request does not change.Before the rebase onto
6ddd6ca50, the same patches, asad47c5688on46bfe02ed, had passed the same runs. The rebase added onlysave_with_inventory's terminal-unit check.Land by fast-forwarding
feature/microvm/devto this head,3e7809ba4343ba630f10841052f35f86b521d231, once microsoft/nvx#1450 is approved, since this repository's merge button squashes and would leave NVX's pin off the branch.