vm-device: generalize BusDevice to use a shared reference

BusDevice trait functions currently holds a mutable reference to self,
and exclusive access is guaranteed by taking a Mutex when dispatched by
the Bus object. However, this prevents individual devices from serving
accesses that do not require an mutable reference or is better served
with different synchronization primitives. We switch Bus to dispatch via
BusDeviceSync, which holds a shared reference, and delegate locking to
the BusDeviceSync trait implementation for Mutex<BusDevice>.

Other changes are made to make use of the dyn BusDeviceSync
trait object.

Signed-off-by: Yuanchu Xie <yuanchu@google.com>
This commit is contained in:
Yuanchu Xie 2024-03-19 18:03:56 -07:00 committed by Liu Wei
parent 026e2c6aa8
commit 954f3dd057
5 changed files with 69 additions and 50 deletions

View File

@ -14,7 +14,7 @@ use std::any::Any;
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
use vm_device::{Bus, BusDevice}; use vm_device::{Bus, BusDevice, BusDeviceSync};
const VENDOR_ID_INTEL: u16 = 0x8086; const VENDOR_ID_INTEL: u16 = 0x8086;
const DEVICE_ID_INTEL_VIRT_PCIE_HOST: u16 = 0x0d57; const DEVICE_ID_INTEL_VIRT_PCIE_HOST: u16 = 0x0d57;
@ -122,7 +122,7 @@ impl PciBus {
pub fn register_mapping( pub fn register_mapping(
&self, &self,
dev: Arc<Mutex<dyn BusDevice>>, dev: Arc<dyn BusDeviceSync>,
#[cfg(target_arch = "x86_64")] io_bus: &Bus, #[cfg(target_arch = "x86_64")] io_bus: &Bus,
mmio_bus: &Bus, mmio_bus: &Bus,
bars: Vec<PciBarConfiguration>, bars: Vec<PciBarConfiguration>,

View File

@ -26,6 +26,31 @@ pub trait BusDevice: Send {
} }
} }
#[allow(unused_variables)]
pub trait BusDeviceSync: Send + Sync {
/// Reads at `offset` from this device
fn read(&self, base: u64, offset: u64, data: &mut [u8]) {}
/// Writes at `offset` into this device
fn write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
None
}
}
impl<B: BusDevice> BusDeviceSync for Mutex<B> {
/// Reads at `offset` from this device
fn read(&self, base: u64, offset: u64, data: &mut [u8]) {
self.lock()
.expect("Failed to acquire device lock")
.read(base, offset, data)
}
/// Writes at `offset` into this device
fn write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
self.lock()
.expect("Failed to acquire device lock")
.write(base, offset, data)
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
/// The insertion failed because the new device overlapped with an old device. /// The insertion failed because the new device overlapped with an old device.
@ -95,7 +120,7 @@ impl PartialOrd for BusRange {
/// only restriction is that no two devices can overlap in this address space. /// only restriction is that no two devices can overlap in this address space.
#[derive(Default)] #[derive(Default)]
pub struct Bus { pub struct Bus {
devices: RwLock<BTreeMap<BusRange, Weak<Mutex<dyn BusDevice>>>>, devices: RwLock<BTreeMap<BusRange, Weak<dyn BusDeviceSync>>>,
} }
impl Bus { impl Bus {
@ -106,7 +131,7 @@ impl Bus {
} }
} }
fn first_before(&self, addr: u64) -> Option<(BusRange, Arc<Mutex<dyn BusDevice>>)> { fn first_before(&self, addr: u64) -> Option<(BusRange, Arc<dyn BusDeviceSync>)> {
let devices = self.devices.read().unwrap(); let devices = self.devices.read().unwrap();
let (range, dev) = devices let (range, dev) = devices
.range(..=BusRange { base: addr, len: 1 }) .range(..=BusRange { base: addr, len: 1 })
@ -115,7 +140,7 @@ impl Bus {
} }
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub fn resolve(&self, addr: u64) -> Option<(u64, u64, Arc<Mutex<dyn BusDevice>>)> { fn resolve(&self, addr: u64) -> Option<(u64, u64, Arc<dyn BusDeviceSync>)> {
if let Some((range, dev)) = self.first_before(addr) { if let Some((range, dev)) = self.first_before(addr) {
let offset = addr - range.base; let offset = addr - range.base;
if offset < range.len { if offset < range.len {
@ -125,8 +150,7 @@ impl Bus {
None None
} }
/// Puts the given device at the given address space. pub fn insert(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> {
pub fn insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()> {
if len == 0 { if len == 0 {
return Err(Error::ZeroSizedRange); return Err(Error::ZeroSizedRange);
} }
@ -171,7 +195,7 @@ impl Bus {
} }
/// Removes all entries referencing the given device. /// Removes all entries referencing the given device.
pub fn remove_by_device(&self, device: &Arc<Mutex<dyn BusDevice>>) -> Result<()> { pub fn remove_by_device(&self, device: &Arc<dyn BusDeviceSync>) -> Result<()> {
let mut device_list = self.devices.write().unwrap(); let mut device_list = self.devices.write().unwrap();
let mut remove_key_list = Vec::new(); let mut remove_key_list = Vec::new();
@ -216,9 +240,7 @@ impl Bus {
pub fn read(&self, addr: u64, data: &mut [u8]) -> Result<()> { pub fn read(&self, addr: u64, data: &mut [u8]) -> Result<()> {
if let Some((base, offset, dev)) = self.resolve(addr) { if let Some((base, offset, dev)) = self.resolve(addr) {
// OK to unwrap as lock() failing is a serious error condition and should panic. // OK to unwrap as lock() failing is a serious error condition and should panic.
dev.lock() dev.read(base, offset, data);
.expect("Failed to acquire device lock")
.read(base, offset, data);
Ok(()) Ok(())
} else { } else {
Err(Error::MissingAddressRange) Err(Error::MissingAddressRange)
@ -231,10 +253,7 @@ impl Bus {
pub fn write(&self, addr: u64, data: &[u8]) -> Result<Option<Arc<Barrier>>> { pub fn write(&self, addr: u64, data: &[u8]) -> Result<Option<Arc<Barrier>>> {
if let Some((base, offset, dev)) = self.resolve(addr) { if let Some((base, offset, dev)) = self.resolve(addr) {
// OK to unwrap as lock() failing is a serious error condition and should panic. // OK to unwrap as lock() failing is a serious error condition and should panic.
Ok(dev Ok(dev.write(base, offset, data))
.lock()
.expect("Failed to acquire device lock")
.write(base, offset, data))
} else { } else {
Err(Error::MissingAddressRange) Err(Error::MissingAddressRange)
} }
@ -246,17 +265,17 @@ mod tests {
use super::*; use super::*;
struct DummyDevice; struct DummyDevice;
impl BusDevice for DummyDevice {} impl BusDeviceSync for DummyDevice {}
struct ConstantDevice; struct ConstantDevice;
impl BusDevice for ConstantDevice { impl BusDeviceSync for ConstantDevice {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { fn read(&self, _base: u64, offset: u64, data: &mut [u8]) {
for (i, v) in data.iter_mut().enumerate() { for (i, v) in data.iter_mut().enumerate() {
*v = (offset as u8) + (i as u8); *v = (offset as u8) + (i as u8);
} }
} }
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { fn write(&self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
for (i, v) in data.iter().enumerate() { for (i, v) in data.iter().enumerate() {
assert_eq!(*v, (offset as u8) + (i as u8)) assert_eq!(*v, (offset as u8) + (i as u8))
} }
@ -268,7 +287,7 @@ mod tests {
#[test] #[test]
fn bus_insert() { fn bus_insert() {
let bus = Bus::new(); let bus = Bus::new();
let dummy = Arc::new(Mutex::new(DummyDevice)); let dummy = Arc::new(DummyDevice);
assert!(bus.insert(dummy.clone(), 0x10, 0).is_err()); assert!(bus.insert(dummy.clone(), 0x10, 0).is_err());
assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok()); assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
@ -290,7 +309,7 @@ mod tests {
#[allow(clippy::redundant_clone)] #[allow(clippy::redundant_clone)]
fn bus_read_write() { fn bus_read_write() {
let bus = Bus::new(); let bus = Bus::new();
let dummy = Arc::new(Mutex::new(DummyDevice)); let dummy = Arc::new(DummyDevice);
assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok()); assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
assert!(bus.read(0x10, &mut [0, 0, 0, 0]).is_ok()); assert!(bus.read(0x10, &mut [0, 0, 0, 0]).is_ok());
assert!(bus.write(0x10, &[0, 0, 0, 0]).is_ok()); assert!(bus.write(0x10, &[0, 0, 0, 0]).is_ok());
@ -308,7 +327,7 @@ mod tests {
#[allow(clippy::redundant_clone)] #[allow(clippy::redundant_clone)]
fn bus_read_write_values() { fn bus_read_write_values() {
let bus = Bus::new(); let bus = Bus::new();
let dummy = Arc::new(Mutex::new(ConstantDevice)); let dummy = Arc::new(ConstantDevice);
assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok()); assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
let mut values = [0, 1, 2, 3]; let mut values = [0, 1, 2, 3];
@ -334,7 +353,7 @@ mod tests {
let bus = Bus::new(); let bus = Bus::new();
let mut data = [1, 2, 3, 4]; let mut data = [1, 2, 3, 4];
let device = Arc::new(Mutex::new(DummyDevice)); let device = Arc::new(DummyDevice);
assert!(bus.insert(device.clone(), 0x10, 0x10).is_ok()); assert!(bus.insert(device.clone(), 0x10, 0x10).is_ok());
assert!(bus.write(0x10, &data).is_ok()); assert!(bus.write(0x10, &data).is_ok());
assert!(bus.read(0x10, &mut data).is_ok()); assert!(bus.read(0x10, &mut data).is_ok());

View File

@ -9,7 +9,7 @@ mod bus;
pub mod dma_mapping; pub mod dma_mapping;
pub mod interrupt; pub mod interrupt;
pub use self::bus::{Bus, BusDevice, Error as BusError}; pub use self::bus::{Bus, BusDevice, BusDeviceSync, Error as BusError};
/// Type of Message Signalled Interrupt /// Type of Message Signalled Interrupt
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -89,7 +89,7 @@ use vm_device::dma_mapping::ExternalDmaMapping;
use vm_device::interrupt::{ use vm_device::interrupt::{
InterruptIndex, InterruptManager, LegacyIrqGroupConfig, MsiIrqGroupConfig, InterruptIndex, InterruptManager, LegacyIrqGroupConfig, MsiIrqGroupConfig,
}; };
use vm_device::{Bus, BusDevice, Resource}; use vm_device::{Bus, BusDevice, BusDeviceSync, Resource};
use vm_memory::guest_memory::FileOffset; use vm_memory::guest_memory::FileOffset;
use vm_memory::GuestMemoryRegion; use vm_memory::GuestMemoryRegion;
use vm_memory::{Address, GuestAddress, GuestUsize, MmapRegion}; use vm_memory::{Address, GuestAddress, GuestUsize, MmapRegion};
@ -818,7 +818,7 @@ pub struct DeviceManager {
// Let the DeviceManager keep strong references to the BusDevice devices. // Let the DeviceManager keep strong references to the BusDevice devices.
// This allows the IO and MMIO buses to be provided with Weak references, // This allows the IO and MMIO buses to be provided with Weak references,
// which prevents cyclic dependencies. // which prevents cyclic dependencies.
bus_devices: Vec<Arc<Mutex<dyn BusDevice>>>, bus_devices: Vec<Arc<dyn BusDeviceSync>>,
// Counter to keep track of the consumed device IDs. // Counter to keep track of the consumed device IDs.
device_id_cnt: Wrapping<usize>, device_id_cnt: Wrapping<usize>,
@ -1183,7 +1183,7 @@ impl DeviceManager {
address_manager address_manager
.mmio_bus .mmio_bus
.insert( .insert(
Arc::clone(&device_manager) as Arc<Mutex<dyn BusDevice>>, Arc::clone(&device_manager) as Arc<dyn BusDeviceSync>,
acpi_address.0, acpi_address.0,
DEVICE_MANAGER_ACPI_SIZE as u64, DEVICE_MANAGER_ACPI_SIZE as u64,
) )
@ -1226,7 +1226,7 @@ impl DeviceManager {
self.address_manager self.address_manager
.mmio_bus .mmio_bus
.insert( .insert(
Arc::clone(&self.memory_manager) as Arc<Mutex<dyn BusDevice>>, Arc::clone(&self.memory_manager) as Arc<dyn BusDeviceSync>,
acpi_address.0, acpi_address.0,
MEMORY_MANAGER_ACPI_SIZE as u64, MEMORY_MANAGER_ACPI_SIZE as u64,
) )
@ -1268,7 +1268,7 @@ impl DeviceManager {
if let Some(tpm) = self.config.clone().lock().unwrap().tpm.as_ref() { if let Some(tpm) = self.config.clone().lock().unwrap().tpm.as_ref() {
let tpm_dev = self.add_tpm_device(tpm.socket.clone())?; let tpm_dev = self.add_tpm_device(tpm.socket.clone())?;
self.bus_devices self.bus_devices
.push(Arc::clone(&tpm_dev) as Arc<Mutex<dyn BusDevice>>) .push(Arc::clone(&tpm_dev) as Arc<dyn BusDeviceSync>)
} }
self.legacy_interrupt_manager = Some(legacy_interrupt_manager); self.legacy_interrupt_manager = Some(legacy_interrupt_manager);
@ -1400,11 +1400,11 @@ impl DeviceManager {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
if let Some(pci_config_io) = segment.pci_config_io.as_ref() { if let Some(pci_config_io) = segment.pci_config_io.as_ref() {
self.bus_devices self.bus_devices
.push(Arc::clone(pci_config_io) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(pci_config_io) as Arc<dyn BusDeviceSync>);
} }
self.bus_devices self.bus_devices
.push(Arc::clone(&segment.pci_config_mmio) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&segment.pci_config_mmio) as Arc<dyn BusDeviceSync>);
} }
Ok(()) Ok(())
@ -1489,7 +1489,7 @@ impl DeviceManager {
.map_err(DeviceManagerError::BusError)?; .map_err(DeviceManagerError::BusError)?;
self.bus_devices self.bus_devices
.push(Arc::clone(&interrupt_controller) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&interrupt_controller) as Arc<dyn BusDeviceSync>);
// Fill the device tree with a new node. In case of restore, we // Fill the device tree with a new node. In case of restore, we
// know there is nothing to do, so we can simply override the // know there is nothing to do, so we can simply override the
@ -1521,7 +1521,7 @@ impl DeviceManager {
))); )));
self.bus_devices self.bus_devices
.push(Arc::clone(&shutdown_device) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&shutdown_device) as Arc<dyn BusDeviceSync>);
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
{ {
@ -1584,12 +1584,12 @@ impl DeviceManager {
) )
.map_err(DeviceManagerError::BusError)?; .map_err(DeviceManagerError::BusError)?;
self.bus_devices self.bus_devices
.push(Arc::clone(&ged_device) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&ged_device) as Arc<dyn BusDeviceSync>);
let pm_timer_device = Arc::new(Mutex::new(devices::AcpiPmTimerDevice::new())); let pm_timer_device = Arc::new(Mutex::new(devices::AcpiPmTimerDevice::new()));
self.bus_devices self.bus_devices
.push(Arc::clone(&pm_timer_device) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&pm_timer_device) as Arc<dyn BusDeviceSync>);
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
{ {
@ -1629,7 +1629,7 @@ impl DeviceManager {
))); )));
self.bus_devices self.bus_devices
.push(Arc::clone(&i8042) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&i8042) as Arc<dyn BusDeviceSync>);
self.address_manager self.address_manager
.io_bus .io_bus
@ -1657,7 +1657,7 @@ impl DeviceManager {
))); )));
self.bus_devices self.bus_devices
.push(Arc::clone(&cmos) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&cmos) as Arc<dyn BusDeviceSync>);
self.address_manager self.address_manager
.io_bus .io_bus
@ -1667,7 +1667,7 @@ impl DeviceManager {
let fwdebug = Arc::new(Mutex::new(devices::legacy::FwDebugDevice::new())); let fwdebug = Arc::new(Mutex::new(devices::legacy::FwDebugDevice::new()));
self.bus_devices self.bus_devices
.push(Arc::clone(&fwdebug) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&fwdebug) as Arc<dyn BusDeviceSync>);
self.address_manager self.address_manager
.io_bus .io_bus
@ -1678,7 +1678,7 @@ impl DeviceManager {
// 0x80 debug port // 0x80 debug port
let debug_port = Arc::new(Mutex::new(devices::legacy::DebugPort::new(self.timestamp))); let debug_port = Arc::new(Mutex::new(devices::legacy::DebugPort::new(self.timestamp)));
self.bus_devices self.bus_devices
.push(Arc::clone(&debug_port) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&debug_port) as Arc<dyn BusDeviceSync>);
self.address_manager self.address_manager
.io_bus .io_bus
.insert(debug_port, 0x80, 0x1) .insert(debug_port, 0x80, 0x1)
@ -1710,7 +1710,7 @@ impl DeviceManager {
let rtc_device = Arc::new(Mutex::new(devices::legacy::Rtc::new(interrupt_group))); let rtc_device = Arc::new(Mutex::new(devices::legacy::Rtc::new(interrupt_group)));
self.bus_devices self.bus_devices
.push(Arc::clone(&rtc_device) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&rtc_device) as Arc<dyn BusDeviceSync>);
let addr = arch::layout::LEGACY_RTC_MAPPED_IO_START; let addr = arch::layout::LEGACY_RTC_MAPPED_IO_START;
@ -1752,7 +1752,7 @@ impl DeviceManager {
))); )));
self.bus_devices self.bus_devices
.push(Arc::clone(&gpio_device) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&gpio_device) as Arc<dyn BusDeviceSync>);
let addr = arch::layout::LEGACY_GPIO_MAPPED_IO_START; let addr = arch::layout::LEGACY_GPIO_MAPPED_IO_START;
@ -1802,7 +1802,7 @@ impl DeviceManager {
.unwrap_or(debug_console::DEFAULT_PORT); .unwrap_or(debug_console::DEFAULT_PORT);
self.bus_devices self.bus_devices
.push(Arc::clone(&debug_console) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&debug_console) as Arc<dyn BusDeviceSync>);
self.address_manager self.address_manager
.allocator .allocator
@ -1853,7 +1853,7 @@ impl DeviceManager {
))); )));
self.bus_devices self.bus_devices
.push(Arc::clone(&serial) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&serial) as Arc<dyn BusDeviceSync>);
self.address_manager self.address_manager
.allocator .allocator
@ -1910,7 +1910,7 @@ impl DeviceManager {
))); )));
self.bus_devices self.bus_devices
.push(Arc::clone(&serial) as Arc<Mutex<dyn BusDevice>>); .push(Arc::clone(&serial) as Arc<dyn BusDeviceSync>);
let addr = arch::layout::LEGACY_SERIAL_MAPPED_IO_START; let addr = arch::layout::LEGACY_SERIAL_MAPPED_IO_START;
@ -3412,7 +3412,7 @@ impl DeviceManager {
fn add_pci_device( fn add_pci_device(
&mut self, &mut self,
bus_device: Arc<Mutex<dyn BusDevice>>, bus_device: Arc<dyn BusDeviceSync>,
pci_device: Arc<Mutex<dyn PciDevice>>, pci_device: Arc<Mutex<dyn PciDevice>>,
segment_id: u16, segment_id: u16,
bdf: PciBdf, bdf: PciBdf,
@ -4076,7 +4076,7 @@ impl DeviceManager {
( (
Arc::clone(&vfio_pci_device) as Arc<Mutex<dyn PciDevice>>, Arc::clone(&vfio_pci_device) as Arc<Mutex<dyn PciDevice>>,
Arc::clone(&vfio_pci_device) as Arc<Mutex<dyn BusDevice>>, Arc::clone(&vfio_pci_device) as Arc<dyn BusDeviceSync>,
None as Option<Arc<Mutex<dyn virtio_devices::VirtioDevice>>>, None as Option<Arc<Mutex<dyn virtio_devices::VirtioDevice>>>,
false, false,
) )
@ -4108,7 +4108,7 @@ impl DeviceManager {
( (
Arc::clone(&virtio_pci_device) as Arc<Mutex<dyn PciDevice>>, Arc::clone(&virtio_pci_device) as Arc<Mutex<dyn PciDevice>>,
Arc::clone(&virtio_pci_device) as Arc<Mutex<dyn BusDevice>>, Arc::clone(&virtio_pci_device) as Arc<dyn BusDeviceSync>,
Some(dev.virtio_device()), Some(dev.virtio_device()),
dev.dma_handler().is_some() && !iommu_attached, dev.dma_handler().is_some() && !iommu_attached,
) )
@ -4124,7 +4124,7 @@ impl DeviceManager {
( (
Arc::clone(&vfio_user_pci_device) as Arc<Mutex<dyn PciDevice>>, Arc::clone(&vfio_user_pci_device) as Arc<Mutex<dyn PciDevice>>,
Arc::clone(&vfio_user_pci_device) as Arc<Mutex<dyn BusDevice>>, Arc::clone(&vfio_user_pci_device) as Arc<dyn BusDeviceSync>,
None as Option<Arc<Mutex<dyn virtio_devices::VirtioDevice>>>, None as Option<Arc<Mutex<dyn virtio_devices::VirtioDevice>>>,
true, true,
) )

View File

@ -18,7 +18,7 @@ use pci::{PciConfigIo, PCI_CONFIG_IO_PORT, PCI_CONFIG_IO_PORT_SIZE};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use uuid::Uuid; use uuid::Uuid;
use vm_allocator::AddressAllocator; use vm_allocator::AddressAllocator;
use vm_device::BusDevice; use vm_device::BusDeviceSync;
pub(crate) struct PciSegment { pub(crate) struct PciSegment {
pub(crate) id: u16, pub(crate) id: u16,
@ -70,7 +70,7 @@ impl PciSegment {
address_manager address_manager
.mmio_bus .mmio_bus
.insert( .insert(
Arc::clone(&pci_config_mmio) as Arc<Mutex<dyn BusDevice>>, Arc::clone(&pci_config_mmio) as Arc<dyn BusDeviceSync>,
mmio_config_address, mmio_config_address,
layout::PCI_MMIO_CONFIG_SIZE_PER_SEGMENT, layout::PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
) )