vmm_core: decouple chipset MMIO ranges from MemoryLayout#3550
Open
jstarks wants to merge 4 commits into
Open
Conversation
Contributor
oh no, here we go again |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors how chipset MMIO ranges are represented and consumed across OpenVMM/OpenHCL boot flows by introducing an explicit ChipsetMmioRanges concept instead of relying on positional indexing into MemoryLayout::mmio(). It also moves VTL2 framebuffer GPA placement into the memory layout resolver so it is allocated alongside other post-MMIO ranges.
Changes:
- Introduce/propagate explicit chipset MMIO range plumbing (low/high/VTL2) through loaders, ACPI/DSDT generation, firmware config, and MTRR computation.
- Remove/relax prior “exactly two MMIO gaps” assertions and error paths by using resolved chipset MMIO ranges directly.
- Allocate the VTL2 framebuffer GPA via the memory layout resolver (PostMmio placement) instead of ad-hoc scanning.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vmm_core/src/acpi_builder.rs | Simplifies the DSDT callback interface to no longer pass MemoryLayout. |
| vm/loader/src/common.rs | Updates x86 variable MTRR computation to take explicit low/high chipset MMIO ranges. |
| vm/devices/firmware/firmware_pcat/src/lib.rs | PCAT config now carries explicit chipset low/high MMIO ranges; runtime reads use those ranges. |
| vm/devices/firmware/firmware_pcat/Cargo.toml | Promotes memory_range from dev-dependency to dependency to support new config fields. |
| vm/acpi/src/dsdt.rs | Uses MemoryRange::len() when generating QWORD memory resources. |
| openvmm/openvmm_core/src/worker/vm_loaders/uefi.rs | UEFI loader consumes ChipsetMmioRanges for UEFI config MMIO ranges. |
| openvmm/openvmm_core/src/worker/vm_loaders/linux.rs | ARM64 DT build path consumes explicit chipset low/high MMIO ranges for VMBus ranges. |
| openvmm/openvmm_core/src/worker/vm_loaders/igvm.rs | Consolidates chipset MMIO parameters into a single ChipsetMmioRanges struct for IGVM load paths. |
| openvmm/openvmm_core/src/worker/memory_layout.rs | Introduces ChipsetMmioRanges in the resolver output and adds PostMmio allocation for VTL2 framebuffer GPA. |
| openvmm/openvmm_core/src/worker/dispatch.rs | Threads resolved chipset MMIO ranges through firmware loaders and DSDT construction; switches MTRR computation callsite to new signature. |
| openhcl/underhill_core/src/worker.rs | Constructs chipset MMIO ranges from boot-info MMIO list and threads them into firmware + MTRR setup and other consumers. |
| openhcl/underhill_core/src/loader/mod.rs | Threads chipset MMIO ranges into ACPI DSDT build and UEFI config blob generation. |
smalis-msft
approved these changes
May 21, 2026
smalis-msft
reviewed
May 22, 2026
| // No high MMIO gap — RAM above the low gap is contiguous. | ||
| // Cover to the 8TB boundary (or GPA space limit) using the | ||
| // same split as the >64GB path below. | ||
| result.push(X86Register::MtrrPhysMask2(mtrr_mask( |
Contributor
There was a problem hiding this comment.
Changing this code at all makes me nervous given that we no longer have all the extra debug checks compiled into the kernel for the MTRR test...
smalis-msft
approved these changes
May 22, 2026
The chipset MMIO ranges (low below 4 GiB, high above RAM) are a logical concept of the chipset configuration, but they were previously read by positional indexing into MemoryLayout::mmio(). This was fragile: it required exactly two MMIO entries, scattered assertions and error paths enforced that invariant, and the coupling prevented evolving the memory layout's MMIO accounting independently of the chipset's view of MMIO. Introduce a ChipsetMmioRanges struct that carries the chipset low, high, and VTL2 MMIO ranges explicitly, and thread it through the loader, ACPI builder, DSDT construction, MTRR computation, firmware_pcat, and IGVM/UEFI/Linux boot paths. This removes all the mmio().len() >= 2 assertions and error variants, since the ranges are now provided directly rather than reverse-engineered from the memory layout. As a drive-by, the VTL2 framebuffer GPA allocation moves into the memory layout resolver so it participates in the same non-overlapping placement as other post-MMIO ranges, and build_acpi_tables's closure no longer receives a &MemoryLayout it didn't need.
Comment on lines
+236
to
+237
| vmod_crs.add_resource(&QwordMemory::new(low.start(), low.len())); | ||
| vmod_crs.add_resource(&QwordMemory::new(high.start(), high.len())); |
| crs.add_resource(&QwordMemory::new(low.start(), low.end() - low.start())); | ||
| crs.add_resource(&QwordMemory::new(high.start(), high.end() - high.start())); | ||
| crs.add_resource(&QwordMemory::new(low.start(), low.len())); | ||
| crs.add_resource(&QwordMemory::new(high.start(), high.len())); |
Comment on lines
135
to
140
| result.push(X86Register::MtrrPhysBase1(pcat_mtrr_size | WRITEBACK)); | ||
| result.push(X86Register::MtrrPhysMask1(mtrr_mask( | ||
| gpa_space_size, | ||
| mmio_gap_low.start() - 1, | ||
| chipset_low_mmio.start() - 1, | ||
| ))); | ||
| } |
Comment on lines
+350
to
+362
| // VTL2 framebuffer: a page-aligned PostMmio allocation so the GPA does | ||
| // not overlap RAM or any MMIO range. | ||
| let mut vtl2_framebuffer_range = MemoryRange::EMPTY; | ||
| if input.vtl2_framebuffer_size != 0 { | ||
| builder.request( | ||
| "vtl2-framebuffer", | ||
| &mut vtl2_framebuffer_range, | ||
| input.vtl2_framebuffer_size, | ||
| PAGE_SIZE, | ||
| Placement::PostMmio, | ||
| ); | ||
| } | ||
|
|
| return Err(PcatBiosDeviceInitError::IncorrectMmioHoles( | ||
| config.mem_layout.mmio().len(), | ||
| )); | ||
| if config.chipset_low_mmio.is_empty() || config.chipset_high_mmio.is_empty() { |
Comment on lines
134
to
139
| if memory.end_of_ram() > pcat_mtrr_size { | ||
| result.push(X86Register::MtrrPhysBase1(pcat_mtrr_size | WRITEBACK)); | ||
| result.push(X86Register::MtrrPhysMask1(mtrr_mask( | ||
| gpa_space_size, | ||
| mmio_gap_low.start() - 1, | ||
| chipset_low_mmio.start() - 1, | ||
| ))); |
Comment on lines
+1712
to
+1725
| // Construct chipset MMIO ranges from the positional convention in the | ||
| // device tree: [0] = low (below 4 GiB), [1] = high (above RAM). | ||
| let mut chipset_mmio = ChipsetMmioRanges { | ||
| low: boot_info | ||
| .vtl0_mmio | ||
| .first() | ||
| .copied() | ||
| .unwrap_or(MemoryRange::EMPTY), | ||
| high: boot_info | ||
| .vtl0_mmio | ||
| .get(1) | ||
| .copied() | ||
| .unwrap_or(MemoryRange::EMPTY), | ||
| }; |
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.
The chipset MMIO ranges (low below 4 GiB, high above RAM) are a logical concept of the chipset configuration, but they were previously read by positional indexing into
MemoryLayout::mmio(). This was fragile: it required exactly two MMIO entries, scattered assertions and error paths enforced that invariant, and the coupling prevented evolving the memory layout's MMIO accounting independently of the chipset's view of MMIO.Introduce a
ChipsetMmioRangesstruct that carries the chipset low, high, and VTL2 MMIO ranges explicitly, and thread it through the loader, ACPI builder, DSDT construction, MTRR computation,firmware_pcat, and IGVM/UEFI/Linux boot paths. This removes all themmio().len() >= 2assertions and error variants, since the ranges are now provided directly rather than reverse-engineered from the memory layout.As a drive-by, the VTL2 framebuffer GPA allocation moves into the memory layout resolver so it participates in the same non-overlapping placement as other post-MMIO ranges.