No need to allocate PCI BARs after all.
Apparently crosvm does this for us, so we can save a bunch of code.
Bug: 237249743
Test: Ran vmbase and pVM firmware manually
Test: atest vmbase_example.integration_test
Change-Id: I3efde5ad1af554a8a1c50fb23d6d1d1de082d25d
diff --git a/pvmfw/src/pci.rs b/pvmfw/src/pci.rs
index d971c7b..301ecfc 100644
--- a/pvmfw/src/pci.rs
+++ b/pvmfw/src/pci.rs
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//! Functions to scan the PCI bus for VirtIO device and allocate BARs.
+//! Functions to scan the PCI bus for VirtIO devices.
use crate::{
entry::RebootReason,
@@ -26,7 +26,7 @@
use libfdt::{AddressRange, Fdt, FdtError, FdtNode};
use log::{debug, error};
use virtio_drivers::pci::{
- bus::{self, BarInfo, Cam, Command, DeviceFunction, MemoryBarType, PciRoot},
+ bus::{Cam, PciRoot},
virtio_device_type,
};
@@ -46,9 +46,6 @@
FdtMissingRanges,
RangeAddressMismatch { bus_address: u64, cpu_physical: u64 },
NoSuitableRange,
- BarInfoFailed(bus::PciError),
- BarAllocationFailed { size: u32, device_function: DeviceFunction },
- UnsupportedBarType(MemoryBarType),
}
impl Display for PciError {
@@ -77,15 +74,6 @@
)
}
Self::NoSuitableRange => write!(f, "No suitable PCI memory range found."),
- Self::BarInfoFailed(e) => write!(f, "Error getting PCI BAR information: {}", e),
- Self::BarAllocationFailed { size, device_function } => write!(
- f,
- "Failed to allocate memory BAR of size {} for PCI device {}.",
- size, device_function
- ),
- Self::UnsupportedBarType(address_type) => {
- write!(f, "Memory BAR address type {:?} not supported.", address_type)
- }
}
}
}
@@ -247,11 +235,8 @@
}
}
-/// Allocates BARs for all VirtIO PCI devices.
-pub fn allocate_all_virtio_bars(
- pci_root: &mut PciRoot,
- allocator: &mut PciMemory32Allocator,
-) -> Result<(), PciError> {
+/// Finds VirtIO PCI devices.
+pub fn find_virtio_devices(pci_root: &mut PciRoot) -> Result<(), PciError> {
for (device_function, info) in pci_root.enumerate_bus(0) {
let (status, command) = pci_root.get_status_command(device_function);
debug!(
@@ -260,87 +245,8 @@
);
if let Some(virtio_type) = virtio_device_type(&info) {
debug!(" VirtIO {:?}", virtio_type);
- allocate_bars(pci_root, device_function, allocator)?;
}
}
Ok(())
}
-
-/// Allocates 32-bit memory addresses for PCI BARs.
-#[derive(Debug)]
-pub struct PciMemory32Allocator {
- /// The start of the available (not yet allocated) address space for PCI BARs.
- start: u32,
- /// The end of the available address space.
- end: u32,
-}
-
-impl PciMemory32Allocator {
- pub fn new(pci_info: &PciInfo) -> Self {
- Self { start: pci_info.bar_range.start, end: pci_info.bar_range.end }
- }
-
- /// Allocates a 32-bit memory address region for a PCI BAR of the given power-of-2 size.
- ///
- /// It will have alignment matching the size. The size must be a power of 2.
- pub fn allocate_memory_32(&mut self, size: u32) -> Option<u32> {
- assert!(size.is_power_of_two());
- let allocated_address = align_up(self.start, size);
- if allocated_address + size <= self.end {
- self.start = allocated_address + size;
- Some(allocated_address)
- } else {
- None
- }
- }
-}
-
-/// Allocates appropriately-sized memory regions and assigns them to the device's BARs.
-fn allocate_bars(
- root: &mut PciRoot,
- device_function: DeviceFunction,
- allocator: &mut PciMemory32Allocator,
-) -> Result<(), PciError> {
- let mut bar_index = 0;
- while bar_index < 6 {
- let info = root.bar_info(device_function, bar_index).map_err(PciError::BarInfoFailed)?;
- debug!("BAR {}: {}", bar_index, info);
- // Ignore I/O bars, as they aren't required for the VirtIO driver.
- if let BarInfo::Memory { address_type, size, .. } = info {
- match address_type {
- _ if size == 0 => {}
- MemoryBarType::Width32 => {
- let address = allocator
- .allocate_memory_32(size)
- .ok_or(PciError::BarAllocationFailed { size, device_function })?;
- debug!("Allocated address {:#010x}", address);
- root.set_bar_32(device_function, bar_index, address);
- }
- _ => {
- return Err(PciError::UnsupportedBarType(address_type));
- }
- }
- }
-
- bar_index += 1;
- if info.takes_two_entries() {
- bar_index += 1;
- }
- }
-
- // Enable the device to use its BARs.
- root.set_command(
- device_function,
- Command::IO_SPACE | Command::MEMORY_SPACE | Command::BUS_MASTER,
- );
- let (status, command) = root.get_status_command(device_function);
- debug!("Allocated BARs and enabled device, status {:?} command {:?}", status, command);
-
- Ok(())
-}
-
-// TODO: Make the alignment functions in the helpers module generic once const_trait_impl is stable.
-const fn align_up(value: u32, alignment: u32) -> u32 {
- ((value - 1) | (alignment - 1)) + 1
-}