devices: virtio-pci: refactor BAR lookup

The read_bar() and write_bar() functions had an open-coded equivalent of
BAR lookup to find out if the access was intended for the settings BAR
or one of the device-specific extra BARs. Instead, we can reuse the same
BAR lookup code to find the index of the relevant BAR and compare it
against the settings_bar field.

BUG=b:232838930
TEST=tools/presubmit

Change-Id: I2e5f3ccff47d31718e835ccb745db75dbda2e4ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3664281
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Anton Romanov <romanton@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Daniel Verkamp 2022-05-16 14:26:31 -07:00 committed by Chromeos LUCI
parent 19da3a6c48
commit 18203fa00f
2 changed files with 36 additions and 26 deletions

View file

@ -707,6 +707,10 @@ impl PciBarConfiguration {
self.addr
}
pub fn address_range(&self) -> std::ops::Range<u64> {
self.addr..self.addr + self.size
}
pub fn set_address(mut self, addr: u64) -> Self {
self.addr = addr;
self

View file

@ -22,9 +22,10 @@ use vm_memory::GuestMemory;
use super::*;
use crate::pci::{
BarRange, MsixCap, MsixConfig, PciAddress, PciBarConfiguration, PciBarPrefetchable,
PciBarRegionType, PciCapability, PciCapabilityID, PciClassCode, PciConfiguration, PciDevice,
PciDeviceError, PciDisplaySubclass, PciHeaderType, PciId, PciInterruptPin, PciSubclass,
BarRange, MsixCap, MsixConfig, PciAddress, PciBarConfiguration, PciBarIndex,
PciBarPrefetchable, PciBarRegionType, PciCapability, PciCapabilityID, PciClassCode,
PciConfiguration, PciDevice, PciDeviceError, PciDisplaySubclass, PciHeaderType, PciId,
PciInterruptPin, PciSubclass,
};
use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
use crate::IrqLevelEvent;
@ -665,18 +666,17 @@ impl PciDevice for VirtioPciDevice {
}
fn read_bar(&mut self, addr: u64, data: &mut [u8]) {
// The driver is only allowed to do aligned, properly sized access.
let bar0 = self.config_regs.get_bar_addr(self.settings_bar as usize);
if addr < bar0 || addr >= bar0 + CAPABILITY_BAR_SIZE {
let bar_config = self.config_regs.get_bars().find(|config| {
addr >= config.address() && addr < (config.address() + config.size())
});
if let Some(c) = bar_config {
self.device
.read_bar(c.bar_index(), addr - c.address(), data);
}
} else {
let offset = addr - bar0;
let bar = match self
.config_regs
.get_bars()
.find(|bar| bar.address_range().contains(&addr))
{
Some(bar) => bar,
None => return,
};
if bar.bar_index() == self.settings_bar as PciBarIndex {
let offset = addr - bar.address();
match offset {
COMMON_CONFIG_BAR_OFFSET..=COMMON_CONFIG_LAST => self.common_config.read(
offset - COMMON_CONFIG_BAR_OFFSET,
@ -709,21 +709,24 @@ impl PciDevice for VirtioPciDevice {
}
_ => (),
}
} else {
self.device
.read_bar(bar.bar_index(), addr - bar.address(), data);
}
}
fn write_bar(&mut self, addr: u64, data: &[u8]) {
let bar0 = self.config_regs.get_bar_addr(self.settings_bar as usize);
if addr < bar0 || addr >= bar0 + CAPABILITY_BAR_SIZE {
let bar_config = self.config_regs.get_bars().find(|config| {
addr >= config.address() && addr < (config.address() + config.size())
});
if let Some(c) = bar_config {
self.device
.write_bar(c.bar_index(), addr - c.address(), data);
}
} else {
let offset = addr - bar0;
let bar = match self
.config_regs
.get_bars()
.find(|bar| bar.address_range().contains(&addr))
{
Some(bar) => bar,
None => return,
};
if bar.bar_index() == self.settings_bar as PciBarIndex {
let offset = addr - bar.address();
match offset {
COMMON_CONFIG_BAR_OFFSET..=COMMON_CONFIG_LAST => self.common_config.write(
offset - COMMON_CONFIG_BAR_OFFSET,
@ -758,6 +761,9 @@ impl PciDevice for VirtioPciDevice {
}
_ => (),
}
} else {
self.device
.write_bar(bar.bar_index(), addr - bar.address(), data);
}
if !self.device_activated && self.is_driver_ready() {