Create per-PCI-segment MMIO allocators over the range `[start, end]`. Both `start` and `end` are inclusive addresses.
(
start: u64,
end: u64,
num_pci_segments: u16,
weights: &[u32],
alignment: u64,
)
| 1155 | /// Create per-PCI-segment MMIO allocators over the range `[start, end]`. |
| 1156 | /// Both `start` and `end` are inclusive addresses. |
| 1157 | fn create_mmio_allocators( |
| 1158 | start: u64, |
| 1159 | end: u64, |
| 1160 | num_pci_segments: u16, |
| 1161 | weights: &[u32], |
| 1162 | alignment: u64, |
| 1163 | ) -> Vec<Arc<Mutex<AddressAllocator>>> { |
| 1164 | let total_weight: u32 = weights.iter().sum(); |
| 1165 | |
| 1166 | // Start each PCI segment mmio range on an aligned boundary |
| 1167 | let pci_segment_mmio_size = (end - start + 1) / (alignment * total_weight as u64) * alignment; |
| 1168 | |
| 1169 | let mut mmio_allocators = vec![]; |
| 1170 | let mut i = 0; |
| 1171 | for segment_id in 0..num_pci_segments as u64 { |
| 1172 | let weight = weights[segment_id as usize] as u64; |
| 1173 | let mmio_start = start + i * pci_segment_mmio_size; |
| 1174 | let is_last = segment_id == num_pci_segments as u64 - 1; |
| 1175 | // Give the last segment all remaining space so no addresses |
| 1176 | // near the top of the physical address space are lost to |
| 1177 | // alignment truncation. |
| 1178 | let mmio_size = if is_last { |
| 1179 | end - mmio_start + 1 |
| 1180 | } else { |
| 1181 | pci_segment_mmio_size * weight |
| 1182 | }; |
| 1183 | let allocator = Arc::new(Mutex::new( |
| 1184 | AddressAllocator::new(GuestAddress(mmio_start), mmio_size).unwrap(), |
| 1185 | )); |
| 1186 | mmio_allocators.push(allocator); |
| 1187 | i += weight; |
| 1188 | } |
| 1189 | |
| 1190 | mmio_allocators |
| 1191 | } |
| 1192 | |
| 1193 | fn use_64bit_bar_for_virtio_device( |
| 1194 | device_type: u32, |