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.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-05-15 07:23:11 +01:00
parent facf0c92e0
commit fba204e2f5
@@ -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)
}