[vmbase][pci] Decouple Hal impl from PciTransportIterator
This cl decouples the specific implementation of the
virtio_drivers::Hal trait from the PciTransportIterator struct,
enabling it to be used in a wider range of scenarios. This
also allows the iterator to be tested in the vmbase integration
test.
Test: m pvmfw_img
Test: atest vmbase_example.integration_test
Bug: 284462758
Change-Id: I0bee834e8db534cbdc49be84d5b4cdda30b8288a
diff --git a/pvmfw/src/gpt.rs b/pvmfw/src/gpt.rs
index b553705..892850c 100644
--- a/pvmfw/src/gpt.rs
+++ b/pvmfw/src/gpt.rs
@@ -24,9 +24,11 @@
use uuid::Uuid;
use virtio_drivers::device::blk::SECTOR_SIZE;
use vmbase::util::ceiling_div;
-use vmbase::virtio::pci::VirtIOBlk;
+use vmbase::virtio::{pci, HalImpl};
use zerocopy::FromBytes;
+type VirtIOBlk = pci::VirtIOBlk<HalImpl>;
+
pub enum Error {
/// VirtIO error during read operation.
FailedRead(virtio_drivers::Error),
diff --git a/pvmfw/src/instance.rs b/pvmfw/src/instance.rs
index 1035559..f2b34da 100644
--- a/pvmfw/src/instance.rs
+++ b/pvmfw/src/instance.rs
@@ -32,6 +32,7 @@
use vmbase::rand;
use vmbase::util::ceiling_div;
use vmbase::virtio::pci::{PciTransportIterator, VirtIOBlk};
+use vmbase::virtio::HalImpl;
use zerocopy::AsBytes;
use zerocopy::FromBytes;
@@ -183,10 +184,11 @@
}
fn find_instance_img(pci_root: &mut PciRoot) -> Result<Partition> {
- for transport in
- PciTransportIterator::new(pci_root).filter(|t| DeviceType::Block == t.device_type())
+ for transport in PciTransportIterator::<HalImpl>::new(pci_root)
+ .filter(|t| DeviceType::Block == t.device_type())
{
- let device = VirtIOBlk::new(transport).map_err(Error::VirtIOBlkCreationFailed)?;
+ let device =
+ VirtIOBlk::<HalImpl>::new(transport).map_err(Error::VirtIOBlkCreationFailed)?;
match Partition::get_by_name(device, "vm-instance") {
Ok(Some(p)) => return Ok(p),
Ok(None) => {}
diff --git a/vmbase/example/src/pci.rs b/vmbase/example/src/pci.rs
index 6abe66e..7188cde 100644
--- a/vmbase/example/src/pci.rs
+++ b/vmbase/example/src/pci.rs
@@ -20,13 +20,14 @@
use fdtpci::PciInfo;
use log::{debug, info};
use virtio_drivers::{
- device::{blk::VirtIOBlk, console::VirtIOConsole},
+ device::console::VirtIOConsole,
transport::{
- pci::{bus::PciRoot, virtio_device_type, PciTransport},
+ pci::{bus::PciRoot, PciTransport},
DeviceType, Transport,
},
BufferDirection, Error, Hal, PhysAddr, PAGE_SIZE,
};
+use vmbase::virtio::pci::{self, PciTransportIterator};
/// The standard sector size of a VirtIO block device, in bytes.
const SECTOR_SIZE_BYTES: usize = 512;
@@ -37,29 +38,23 @@
pub fn check_pci(pci_root: &mut PciRoot) {
let mut checked_virtio_device_count = 0;
let mut block_device_count = 0;
- for (device_function, info) in pci_root.enumerate_bus(0) {
- let (status, command) = pci_root.get_status_command(device_function);
- info!("Found {} at {}, status {:?} command {:?}", info, device_function, status, command);
- if let Some(virtio_type) = virtio_device_type(&info) {
- info!(" VirtIO {:?}", virtio_type);
- let mut transport = PciTransport::new::<HalImpl>(pci_root, device_function).unwrap();
- info!(
- "Detected virtio PCI device with device type {:?}, features {:#018x}",
- transport.device_type(),
- transport.read_device_features(),
- );
- match virtio_type {
- DeviceType::Block => {
- check_virtio_block_device(transport, block_device_count);
- block_device_count += 1;
- checked_virtio_device_count += 1;
- }
- DeviceType::Console => {
- check_virtio_console_device(transport);
- checked_virtio_device_count += 1;
- }
- _ => {}
+ for mut transport in PciTransportIterator::<HalImpl>::new(pci_root) {
+ info!(
+ "Detected virtio PCI device with device type {:?}, features {:#018x}",
+ transport.device_type(),
+ transport.read_device_features(),
+ );
+ match transport.device_type() {
+ DeviceType::Block => {
+ check_virtio_block_device(transport, block_device_count);
+ block_device_count += 1;
+ checked_virtio_device_count += 1;
}
+ DeviceType::Console => {
+ check_virtio_console_device(transport);
+ checked_virtio_device_count += 1;
+ }
+ _ => {}
}
}
@@ -68,8 +63,8 @@
}
/// Checks the given VirtIO block device.
-fn check_virtio_block_device(transport: impl Transport, index: usize) {
- let mut blk = VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
+fn check_virtio_block_device(transport: PciTransport, index: usize) {
+ let mut blk = pci::VirtIOBlk::<HalImpl>::new(transport).expect("failed to create blk driver");
info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
match index {
0 => {
@@ -94,8 +89,8 @@
}
/// Checks the given VirtIO console device.
-fn check_virtio_console_device(transport: impl Transport) {
- let mut console = VirtIOConsole::<HalImpl, _>::new(transport)
+fn check_virtio_console_device(transport: PciTransport) {
+ let mut console = VirtIOConsole::<HalImpl, PciTransport>::new(transport)
.expect("Failed to create VirtIO console driver");
info!("Found console device: {:?}", console.info());
for &c in b"Hello VirtIO console\n" {
diff --git a/vmbase/src/virtio/mod.rs b/vmbase/src/virtio/mod.rs
index df916bc..fbe41e3 100644
--- a/vmbase/src/virtio/mod.rs
+++ b/vmbase/src/virtio/mod.rs
@@ -16,3 +16,5 @@
mod hal;
pub mod pci;
+
+pub use hal::HalImpl;
diff --git a/vmbase/src/virtio/pci.rs b/vmbase/src/virtio/pci.rs
index 534d91a..a75f0e2 100644
--- a/vmbase/src/virtio/pci.rs
+++ b/vmbase/src/virtio/pci.rs
@@ -14,10 +14,10 @@
//! Functions to scan the PCI bus for VirtIO devices.
-use super::hal::HalImpl;
use crate::memory::{MemoryTracker, MemoryTrackerError};
use alloc::boxed::Box;
use core::fmt;
+use core::marker::PhantomData;
use fdtpci::PciInfo;
use log::debug;
use once_cell::race::OnceBox;
@@ -27,6 +27,7 @@
bus::{BusDeviceIterator, PciRoot},
virtio_device_type, PciTransport,
},
+ Hal,
};
pub(super) static PCI_INFO: OnceBox<PciInfo> = OnceBox::new();
@@ -76,23 +77,24 @@
}
/// Virtio Block device.
-pub type VirtIOBlk = blk::VirtIOBlk<HalImpl, PciTransport>;
+pub type VirtIOBlk<T> = blk::VirtIOBlk<T, PciTransport>;
/// An iterator that iterates over the PCI transport for each device.
-pub struct PciTransportIterator<'a> {
+pub struct PciTransportIterator<'a, T: Hal> {
pci_root: &'a mut PciRoot,
bus: BusDeviceIterator,
+ _hal: PhantomData<T>,
}
-impl<'a> PciTransportIterator<'a> {
+impl<'a, T: Hal> PciTransportIterator<'a, T> {
/// Creates a new iterator.
pub fn new(pci_root: &'a mut PciRoot) -> Self {
let bus = pci_root.enumerate_bus(0);
- Self { pci_root, bus }
+ Self { pci_root, bus, _hal: PhantomData }
}
}
-impl<'a> Iterator for PciTransportIterator<'a> {
+impl<'a, T: Hal> Iterator for PciTransportIterator<'a, T> {
type Item = PciTransport;
fn next(&mut self) -> Option<Self::Item> {
@@ -109,7 +111,7 @@
};
debug!(" VirtIO {:?}", virtio_type);
- return PciTransport::new::<HalImpl>(self.pci_root, device_function).ok();
+ return PciTransport::new::<T>(self.pci_root, device_function).ok();
}
}
}