pci_core/pcie: allow advertising support for PASID (TLP prefixing) in ports/switches#3997
Conversation
There was a problem hiding this comment.
⚠️ Not ready to approve
It introduces user-facing PASID terminology and new error paths without sufficiently accurate/helpful descriptions and without tests asserting the new config-space behavior.
Pull request overview
Enables PCIe root ports and switches in OpenVMM’s emulated topology to advertise End-to-End TLP prefixing capability, which is required for guest OSes to enable guest-PASID for devices behind a virtual IOMMU.
Changes:
- Add a
MaxEndEndTlpPrefixesencoding enum and aPciExpressCapability::with_tlp_prefixing_supported()helper to set Device Capabilities 2 bits. - Plumb a new per-port setting (
tlp_prefixing_supported) through downstream ports and switch upstream-port creation/validation. - Expose a new
pasidCLI/config flag that maps to advertising up to 4 TLP prefixes on ports/switch downstream ports.
File summaries
| File | Description |
|---|---|
vm/devices/pci/pcie/src/switch.rs |
Advertises/validates switch-level End-to-End TLP prefixing and adjusts tests. |
vm/devices/pci/pcie/src/port.rs |
Adds a port setting to advertise End-to-End TLP prefixing via PCIe capability. |
vm/devices/pci/pci_core/src/spec.rs |
Introduces MaxEndEndTlpPrefixes encoding used in Device Capabilities 2. |
vm/devices/pci/pci_core/src/capabilities/pci_express.rs |
Adds helper to set TLP prefixing-related capability bits. |
openvmm/openvmm_entry/src/cli_args.rs |
Adds pasid option for --pcie-root-port and --pcie-switch. |
openvmm/openvmm_entry/src/lib.rs |
Plumbs CLI pasid into the manifest/config objects. |
openvmm/openvmm_entry/src/ttrpc/mod.rs |
Initializes the new pasid field to false in ttrpc-built topologies. |
openvmm/openvmm_defs/src/config.rs |
Adds pasid: bool to PciePortConfig. |
openvmm/openvmm_core/src/worker/dispatch/pcie_topology.rs |
Maps PciePortConfig.pasid to tlp_prefixing_supported = Four. |
openvmm/openvmm_core/src/worker/dispatch.rs |
Updates call sites to renamed port-definition builder. |
Review details
Comments suppressed due to low confidence (1)
vm/devices/pci/pcie/src/switch.rs:751
test_upstream_switch_port_creationnow exercises both constructors but still only asserts vendor/device ID. Since this PR adds new observable config-space behavior (Device Capabilities 2 bits for End-to-End TLP prefixing), the test should assert those bits are set/clear accordingly.
#[test]
fn test_upstream_switch_port_creation() {
// Verify that we can read the vendor/device ID from config space
let port = UpstreamSwitchPort::new(false);
let vendor_device_id = port.cfg_space.read_u32(0x0);
let expected = (UPSTREAM_SWITCH_PORT_DEVICE_ID as u32) << 16 | (VENDOR_ID as u32);
assert_eq!(vendor_device_id, expected);
let port = UpstreamSwitchPort::new(true);
let vendor_device_id = port.cfg_space.read_u32(0x0);
let expected = (UPSTREAM_SWITCH_PORT_DEVICE_ID as u32) << 16 | (VENDOR_ID as u32);
assert_eq!(vendor_device_id, expected);
}
- Files reviewed: 10/10 changed files
- Comments generated: 7
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
There was a problem hiding this comment.
⚠️ Not ready to approve
New TLP-prefixing advertisement and switch validation logic are not covered by unit tests, increasing regression risk.
Review details
Comments suppressed due to low confidence (1)
vm/devices/pci/pcie/src/switch.rs:191
- The error text for InvalidMaxEndToEndTlpPrefixing reads like a boolean expression ("{supported_prefixes} != 0"), which is harder to understand when debugging. Consider phrasing it as an expected-vs-actual value (note that MaxEndEndTlpPrefixes::Four encodes to 0).
/// If the switch supports End-to-End TLP Prefixing, all downstream ports must support up to 4 prefixes.
#[error(
"downstream port '{name}' has invalid max end-to-end TLP prefixing support ({supported_prefixes} != 0)"
)]
- Files reviewed: 13/13 changed files
- Comments generated: 2
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| /// A downstream port's devfn could not be assigned. | ||
| #[error(transparent)] | ||
| Devfn(#[from] PortDevfnError), | ||
| /// All ports within a switch have to expose the same value for TLP prefixing support. |
There was a problem hiding this comment.
If this is the case, then shouldn't the property be on the switch and not the ports?
There was a problem hiding this comment.
Or do we need to do this because root ports don't have to all have the same config, and we share port config between downstream and root ports?
There was a problem hiding this comment.
Or do we need to do this because root ports don't have to all have the same config, and we share port config between downstream and root ports?
Yeah, this is why I wrote it like this. The uniformity and requirement of up to 4 only applies to switches, but we share the configuration types with root ports
There was a problem hiding this comment.
✅ Ready to approve
The functional changes are cohesive and covered by targeted unit tests; only minor error-message/docstring clarity nits were identified.
Note: this review does not count toward required approvals for merging.
Review details
Comments suppressed due to low confidence (1)
vm/devices/pci/pcie/src/switch.rs:191
- The error message for
InvalidMaxEndToEndTlpPrefixingcompares against0, but doesn’t explain that0is the encoding forMaxEndEndTlpPrefixes::Four(4 prefixes). This makes the message hard to interpret when debugging switch construction failures.
/// If the switch supports End-to-End TLP Prefixing, all downstream ports must support up to 4 prefixes.
#[error(
"downstream port '{name}' has invalid max end-to-end TLP prefixing support ({supported_prefixes} != 0)"
)]
- Files reviewed: 13/13 changed files
- Comments generated: 1
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
|
Needs a rebase. |
|
Otherwise looks good. |
There was a problem hiding this comment.
⚠️ Not ready to approve
Several user-facing/help/documentation strings around the new pasid flag are misleading or unclear relative to the actual behavior (TLP prefixing advertisement), and should be tightened before approval.
Review details
Comments suppressed due to low confidence (4)
openvmm/openvmm_defs/src/config.rs:267
- The
pasidfield doc comment says it "Enables PASID support" but the implementation only uses this flag to advertise End-to-End TLP prefixing support on the port. The comment should describe the actual behavior to avoid implying endpoint PASID capability changes.
/// Enables PASID support for functions downstream of this port.
pub pasid: bool,
openvmm/openvmm_entry/src/cli_args.rs:1153
- The
pasidCLI option help text implies full PASID enablement; in this PR it only controls advertising End-to-End TLP prefixing support upstream of devices. Consider tightening the wording so users understand what the flag actually toggles.
`acs=<mask>` ACS capability bitmask (u16, decimal or 0x-prefixed hex)
`cxl` configure this root port as CXL-capable
`pasid` configure this port to support PASID for downstream devices
openvmm/openvmm_entry/src/cli_args.rs:1190
- Same as above for
--pcie-switch: thepasidhelp text reads like it enables PASID generally, but it really controls TLP prefixing advertisement on the switch ports.
`num_downstream_ports=<value>` number of downstream ports, default 4
`acs=<mask>` ACS capability bitmask for downstream switch ports
`pasid` configure this port to support PASID for downstream devices
vm/devices/pci/pcie/src/switch.rs:191
- The
InvalidMaxEndToEndTlpPrefixingerror message hardcodes!= 0, which relies on readers knowing thatMaxEndEndTlpPrefixes::Fouris encoded as0b00. Making the expected value explicit (and printing the actual value in a clearer format) would make this much easier to interpret when it triggers.
/// If the switch supports End-to-End TLP Prefixing, all downstream ports must support up to 4 prefixes.
#[error(
"downstream port '{name}' has invalid max end-to-end TLP prefixing support ({supported_prefixes} != 0)"
)]
- Files reviewed: 13/13 changed files
- Comments generated: 2
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| - `pasid`: advertises support for TLP prefixing (such as for guest PASID | ||
| behind a virtual IOMMU) |
| - `pasid`: advertises support for TLP prefixing (such as for guest PASID | ||
| behind a virtual IOMMU) |
This change allows PCIe root ports and switches to advertise support for TLP prefixing, which guest OSes (like Linux) require to enable guest-PASID for assigned devices behind virtual IOMMUs.
PASID, or "process address space ID", is a hardware feature for DMA isolation. It relies on a couple different things:
This change specifically addresses #2 in this list