Add generic ISA DMA support to chipset resources#3117
Add generic ISA DMA support to chipset resources#3117moor-coding wants to merge 77 commits intomicrosoft:mainfrom
Conversation
- 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.
There was a problem hiding this comment.
Pull request overview
Adds resource-level support for ISA DMA (and normalizes PIT/UHCI stub to resources) so the base chipset can resolve DMA early enough for floppy wiring, while also carrying optional static PCI placement metadata in chipset device handles.
Changes:
- Introduces
GenericIsaDmaDeviceHandle(+ resolver) and exposes ISA DMA controller access viaChipsetDevice::supports_isa_dma_controller. - Reworks base chipset wiring to resolve ISA DMA handles before floppy setup; shifts PIT and PIIX4 UHCI stub instantiation to resource resolvers and manifest handles (with optional fixed PCI placement).
- Plumbs a new
with_pitboolean through config/worker paths for ACPI table generation and adds manifest-builder tests around PIT attachment.
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
vmm_core/vmotherboard/src/lib.rs |
Adds ChipsetDevicePciPlacement and extends ChipsetDeviceHandle with optional PCI placement metadata. |
vmm_core/vmotherboard/src/base_chipset.rs |
Resolves ISA DMA device handle early (before floppy wiring), applies optional PCI placement when resolving handles, and adapts DMA channel wiring to erased devices. |
vmm_core/vm_manifest_builder/src/lib.rs |
Adds DMA/PIT/UHCI stub handles to manifests, provides with_pit() helper, and adds unit tests for PIT attachment matrix/idempotency. |
vm/devices/chipset_resources/src/lib.rs |
Adds resource IDs for PIT, generic ISA DMA, and PIIX4 UHCI stub. |
vm/devices/chipset_legacy/src/piix4_uhci/resolver.rs |
New async resolver for the PIIX4 UHCI stub device. |
vm/devices/chipset_legacy/src/piix4_uhci.rs |
Exposes the new UHCI resolver module. |
vm/devices/chipset_legacy/Cargo.toml |
Adds dependencies needed for chipset-device resource resolving (and async resolver). |
vm/devices/chipset/src/pit/resolver.rs |
New PIT resolver that wires IRQ2 and vmtime access. |
vm/devices/chipset/src/pit/mod.rs |
Exposes PIT resolver module. |
vm/devices/chipset/src/dma/resolver.rs |
New resolver for the generic ISA DMA controller. |
vm/devices/chipset/src/dma/mod.rs |
Adds ISA DMA controller capability plumbing to the DMA device. |
vm/chipset_device_resources/src/lib.rs |
Extends erased chipset device wrapper to forward ISA DMA controller capability. |
vm/chipset_device/src/lib.rs |
Adds supports_isa_dma_controller() capability hook and exports new isa_dma module. |
vm/chipset_device/src/isa_dma.rs |
Introduces the ISA DMA controller capability trait and transfer types. |
petri/src/vm/openvmm/modify.rs |
Updates chipset device handle construction for the new pci_placement field. |
petri/src/vm/openvmm/construct.rs |
Captures manifest with_pit() and propagates it into OpenVMM config; updates handle construction. |
openvmm/openvmm_resources/src/lib.rs |
Registers new chipset resolvers (DMA, PIT, UHCI stub) for OpenVMM. |
openvmm/openvmm_resources/Cargo.toml |
Adds chipset_legacy dependency to support UHCI stub resolver registration. |
openvmm/openvmm_entry/src/ttrpc/mod.rs |
Propagates with_pit from manifest into worker config. |
openvmm/openvmm_entry/src/lib.rs |
Propagates with_pit from manifest into worker config; updates handle construction. |
openvmm/openvmm_defs/src/config.rs |
Adds with_pit: bool to worker Config. |
openvmm/openvmm_core/src/worker/dispatch.rs |
Uses with_pit (plus manifest flags) for ACPI table generation and carries capabilities through VM lifecycle. |
openhcl/underhill_core/src/worker.rs |
Removes PIT/UHCI deps plumbing and updates handle construction for pci_placement. |
openhcl/openvmm_hcl_resources/src/lib.rs |
Registers PIT and UHCI stub resolvers for OpenVMM-HCL (but currently missing DMA resolver). |
openhcl/openvmm_hcl_resources/Cargo.toml |
Adds chipset_legacy dependency for UHCI stub resolver registration. |
Cargo.lock |
Lockfile updates for new/changed dependencies. |
Comments suppressed due to low confidence (1)
vm/devices/chipset/src/dma/mod.rs:225
impl IsaDmaController for DmaControllercurrently callsself.check_transfer_size(...)insidecheck_transfer_size, which resolves back to the same trait method and will recurse until stack overflow. Disambiguate the call to the inherent method (or rename one of the methods) so the trait implementation delegates to the existing controller logic instead of recursing.
…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.
- Add a generic ISA DMA resource handle and resolver registration. - Add ISA DMA controller capability plumbing to chipset_device and erased wrappers. - Resolve DMA before floppy wiring in base chipset to avoid NoDmaForFloppy at runtime.
- register generic ISA DMA resolver for HCL resources - ratelimit ISA DMA mismatch logging and warn on duplicate DMA handles - switch vm_manifest_builder tests to test_with_tracing
3afadb5 to
f1e4888
Compare
| pub struct PciPlacementHint { | ||
| /// Name of the PCI bus this device should attach to. | ||
| pub bus_name: &'static str, | ||
| /// Optional static BDF for this device. | ||
| /// | ||
| /// If absent, the VMM may use `PciConfigSpace::suggested_bdf`. | ||
| pub bdf: Option<(u8, u8, u8)>, |
There was a problem hiding this comment.
PciPlacementHint::bus_name is typed as &'static str, which forces callers without truly-static bus names (e.g. remote device proxies) to leak memory or otherwise manufacture a 'static reference. Since BusId::new only needs &str (it clones into Arc<str>), consider making bus_name owned (e.g. Arc<str>/Box<str>/String) or lifetime-parameterized so implementations can return borrowed data without leaks.
| // The transport payload is owned String; leak once to satisfy the | ||
| // static lifetime required by PciPlacementHint. | ||
| bus_name: Box::leak(placement.bus_name.into_boxed_str()), |
There was a problem hiding this comment.
Using Box::leak here permanently leaks the bus name string for every proxied device instance, which can accumulate across VM create/destroy cycles. If the goal is only to pass a placement hint through, consider adjusting the PciPlacementHint API to avoid requiring a 'static bus name (or store the owned string in the proxy and return a borrowed reference tied to self).
| // The transport payload is owned String; leak once to satisfy the | |
| // static lifetime required by PciPlacementHint. | |
| bus_name: Box::leak(placement.bus_name.into_boxed_str()), | |
| // The transport payload is an owned String; store it directly to avoid leaks. | |
| bus_name: placement.bus_name, |
| fn attach_piix4_pci_usb_uhci_stub(&mut self) -> &mut Self { | ||
| self.chipset_devices.push(ChipsetDeviceHandle { | ||
| name: "piix4-usb-uhci-stub".to_string(), | ||
| resource: Piix4PciUsbUhciStubDeviceHandle.into_resource(), | ||
| }); | ||
| self |
There was a problem hiding this comment.
attach_piix4_pci_usb_uhci_stub is not idempotent (unlike attach_generic_isa_dma/attach_pit), so callers that already provided a Piix4PciUsbUhciStubDeviceHandle can end up with duplicate UHCI stub devices in chipset_devices. Consider checking for an existing handle (by resource.id()) and returning early if present.
This PR: