Add Guest Watchdog to chipset resources#3159
Add Guest Watchdog to chipset resources#3159moor-coding wants to merge 67 commits intomicrosoft:mainfrom
Conversation
moor-coding
commented
Mar 30, 2026
- Added Hyper-V guest watchdog resource handle support and resolver-based instantiation for chipset wiring.
- Updated VM manifest construction to include the guest watchdog via chipset-device resources instead of legacy direct deps wiring.
- Removed deprecated base-chipset guest watchdog dependency plumbing and manual runtime device-id checks.
- Added watchdog platform capability resource resolution and moved enablement to chipset capabilities (with_guest_watchdog).
- Registered the watchdog resolver path in both OpenVMM and OpenHCL static resource registries, including required crate/dependency updates.
- Introduced a new `PitDeviceHandle` struct in `chipset_resources` for resource identification. - Updated `vm_manifest_builder` to attach the PIT device during VM build. - Removed deprecated generic PIT dependencies from `base_chipset`. - Implemented the PIT device functionality in `pit/mod.rs`, including timer management and I/O operations. - Created a resource resolver for the PIT device in `pit/resolver.rs` to handle IRQ configuration and instantiation. - Added tests for the PIT device to ensure correct behavior in both binary and BCD modes.
- Introduced a new struct in for resource identification and bus attachment metadata. - Updated to attach the PIIX4 UHCI stub device during Hyper-V Gen1 VM manifest construction. - Removed deprecated legacy dependencies and direct instantiation from . - Implemented a UHCI resource resolver in to instantiate the device and register fixed PCI BDF . - Registered the resolver in both OpenVMM and OpenHCL static resource registries and added required crate dependencies. - Added tests to verify manifest attachment behavior and resolver PCI registration semantics.
…icrosoft#2944) ContiguousBufferMemory works by having a rolling `len`-sized window of valid offsets across all `u32` values. The only safe window sizes are therefore powers of 2, otherwise you can potentially have multiple buffers assigned the same offset near the end of the `u32` space, due to how modular arithmetic rolls over values. --------- Co-authored-by: Ben Lewis <Ben.Lewis@microsoft.com>
Previously, consomme dropped out-of-order TCP segments and relied on the sender to retransmit all data after a gap. This is correct but slow when segments arrive out of order — every gap causes a full retransmission cycle. Add a small assembler that tracks up to 4 non-contiguous received byte ranges, allowing out-of-order segments to be buffered in the ring and delivered once the gaps are filled. FIN handling is integrated: a FIN is latched when received but only delivered to the state machine once all preceding data is contiguous. - assembler.rs: new Assembler type with add/clear/try_fin, extensive unit tests covering merges, overlaps, table-full rejection, and FIN ordering - ring.rs: add write_at() for arbitrary-offset writes into the ring buffer (used for both in-order and OOO segments), support zero- capacity rings, fix wrapping mask computation - tcp.rs: replace VecDeque rx_buffer with Ring, integrate 3-stage reassembly (write to ring, record in assembler, advance frontier), add Inspect support to Assembler, fix DNS TCP backend for Ring API - tests.rs: end-to-end TCP test harness with real loopback sockets, covering in-order data, OOO reassembly, FIN in/out of order, host- to-guest data, host FIN, duplicate segments, and overlapping retransmissions
…rosoft#3080) External device backends (vhost-user) need access to the backing fds and region layout of guest RAM so they can mmap the same physical memory in their own process. This adds the plumbing to expose that information through GuestMemory without requiring direct knowledge of membacking. The MappingManager already tracks all active mappings. Rather than maintaining a separate snapshot, a new dma_target flag on regions marks which mappings are guest RAM (vs device MMIO). A DmaRegionProvider queries the MappingManager asynchronously and translates the results into ShareableRegions exposed through the GuestMemorySharing trait object, accessible via GuestMemory::sharing(). The guestmem crate defines the abstraction boundary: ShareableRegion, GuestMemorySharing, and the ProvideShareableRegions trait. The membacking crate provides the implementation. Consumers like vhost-user only depend on guestmem.
…microsoft#3084) Move GuestMemory from virtio device construction time to queue start time. This allows the transport to provide the correct GuestMemory at the point where it's actually needed (when queues are activated), rather than requiring it up front. This is useful in particular for vhost-user, where the memory cannot be provided until the VMM actually attaches.
Move the virtio specification constants and types (VirtioDeviceType, VirtioDeviceFeatures, VirtioDeviceStatus, PCI/MMIO register offsets, queue structures) into a new virtio_spec crate. Re-export as 'pub use virtio_spec as spec' from the virtio crate so all existing virtio::spec::* paths continue to work. Also change DeviceTraits::device_id from u16 to VirtioDeviceType for type safety.
…ft#3099) Add .github/workflows/copilot-setup-steps.yml to give the Copilot coding agent a working Rust toolchain, cargo-nextest, and restore-packages (protoc + build deps) so it can validate changes locally before pushing.
ARM64 VMs currently have no way to deliver PCIe MSIs because the GIC emulation exposes an ITS (LPI-based) interface that neither WHP nor our software model fully implements. Rather than building out ITS support, this change adds the simpler GIC v2m path: a single MMIO frame with a SETSPI_NS doorbell that converts MSI writes into SPI assertions, which the existing GIC SPI infrastructure already handles. The v2m frame is described to the guest via a child node of the GICv3 device-tree entry, and PCIe host bridge nodes reference it as their msi-parent. On WHP, LPI support is conditionally disabled when v2m is configured so Linux selects the v2m MSI domain instead of probing for a non-functional ITS. A new GicV2mSignalMsi type implements the SignalMsi trait by validating the doorbell address and SPI range, then forwarding to ControlGic. Both the KVM and WHP backends wire this into their Partition::as_signal_msi for aarch64. Legacy INTx is intentionally unsupported; all PCIe interrupt delivery goes through MSIs.
This pull request refactors the encryption feature for VMGS to use the new `crypto` crate. * Adds a new `aes_256_gcm` module to `support/crypto` * Replaces platform-specific VMGS encryption features (`encryption_win`, `encryption_ossl`) with a single `encryption` feature in all relevant `Cargo.toml` files and documentation, simplifying builds and dependencies * Refactors the XTS-AES-256 API to match the structure of the new AES-256-GCM module.
This seems to be the correct thing to do--these registers are RES1 when Aarch32 is not supported. This may require more iteration based on the behavior on other hardware. Fixes reset on virt_whp.
…icrosoft#3122) Replace the four tracing::trace! calls that dumped TcpRepr via Debug (which included raw payload bytes and produced huge, hard-to-filter output) with a trace_tcp_packet() helper that logs structured key/value fields: label, flags, seq, next_seq, ack, window, and payload_len. This makes traces lightweight, filterable, and avoids logging payload data entirely.
…osoft#3119) `VirtioWorkPool::capacity()` was returning the full writeable payload length, which includes the 12-byte virtio-net header. Backends use `capacity()` to determine the maximum Ethernet frame size they can deliver (via `rx_mtu()`), so they would construct frames up to `capacity()` bytes. `write_data()` then writes at offset `header_size()`, needing `header_size() + frame_len` total bytes -- overflowing the descriptor for max-size packets. This caused silent truncation of the last 12 bytes and reported a `used_len` exceeding the descriptor size. Fix this by computing the data capacity (`payload_length - header_size`) at `queue_work()` time and caching it in the `RxPacket`. `capacity()` now returns this value, and `complete_packet()` adds `header_size()` back to get the correct `used_len`.
…est-watchdog-base
There was a problem hiding this comment.
Pull request overview
This PR migrates the Hyper-V guest watchdog (and a couple of other legacy chipset devices) into the chipset-device resource/resolve path, adds a one-shot watchdog platform capability resource, and introduces static PCI placement hints so devices can self-describe where they should be wired on PCI without legacy “manual” plumbing.
Changes:
- Add
PciPlacementHint/PciPlacementsupport and propagate placement hints through the remote-device worker protocol and proxy. - Move PIT, PIIX4 USB UHCI stub, and Hyper-V guest watchdog instantiation to resource handles + resolvers; remove legacy
BaseChipsetBuilderdependency plumbing. - Add derived
ChipsetCapabilitiesto VM config/build results and use it for firmware/table generation decisions; register the new resolvers in OpenVMM + OpenHCL.
Reviewed changes
Copilot reviewed 33 out of 34 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| workers/chipset_device_worker/src/worker.rs | Sends optional static PCI placement hint in remote device init. |
| workers/chipset_device_worker/src/proxy.rs | Exposes supports_pci_placement() and returns placement hints from the proxy. |
| workers/chipset_device_worker/src/protocol.rs | Extends PciInit with optional PciPlacementInit payload. |
| vmm_core/vmotherboard/src/chipset/backing/arc_mutex/device.rs | Uses optional static placement hints to derive PCI bus/BDF when not explicitly wired. |
| vmm_core/vmotherboard/src/base_chipset.rs | Removes legacy PIT/UHCI/watchdog dependency wiring; iterates resource handles; adds explicit mesh indices for manifest fields. |
| vmm_core/vmotherboard/Cargo.toml | Drops direct guest_watchdog dependency from vmotherboard. |
| vmm_core/vm_manifest_builder/src/lib.rs | Attaches PIT/UHCI/watchdog via chipset resource handles; computes and exports chipset capabilities. |
| vm/devices/watchdog/watchdog_core/src/resources.rs | Adds watchdog platform capability resource kind + static resolver for a one-shot platform object. |
| vm/devices/watchdog/watchdog_core/src/lib.rs | Exposes the new resources module. |
| vm/devices/watchdog/watchdog_core/Cargo.toml | Adds vm_resource + parking_lot deps for watchdog platform capability resources. |
| vm/devices/watchdog/guest_watchdog/src/resolver.rs | Adds async resolver for Hyper-V guest watchdog chipset device handle. |
| vm/devices/watchdog/guest_watchdog/src/lib.rs | Updates constructor to accept a pre-mapped PIO region; exports resolver module. |
| vm/devices/watchdog/guest_watchdog/Cargo.toml | Adds resolver/resource-related dependencies. |
| vm/devices/chipset_resources/src/lib.rs | Adds resource handle definitions for PIT, PIIX4 UHCI stub, and Hyper-V guest watchdog. |
| vm/devices/chipset_resources/Cargo.toml | Adds watchdog_core dependency for watchdog platform kind. |
| vm/devices/chipset_legacy/src/piix4_uhci/resolver.rs | Adds resolver for PIIX4 UHCI stub device handle. |
| vm/devices/chipset_legacy/src/piix4_uhci.rs | Implements static PCI placement for the UHCI stub and exports resolver. |
| vm/devices/chipset_legacy/Cargo.toml | Adds resolver/resource dependencies needed for UHCI stub resolver. |
| vm/devices/chipset/src/pit/resolver.rs | Adds resolver for PIT device handle. |
| vm/devices/chipset/src/pit/mod.rs | Exports PIT resolver module. |
| vm/chipset_device_resources/src/lib.rs | Plumbs supports_pci_placement() through erased devices. |
| vm/chipset_device/src/pci.rs | Introduces PciPlacementHint and PciPlacement trait for static placement. |
| vm/chipset_device/src/lib.rs | Adds supports_pci_placement() capability hook to ChipsetDevice. |
| petri/src/vm/openvmm/construct.rs | Passes derived ChipsetCapabilities into OpenVMM config. |
| openvmm/openvmm_resources/src/lib.rs | Registers PIT/UHCI/watchdog resolvers in OpenVMM static resolver registry. |
| openvmm/openvmm_resources/Cargo.toml | Adds dependencies for chipset_legacy and guest_watchdog resolvers. |
| openvmm/openvmm_entry/src/ttrpc/mod.rs | Threads chipset capabilities into constructed Config. |
| openvmm/openvmm_entry/src/lib.rs | Threads chipset capabilities into CLI-built Config. |
| openvmm/openvmm_defs/src/config.rs | Adds ChipsetCapabilities and stores it on Config. |
| openvmm/openvmm_core/src/worker/dispatch.rs | Registers runtime watchdog platform resolver and switches firmware/table inputs to chipset capabilities. |
| openhcl/underhill_core/src/worker.rs | Registers runtime watchdog platform resolver and uses capabilities for watchdog enablement. |
| openhcl/openvmm_hcl_resources/src/lib.rs | Registers PIT/UHCI/watchdog resolvers in OpenHCL static resolver registry. |
| openhcl/openvmm_hcl_resources/Cargo.toml | Adds dependencies for chipset_legacy and guest_watchdog resolvers. |
| Cargo.lock | Updates dependency graph for added crates/edges. |
| fn attach_guest_watchdog(&mut self) -> &mut Self { | ||
| self.chipset_devices.push(ChipsetDeviceHandle { | ||
| name: "hyperv-guest-watchdog".to_owned(), | ||
| resource: HyperVGuestWatchdogDeviceHandle { | ||
| port_base: WDAT_PORT, | ||
| platform: PlatformResource.into_resource(), | ||
| } | ||
| .into_resource(), | ||
| }); |
There was a problem hiding this comment.
The guest watchdog device handle is introduced with the name "hyperv-guest-watchdog", but the device previously existed in BaseChipsetBuilder as "guest-watchdog". Since vmotherboard uses device names as state-unit keys, changing the name can break snapshot/save-restore compatibility for VMs that already have a saved state containing the watchdog. Consider keeping the device name stable (e.g., continue using "guest-watchdog") while still using the new resource handle/resolver wiring.