From c56db8d11b4d17d02699ce206b50ed75a0e02002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Wed, 25 Sep 2024 20:46:32 +0300 Subject: [PATCH] virtio-pci: map BAR with the information from capabilities Currently, we map the BAR spaces ahead of time and then match them with the capability they belong to. We can get the slot index from the capability and map the space based on that instead. Although creating a BAR list independent of the capability list could be useful for devices that do not support capability lists, we assume the existence of that support anyways. Fixes #1392. --- src/drivers/virtio/env.rs | 53 ----------------------------- src/drivers/virtio/mod.rs | 1 - src/drivers/virtio/transport/pci.rs | 25 ++++++-------- 3 files changed, 11 insertions(+), 68 deletions(-) delete mode 100644 src/drivers/virtio/env.rs diff --git a/src/drivers/virtio/env.rs b/src/drivers/virtio/env.rs deleted file mode 100644 index 2cf5f5592e..0000000000 --- a/src/drivers/virtio/env.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! A module containing all environment specific function calls. -//! -//! The module should easy partability of the code. Furthermore it provides -//! a clean boundary between virtio and the rest of the kernel. One additional aspect is to -//! ensure only a single location needs changes, in cases where the underlying kernel code is changed - -/// This module is used as a single entry point from Virtio code into -/// other parts of the kernel. -/// -/// INFO: Values passed on to PCI devices are automatically converted into little endian -/// coding. Values provided from PCI devices are passed as native endian values. -/// Meaning they are converted into big endian values on big endian machines and -/// are not changed on little endian machines. -#[cfg(feature = "pci")] -pub mod pci { - use alloc::vec::Vec; - - use pci_types::MAX_BARS; - - use crate::arch::pci::PciConfigRegion; - use crate::drivers::pci::error::PciError; - use crate::drivers::pci::PciDevice; - use crate::drivers::virtio::transport::pci::PciBar as VirtioPciBar; - - /// Maps all memory areas indicated by the devices BAR's into - /// Virtual address space. - /// - /// As this function uses parts of the kernel pci code it is - /// outsourced into the env::pci module. - /// - /// WARN: Currently unsafely casts kernel::PciBar.size (usize) to an - /// u64 - pub(crate) fn map_bar_mem( - device: &PciDevice, - ) -> Result, PciError> { - let mapped_bars: Vec = (0..u8::try_from(MAX_BARS).unwrap()) - .filter_map(|i| { - device - .memory_map_bar(i, true) - .map(|(addr, size)| (i, addr, size)) - }) - .map(|(i, addr, size)| VirtioPciBar::new(i, addr.as_u64(), size.try_into().unwrap())) - .collect::>(); - - if mapped_bars.is_empty() { - let device_id = device.device_id(); - error!("No correct memory BAR for device {:x} found.", device_id); - Err(PciError::NoBar(device_id)) - } else { - Ok(mapped_bars) - } - } -} diff --git a/src/drivers/virtio/mod.rs b/src/drivers/virtio/mod.rs index e32cd5f375..89366b49b4 100644 --- a/src/drivers/virtio/mod.rs +++ b/src/drivers/virtio/mod.rs @@ -1,7 +1,6 @@ //! A module containing virtios core infrastructure for hermit-rs. //! //! The module contains virtios transport mechanisms, virtqueues and virtio specific errors -pub mod env; pub mod transport; pub mod virtqueue; diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index c7698bb9e5..30d1e34e12 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -37,6 +37,7 @@ use crate::drivers::virtio::error::VirtioError; any(feature = "tcp", feature = "udp", feature = "vsock") ))] use crate::drivers::virtio::transport::hardware; +use crate::drivers::virtio::transport::pci::PciBar as VirtioPciBar; #[cfg(feature = "vsock")] use crate::drivers::vsock::VirtioVsockDriver; @@ -765,10 +766,7 @@ impl PciBar { /// /// Returns ONLY Virtio specific capabilities, which allow to locate the actual capability /// structures inside the memory areas, indicated by the BaseAddressRegisters (BAR's). -fn read_caps( - device: &PciDevice, - bars: &[PciBar], -) -> Result, PciError> { +fn read_caps(device: &PciDevice) -> Result, PciError> { let device_id = device.device_id(); let capabilities = device @@ -780,10 +778,14 @@ fn read_caps( }) .map(|addr| CapData::read(addr, device.access()).unwrap()) .filter(|cap| cap.cfg_type != CapCfgType::Pci) - .map(|cap| PciCap { - bar: *bars.iter().find(|bar| bar.index == cap.bar).unwrap(), - dev_id: device_id, - cap, + .map(|cap| { + let slot = cap.bar; + let (addr, size) = device.memory_map_bar(slot, true).unwrap(); + PciCap { + bar: VirtioPciBar::new(slot, addr.as_u64(), size.try_into().unwrap()), + dev_id: device_id, + cap, + } }) .collect::>(); @@ -795,11 +797,6 @@ fn read_caps( } } -/// Maps memory areas indicated by devices BAR's into virtual address space. -fn map_bars(device: &PciDevice) -> Result, PciError> { - crate::drivers::virtio::env::pci::map_bar_mem(device) -} - /// Checks if minimal set of capabilities is present. /// /// INFO: Currently only checks if at least one common config struct has been found and mapped. @@ -828,7 +825,7 @@ pub(crate) fn map_caps(device: &PciDevice) -> Result list, Err(pci_error) => return Err(pci_error), };