openvmm_entry/ttrpc: expose PCIe NUMA and ACS config#4009
Conversation
GB200-style device topologies need the management interface to describe PCIe devices as ACPI Generic Initiators and control the ACS capabilities advertised by individual ports. Extend the VM service schema and topology conversion so these settings reach the canonical OpenVMM configuration. Use pipette in the ttrpc integration test to verify the resulting SRAT Generic Initiator entry and ACS capability directly from inside the guest.
There was a problem hiding this comment.
Pull request overview
This PR extends the OpenVMM ttrpc VM service schema and its openvmm_entry conversion layer to support (1) PCIe NUMA “Generic Initiator” descriptions and (2) per-port ACS capability advertisement, and adds a VMM integration test that validates both behaviors from inside the guest using pipette.
Changes:
- Extend
vmservice.protowithPcieGenericInitiatorandPciePort.acs_capabilities_supported. - Plumb the new schema fields through
openvmm_entrytopology conversion into the canonicalopenvmm_defs::config. - Enhance the ttrpc VMM test to inject pipette into the initrd and validate SRAT GI affinity + ACS capability in-guest.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vmm_tests/vmm_tests/tests/tests/ttrpc.rs | Injects pipette into the guest initrd, enables hvsocket for one VM instance, configures ACS + GI, and validates SRAT/PCIe config from inside the guest. |
| vmm_tests/vmm_tests/Cargo.toml | Adds initrd_cpio dependency for initrd injection in the test. |
| openvmm/openvmm_ttrpc_vmservice/src/vmservice.proto | Adds schema support for PCIe Generic Initiators and per-port ACS capability configuration. |
| openvmm/openvmm_entry/src/ttrpc/mod.rs | Threads new PCIe schema fields into openvmm_defs::config via a flattened BuiltPcieTopology. |
| Cargo.lock | Locks the new initrd_cpio dependency. |
Comments suppressed due to low confidence (2)
vmm_tests/vmm_tests/tests/tests/ttrpc.rs:866
- This
unwrap()can panic if the slice length is wrong; prefer propagating a contextual error so failures are reported cleanly (especially when debugging guest PCI config parsing).
config
.get(capability_offset..capability_offset + 4)
.context("invalid PCIe extended capability offset")?
.try_into()
.unwrap(),
vmm_tests/vmm_tests/tests/tests/ttrpc.rs:885
- This
unwrap()can panic on unexpected config layout. Usingcontext(...)?here will keep the test failure in the anyhow error path with a clearer message.
config
.get(acs_offset + 4..acs_offset + 6)
.context("parent port has no ACS capability register")?
.try_into()
.unwrap(),
| let proximity_domain = | ||
| u32::from_le_bytes(srat[offset + 4..offset + 8].try_into().unwrap()); | ||
| let entry_segment = | ||
| u16::from_le_bytes(srat[offset + 8..offset + 10].try_into().unwrap()); | ||
| let entry_bus = srat[offset + 10]; | ||
| let entry_devfn = srat[offset + 11]; | ||
| let flags = u32::from_le_bytes(srat[offset + 24..offset + 28].try_into().unwrap()); |
| message PcieTopologyConfig { | ||
| // The PCIe root complexes in the VM. | ||
| repeated PcieRootComplex root_complexes = 1; | ||
| // Devices that act as initiators for device-only NUMA nodes. |
| let pipette_initrd = initrd_cpio::inject_into_initrd(&initrd, "pipette", &pipette, 0o100755) | ||
| .context("failed to inject pipette into test initrd")?; | ||
| let mut pipette_initrd_file = tempfile::NamedTempFile::new()?; | ||
| pipette_initrd_file.write_all(&pipette_initrd)?; |
| if let Some(listener) = pipette_listener { | ||
| let mut listener = PolledSocket::new(&driver, listener)?; | ||
| let (conn, _) = listener.accept().await?; | ||
| let conn = PolledSocket::new(&driver, conn)?; | ||
| let agent = pipette_client::PipetteClient::new( | ||
| &driver, | ||
| conn, | ||
| params.logger.output_dir(), | ||
| ) | ||
| .await?; | ||
| validate_pcie_config(&agent).await?; | ||
| agent.power_off().await?; | ||
| } |
d806e1c to
09f26e6
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
vmm_tests/vmm_tests/tests/tests/ttrpc.rs:539
listener.accept().awaithas no timeout, so if the guest fails to start pipette (or HvSocket wiring breaks) this test can hang indefinitely in CI. Add an explicit deadline around the accept and fail with a clear error message on timeout.
if let Some(listener) = pipette_listener {
let mut listener = PolledSocket::new(&driver, listener)?;
let (conn, _) = listener.accept().await?;
let conn = PolledSocket::new(&driver, conn)?;
let agent = pipette_client::PipetteClient::new(
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
vmm_tests/vmm_tests/tests/tests/ttrpc.rs:66
pipette_initrd_fileis created withNamedTempFile::new(), which places it in the global temp directory rather than undertempdir. This contradicts the comment above that all temporary files for the test live under a single temp directory, and also makes it harder to correlate artifacts when debugging failures.
Create the file inside tempdir with NamedTempFile::new_in(tempdir.path()) (or update the comment if the intent is to allow temp files elsewhere).
let pipette_initrd = initrd_cpio::inject_into_initrd(&initrd, "pipette", &pipette, 0o100755)
.context("failed to inject pipette into test initrd")?;
let mut pipette_initrd_file = tempfile::NamedTempFile::new()?;
pipette_initrd_file.write_all(&pipette_initrd)?;
| // graph to the log so VM state is captured for | ||
| // post-mortem diagnosis even when no client is | ||
| // attached to inspect it. | ||
| self.dump_inspect_graph().await; |
GB200-style device topologies need the management interface to describe PCIe devices as ACPI Generic Initiators and control the ACS capabilities advertised by individual ports. Extend the VM service schema and topology conversion so these settings reach the canonical OpenVMM configuration.
Use pipette in the ttrpc integration test to verify the resulting SRAT Generic Initiator entry and ACS capability directly from inside the guest.