Skip to content

vfio_assigned_device: unmap BARs on PCI PM state transitions#3609

Open
jstarks wants to merge 6 commits into
microsoft:mainfrom
jstarks:vfio_d0
Open

vfio_assigned_device: unmap BARs on PCI PM state transitions#3609
jstarks wants to merge 6 commits into
microsoft:mainfrom
jstarks:vfio_d0

Conversation

@jstarks
Copy link
Copy Markdown
Member

@jstarks jstarks commented May 31, 2026

When a guest transitions a VFIO-assigned device to D3hot via a PMCSR write, the VFIO driver puts the physical device into D3hot and tears down the userspace BAR mmap mappings. Any subsequent access to those pages faults with SIGBUS. Since OpenVMM maps these pages into KVM as guest physical address space for direct MMIO access, the stale mappings cause the VMM process to be killed on the next guest MMIO access to the device.

Fix this by intercepting PMCSR writes and unmapping BARs from the guest address space whenever the device leaves D0, using the same pattern already used for the Memory Space Enable bit in the Command register. BARs are remapped when the device returns to D0. This is slightly more conservative than VFIO, which only tears down mappings on D3hot -- we also unmap on D1/D2 transitions per the PCI spec requirement that BARs not decode in non-D0 states. D1/D2 are extremely rare in practice so the conservatism has zero cost.

The capability discovery code was refactored as part of this change. The three separate functions that each independently walked capability chains via raw file descriptor parameters are now unified into a single discover_capabilities function that walks both the standard and extended chains in one pass. The function takes a &dyn ConfigSpaceRead trait object instead of raw file parameters, allowing the capability parsing logic to be unit tested with an in-memory mock config space.

When a guest transitions a VFIO-assigned device to D3hot via a PMCSR
write, the VFIO driver puts the physical device into D3hot and tears down
the userspace BAR mmap mappings. Any subsequent access to those pages
faults with SIGBUS. Since OpenVMM maps these pages into KVM as guest
physical address space for direct MMIO access, the stale mappings cause
the VMM process to be killed on the next guest MMIO access to the device.

Fix this by intercepting PMCSR writes and unmapping BARs from the guest
address space whenever the device leaves D0, using the same pattern
already used for the Memory Space Enable bit in the Command register.
BARs are remapped when the device returns to D0. This is slightly more
conservative than VFIO, which only tears down mappings on D3hot -- we also
unmap on D1/D2 transitions per the PCI spec requirement that BARs not
decode in non-D0 states. D1/D2 are extremely rare in practice so the
conservatism has zero cost.

The capability discovery code was refactored as part of this change. The
three separate functions that each independently walked capability chains
via raw file descriptor parameters are now unified into a single
discover_capabilities function that walks both the standard and extended
chains in one pass. The function takes a \`&dyn ConfigSpaceRead\` trait
object instead of raw file parameters, allowing the capability parsing
logic to be unit tested with an in-memory mock config space.
Copilot AI review requested due to automatic review settings May 31, 2026 23:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens VFIO PCI passthrough against guest-initiated PCI Power Management (PMCSR) D-state transitions by ensuring BAR-backed guest mappings are torn down when the device is not in D0, preventing SIGBUS crashes from stale VFIO mmaps. It also refactors PCI capability discovery into a single pass over standard + extended capability chains and adds unit tests via a mock config space reader.

Changes:

  • Intercept PMCSR writes to toggle BAR mappings based on D0 vs non-D0 power state, similar to existing Command(MSE) handling.
  • Unify capability discovery into discover_capabilities(&dyn ConfigSpaceRead, ...) and expand discovery to include PM capability + config patch generation.
  • Add unit tests for capability discovery using an in-memory mock config space; extend PCI capability IDs to include Power Management.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

File Description
vm/devices/pci/vfio_assigned_device/src/lib.rs Adds PMCSR interception + D-state tracking for BAR unmapping, refactors capability discovery, and introduces unit tests with a mock config-space reader.
vm/devices/pci/vfio_assigned_device/Cargo.toml Adds Linux-only dev-dependencies needed for the new unit tests.
vm/devices/pci/pci_core/src/spec.rs Adds POWER_MANAGEMENT to the PCI standard capability ID enum for capability parsing.
Cargo.lock Records the new dev-dependency (test_with_tracing) in the lockfile.

Comment thread vm/devices/pci/vfio_assigned_device/src/lib.rs Outdated
Copilot AI review requested due to automatic review settings June 1, 2026 00:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

Comment thread vm/devices/pci/vfio_assigned_device/src/lib.rs Outdated
@jstarks jstarks marked this pull request as ready for review June 1, 2026 02:51
@jstarks jstarks requested a review from a team as a code owner June 1, 2026 02:51
Copilot AI review requested due to automatic review settings June 1, 2026 02:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.

Comment thread vm/devices/pci/vfio_assigned_device/src/lib.rs
Comment thread vm/devices/pci/vfio_assigned_device/src/lib.rs
Comment thread vm/devices/pci/vfio_assigned_device/src/lib.rs
Comment thread vm/devices/pci/vfio_assigned_device/src/lib.rs
Comment thread vm/devices/pci/vfio_assigned_device/Cargo.toml
Copilot AI review requested due to automatic review settings June 1, 2026 04:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

vm/devices/pci/vfio_assigned_device/src/lib.rs:141

  • bar_masks is no longer derived via the "write all 1s, read back" BAR probe cycle (it’s derived from the VFIO BAR region sizes below). The field doc comment is now misleading and should be updated to match the actual derivation, since this is security-/stability-adjacent code and incorrect comments can cause future regressions.
    /// BAR masks as read from the physical device (write 0xFFFFFFFF, read back).
    #[inspect(iter_by_index, hex)]
    bar_masks: [u32; 6],

Comment thread vm/devices/pci/vfio_assigned_device/src/lib.rs
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants