mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: assign each pci segment 32-bit mmio allocator
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
This commit is contained in:
@@ -561,7 +561,8 @@ pub(crate) struct AddressManager {
|
||||
pub(crate) mmio_bus: Arc<Bus>,
|
||||
pub(crate) vm: Arc<dyn hypervisor::Vm>,
|
||||
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 {
|
||||
@@ -604,56 +605,35 @@ impl DeviceRelocation for AddressManager {
|
||||
error!("I/O region is not supported");
|
||||
}
|
||||
PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
|
||||
// Update system allocator
|
||||
if region_type == PciBarRegionType::Memory32BitRegion {
|
||||
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",
|
||||
)
|
||||
})?;
|
||||
let allocators = if region_type == PciBarRegionType::Memory32BitRegion {
|
||||
&self.pci_mmio32_allocators
|
||||
} else {
|
||||
// Find the specific allocator that this BAR was allocated from and use it for new one
|
||||
for allocator in &self.pci_mmio_allocators {
|
||||
let allocator_base = allocator.lock().unwrap().base();
|
||||
let allocator_end = allocator.lock().unwrap().end();
|
||||
&self.pci_mmio64_allocators
|
||||
};
|
||||
|
||||
if old_base >= allocator_base.0 && old_base <= allocator_end.0 {
|
||||
allocator
|
||||
.lock()
|
||||
.unwrap()
|
||||
.free(GuestAddress(old_base), len as GuestUsize);
|
||||
// Find the specific allocator that this BAR was allocated from and use it for new one
|
||||
for allocator in allocators {
|
||||
let allocator_base = allocator.lock().unwrap().base();
|
||||
let allocator_end = allocator.lock().unwrap().end();
|
||||
|
||||
allocator
|
||||
.lock()
|
||||
.unwrap()
|
||||
.allocate(
|
||||
Some(GuestAddress(new_base)),
|
||||
len as GuestUsize,
|
||||
Some(len),
|
||||
if old_base >= allocator_base.0 && old_base <= allocator_end.0 {
|
||||
allocator
|
||||
.lock()
|
||||
.unwrap()
|
||||
.free(GuestAddress(old_base), len as GuestUsize);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
let start_of_device_area = memory_manager.lock().unwrap().start_of_device_area().0;
|
||||
let end_of_device_area = memory_manager.lock().unwrap().end_of_device_area().0;
|
||||
let create_mmio_allocators = |start, end, num_pci_segments, alignment| {
|
||||
// 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 pci_segment_size = (end_of_device_area - start_of_device_area + 1)
|
||||
/ ((4 << 30) * num_pci_segments as u64)
|
||||
* (4 << 30);
|
||||
let mut mmio_allocators = vec![];
|
||||
for i in 0..num_pci_segments as u64 {
|
||||
let mmio_start = start + i * pci_segment_mmio_size;
|
||||
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![];
|
||||
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(
|
||||
AddressAllocator::new(GuestAddress(mmio_start), pci_segment_size).unwrap(),
|
||||
));
|
||||
pci_mmio_allocators.push(allocator)
|
||||
}
|
||||
mmio_allocators
|
||||
};
|
||||
|
||||
let start_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0;
|
||||
let end_of_mmio32_area = layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE;
|
||||
let pci_mmio32_allocators = create_mmio_allocators(
|
||||
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 {
|
||||
allocator: memory_manager.lock().unwrap().allocator(),
|
||||
@@ -1031,7 +1029,8 @@ impl DeviceManager {
|
||||
mmio_bus,
|
||||
vm: vm.clone(),
|
||||
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
|
||||
@@ -1061,7 +1060,8 @@ impl DeviceManager {
|
||||
|
||||
let mut pci_segments = vec![PciSegment::new_default_segment(
|
||||
&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,
|
||||
)?];
|
||||
|
||||
@@ -1070,7 +1070,8 @@ impl DeviceManager {
|
||||
i as u16,
|
||||
numa_node_id_from_pci_segment_id(&numa_nodes, i as u16),
|
||||
&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,
|
||||
)?);
|
||||
}
|
||||
@@ -2765,7 +2766,7 @@ impl DeviceManager {
|
||||
// The memory needs to be 2MiB aligned in order to support
|
||||
// hugepages.
|
||||
self.pci_segments[pmem_cfg.pci_segment as usize]
|
||||
.allocator
|
||||
.mem64_allocator
|
||||
.lock()
|
||||
.unwrap()
|
||||
.allocate(
|
||||
@@ -2780,7 +2781,7 @@ impl DeviceManager {
|
||||
// The memory needs to be 2MiB aligned in order to support
|
||||
// hugepages.
|
||||
let base = self.pci_segments[pmem_cfg.pci_segment as usize]
|
||||
.allocator
|
||||
.mem64_allocator
|
||||
.lock()
|
||||
.unwrap()
|
||||
.allocate(None, size as GuestUsize, Some(0x0020_0000))
|
||||
@@ -3367,7 +3368,11 @@ impl DeviceManager {
|
||||
.allocate_bars(
|
||||
&self.address_manager.allocator,
|
||||
&mut self.pci_segments[segment_id as usize]
|
||||
.allocator
|
||||
.mem32_allocator
|
||||
.lock()
|
||||
.unwrap(),
|
||||
&mut self.pci_segments[segment_id as usize]
|
||||
.mem64_allocator
|
||||
.lock()
|
||||
.unwrap(),
|
||||
resources,
|
||||
@@ -4080,7 +4085,11 @@ impl DeviceManager {
|
||||
.free_bars(
|
||||
&mut self.address_manager.allocator.lock().unwrap(),
|
||||
&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()
|
||||
.unwrap(),
|
||||
)
|
||||
|
||||
@@ -16,7 +16,7 @@ use acpi_tables::{aml, Aml};
|
||||
use anyhow::anyhow;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use arch::x86_64::{SgxEpcRegion, SgxEpcSection};
|
||||
use arch::{layout, RegionType};
|
||||
use arch::RegionType;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use devices::ioapic;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@@ -1160,8 +1160,6 @@ impl MemoryManager {
|
||||
},
|
||||
start_of_platform_device_area,
|
||||
PLATFORM_DEVICE_AREA_SIZE,
|
||||
layout::MEM_32BIT_DEVICES_START,
|
||||
layout::MEM_32BIT_DEVICES_SIZE,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
vec![GsiApic::new(
|
||||
X86_64_IRQ_BASE,
|
||||
|
||||
@@ -38,10 +38,14 @@ pub(crate) struct PciSegment {
|
||||
pub(crate) pci_irq_slots: [u8; 32],
|
||||
|
||||
// Device memory covered by this segment
|
||||
pub(crate) start_of_device_area: u64,
|
||||
pub(crate) end_of_device_area: u64,
|
||||
pub(crate) start_of_mem32_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 {
|
||||
@@ -49,7 +53,8 @@ impl PciSegment {
|
||||
id: u16,
|
||||
numa_node: u32,
|
||||
address_manager: &Arc<AddressManager>,
|
||||
allocator: Arc<Mutex<AddressAllocator>>,
|
||||
mem32_allocator: Arc<Mutex<AddressAllocator>>,
|
||||
mem64_allocator: Arc<Mutex<AddressAllocator>>,
|
||||
pci_irq_slots: &[u8; 32],
|
||||
) -> DeviceManagerResult<PciSegment> {
|
||||
let pci_root = PciRoot::new(None);
|
||||
@@ -71,8 +76,11 @@ impl PciSegment {
|
||||
)
|
||||
.map_err(DeviceManagerError::BusError)?;
|
||||
|
||||
let start_of_device_area = allocator.lock().unwrap().base().0;
|
||||
let end_of_device_area = allocator.lock().unwrap().end().0;
|
||||
let start_of_mem32_area = mem32_allocator.lock().unwrap().base().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 {
|
||||
id,
|
||||
@@ -84,15 +92,18 @@ impl PciSegment {
|
||||
pci_devices_down: 0,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pci_config_io: None,
|
||||
allocator,
|
||||
start_of_device_area,
|
||||
end_of_device_area,
|
||||
mem32_allocator,
|
||||
mem64_allocator,
|
||||
start_of_mem32_area,
|
||||
end_of_mem32_area,
|
||||
start_of_mem64_area,
|
||||
end_of_mem64_area,
|
||||
pci_irq_slots: *pci_irq_slots,
|
||||
};
|
||||
|
||||
info!(
|
||||
"Adding PCI segment: id={}, PCI MMIO config address: 0x{:x}, device area [0x{:x}-0x{:x}",
|
||||
segment.id, segment.mmio_config_address, segment.start_of_device_area, segment.end_of_device_area
|
||||
"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_mem32_area, segment.end_of_mem32_area, segment.start_of_mem64_area, segment.end_of_mem64_area
|
||||
);
|
||||
Ok(segment)
|
||||
}
|
||||
@@ -100,10 +111,18 @@ impl PciSegment {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub(crate) fn new_default_segment(
|
||||
address_manager: &Arc<AddressManager>,
|
||||
allocator: Arc<Mutex<AddressAllocator>>,
|
||||
mem32_allocator: Arc<Mutex<AddressAllocator>>,
|
||||
mem64_allocator: Arc<Mutex<AddressAllocator>>,
|
||||
pci_irq_slots: &[u8; 32],
|
||||
) -> 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))));
|
||||
|
||||
address_manager
|
||||
@@ -123,10 +142,18 @@ impl PciSegment {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub(crate) fn new_default_segment(
|
||||
address_manager: &Arc<AddressManager>,
|
||||
allocator: Arc<Mutex<AddressAllocator>>,
|
||||
mem32_allocator: Arc<Mutex<AddressAllocator>>,
|
||||
mem64_allocator: Arc<Mutex<AddressAllocator>>,
|
||||
pci_irq_slots: &[u8; 32],
|
||||
) -> 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> {
|
||||
@@ -340,6 +367,7 @@ impl Aml for PciSegment {
|
||||
let pci_dsm = PciDsmMethod {};
|
||||
pci_dsdt_inner_data.push(&pci_dsm);
|
||||
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
let crs = if self.id == 0 {
|
||||
aml::Name::new(
|
||||
"_CRS".into(),
|
||||
@@ -347,19 +375,23 @@ impl Aml for PciSegment {
|
||||
&aml::AddressSpace::new_bus_number(0x0u16, 0x0u16),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
&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::AddressSpaceCacheable::NotCacheable,
|
||||
true,
|
||||
layout::MEM_32BIT_DEVICES_START.0 as u32,
|
||||
(layout::MEM_32BIT_DEVICES_START.0 + layout::MEM_32BIT_DEVICES_SIZE - 1)
|
||||
as u32,
|
||||
self.start_of_mem32_area,
|
||||
self.end_of_mem32_area,
|
||||
None,
|
||||
),
|
||||
&aml::AddressSpace::new_memory(
|
||||
aml::AddressSpaceCacheable::NotCacheable,
|
||||
true,
|
||||
self.start_of_device_area,
|
||||
self.end_of_device_area,
|
||||
self.start_of_mem64_area,
|
||||
self.end_of_mem64_area,
|
||||
None,
|
||||
),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -381,8 +413,15 @@ impl Aml for PciSegment {
|
||||
&aml::AddressSpace::new_memory(
|
||||
aml::AddressSpaceCacheable::NotCacheable,
|
||||
true,
|
||||
self.start_of_device_area,
|
||||
self.end_of_device_area,
|
||||
self.start_of_mem32_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,
|
||||
),
|
||||
]),
|
||||
|
||||
@@ -1162,9 +1162,9 @@ impl Vm {
|
||||
let pci_space = PciSpaceInfo {
|
||||
pci_segment_id: pci_segment.id,
|
||||
mmio_config_address: pci_segment.mmio_config_address,
|
||||
pci_device_space_start: pci_segment.start_of_device_area,
|
||||
pci_device_space_size: pci_segment.end_of_device_area
|
||||
- pci_segment.start_of_device_area
|
||||
pci_device_space_start: pci_segment.start_of_mem64_area,
|
||||
pci_device_space_size: pci_segment.end_of_mem64_area
|
||||
- pci_segment.start_of_mem64_area
|
||||
+ 1,
|
||||
};
|
||||
pci_space_info.push(pci_space);
|
||||
|
||||
Reference in New Issue
Block a user