Skip to content

Commit

Permalink
Merge pull request #1246 from hermit-os/pci-cap
Browse files Browse the repository at this point in the history
refactor(virtio/pci): migrate `CfgType` to `virtio-spec`
  • Loading branch information
mkroening authored Jun 3, 2024
2 parents 065045f + 8423f8b commit 35c6b57
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 59 deletions.
70 changes: 11 additions & 59 deletions src/drivers/virtio/transport/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,54 +32,6 @@ use crate::drivers::pci::{DeviceHeader, Masks, PciDevice};
use crate::drivers::virtio::env::memory::{MemLen, MemOff, VirtMemAddr};
use crate::drivers::virtio::error::VirtioError;

/// Virtio's cfg_type constants; indicating type of structure in capabilities list
/// See Virtio specification v1.1 - 4.1.4
//
// WARN: Upon changes in the set of the enum variants
// one MUST adjust the associated From<u8>
// implementation, in order catch all cases correctly,
// as this function uses the catch-all "_" case!
#[allow(dead_code, non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum CfgType {
INVALID = 0,
VIRTIO_PCI_CAP_COMMON_CFG = 1,
VIRTIO_PCI_CAP_NOTIFY_CFG = 2,
VIRTIO_PCI_CAP_ISR_CFG = 3,
VIRTIO_PCI_CAP_DEVICE_CFG = 4,
VIRTIO_PCI_CAP_PCI_CFG = 5,
VIRTIO_PCI_CAP_SHARED_MEMORY_CFG = 8,
}

impl From<CfgType> for u8 {
fn from(val: CfgType) -> u8 {
match val {
CfgType::INVALID => 0,
CfgType::VIRTIO_PCI_CAP_COMMON_CFG => 1,
CfgType::VIRTIO_PCI_CAP_NOTIFY_CFG => 2,
CfgType::VIRTIO_PCI_CAP_ISR_CFG => 3,
CfgType::VIRTIO_PCI_CAP_DEVICE_CFG => 4,
CfgType::VIRTIO_PCI_CAP_PCI_CFG => 5,
CfgType::VIRTIO_PCI_CAP_SHARED_MEMORY_CFG => 8,
}
}
}

impl From<u8> for CfgType {
fn from(val: u8) -> Self {
match val {
1 => CfgType::VIRTIO_PCI_CAP_COMMON_CFG,
2 => CfgType::VIRTIO_PCI_CAP_NOTIFY_CFG,
3 => CfgType::VIRTIO_PCI_CAP_ISR_CFG,
4 => CfgType::VIRTIO_PCI_CAP_DEVICE_CFG,
5 => CfgType::VIRTIO_PCI_CAP_PCI_CFG,
8 => CfgType::VIRTIO_PCI_CAP_SHARED_MEMORY_CFG,
_ => CfgType::INVALID,
}
}
}

/// Public structure to allow drivers to read the configuration space
/// safely
#[derive(Clone)]
Expand All @@ -92,7 +44,7 @@ pub struct Origin {
/// Maps a given device specific pci configuration structure and
/// returns a static reference to it.
pub fn map_dev_cfg<T>(cap: &PciCap) -> Option<&'static mut T> {
if cap.cfg_type != CfgType::VIRTIO_PCI_CAP_DEVICE_CFG {
if cap.cfg_type != virtio_spec::pci::Cap::DeviceCfg {
error!("Capability of device config has wrong id. Mapping not possible...");
return None;
};
Expand Down Expand Up @@ -131,10 +83,10 @@ pub fn map_dev_cfg<T>(cap: &PciCap) -> Option<&'static mut T> {
/// as it is not directly mapped into address space from PCI device
/// configuration space.
/// Therefore the struct only contains necessary information to map
/// corresponding [CfgType] into address space.
/// corresponding config type (`pci::Cap`) into address space.
#[derive(Clone)]
pub struct PciCap {
cfg_type: CfgType,
cfg_type: virtio_spec::pci::Cap,
bar: PciBar,
id: u8,
offset: MemOff,
Expand Down Expand Up @@ -262,7 +214,7 @@ impl PartialEq for PciCapRaw {
/// a given Virtio PCI device.
///
/// As Virtio's PCI devices are allowed to present multiple capability
/// structures of the same [CfgType], the structure
/// structures of the same config type (`pci::Cap`), the structure
/// provides a driver with all capabilities, sorted in descending priority,
/// allowing the driver to choose.
/// The structure contains a special dev_cfg_list field, a vector holding
Expand Down Expand Up @@ -1064,7 +1016,7 @@ fn read_caps(
};

cap_list.push(PciCap {
cfg_type: CfgType::from(cap_raw.cfg_type),
cfg_type: virtio_spec::pci::Cap::from(cap_raw.cfg_type),
bar: cap_bar,
id: cap_raw.id,
offset: MemOff::from(cap_raw.offset),
Expand Down Expand Up @@ -1155,36 +1107,36 @@ pub(crate) fn map_caps(device: &PciDevice<PciConfigRegion>) -> Result<UniCapsCol
// Map Caps in virtual memory
for pci_cap in cap_list {
match pci_cap.cfg_type {
CfgType::VIRTIO_PCI_CAP_COMMON_CFG => match pci_cap.map_common_cfg() {
virtio_spec::pci::Cap::CommonCfg => match pci_cap.map_common_cfg() {
Some(cap) => caps.add_cfg_common(ComCfg::new(cap, pci_cap.id)),
None => error!(
"Common config capability with id {}, of device {:x}, could not be mapped!",
pci_cap.id, device_id
),
},
CfgType::VIRTIO_PCI_CAP_NOTIFY_CFG => match NotifCfg::new(&pci_cap) {
virtio_spec::pci::Cap::NotifyCfg => match NotifCfg::new(&pci_cap) {
Some(notif) => caps.add_cfg_notif(notif),
None => error!(
"Notification config capability with id {}, of device {:x} could not be used!",
pci_cap.id, device_id
),
},
CfgType::VIRTIO_PCI_CAP_ISR_CFG => match pci_cap.map_isr_status() {
virtio_spec::pci::Cap::IsrCfg => match pci_cap.map_isr_status() {
Some(isr_stat) => caps.add_cfg_isr(IsrStatus::new(isr_stat, pci_cap.id)),
None => error!(
"ISR status config capability with id {}, of device {:x} could not be used!",
pci_cap.id, device_id
),
},
CfgType::VIRTIO_PCI_CAP_PCI_CFG => caps.add_cfg_alt(PciCfgAlt::new(&pci_cap)),
CfgType::VIRTIO_PCI_CAP_SHARED_MEMORY_CFG => match ShMemCfg::new(&pci_cap) {
virtio_spec::pci::Cap::PciCfg => caps.add_cfg_alt(PciCfgAlt::new(&pci_cap)),
virtio_spec::pci::Cap::SharedMemoryCfg => match ShMemCfg::new(&pci_cap) {
Some(sh_mem) => caps.add_cfg_sh_mem(sh_mem),
None => error!(
"Shared Memory config capability with id {}, of device {:x} could not be used!",
pci_cap.id, device_id
),
},
CfgType::VIRTIO_PCI_CAP_DEVICE_CFG => caps.add_cfg_dev(pci_cap),
virtio_spec::pci::Cap::DeviceCfg => caps.add_cfg_dev(pci_cap),

// PCI's configuration space is allowed to hold other structures, which are not virtio specific and are therefore ignored
// in the following
Expand Down
41 changes: 41 additions & 0 deletions virtio-spec/src/pci.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Definitions for Virtio over PCI bus.
use num_enum::{FromPrimitive, IntoPrimitive};
use volatile::access::{ReadOnly, ReadWrite, RestrictAccess};
use volatile::{VolatileFieldAccess, VolatilePtr};

Expand All @@ -9,6 +10,8 @@ use crate::{le16, le32, DeviceStatus};
/// Common configuration structure
///
/// The common configuration structure is found at the bar and offset within the [`VIRTIO_PCI_CAP_COMMON_CFG`] capability.
///
/// [`VIRTIO_PCI_CAP_COMMON_CFG`]: Cap::CommonCfg
#[doc(alias = "virtio_pci_common_cfg")]
#[cfg_attr(
feature = "zerocopy",
Expand Down Expand Up @@ -151,3 +154,41 @@ virtio_bitflags! {
const DEVICE_CONFIGURATION_INTERRUPT = 1 << 1;
}
}

/// PCI Capability Configuration Type
#[derive(IntoPrimitive, FromPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
#[non_exhaustive]
#[repr(u8)]
pub enum Cap {
/// Common configuration
#[doc(alias = "VIRTIO_PCI_CAP_COMMON_CFG")]
CommonCfg = 1,

/// Notifications
#[doc(alias = "VIRTIO_PCI_CAP_NOTIFY_CFG")]
NotifyCfg = 2,

/// ISR Status
#[doc(alias = "VIRTIO_PCI_CAP_ISR_CFG")]
IsrCfg = 3,

/// Device specific configuration
#[doc(alias = "VIRTIO_PCI_CAP_DEVICE_CFG")]
DeviceCfg = 4,

/// PCI configuration access
#[doc(alias = "VIRTIO_PCI_CAP_PCI_CFG")]
PciCfg = 5,

/// Shared memory region
#[doc(alias = "VIRTIO_PCI_CAP_SHARED_MEMORY_CFG")]
SharedMemoryCfg = 8,

/// Vendor-specific data
#[doc(alias = "VIRTIO_PCI_CAP_VENDOR_CFG")]
VencodCfg = 9,

/// Unknown device
#[num_enum(catch_all)]
Unknown(u8),
}

0 comments on commit 35c6b57

Please sign in to comment.