Repository navigation
openvmm: keep a held input gate across a guest's device reset - #1452
Pedro Henrique Penna (ppenna) merged 2 commits into
Conversation
A guest that reset a virtio device while OpenVMM held host input gated let host input past the gate (#1416): between a snapshot boundary's input gate and the vCPU stop, or during a gated restore before the guest acknowledged it, the device's reset cleared its gate, and once the guest set DRIVER_OK again, the device delivered the host input that the gate held back, virtio-net's packets, a console's input, and virtio-fs's replies, while the VM worker still recorded input as gated. A capture whose virtio-fs device the guest reset failed its save and rolled back. Pin 61cdd63978ea58ce045d159208ed4ca22f30cbb8, the head of microsoft/openvmm#5022, one commit on cd5cd3814, the head of feature/microvm/dev: - 61cdd6397 virtio: keep a held input gate across a device reset The revision makes each device's reset keep its input gate, so that only resuming input releases it, also for a reset of the VM: the VM worker holds the gate and releases it when it releases the boundary or the guest acknowledges the restore, and no reset changes its record. Evidence: the platform tier of the snapshot-tiers scenario, whose restore gates host input until the guest acknowledges it, with a runtime post-restore hook, which runs before the acknowledgement, that resets the guest's virtio-net device by unbinding and binding its driver, configures it, and pings the gateway, whose reply is host input. The reply arrived before the acknowledgement in every run on nvx-kvm-test (KVM), nvx-mshv-test (MSHV), and nvx-whp-test (WHP), all virtual machines, with the OpenVMM of the releases that CI built from 46bfe02ed, 4 of 4 runs each, and from a8a0e3517, which differs from cd5cd3814 only in tests, 2 of 2 runs each. With OpenVMM built on each host from 61cdd6397, it arrived in none of 3 runs each, every run passed the scenario, whose host input reached the guest only after the acknowledgement, and the affected microVM scenarios passed. At the pinned revision, the OpenVMM tests of the changed packages pass, 515 on Windows and 520 on Linux; without the fix, the 7 new ones fail. NVX needs no coordinated change: the control-session vectors, the source excerpts, the contract versions, and the CPU profiles that nvx-rs copies from OpenVMM match the revision's. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Maps NVX's new pin, 61cdd6397, the head of microsoft/openvmm#5022, at position 247, after position 246, cd5cd3814, the head of feature/microvm/dev, which microsoft/openvmm#5016 merged. The pin is 116 commits past the mapped tip. Position 247 is a PR13 fixup. It changes the input gates that PR13's positions 043 and 048 and PR18's position 088 give the console, virtio-net, and virtio-fs with their saved state: each device's reset cleared its gate, and now keeps it. It states that rule on the gate's methods of VirtioDevice and ChangeDeviceState, which PR13's position 040 and PR09's position 018 add, extends the snapshot guide's paragraph on the post-restore gate that PR20's position 095 adds, and adds tests beside those of the devices, which extend the broker's test harness of PR23's position 113 and the gated-queue tests of position 172. It folds into positions 043 and 048, its virtio-fs change into PR18's position 088, and its other parts into the positions that add what they change, as the fold sentences after the DAG and the commit mapping say; the Scope, the DAG, the dependency graph, the PR summary, and the commit mapping record it with PR13. Replaying it on upstream main conflicts in 13 of its 15 files, all but a new module of console tests and the development dependency that virtio-fs takes for its transport tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The pin changes snapshot input isolation, but OpenVMM #5022 remains unmerged and exact-head build/test checks are skipped, requiring maintainer verification of upstream review, required CI, and landing before NVX merges.
No open issues 🎉
What changed in this PR
Updates the OpenVMM upstream roadmap for the pin that preserves host-input gates across guest device resets, addressing #1416’s snapshot and gated-restore issue.
Changes:
- Records revision
61cdd6397at position 247 and updates the chain counts. - Classifies position 247 as a PR13 fixup and identifies where its device, documentation, and test changes should fold upstream.
- Documents the fix’s dependencies and upstream replay conflicts.
| File | Description |
|---|---|
doc/openvmm-upstream-roadmap.md |
Updates the pin, commit mapping, and upstream folding plan for reset-safe input gates. |
Review effort: Balanced
|
No change needed here. As Copilot's overview says, microsoft/openvmm#5022 must land first, and this pull request already orders it so: its "Landing order" section has the maintainer fast-forward |
Fixes #1416
What and why
A guest that reset a virtio device while OpenVMM held host input gated let
host input past the gate. The VM worker gates host input at a snapshot
boundary before it stops the vCPUs, and during a gated restore until the
guest acknowledges it, and the vCPUs run in both windows. When the guest
wrote 0 to a device's status there, the transport reset the device, and each
device's reset cleared its own gate: virtio-net cleared the latch under which
its endpoint queues start, the consoles their
input_gatedflag, andvirtio-fs reopened its request admission. Nothing gated the device again, so
once the guest set
DRIVER_OKagain, the device delivered host packets,console input, the control console's host records among it, and virtio-fs
replies that the gate held back, while the worker still recorded input as
gated. A capture whose virtio-fs device the guest reset also failed its save
(
virtio-fs save was not preceded by input quiesce) and rolled back.Root cause: the VM worker takes and releases the input gate (
quiesce_input,resume_input), but each device kept it in state that itsVirtioDevice::resetreturned to its initial value, so a reset, which theguest controls, opened it.
microsoft/openvmm#5022,
virtio: keep a held input gate across a device reset, makes each device's reset keep its gate, so that onlyresume_inputreleases it:
of the queues creates gates its new endpoint queues, as it already did for a
gate taken before the queues first start;
input_gated, so its direct worker reads no host inputand its broker neither reads the host's records nor times its
authentication;
virtqueues.
VirtioDevice::resetandquiesce_input,ChangeDeviceState::quiesce_inputand
reset, and OpenVMM's snapshot guide state the rule.Commits:
openvmm: pin input gates that a guest's device reset keepsmoves thegitlink, and nothing else, from
cd5cd3814, the head offeature/microvm/dev, to61cdd63978ea58ce045d159208ed4ca22f30cbb8, thehead of [DO NOT REVIEW] virtio: keep a held input gate across a device reset openvmm#5022, one commit on it; its message carries the
host evidence below. NVX needs no coordinated change: the control-session
vectors, source excerpts, contract versions, and CPU profiles that nvx-rs
copies from OpenVMM match the revision's.
doc: map the input gates that resets keep in the OpenVMM roadmapmapsposition 247, 116 commits past the mapped tip, as a PR13 fixup: it folds
into PR13's positions 043 and 048, its virtio-fs change into PR18's
position 088, and its other parts into the positions that add what they
change, as the fold sentences and the commit mapping say. Replaying it on
upstream main conflicts in 13 of its 15 files.
Decisions:
state across its reset, rather than in a latch in the transport's device
task that quiesces the device again after the guest's reset, which openvmm: a guest's virtio device reset lets host input past a held input gate #1416
also proposed. The gate state already lives in the devices, and their reset
is what cleared it; a latch in the task would give the gate two owners, and
a quiesce after a reset could fail and need handling of its own, while the
task and the transports stay what [DO NOT REVIEW] vmotherboard: gate a device's input without closing it to the vCPUs openvmm#5005 made them,
forwarders of the gate in the order of the guest's accesses.
(
snapshot_restore.input_gated, the snapshot boundary), and its resetchanges neither record: the worker refuses a VM reset while a boundary is
active, and a gated restore's resume gates input again before the units
start. Releasing the gate on a VM reset would recreate the mismatch between
the device and the worker's record that openvmm: a guest's virtio device reset lets host input past a held input gate #1416 describes, so only
resume_inputreleases it. The alternative, telling a VM reset from theguest's in the device task and opening the gate on the former, has no
caller that needs it.
documentation, and its tests are one commit, as position 238 was for openvmm: snapshot input gating closes device mutexes while other vCPUs still access them #1138.
Since it fixes what PR13's positions 043 and 048 and PR18's position 088
add, the roadmap records it as a fixup, as it records positions 241-243 as
PR09 fixups, with the parts that fold elsewhere named.
consoles' and virtio-fs's cases, through the devices and the virtio-mmio
transport.
Landing order
feature/microvm/devto61cdd63978ea58ce045d159208ed4ca22f30cbb8, since OpenVMM's merge buttonsquashes and would leave the pin off the branch.
Validation
OpenVMM, Rust 1.97.1, at
61cdd6397, which is7870c09e2, the commit thatthe first validation below tested on
46bfe02ed, rebased ontocd5cd3814:git range-diffshows the patch identical.direct worker and broker, after a reset made as the transport makes the
guest's, receive no host input until input resumes (without the fix, the
input and the host's attachment are read); a guest that writes 0 to the
status of the running console through the virtio-mmio transport and starts
it again receives none (without the fix, it is delivered); virtio-net
quiesces the endpoint queues of the next start (without the fix, it never
does); virtio-fs leaves a
FUSE_INITon its virtqueue (without the fix, itis answered); and after a status write of 0 to an inactive virtio-fs
device, or a reset of the VM, the save succeeds (without the fix, it fails
with
virtio-fs save was not preceded by input quiesce).cargo clippy --all-targetsandcargo doc --no-depsforvmcore,virtio,virtio_net,virtio_console, andvirtiofs, withoutwarnings;
cargo nextest run --profile agentfor the five, 515 passed and2 skipped;
cargo xtask fmt, clean.nextest commands, without warnings, 520 passed and 2 skipped.
End to end, the platform tier of the
snapshot-tiersscenario, whose restoregates host input until the guest acknowledges it, with a runtime post-restore
hook, which runs before the acknowledgement, that resets the guest's
virtio-net device by unbinding and binding its driver, configures it, and
pings the gateway, whose reply is host input. "Before" is the OpenVMM of the
release that CI built from the named revision; "after" is OpenVMM built on
each host from the named revision with
build-openvmm(GNU for KVM, musl forMSHV, MSVC for WHP). Runs whose reply arrived before the acknowledgement:
46bfe02ed7870c09e2a8a0e351761cdd639746bfe02edwas the base of the first validation, anda8a0e3517, theOpenVMM of release
v0.1.0-dev.705412fddc32, differs from this pin's base,cd5cd3814, only in tests. Every run passed the scenario's own checks, amongthem that the input that the host sends while input is gated reaches the
guest only after the acknowledgement. The binaries that the "after" runs on
61cdd6397used had the SHA-256 digests9498d617…(KVM),b32de940…(MSHV), and
FB907106…(WHP), and those of the "before" runs ona8a0e3517,b4aaea17…,1a46efb6…, and088820BC…. With OpenVMM at61cdd6397, as with7870c09e2,test-microvm --processors 1 2 4passedguest-boot,lifecycle,virtio-net,snapshot-core,snapshot-rollback,snapshot-tiers,network-snapshot,console-snapshot,filesystem-snapshot,platform-filesystem,platform-network-policy,untiered-network-policy,run-console-restore, andsmp-snapshoton allthree hosts.
NVX, at this head:
python scripts/nvx.py verify, passed.python scripts/local_gates.py --base origin/dev --only test-changes markdown-links test-layout openvmm-vectors openvmm-cpu-profiles --run,passed, with no change to an existing test and the 4 vector and 1
CPU-profile comparisons passing against
61cdd6397.python scripts/openvmm_pin.py check-roadmap --worktreeandcheck-branch --topic, passed.nvx-cli, run before the rebase on scripts identical todev's, whichthis pull request leaves unchanged: of its 2188 tests, 88 were skipped and
7 subtests of two tests, the host-loopback and private-ingress script tests
of
test_microvm_tests, errored when their scripts timed out after 10seconds under Git's
sh.exeon a loaded Windows workstation, again whenrerun alone; the others passed, and so did
test_adversarialand the helpcommands. CI runs the gate on Linux and Windows.
openvmm-ciis left to CI, which waits for OpenVMM's CI of the pin.