vmm: roll back mem64/IO allocator on failed move_bar

After free(old_base), if allocate(new_base) fails the allocator
treats old_base as free even though the MMIO/PIO bus still maps the
device there. Subsequent allocations pick old_base, mmio_bus.insert
hits the live mapping and returns Overlap.

Restore old_base on the failure path in both the Memory*BitRegion
and IoRegion branches before bubbling the error up.

PR #7950 added restore_bar_addr() so the BAR config register stays
consistent on failed move_bar(); this completes the same picture
for the allocator side.

Signed-off-by: CMGS <ilskdw@gmail.com>
This commit is contained in:
CMGS
2026-05-14 10:15:51 +08:00
committed by Rob Bradford
parent 4efb8b7951
commit e65cca3bf5

View File

@@ -729,9 +729,24 @@ impl DeviceRelocation for AddressManager {
let mut sys_allocator = self.allocator.lock().unwrap();
// Update system allocator
sys_allocator.free_io_addresses(GuestAddress(old_base), len as GuestUsize);
sys_allocator
if sys_allocator
.allocate_io_addresses(Some(GuestAddress(new_base)), len as GuestUsize, None)
.ok_or_else(|| io::Error::other("failed allocating new IO range"))?;
.is_none()
{
if sys_allocator
.allocate_io_addresses(
Some(GuestAddress(old_base)),
len as GuestUsize,
None,
)
.is_none()
{
error!(
"Failed to restore old IO range 0x{old_base:x} after rejected move_bar"
);
}
return Err(io::Error::other("failed allocating new IO range"));
}
// Update PIO bus
self.io_bus
@@ -753,10 +768,24 @@ impl DeviceRelocation for AddressManager {
&& old_base <= pci_mmio_allocator.end().0
{
pci_mmio_allocator.free(GuestAddress(old_base), len as GuestUsize);
pci_mmio_allocator
if pci_mmio_allocator
.allocate(Some(GuestAddress(new_base)), len as GuestUsize, Some(len))
.ok_or_else(|| io::Error::other("failed allocating new MMIO range"))?;
.is_none()
{
if pci_mmio_allocator
.allocate(
Some(GuestAddress(old_base)),
len as GuestUsize,
Some(len),
)
.is_none()
{
error!(
"Failed to restore old MMIO range 0x{old_base:x} after rejected move_bar"
);
}
return Err(io::Error::other("failed allocating new MMIO range"));
}
break;
}