fix: correct BAR size probing for non-zero base addresses
The previous BAR size calculation used !(inverted & mask) & mask which\nproduces incorrect results when the BAR has a non-zero base address.\nUse lowest-set-bit extraction (masked & (!masked + 1)) to correctly\ncompute the BAR size from the writable bit pattern read back from hardware.
This commit is contained in:
@@ -574,11 +574,16 @@ impl PciDevice {
|
||||
let is_io = (original & 0x01) != 0;
|
||||
let mask = if is_io { 0xFFFFFFFC } else { 0xFFFFFFF0 };
|
||||
|
||||
let size_val = !(inverted & mask) & mask;
|
||||
if size_val == 0 {
|
||||
let masked = inverted & mask;
|
||||
if masked == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
Ok(size_val as u64)
|
||||
// The lowest set bit in the readback IS the BAR size.
|
||||
// This correctly handles non-zero base addresses because
|
||||
// writable address bits above the size boundary are all 1s
|
||||
// while hardwired size bits below are all 0s.
|
||||
let size = masked & (!masked).wrapping_add(1);
|
||||
Ok(size as u64)
|
||||
}
|
||||
|
||||
fn probe_bar64_size(&mut self, offset: u64) -> Result<u64> {
|
||||
@@ -594,14 +599,16 @@ impl PciDevice {
|
||||
self.write_config_dword(offset, original_lo)?;
|
||||
self.write_config_dword(offset + 4, original_hi)?;
|
||||
|
||||
let lo = !(inverted_lo & 0xFFFFFFF0) & 0xFFFFFFF0;
|
||||
let hi = !inverted_hi;
|
||||
let masked_lo = inverted_lo & 0xFFFFFFF0;
|
||||
let masked_hi = inverted_hi;
|
||||
let masked = ((masked_hi as u64) << 32) | (masked_lo as u64);
|
||||
|
||||
if lo == 0 && hi == 0 {
|
||||
if masked == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let size = ((hi as u64) << 32) | (lo as u64);
|
||||
// The lowest set bit in the readback IS the BAR size.
|
||||
let size = masked & (!masked).wrapping_add(1);
|
||||
Ok(size)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user