pci: rollback BAR address on failed move_bar

When BAR reprogramming is detected, detect_bar_reprogramming()
eagerly updates the BAR address in config space before the actual
MMIO remapping occurs. If the subsequent move_bar() fails (e.g.
the new address falls outside the allocator range), the config
register retains the new address while the MMIO bus still uses
the old one, leaving the device broken.

Add restore_bar_addr() to undo the config space update when
move_bar() fails, so the device remains functional at its
original address.

For 64-bit BARs, restore both the low and high BAR slots as well
as the corresponding config registers, mirroring the two-slot
update logic in detect_bar_reprogramming().

Implement restore_bar_addr() for all PciDevice implementations
(VirtioPciDevice, VfioPciDevice, VfioUserPciDevice, IvshmemDevice,
PvPanicDevice, and PvmemcontrolPciDevice) by delegating to their
respective PciConfiguration::restore_bar_addr().

Signed-off-by: CMGS <ilskdw@gmail.com>
This commit is contained in:
CMGS
2026-04-13 17:23:08 +08:00
committed by Rob Bradford
parent fd2d33e8ab
commit e38c5c4340
9 changed files with 88 additions and 5 deletions

View File

@@ -382,6 +382,10 @@ impl PciDevice for IvshmemDevice {
Ok(())
}
fn restore_bar_addr(&mut self, params: &BarReprogrammingParams) {
self.configuration.restore_bar_addr(params);
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

View File

@@ -712,6 +712,10 @@ impl PciDevice for PvmemcontrolPciDevice {
self.configuration.read_config_register(reg_idx)
}
fn restore_bar_addr(&mut self, params: &BarReprogrammingParams) {
self.configuration.restore_bar_addr(params);
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}

View File

@@ -231,6 +231,10 @@ impl PciDevice for PvPanicDevice {
Ok(())
}
fn restore_bar_addr(&mut self, params: &BarReprogrammingParams) {
self.configuration.restore_bar_addr(params);
}
fn read_bar(&mut self, _base: u64, _offset: u64, data: &mut [u8]) {
data[0] = self.events;
}