From 07bad79fd7d09c4e04ec15419a4b67ef4caf623e Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Wed, 8 Jan 2020 17:59:21 +0100 Subject: [PATCH] pci: Fix detection of expansion ROM BAR reprogramming The expansion ROM BAR reprogramming was being triggered for the wrong reason and was causing the following error to be reported: ERROR:pci/src/bus.rs:207 -- Failed moving device BAR: failed allocating new 32 bits MMIO range Following the PCI specification, here is what is defined: Device independent configuration software can determine how much address space the device requires by writing a value of all 1's to the address portion of the register and then reading the value back. This means we cannot expect 0xffffffff to be written, as the address portion corresponds to the bits 31-11. That's why whenever the size of this special BAR is being asked for, the value being written is 0xfffff800. Signed-off-by: Sebastien Boeuf --- pci/src/configuration.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pci/src/configuration.rs b/pci/src/configuration.rs index ffb048468..b4887e0af 100755 --- a/pci/src/configuration.rs +++ b/pci/src/configuration.rs @@ -399,12 +399,17 @@ impl PciConfiguration { pub fn write_reg(&mut self, reg_idx: usize, value: u32) { let mut mask = self.writable_bits[reg_idx]; - if value == 0xffff_ffff { - if reg_idx >= BAR0_REG && reg_idx < BAR0_REG + NUM_BAR_REGS { - // Handle very specific case where the BAR is being written with - // all 1's to retrieve the BAR size on next BAR reading. + if reg_idx >= BAR0_REG && reg_idx < BAR0_REG + NUM_BAR_REGS { + // Handle very specific case where the BAR is being written with + // all 1's to retrieve the BAR size during next BAR reading. + if value == 0xffff_ffff { mask = self.bar_size[reg_idx - 4]; - } else if reg_idx == ROM_BAR_REG { + } + } else if reg_idx == ROM_BAR_REG { + // Handle very specific case where the BAR is being written with + // all 1's on bits 31-11 to retrieve the BAR size during next BAR + // reading. + if value & ROM_BAR_ADDR_MASK == ROM_BAR_ADDR_MASK { mask = self.rom_bar_size; } } @@ -731,6 +736,11 @@ impl PciConfiguration { } } } else if reg_idx == ROM_BAR_REG && (value & mask) != (self.rom_bar_addr & mask) { + // Ignore the case where the BAR size is being asked for. + if value & ROM_BAR_ADDR_MASK == ROM_BAR_ADDR_MASK { + return None; + } + debug!( "DETECT ROM BAR REPROG: current 0x{:x}, new 0x{:x}", self.registers[reg_idx], value