virtio-devices: 8 MiB-aligned initial BAR placement

Windows 11 PnP rebalance rewrites peer BARs into the same range CH
packed the initial layout at, causing move_bar() failures and boot
deadlock. Pack Mmio64 BARs at 8 MiB stride. Mmio32 isn't wide enough
for the same stride, but its BARs don't participate in guest BAR
rebalancing.

On restore, pin the BAR to the snapshot address (alignment=None) so a
guest-relocated BAR with smaller alignment is accepted.

Signed-off-by: CMGS <ilskdw@gmail.com>
This commit is contained in:
CMGS
2026-05-19 10:54:58 +08:00
committed by Rob Bradford
parent a495841515
commit f8f92bd628

View File

@@ -281,6 +281,8 @@ const MSIX_PBA_BAR_OFFSET: u64 = next_bar_addr(MSIX_TABLE_BAR_OFFSET, MSIX_TABLE
const MSIX_PBA_SIZE: u64 = 0x800;
// The BAR size must be a power of 2.
const CAPABILITY_BAR_SIZE: u64 = (MSIX_PBA_BAR_OFFSET + MSIX_PBA_SIZE).next_power_of_two();
// Align larger than natural alignment to work around Windows driver issues
const VIRTIO_PCI_BAR_ALIGN: u64 = 0x80_0000;
const VIRTIO_COMMON_BAR_INDEX: u8 = 0;
const VIRTIO_SHM_BAR_INDEX: usize = 2;
@@ -1044,12 +1046,13 @@ impl PciDevice for VirtioPciDevice {
// See http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-740004
let (virtio_pci_bar_addr, region_type) = if use_64bit_bar {
let region_type = PciBarRegionType::Memory64BitRegion;
let alignment = if restoring {
None
} else {
Some(VIRTIO_PCI_BAR_ALIGN)
};
let addr = mmio64_allocator
.allocate(
settings_bar_addr,
CAPABILITY_BAR_SIZE,
Some(CAPABILITY_BAR_SIZE),
)
.allocate(settings_bar_addr, CAPABILITY_BAR_SIZE, alignment)
.ok_or(PciDeviceError::IoAllocationFailed(CAPABILITY_BAR_SIZE))?;
(addr, region_type)
} else {