devices: PCI: use configuration callback
Not sure if adding the device addresses to the mmio bus
is the desired behavior, but it seems to work.
BUG=chromium:924405
TEST=boot VM
Change-Id: I7f6057b3e7d041a52b251af1203353ba7a0d3c22
Reviewed-on: https://chromium-review.googlesource.com/1480743
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
diff --git a/arch/src/lib.rs b/arch/src/lib.rs
index 74545a5..2560ff5 100644
--- a/arch/src/lib.rs
+++ b/arch/src/lib.rs
@@ -94,6 +94,8 @@
pub enum DeviceRegistrationError {
/// Could not allocate IO space for the device.
AllocateIoAddrs(PciDeviceError),
+ /// Could not allocate device address space for the device.
+ AllocateDeviceAddrs(PciDeviceError),
/// Could not allocate an IRQ number.
AllocateIrq,
/// Could not create the mmio device to wrap a VirtioDevice.
@@ -122,6 +124,9 @@
DeviceRegistrationError::AllocateIoAddrs(e) => {
write!(f, "Allocating IO addresses: {}", e)
}
+ DeviceRegistrationError::AllocateDeviceAddrs(e) => {
+ write!(f, "Allocating device addresses: {:?}", e)
+ }
DeviceRegistrationError::AllocateIrq => write!(f, "Allocating IRQ number"),
DeviceRegistrationError::CreateMmioDevice(e) => {
write!(f, "failed to create mmio device: {}", e)
@@ -187,6 +192,9 @@
let ranges = device
.allocate_io_bars(resources)
.map_err(DeviceRegistrationError::AllocateIoAddrs)?;
+ let device_ranges = device
+ .allocate_device_bars(resources)
+ .map_err(DeviceRegistrationError::AllocateDeviceAddrs)?;
for (event, addr, datamatch) in device.ioeventfds() {
let io_addr = IoeventAddress::Mmio(addr);
vm.register_ioevent(&event, io_addr, datamatch)
@@ -207,6 +215,12 @@
.insert(arced_dev.clone(), range.0, range.1, true)
.map_err(DeviceRegistrationError::MmioInsert)?;
}
+
+ for range in &device_ranges {
+ mmio_bus
+ .insert(arced_dev.clone(), range.0, range.1, true)
+ .map_err(DeviceRegistrationError::MmioInsert)?;
+ }
}
Ok((root, pci_irqs, pid_labels))
}
diff --git a/devices/src/pci/pci_device.rs b/devices/src/pci/pci_device.rs
index b27dc47..3b8b93e 100644
--- a/devices/src/pci/pci_device.rs
+++ b/devices/src/pci/pci_device.rs
@@ -60,6 +60,17 @@
fn allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<(u64, u64)>> {
Ok(Vec::new())
}
+
+ /// Allocates the needed device BAR space. Returns a Vec of (address, length) tuples.
+ /// Unlike MMIO BARs (see allocate_io_bars), device BARs are not expected to incur VM exits
+ /// - these BARs represent normal memory.
+ fn allocate_device_bars(
+ &mut self,
+ _resources: &mut SystemAllocator,
+ ) -> Result<Vec<(u64, u64)>> {
+ Ok(Vec::new())
+ }
+
/// Gets a list of ioeventfds that should be registered with the running VM. The list is
/// returned as a Vec of (eventfd, addr, datamatch) tuples.
fn ioeventfds(&self) -> Vec<(&EventFd, u64, Datamatch)> {
@@ -141,6 +152,9 @@
fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<(u64, u64)>> {
(**self).allocate_io_bars(resources)
}
+ fn allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<(u64, u64)>> {
+ (**self).allocate_device_bars(resources)
+ }
fn ioeventfds(&self) -> Vec<(&EventFd, u64, Datamatch)> {
(**self).ioeventfds()
}
diff --git a/devices/src/virtio/virtio_pci_device.rs b/devices/src/virtio/virtio_pci_device.rs
index bdd10c2..e764569 100644
--- a/devices/src/virtio/virtio_pci_device.rs
+++ b/devices/src/virtio/virtio_pci_device.rs
@@ -329,6 +329,31 @@
Ok(ranges)
}
+ fn allocate_device_bars(
+ &mut self,
+ resources: &mut SystemAllocator,
+ ) -> std::result::Result<Vec<(u64, u64)>, PciDeviceError> {
+ let mut ranges = Vec::new();
+ let configs = self.device.get_device_bars();
+ match configs {
+ Some(configs) => {
+ for mut config in configs {
+ let device_addr = resources
+ .allocate_device_addresses(config.get_size())
+ .ok_or(PciDeviceError::IoAllocationFailed(config.get_size()))?;
+ config.set_address(device_addr);
+ let _device_bar = self
+ .config_regs
+ .add_pci_bar(&config)
+ .ok_or(PciDeviceError::IoRegistrationFailed(device_addr))?;
+ ranges.push((device_addr, config.get_size()));
+ }
+ }
+ None => (),
+ };
+ Ok(ranges)
+ }
+
fn ioeventfds(&self) -> Vec<(&EventFd, u64, Datamatch)> {
let bar0 = self.config_regs.get_bar_addr(self.settings_bar as usize) as u64;
let notify_base = bar0 + NOTIFICATION_BAR_OFFSET;