vmm: assign each pci segment 32-bit mmio allocator

Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
This commit is contained in:
Thomas Barrett 2023-11-14 19:31:57 +00:00 committed by Bo Chen
parent ef16ee37d9
commit 45b01d592a
10 changed files with 192 additions and 165 deletions

View File

@ -181,8 +181,9 @@ impl PciDevice for PvPanicDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, _allocator: &Arc<Mutex<SystemAllocator>>,
_mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new(); let mut bars = Vec::new();
@ -190,10 +191,8 @@ impl PciDevice for PvPanicDevice {
let bar_id = 0; let bar_id = 0;
let region_size = PVPANIC_DEVICE_MMIO_SIZE; let region_size = PVPANIC_DEVICE_MMIO_SIZE;
let restoring = resources.is_some(); let restoring = resources.is_some();
let bar_addr = allocator let bar_addr = mmio32_allocator
.lock() .allocate(None, region_size, Some(PVPANIC_DEVICE_MMIO_ALIGNMENT))
.unwrap()
.allocate_mmio_hole_addresses(None, region_size, Some(PVPANIC_DEVICE_MMIO_ALIGNMENT))
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?; .ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
let bar = PciBarConfiguration::default() let bar = PciBarConfiguration::default()
@ -218,11 +217,12 @@ impl PciDevice for PvPanicDevice {
fn free_bars( fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, _allocator: &mut SystemAllocator,
_mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
) -> std::result::Result<(), PciDeviceError> { ) -> std::result::Result<(), PciDeviceError> {
for bar in self.bar_regions.drain(..) { for bar in self.bar_regions.drain(..) {
allocator.free_mmio_hole_addresses(GuestAddress(bar.addr()), bar.size()); mmio32_allocator.free(GuestAddress(bar.addr()), bar.size());
} }
Ok(()) Ok(())

View File

@ -58,7 +58,8 @@ pub trait PciDevice: BusDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
_allocator: &Arc<Mutex<SystemAllocator>>, _allocator: &Arc<Mutex<SystemAllocator>>,
_mmio_allocator: &mut AddressAllocator, _mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
_resources: Option<Vec<Resource>>, _resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>> { ) -> Result<Vec<PciBarConfiguration>> {
Ok(Vec::new()) Ok(Vec::new())
@ -68,7 +69,8 @@ pub trait PciDevice: BusDevice {
fn free_bars( fn free_bars(
&mut self, &mut self,
_allocator: &mut SystemAllocator, _allocator: &mut SystemAllocator,
_mmio_allocator: &mut AddressAllocator, _mmio32_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }

View File

@ -529,10 +529,13 @@ impl VfioCommon {
} }
} }
// The `allocator` argument is unused on `aarch64`
#[allow(unused_variables)]
pub(crate) fn allocate_bars( pub(crate) fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new(); let mut bars = Vec::new();
@ -681,21 +684,15 @@ impl VfioCommon {
} }
PciBarRegionType::Memory32BitRegion => { PciBarRegionType::Memory32BitRegion => {
// BAR allocation must be naturally aligned // BAR allocation must be naturally aligned
allocator mmio32_allocator
.lock() .allocate(restored_bar_addr, region_size, Some(region_size))
.unwrap()
.allocate_mmio_hole_addresses(
restored_bar_addr,
region_size,
Some(region_size),
)
.ok_or(PciDeviceError::IoAllocationFailed(region_size))? .ok_or(PciDeviceError::IoAllocationFailed(region_size))?
} }
PciBarRegionType::Memory64BitRegion => { PciBarRegionType::Memory64BitRegion => {
// We need do some fixup to keep MMIO RW region and msix cap region page size // We need do some fixup to keep MMIO RW region and msix cap region page size
// aligned. // aligned.
region_size = self.fixup_msix_region(bar_id, region_size); region_size = self.fixup_msix_region(bar_id, region_size);
mmio_allocator mmio64_allocator
.allocate( .allocate(
restored_bar_addr, restored_bar_addr,
region_size, region_size,
@ -742,10 +739,13 @@ impl VfioCommon {
Ok(bars) Ok(bars)
} }
// The `allocator` argument is unused on `aarch64`
#[allow(unused_variables)]
pub(crate) fn free_bars( pub(crate) fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> { ) -> Result<(), PciDeviceError> {
for region in self.mmio_regions.iter() { for region in self.mmio_regions.iter() {
match region.type_ { match region.type_ {
@ -756,10 +756,10 @@ impl VfioCommon {
error!("I/O region is not supported"); error!("I/O region is not supported");
} }
PciBarRegionType::Memory32BitRegion => { PciBarRegionType::Memory32BitRegion => {
allocator.free_mmio_hole_addresses(region.start, region.length); mmio32_allocator.free(region.start, region.length);
} }
PciBarRegionType::Memory64BitRegion => { PciBarRegionType::Memory64BitRegion => {
mmio_allocator.free(region.start, region.length); mmio64_allocator.free(region.start, region.length);
} }
} }
} }
@ -1694,19 +1694,22 @@ impl PciDevice for VfioPciDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
self.common self.common
.allocate_bars(allocator, mmio_allocator, resources) .allocate_bars(allocator, mmio32_allocator, mmio64_allocator, resources)
} }
fn free_bars( fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> { ) -> Result<(), PciDeviceError> {
self.common.free_bars(allocator, mmio_allocator) self.common
.free_bars(allocator, mmio32_allocator, mmio64_allocator)
} }
fn write_config_register( fn write_config_register(

View File

@ -397,19 +397,22 @@ impl PciDevice for VfioUserPciDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
self.common self.common
.allocate_bars(allocator, mmio_allocator, resources) .allocate_bars(allocator, mmio32_allocator, mmio64_allocator, resources)
} }
fn free_bars( fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> { ) -> Result<(), PciDeviceError> {
self.common.free_bars(allocator, mmio_allocator) self.common
.free_bars(allocator, mmio32_allocator, mmio64_allocator)
} }
fn as_any(&mut self) -> &mut dyn Any { fn as_any(&mut self) -> &mut dyn Any {

View File

@ -955,8 +955,9 @@ impl PciDevice for VirtioPciDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, _allocator: &Arc<Mutex<SystemAllocator>>,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new(); let mut bars = Vec::new();
@ -995,7 +996,7 @@ impl PciDevice for VirtioPciDevice {
// See http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-740004 // See http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-740004
let (virtio_pci_bar_addr, region_type) = if use_64bit_bar { let (virtio_pci_bar_addr, region_type) = if use_64bit_bar {
let region_type = PciBarRegionType::Memory64BitRegion; let region_type = PciBarRegionType::Memory64BitRegion;
let addr = mmio_allocator let addr = mmio64_allocator
.allocate( .allocate(
settings_bar_addr, settings_bar_addr,
CAPABILITY_BAR_SIZE, CAPABILITY_BAR_SIZE,
@ -1005,10 +1006,8 @@ impl PciDevice for VirtioPciDevice {
(addr, region_type) (addr, region_type)
} else { } else {
let region_type = PciBarRegionType::Memory32BitRegion; let region_type = PciBarRegionType::Memory32BitRegion;
let addr = allocator let addr = mmio32_allocator
.lock() .allocate(
.unwrap()
.allocate_mmio_hole_addresses(
settings_bar_addr, settings_bar_addr,
CAPABILITY_BAR_SIZE, CAPABILITY_BAR_SIZE,
Some(CAPABILITY_BAR_SIZE), Some(CAPABILITY_BAR_SIZE),
@ -1078,16 +1077,17 @@ impl PciDevice for VirtioPciDevice {
fn free_bars( fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, _allocator: &mut SystemAllocator,
mmio_allocator: &mut AddressAllocator, mmio32_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> std::result::Result<(), PciDeviceError> { ) -> std::result::Result<(), PciDeviceError> {
for bar in self.bar_regions.drain(..) { for bar in self.bar_regions.drain(..) {
match bar.region_type() { match bar.region_type() {
PciBarRegionType::Memory32BitRegion => { PciBarRegionType::Memory32BitRegion => {
allocator.free_mmio_hole_addresses(GuestAddress(bar.addr()), bar.size()); mmio32_allocator.free(GuestAddress(bar.addr()), bar.size());
} }
PciBarRegionType::Memory64BitRegion => { PciBarRegionType::Memory64BitRegion => {
mmio_allocator.free(GuestAddress(bar.addr()), bar.size()); mmio64_allocator.free(GuestAddress(bar.addr()), bar.size());
} }
_ => error!("Unexpected PCI bar type"), _ => error!("Unexpected PCI bar type"),
} }

View File

@ -30,7 +30,6 @@ use crate::page_size::get_page_size;
/// #[cfg(target_arch = "x86_64")] GuestAddress(0x1000), /// #[cfg(target_arch = "x86_64")] GuestAddress(0x1000),
/// #[cfg(target_arch = "x86_64")] 0x10000, /// #[cfg(target_arch = "x86_64")] 0x10000,
/// GuestAddress(0x10000000), 0x10000000, /// GuestAddress(0x10000000), 0x10000000,
/// GuestAddress(0x20000000), 0x100000,
/// #[cfg(target_arch = "x86_64")] vec![GsiApic::new(5, 19)]).unwrap(); /// #[cfg(target_arch = "x86_64")] vec![GsiApic::new(5, 19)]).unwrap();
/// #[cfg(target_arch = "x86_64")] /// #[cfg(target_arch = "x86_64")]
/// assert_eq!(allocator.allocate_irq(), Some(5)); /// assert_eq!(allocator.allocate_irq(), Some(5));
@ -47,7 +46,6 @@ pub struct SystemAllocator {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
io_address_space: AddressAllocator, io_address_space: AddressAllocator,
platform_mmio_address_space: AddressAllocator, platform_mmio_address_space: AddressAllocator,
mmio_hole_address_space: AddressAllocator,
gsi_allocator: GsiAllocator, gsi_allocator: GsiAllocator,
} }
@ -59,8 +57,6 @@ impl SystemAllocator {
/// * `io_size` - (X86) The size of IO memory. /// * `io_size` - (X86) The size of IO memory.
/// * `platform_mmio_base` - The starting address of platform MMIO memory. /// * `platform_mmio_base` - The starting address of platform MMIO memory.
/// * `platform_mmio_size` - The size of platform MMIO memory. /// * `platform_mmio_size` - The size of platform MMIO memory.
/// * `mmio_hole_base` - The starting address of MMIO memory in 32-bit address space.
/// * `mmio_hole_size` - The size of MMIO memory in 32-bit address space.
/// * `apics` - (X86) Vector of APIC's. /// * `apics` - (X86) Vector of APIC's.
/// ///
pub fn new( pub fn new(
@ -68,8 +64,6 @@ impl SystemAllocator {
#[cfg(target_arch = "x86_64")] io_size: GuestUsize, #[cfg(target_arch = "x86_64")] io_size: GuestUsize,
platform_mmio_base: GuestAddress, platform_mmio_base: GuestAddress,
platform_mmio_size: GuestUsize, platform_mmio_size: GuestUsize,
mmio_hole_base: GuestAddress,
mmio_hole_size: GuestUsize,
#[cfg(target_arch = "x86_64")] apics: Vec<GsiApic>, #[cfg(target_arch = "x86_64")] apics: Vec<GsiApic>,
) -> Option<Self> { ) -> Option<Self> {
Some(SystemAllocator { Some(SystemAllocator {
@ -79,7 +73,6 @@ impl SystemAllocator {
platform_mmio_base, platform_mmio_base,
platform_mmio_size, platform_mmio_size,
)?, )?,
mmio_hole_address_space: AddressAllocator::new(mmio_hole_base, mmio_hole_size)?,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
gsi_allocator: GsiAllocator::new(apics), gsi_allocator: GsiAllocator::new(apics),
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
@ -123,20 +116,6 @@ impl SystemAllocator {
) )
} }
/// Reserves a section of `size` bytes of MMIO address space.
pub fn allocate_mmio_hole_addresses(
&mut self,
address: Option<GuestAddress>,
size: GuestUsize,
align_size: Option<GuestUsize>,
) -> Option<GuestAddress> {
self.mmio_hole_address_space.allocate(
address,
size,
Some(align_size.unwrap_or_else(get_page_size)),
)
}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// Free an IO address range. /// Free an IO address range.
/// We can only free a range if it matches exactly an already allocated range. /// We can only free a range if it matches exactly an already allocated range.
@ -149,10 +128,4 @@ impl SystemAllocator {
pub fn free_platform_mmio_addresses(&mut self, address: GuestAddress, size: GuestUsize) { pub fn free_platform_mmio_addresses(&mut self, address: GuestAddress, size: GuestUsize) {
self.platform_mmio_address_space.free(address, size) self.platform_mmio_address_space.free(address, size)
} }
/// Free an MMIO address range from the 32 bits hole.
/// We can only free a range if it matches exactly an already allocated range.
pub fn free_mmio_hole_addresses(&mut self, address: GuestAddress, size: GuestUsize) {
self.mmio_hole_address_space.free(address, size)
}
} }

View File

@ -561,7 +561,8 @@ pub(crate) struct AddressManager {
pub(crate) mmio_bus: Arc<Bus>, pub(crate) mmio_bus: Arc<Bus>,
pub(crate) vm: Arc<dyn hypervisor::Vm>, pub(crate) vm: Arc<dyn hypervisor::Vm>,
device_tree: Arc<Mutex<DeviceTree>>, device_tree: Arc<Mutex<DeviceTree>>,
pci_mmio_allocators: Vec<Arc<Mutex<AddressAllocator>>>, pci_mmio32_allocators: Vec<Arc<Mutex<AddressAllocator>>>,
pci_mmio64_allocators: Vec<Arc<Mutex<AddressAllocator>>>,
} }
impl DeviceRelocation for AddressManager { impl DeviceRelocation for AddressManager {
@ -604,56 +605,35 @@ impl DeviceRelocation for AddressManager {
error!("I/O region is not supported"); error!("I/O region is not supported");
} }
PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => { PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
// Update system allocator let allocators = if region_type == PciBarRegionType::Memory32BitRegion {
if region_type == PciBarRegionType::Memory32BitRegion { &self.pci_mmio32_allocators
self.allocator
.lock()
.unwrap()
.free_mmio_hole_addresses(GuestAddress(old_base), len as GuestUsize);
self.allocator
.lock()
.unwrap()
.allocate_mmio_hole_addresses(
Some(GuestAddress(new_base)),
len as GuestUsize,
Some(len),
)
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"failed allocating new 32 bits MMIO range",
)
})?;
} else { } else {
// Find the specific allocator that this BAR was allocated from and use it for new one &self.pci_mmio64_allocators
for allocator in &self.pci_mmio_allocators { };
let allocator_base = allocator.lock().unwrap().base();
let allocator_end = allocator.lock().unwrap().end();
if old_base >= allocator_base.0 && old_base <= allocator_end.0 { // Find the specific allocator that this BAR was allocated from and use it for new one
allocator for allocator in allocators {
.lock() let allocator_base = allocator.lock().unwrap().base();
.unwrap() let allocator_end = allocator.lock().unwrap().end();
.free(GuestAddress(old_base), len as GuestUsize);
allocator if old_base >= allocator_base.0 && old_base <= allocator_end.0 {
.lock() allocator
.unwrap() .lock()
.allocate( .unwrap()
Some(GuestAddress(new_base)), .free(GuestAddress(old_base), len as GuestUsize);
len as GuestUsize,
Some(len), allocator
.lock()
.unwrap()
.allocate(Some(GuestAddress(new_base)), len as GuestUsize, Some(len))
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"failed allocating new MMIO range",
) )
.ok_or_else(|| { })?;
io::Error::new(
io::ErrorKind::Other,
"failed allocating new 64 bits MMIO range",
)
})?;
break; break;
}
} }
} }
@ -1007,22 +987,40 @@ impl DeviceManager {
1 1
}; };
let start_of_device_area = memory_manager.lock().unwrap().start_of_device_area().0; let create_mmio_allocators = |start, end, num_pci_segments, alignment| {
let end_of_device_area = memory_manager.lock().unwrap().end_of_device_area().0; // Start each PCI segment mmio range on an aligned boundary
let pci_segment_mmio_size =
(end - start + 1) / (alignment * num_pci_segments as u64) * alignment;
// Start each PCI segment range on a 4GiB boundary let mut mmio_allocators = vec![];
let pci_segment_size = (end_of_device_area - start_of_device_area + 1) for i in 0..num_pci_segments as u64 {
/ ((4 << 30) * num_pci_segments as u64) let mmio_start = start + i * pci_segment_mmio_size;
* (4 << 30); let allocator = Arc::new(Mutex::new(
AddressAllocator::new(GuestAddress(mmio_start), pci_segment_mmio_size).unwrap(),
));
mmio_allocators.push(allocator)
}
let mut pci_mmio_allocators = vec![]; mmio_allocators
for i in 0..num_pci_segments as u64 { };
let mmio_start = start_of_device_area + i * pci_segment_size;
let allocator = Arc::new(Mutex::new( let start_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0;
AddressAllocator::new(GuestAddress(mmio_start), pci_segment_size).unwrap(), let end_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE;
)); let pci_mmio32_allocators = create_mmio_allocators(
pci_mmio_allocators.push(allocator) start_of_mmio32_area,
} end_of_mmio32_area,
num_pci_segments,
4 << 10,
);
let start_of_mmio64_area = memory_manager.lock().unwrap().start_of_device_area().0;
let end_of_mmio64_area = memory_manager.lock().unwrap().end_of_device_area().0;
let pci_mmio64_allocators = create_mmio_allocators(
start_of_mmio64_area,
end_of_mmio64_area,
num_pci_segments,
4 << 30,
);
let address_manager = Arc::new(AddressManager { let address_manager = Arc::new(AddressManager {
allocator: memory_manager.lock().unwrap().allocator(), allocator: memory_manager.lock().unwrap().allocator(),
@ -1031,7 +1029,8 @@ impl DeviceManager {
mmio_bus, mmio_bus,
vm: vm.clone(), vm: vm.clone(),
device_tree: Arc::clone(&device_tree), device_tree: Arc::clone(&device_tree),
pci_mmio_allocators, pci_mmio32_allocators,
pci_mmio64_allocators,
}); });
// First we create the MSI interrupt manager, the legacy one is created // First we create the MSI interrupt manager, the legacy one is created
@ -1061,7 +1060,8 @@ impl DeviceManager {
let mut pci_segments = vec![PciSegment::new_default_segment( let mut pci_segments = vec![PciSegment::new_default_segment(
&address_manager, &address_manager,
Arc::clone(&address_manager.pci_mmio_allocators[0]), Arc::clone(&address_manager.pci_mmio32_allocators[0]),
Arc::clone(&address_manager.pci_mmio64_allocators[0]),
&pci_irq_slots, &pci_irq_slots,
)?]; )?];
@ -1070,7 +1070,8 @@ impl DeviceManager {
i as u16, i as u16,
numa_node_id_from_pci_segment_id(&numa_nodes, i as u16), numa_node_id_from_pci_segment_id(&numa_nodes, i as u16),
&address_manager, &address_manager,
Arc::clone(&address_manager.pci_mmio_allocators[i]), Arc::clone(&address_manager.pci_mmio32_allocators[i]),
Arc::clone(&address_manager.pci_mmio64_allocators[i]),
&pci_irq_slots, &pci_irq_slots,
)?); )?);
} }
@ -2765,7 +2766,7 @@ impl DeviceManager {
// The memory needs to be 2MiB aligned in order to support // The memory needs to be 2MiB aligned in order to support
// hugepages. // hugepages.
self.pci_segments[pmem_cfg.pci_segment as usize] self.pci_segments[pmem_cfg.pci_segment as usize]
.allocator .mem64_allocator
.lock() .lock()
.unwrap() .unwrap()
.allocate( .allocate(
@ -2780,7 +2781,7 @@ impl DeviceManager {
// The memory needs to be 2MiB aligned in order to support // The memory needs to be 2MiB aligned in order to support
// hugepages. // hugepages.
let base = self.pci_segments[pmem_cfg.pci_segment as usize] let base = self.pci_segments[pmem_cfg.pci_segment as usize]
.allocator .mem64_allocator
.lock() .lock()
.unwrap() .unwrap()
.allocate(None, size as GuestUsize, Some(0x0020_0000)) .allocate(None, size as GuestUsize, Some(0x0020_0000))
@ -3367,7 +3368,11 @@ impl DeviceManager {
.allocate_bars( .allocate_bars(
&self.address_manager.allocator, &self.address_manager.allocator,
&mut self.pci_segments[segment_id as usize] &mut self.pci_segments[segment_id as usize]
.allocator .mem32_allocator
.lock()
.unwrap(),
&mut self.pci_segments[segment_id as usize]
.mem64_allocator
.lock() .lock()
.unwrap(), .unwrap(),
resources, resources,
@ -4080,7 +4085,11 @@ impl DeviceManager {
.free_bars( .free_bars(
&mut self.address_manager.allocator.lock().unwrap(), &mut self.address_manager.allocator.lock().unwrap(),
&mut self.pci_segments[pci_segment_id as usize] &mut self.pci_segments[pci_segment_id as usize]
.allocator .mem32_allocator
.lock()
.unwrap(),
&mut self.pci_segments[pci_segment_id as usize]
.mem64_allocator
.lock() .lock()
.unwrap(), .unwrap(),
) )

View File

@ -16,7 +16,7 @@ use acpi_tables::{aml, Aml};
use anyhow::anyhow; use anyhow::anyhow;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use arch::x86_64::{SgxEpcRegion, SgxEpcSection}; use arch::x86_64::{SgxEpcRegion, SgxEpcSection};
use arch::{layout, RegionType}; use arch::RegionType;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use devices::ioapic; use devices::ioapic;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
@ -1160,8 +1160,6 @@ impl MemoryManager {
}, },
start_of_platform_device_area, start_of_platform_device_area,
PLATFORM_DEVICE_AREA_SIZE, PLATFORM_DEVICE_AREA_SIZE,
layout::MEM_32BIT_DEVICES_START,
layout::MEM_32BIT_DEVICES_SIZE,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
vec![GsiApic::new( vec![GsiApic::new(
X86_64_IRQ_BASE, X86_64_IRQ_BASE,

View File

@ -38,10 +38,14 @@ pub(crate) struct PciSegment {
pub(crate) pci_irq_slots: [u8; 32], pub(crate) pci_irq_slots: [u8; 32],
// Device memory covered by this segment // Device memory covered by this segment
pub(crate) start_of_device_area: u64, pub(crate) start_of_mem32_area: u64,
pub(crate) end_of_device_area: u64, pub(crate) end_of_mem32_area: u64,
pub(crate) allocator: Arc<Mutex<AddressAllocator>>, pub(crate) start_of_mem64_area: u64,
pub(crate) end_of_mem64_area: u64,
pub(crate) mem32_allocator: Arc<Mutex<AddressAllocator>>,
pub(crate) mem64_allocator: Arc<Mutex<AddressAllocator>>,
} }
impl PciSegment { impl PciSegment {
@ -49,7 +53,8 @@ impl PciSegment {
id: u16, id: u16,
numa_node: u32, numa_node: u32,
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
allocator: Arc<Mutex<AddressAllocator>>, mem32_allocator: Arc<Mutex<AddressAllocator>>,
mem64_allocator: Arc<Mutex<AddressAllocator>>,
pci_irq_slots: &[u8; 32], pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> { ) -> DeviceManagerResult<PciSegment> {
let pci_root = PciRoot::new(None); let pci_root = PciRoot::new(None);
@ -71,8 +76,11 @@ impl PciSegment {
) )
.map_err(DeviceManagerError::BusError)?; .map_err(DeviceManagerError::BusError)?;
let start_of_device_area = allocator.lock().unwrap().base().0; let start_of_mem32_area = mem32_allocator.lock().unwrap().base().0;
let end_of_device_area = allocator.lock().unwrap().end().0; let end_of_mem32_area = mem32_allocator.lock().unwrap().end().0;
let start_of_mem64_area = mem64_allocator.lock().unwrap().base().0;
let end_of_mem64_area = mem64_allocator.lock().unwrap().end().0;
let segment = PciSegment { let segment = PciSegment {
id, id,
@ -84,15 +92,18 @@ impl PciSegment {
pci_devices_down: 0, pci_devices_down: 0,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pci_config_io: None, pci_config_io: None,
allocator, mem32_allocator,
start_of_device_area, mem64_allocator,
end_of_device_area, start_of_mem32_area,
end_of_mem32_area,
start_of_mem64_area,
end_of_mem64_area,
pci_irq_slots: *pci_irq_slots, pci_irq_slots: *pci_irq_slots,
}; };
info!( info!(
"Adding PCI segment: id={}, PCI MMIO config address: 0x{:x}, device area [0x{:x}-0x{:x}", "Adding PCI segment: id={}, PCI MMIO config address: 0x{:x}, mem32 area [0x{:x}-0x{:x}, mem64 area [0x{:x}-0x{:x}",
segment.id, segment.mmio_config_address, segment.start_of_device_area, segment.end_of_device_area segment.id, segment.mmio_config_address, segment.start_of_mem32_area, segment.end_of_mem32_area, segment.start_of_mem64_area, segment.end_of_mem64_area
); );
Ok(segment) Ok(segment)
} }
@ -100,10 +111,18 @@ impl PciSegment {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub(crate) fn new_default_segment( pub(crate) fn new_default_segment(
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
allocator: Arc<Mutex<AddressAllocator>>, mem32_allocator: Arc<Mutex<AddressAllocator>>,
mem64_allocator: Arc<Mutex<AddressAllocator>>,
pci_irq_slots: &[u8; 32], pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> { ) -> DeviceManagerResult<PciSegment> {
let mut segment = Self::new(0, 0, address_manager, allocator, pci_irq_slots)?; let mut segment = Self::new(
0,
0,
address_manager,
mem32_allocator,
mem64_allocator,
pci_irq_slots,
)?;
let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(Arc::clone(&segment.pci_bus)))); let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(Arc::clone(&segment.pci_bus))));
address_manager address_manager
@ -123,10 +142,18 @@ impl PciSegment {
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub(crate) fn new_default_segment( pub(crate) fn new_default_segment(
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
allocator: Arc<Mutex<AddressAllocator>>, mem32_allocator: Arc<Mutex<AddressAllocator>>,
mem64_allocator: Arc<Mutex<AddressAllocator>>,
pci_irq_slots: &[u8; 32], pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> { ) -> DeviceManagerResult<PciSegment> {
Self::new(0, 0, address_manager, allocator, pci_irq_slots) Self::new(
0,
0,
address_manager,
mem32_allocator,
mem64_allocator,
pci_irq_slots,
)
} }
pub(crate) fn next_device_bdf(&self) -> DeviceManagerResult<PciBdf> { pub(crate) fn next_device_bdf(&self) -> DeviceManagerResult<PciBdf> {
@ -340,6 +367,7 @@ impl Aml for PciSegment {
let pci_dsm = PciDsmMethod {}; let pci_dsm = PciDsmMethod {};
pci_dsdt_inner_data.push(&pci_dsm); pci_dsdt_inner_data.push(&pci_dsm);
#[allow(clippy::if_same_then_else)]
let crs = if self.id == 0 { let crs = if self.id == 0 {
aml::Name::new( aml::Name::new(
"_CRS".into(), "_CRS".into(),
@ -347,19 +375,23 @@ impl Aml for PciSegment {
&aml::AddressSpace::new_bus_number(0x0u16, 0x0u16), &aml::AddressSpace::new_bus_number(0x0u16, 0x0u16),
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
&aml::IO::new(0xcf8, 0xcf8, 1, 0x8), &aml::IO::new(0xcf8, 0xcf8, 1, 0x8),
&aml::Memory32Fixed::new(
true,
self.mmio_config_address as u32,
layout::PCI_MMIO_CONFIG_SIZE_PER_SEGMENT as u32,
),
&aml::AddressSpace::new_memory( &aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable, aml::AddressSpaceCacheable::NotCacheable,
true, true,
layout::MEM_32BIT_DEVICES_START.0 as u32, self.start_of_mem32_area,
(layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE - 1) self.end_of_mem32_area,
as u32,
None, None,
), ),
&aml::AddressSpace::new_memory( &aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable, aml::AddressSpaceCacheable::NotCacheable,
true, true,
self.start_of_device_area, self.start_of_mem64_area,
self.end_of_device_area, self.end_of_mem64_area,
None, None,
), ),
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@ -381,8 +413,15 @@ impl Aml for PciSegment {
&aml::AddressSpace::new_memory( &aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable, aml::AddressSpaceCacheable::NotCacheable,
true, true,
self.start_of_device_area, self.start_of_mem32_area,
self.end_of_device_area, self.end_of_mem32_area,
None,
),
&aml::AddressSpace::new_memory(
aml::AddressSpaceCacheable::NotCacheable,
true,
self.start_of_mem64_area,
self.end_of_mem64_area,
None, None,
), ),
]), ]),

View File

@ -1162,9 +1162,9 @@ impl Vm {
let pci_space = PciSpaceInfo { let pci_space = PciSpaceInfo {
pci_segment_id: pci_segment.id, pci_segment_id: pci_segment.id,
mmio_config_address: pci_segment.mmio_config_address, mmio_config_address: pci_segment.mmio_config_address,
pci_device_space_start: pci_segment.start_of_device_area, pci_device_space_start: pci_segment.start_of_mem64_area,
pci_device_space_size: pci_segment.end_of_device_area pci_device_space_size: pci_segment.end_of_mem64_area
- pci_segment.start_of_device_area - pci_segment.start_of_mem64_area
+ 1, + 1,
}; };
pci_space_info.push(pci_space); pci_space_info.push(pci_space);