vmm: defer PCI device visibility to fix hotplug race condition - #8369
Merged
rbradford merged 2 commits intoJun 12, 2026
Merged
Conversation
Member
|
I think this partially goes into the direction we discussed in #8255 - nice |
Contributor
Author
rbradford
approved these changes
Jun 11, 2026
rbradford
left a comment
Member
There was a problem hiding this comment.
Really happy. Thanks! Although it needs a rebase.
`PciBus::register_mapping()` operates on `mmio_bus` and `io_bus` which are passed in as external parameters and have nothing to do with PciBus internal state. Move this logic into `DeviceManager::register_bar_mapping()` where it belongs, and move the `PioInsert`/`MmioInsert` error variants from `PciRootError` to `DeviceManagerError` accordingly. Signed-off-by: wuxinyue <[email protected]> Assisted-by: Claude:Opus-4.6
Split `add_pci_device()` into two phases: `allocate_pci_bars()` which only allocates BAR address space, and `commit_pci_device()` which makes the device visible to the guest on the PCI bus. All callers now follow the pattern: allocate BARs → perform device- specific setup (ioeventfd, device_tree, mmio mapping) → commit device. This eliminates a race window where the guest could discover a partially-initialized device via `acpiphp_check_bridge()` during rapid sequential hotplug, causing BAR reprogramming to fail because ioeventfds and device_tree entries were not yet in place. Signed-off-by: wuxinyue <[email protected]> Assisted-by: Claude:Opus-4.6
elainewu1222
force-pushed
the
avoid-bar-reprogramming-race
branch
from
June 12, 2026 02:23
b3c08f6 to
159090e
Compare
Contributor
Author
|
@rbradford rebase done 🙌 |
sboeuf
approved these changes
Jun 12, 2026
rbradford
approved these changes
Jun 12, 2026
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.
Summary
Fix a race condition during PCI device hotplug where the guest can discover a partially-initialized device, causing BAR reprogramming failures.
Problem
When PCI devices are hotplugged, the Linux guest kernel scans all PCI slots upon each hotplug notification — not just the slot that triggered it. A device that has been added to the PCI bus but whose
device_treeentry and ioeventfds have not yet been registered can be discovered and probed by the guest prematurely.The previous
add_pci_device()made the device visible on the PCI bus (viapci_bus.add_device()) before completing device-specific setup. The following timeline illustrates the race:The root cause is that
pci_bus.add_device()made disk3 discoverable on the bus before itsdevice_treeentry was registered, so when vcpu3 scanned all slots and attempted BAR reprogramming on disk3, the VMM could not find the device in the device tree to complete the BAR move.Solution
Commit 1 refactors
PciBus::register_mapping()intoDeviceManager::register_bar_mapping(), since it operates onmmio_bus/io_buswhich are external toPciBus. The corresponding error variants are moved fromPciRootErrortoDeviceManagerError.Commit 2 splits
add_pci_device()into two phases:allocate_pci_bars()— reserves BAR address space only, without making the device visible to the guest.commit_pci_device()— pushes the device intobus_devices, registers BAR mappings on the VMM buses, and finally adds the device to the PCI bus. At this point, the device is discoverable by guest.All six callers now follow the pattern:
allocate_pci_bars() → device-specific setup → commit_pci_device()
This ensures ioeventfds, device_tree entries, and MMIO mappings are fully in place before the device becomes discoverable by the guest, closing the race window.