mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-18 18:45:19 +00:00
pci: Fix BAR reprogramming detection logic
The logic wasn't quite right, as it wasn't detecting BAR reprogramming when the upper part of the address was identical. For instance, a BAR moved from 0x7fc0000000 to 0x7fd0000000 wasn't detected properly. The logic has been updated and cleaned up to fix this issue, which was observed when running Windows guests. This fixes the network hotplug support as well. Fixes #1797 Fixes #1798 Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
3d06657f06
commit
7c457378e5
@ -768,18 +768,25 @@ impl PciConfiguration {
|
|||||||
|
|
||||||
let mask = self.writable_bits[reg_idx];
|
let mask = self.writable_bits[reg_idx];
|
||||||
if (BAR0_REG..BAR0_REG + NUM_BAR_REGS).contains(®_idx) {
|
if (BAR0_REG..BAR0_REG + NUM_BAR_REGS).contains(®_idx) {
|
||||||
|
// Ignore the case where the BAR size is being asked for.
|
||||||
|
if value == 0xffff_ffff {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let bar_idx = reg_idx - 4;
|
let bar_idx = reg_idx - 4;
|
||||||
if (value & mask) != (self.bars[bar_idx].addr & mask) {
|
|
||||||
// Handle special case where the address being written is
|
// Handle special case where the address being written is
|
||||||
// different from the address initially provided. This is a
|
// different from the address initially provided. This is a
|
||||||
// BAR reprogramming case which needs to be properly caught.
|
// BAR reprogramming case which needs to be properly caught.
|
||||||
if let Some(bar_type) = self.bars[bar_idx].r#type {
|
if let Some(bar_type) = self.bars[bar_idx].r#type {
|
||||||
match bar_type {
|
// In case of 64 bits memory BAR, we don't do anything until
|
||||||
PciBarRegionType::Memory64BitRegion => {}
|
// the upper BAR is modified, otherwise we would be moving the
|
||||||
_ => {
|
// BAR to a wrong location in memory.
|
||||||
// Ignore the case where the BAR size is being
|
if bar_type == PciBarRegionType::Memory64BitRegion {
|
||||||
// asked for.
|
return None;
|
||||||
if value == 0xffff_ffff {
|
}
|
||||||
|
|
||||||
|
// Ignore the case where the value is unchanged.
|
||||||
|
if (value & mask) == (self.bars[bar_idx].addr & mask) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -804,23 +811,11 @@ impl PciConfiguration {
|
|||||||
len,
|
len,
|
||||||
region_type,
|
region_type,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (reg_idx > BAR0_REG)
|
} else if (reg_idx > BAR0_REG)
|
||||||
&& (self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1])
|
&& ((self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1])
|
||||||
!= (self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1])
|
!= (self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1])
|
||||||
|
|| (value & mask) != (self.bars[bar_idx].addr & mask))
|
||||||
{
|
{
|
||||||
// Ignore the case where the BAR size is being asked for.
|
|
||||||
// Because we are in the 64bits case here, we have to check
|
|
||||||
// if the lower 32bits of the current BAR have already been
|
|
||||||
// asked for the BAR size too.
|
|
||||||
if value == 0xffff_ffff
|
|
||||||
&& self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1]
|
|
||||||
== self.bars[bar_idx - 1].size & self.writable_bits[reg_idx - 1]
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"DETECT BAR REPROG: current 0x{:x}, new 0x{:x}",
|
"DETECT BAR REPROG: current 0x{:x}, new 0x{:x}",
|
||||||
self.registers[reg_idx], value
|
self.registers[reg_idx], value
|
||||||
@ -829,10 +824,8 @@ impl PciConfiguration {
|
|||||||
| u64::from(self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1]);
|
| u64::from(self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1]);
|
||||||
let new_base = u64::from(value & mask) << 32
|
let new_base = u64::from(value & mask) << 32
|
||||||
| u64::from(self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1]);
|
| u64::from(self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1]);
|
||||||
let len = decode_64_bits_bar_size(
|
let len =
|
||||||
self.bars[bar_idx].size,
|
decode_64_bits_bar_size(self.bars[bar_idx].size, self.bars[bar_idx - 1].size)
|
||||||
self.bars[bar_idx - 1].size,
|
|
||||||
)
|
|
||||||
.ok_or(Error::Decode64BarSize)
|
.ok_or(Error::Decode64BarSize)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let region_type = PciBarRegionType::Memory64BitRegion;
|
let region_type = PciBarRegionType::Memory64BitRegion;
|
||||||
@ -847,7 +840,6 @@ impl PciConfiguration {
|
|||||||
region_type,
|
region_type,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if reg_idx == ROM_BAR_REG && (value & mask) != (self.rom_bar_addr & mask) {
|
} 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.
|
// Ignore the case where the BAR size is being asked for.
|
||||||
if value & ROM_BAR_ADDR_MASK == ROM_BAR_ADDR_MASK {
|
if value & ROM_BAR_ADDR_MASK == ROM_BAR_ADDR_MASK {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user