Skip to content

pci_core/pcie: allow advertising support for PASID (TLP prefixing) in ports/switches#3997

Merged
jstarks merged 5 commits into
microsoft:mainfrom
jackschefer-msft:pcie-port-pasid-tlp-prefixing
Jul 23, 2026
Merged

pci_core/pcie: allow advertising support for PASID (TLP prefixing) in ports/switches#3997
jstarks merged 5 commits into
microsoft:mainfrom
jackschefer-msft:pcie-port-pasid-tlp-prefixing

Conversation

@jackschefer-msft

Copy link
Copy Markdown
Contributor

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:

  1. The endpoint device must expose a PASID capability structure in config space, and support generating PASID-tagged DMA
  2. All PCIe ports on the path from endpoint device to root complex must support end-to-end TLP prefixes, or the ability to forward TLP prefixes transparently
  3. The endpoint device must be behind an IOMMU that supports PASID

This change specifically addresses #2 in this list

@jackschefer-msft
jackschefer-msft requested a review from a team as a code owner July 22, 2026 00:35
Copilot AI review requested due to automatic review settings July 22, 2026 00:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 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 MaxEndEndTlpPrefixes encoding enum and a PciExpressCapability::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 pasid CLI/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_creation now 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.

Comment thread vm/devices/pci/pci_core/src/spec.rs Outdated
Comment thread vm/devices/pci/pci_core/src/spec.rs
Comment thread vm/devices/pci/pcie/src/switch.rs
Comment thread vm/devices/pci/pcie/src/switch.rs
Comment thread openvmm/openvmm_entry/src/cli_args.rs Outdated
Comment thread openvmm/openvmm_entry/src/cli_args.rs Outdated
Comment thread openvmm/openvmm_defs/src/config.rs
Copilot AI review requested due to automatic review settings July 22, 2026 00:51
@github-actions github-actions Bot added the Guide label Jul 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 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.

Comment thread vm/devices/pci/pci_core/src/capabilities/pci_express.rs
Comment thread vm/devices/pci/pcie/src/switch.rs
/// 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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the case, then shouldn't the property be on the switch and not the ports?

@jstarks jstarks Jul 22, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread vm/devices/pci/pci_core/src/capabilities/pci_express.rs Outdated
Comment thread vm/devices/pci/pci_core/src/spec.rs Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 16:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 InvalidMaxEndToEndTlpPrefixing compares against 0, but doesn’t explain that 0 is the encoding for MaxEndEndTlpPrefixes::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.

Comment thread vm/devices/pci/pcie/src/switch.rs
@jstarks

jstarks commented Jul 22, 2026

Copy link
Copy Markdown
Member

Needs a rebase.

@jstarks

jstarks commented Jul 22, 2026

Copy link
Copy Markdown
Member

Otherwise looks good.

Copilot AI review requested due to automatic review settings July 22, 2026 19:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 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 pasid field 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 pasid CLI 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: the pasid help 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 InvalidMaxEndToEndTlpPrefixing error message hardcodes != 0, which relies on readers knowing that MaxEndEndTlpPrefixes::Four is encoded as 0b00. 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.

Comment on lines +306 to +307
- `pasid`: advertises support for TLP prefixing (such as for guest PASID
behind a virtual IOMMU)
Comment on lines +320 to +321
- `pasid`: advertises support for TLP prefixing (such as for guest PASID
behind a virtual IOMMU)
@github-actions

Copy link
Copy Markdown

@jstarks
jstarks merged commit 78f3f61 into microsoft:main Jul 23, 2026
68 of 69 checks passed
@jackschefer-msft
jackschefer-msft deleted the pcie-port-pasid-tlp-prefixing branch July 23, 2026 15:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants