From d831e9c51305e64e0fc1db49bbd8e16d265b3199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sun, 2 Jun 2024 17:14:29 +0200 Subject: [PATCH 1/3] feat(virtio-spec): add device id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- Cargo.lock | 21 ++++++ virtio-spec/Cargo.toml | 1 + virtio-spec/src/lib.rs | 131 ++++++++++++++++++++++++++++++++++++ virtio-spec/src/volatile.rs | 15 ++++- 4 files changed, 166 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e183e2d35f..5bc23b871b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -916,6 +916,26 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -1517,6 +1537,7 @@ version = "0.0.0" dependencies = [ "bitflags 2.5.0", "endian-num", + "num_enum", "volatile 0.5.4", "zerocopy", "zerocopy-derive", diff --git a/virtio-spec/Cargo.toml b/virtio-spec/Cargo.toml index 02e0970862..fc1454983a 100644 --- a/virtio-spec/Cargo.toml +++ b/virtio-spec/Cargo.toml @@ -11,6 +11,7 @@ categories = ["no-std", "no-std::no-alloc"] [dependencies] bitflags = "2" endian-num = { version = "0.1", features = ["bitflags", "linux-types"] } +num_enum = { version = "0.7", default-features = false } volatile = { version = "0.5.3", features = ["derive"] } zerocopy = { version = "0.7", optional = true, default-features = false } zerocopy-derive = { version = "0.7", optional = true } diff --git a/virtio-spec/src/lib.rs b/virtio-spec/src/lib.rs index c0704fadac..cf5ffe048c 100644 --- a/virtio-spec/src/lib.rs +++ b/virtio-spec/src/lib.rs @@ -15,6 +15,7 @@ pub mod net; pub mod pci; pub use endian_num::{be128, be16, be32, be64, le128, le16, le32, le64}; +use num_enum::{FromPrimitive, IntoPrimitive}; pub use self::features::{FeatureBits, F}; @@ -73,3 +74,133 @@ virtio_bitflags! { const DEVICE_NEEDS_RESET = 64; } } + +/// Virtio Device IDs +#[derive(IntoPrimitive, FromPrimitive, PartialEq, Eq, Clone, Copy, Debug)] +#[non_exhaustive] +#[repr(u8)] +pub enum Id { + /// reserved (invalid) + Reserved = 0, + + /// network card + Net = 1, + + /// block device + Block = 2, + + /// console + Console = 3, + + /// entropy source + Rng = 4, + + /// memory ballooning (traditional) + Balloon = 5, + + /// ioMemory + IoMem = 6, + + /// rpmsg + Rpmsg = 7, + + /// SCSI host + Scsi = 8, + + /// 9P transport + NineP = 9, + + /// mac80211 wlan + Mac80211Wlan = 10, + + /// rproc serial + RprocSerial = 11, + + /// virtio CAIF + Caif = 12, + + /// memory balloon + MemoryBalloon = 13, + + /// GPU device + Gpu = 16, + + /// Timer/Clock device + Clock = 17, + + /// Input device + Input = 18, + + /// Socket device + Vsock = 19, + + /// Crypto device + Crypto = 20, + + /// Signal Distribution Module + SignalDist = 21, + + /// pstore device + Pstore = 22, + + /// IOMMU device + Iommu = 23, + + /// Memory device + Mem = 24, + + /// Audio device + Sound = 25, + + /// file system device + Fs = 26, + + /// PMEM device + Pmem = 27, + + /// RPMB device + Rpmb = 28, + + /// mac80211 hwsim wireless simulation device + Mac80211Hwsim = 29, + + /// Video encoder device + VideoEncoder = 30, + + /// Video decoder device + VideoDecoder = 31, + + /// SCMI device + Scmi = 32, + + /// NitroSecureModule + NitroSecMod = 33, + + /// I2C adapter + I2cAdapter = 34, + + /// Watchdog + Watchdog = 35, + + /// CAN device + Can = 36, + + /// Parameter Server + ParamServ = 38, + + /// Audio policy device + AudioPolicy = 39, + + /// Bluetooth device + Bt = 40, + + /// GPIO device + Gpio = 41, + + /// RDMA device + Rdma = 42, + + /// Unknown device + #[num_enum(catch_all)] + Unknown(u8), +} diff --git a/virtio-spec/src/volatile.rs b/virtio-spec/src/volatile.rs index 634abe75a8..f0dfa31164 100644 --- a/virtio-spec/src/volatile.rs +++ b/virtio-spec/src/volatile.rs @@ -6,7 +6,7 @@ use volatile::access::{Readable, Writable}; use volatile::VolatilePtr; use crate::mmio::InterruptStatus; -use crate::{be32, be64, le16, le32, le64, DeviceStatus}; +use crate::{be32, be64, le16, le32, le64, DeviceStatus, Id}; /// A wide volatile pointer for 64-bit fields. /// @@ -263,6 +263,16 @@ impl OveralignedField for u8 { } } +impl OveralignedField for Id { + fn from_field(field: le32) -> Self { + Self::from(u8::from_field(field)) + } + + fn into_field(self) -> le32 { + u8::from(self).into_field() + } +} + impl OveralignedField for DeviceStatus { fn from_field(field: le32) -> Self { Self::from_bits_retain(u8::from_field(field)) @@ -285,13 +295,14 @@ impl OveralignedField for InterruptStatus { mod private { use crate::mmio::InterruptStatus; - use crate::{le16, le32, DeviceStatus}; + use crate::{le16, le32, DeviceStatus, Id}; pub trait Sealed {} impl Sealed for bool {} impl Sealed for u8 {} impl Sealed for le16 {} + impl Sealed for Id {} impl Sealed for DeviceStatus {} impl Sealed for InterruptStatus {} } From 5c819719534e13e60e81325d11defbc788be4dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sun, 2 Jun 2024 17:15:28 +0200 Subject: [PATCH 2/3] refactor(virtio/mmio): migrate `DevId` to `virtio-spec` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/riscv64/kernel/devicetree.rs | 6 ++-- src/arch/x86_64/kernel/mmio.rs | 6 ++-- src/drivers/virtio/transport/mmio.rs | 43 ++------------------------- virtio-spec/src/mmio.rs | 4 +-- 4 files changed, 9 insertions(+), 50 deletions(-) diff --git a/src/arch/riscv64/kernel/devicetree.rs b/src/arch/riscv64/kernel/devicetree.rs index 71b00378a6..2905f3cb8a 100644 --- a/src/arch/riscv64/kernel/devicetree.rs +++ b/src/arch/riscv64/kernel/devicetree.rs @@ -16,8 +16,6 @@ use crate::arch::riscv64::kernel::mmio::MmioDriver; use crate::arch::riscv64::mm::{paging, PhysAddr}; #[cfg(feature = "gem-net")] use crate::drivers::net::gem; -#[cfg(all(feature = "tcp", not(feature = "pci")))] -use crate::drivers::virtio::transport::mmio::DevId; #[cfg(all(feature = "tcp", not(feature = "pci"), not(feature = "gem-net")))] use crate::drivers::virtio::transport::mmio::{self as mmio_virtio, VirtioDriver}; #[cfg(all(feature = "tcp", not(feature = "pci")))] @@ -209,9 +207,9 @@ pub fn init_drivers() { trace!("Found a MMIO-device at {mmio:p}"); // Verify the device-ID to find the network card - let id = DevId::from(mmio.as_ptr().device_id().read().to_ne()); + let id = mmio.as_ptr().device_id().read(); - if id != DevId::VIRTIO_DEV_ID_NET { + if id != virtio_spec::Id::Net { debug!("It's not a network card at {mmio:p}"); } else { info!("Found network card at {mmio:p}"); diff --git a/src/arch/x86_64/kernel/mmio.rs b/src/arch/x86_64/kernel/mmio.rs index 95329b6177..a738ee7b61 100644 --- a/src/arch/x86_64/kernel/mmio.rs +++ b/src/arch/x86_64/kernel/mmio.rs @@ -14,7 +14,7 @@ use crate::arch::x86_64::mm::paging::{ use crate::arch::x86_64::mm::{paging, PhysAddr}; use crate::drivers::net::virtio_net::VirtioNetDriver; use crate::drivers::virtio::transport::mmio as mmio_virtio; -use crate::drivers::virtio::transport::mmio::{DevId, VirtioDriver}; +use crate::drivers::virtio::transport::mmio::VirtioDriver; use crate::env; pub const MAGIC_VALUE: u32 = 0x74726976; @@ -60,9 +60,9 @@ unsafe fn check_ptr(ptr: *mut u8) -> Option -// implementation, in order catch all cases correctly, -// as this function uses the catch-all "_" case! -#[allow(non_camel_case_types, clippy::upper_case_acronyms)] -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] -#[repr(u32)] -pub enum DevId { - INVALID = 0x0, - VIRTIO_DEV_ID_NET = 1, - VIRTIO_DEV_ID_BLK = 2, - VIRTIO_DEV_ID_CONSOLE = 3, -} - -impl From for u32 { - fn from(val: DevId) -> u32 { - match val { - DevId::VIRTIO_DEV_ID_NET => 1, - DevId::VIRTIO_DEV_ID_BLK => 2, - DevId::VIRTIO_DEV_ID_CONSOLE => 3, - DevId::INVALID => 0x0, - } - } -} - -impl From for DevId { - fn from(val: u32) -> Self { - match val { - 1 => DevId::VIRTIO_DEV_ID_NET, - 2 => DevId::VIRTIO_DEV_ID_BLK, - 3 => DevId::VIRTIO_DEV_ID_CONSOLE, - _ => DevId::INVALID, - } - } -} - pub struct VqCfgHandler<'a> { vq_index: u16, raw: VolatileRef<'a, DeviceRegisters>, @@ -442,9 +403,9 @@ pub(crate) fn init_device( } // Verify the device-ID to find the network card - match registers.as_ptr().device_id().read().to_ne().into() { + match registers.as_ptr().device_id().read() { #[cfg(any(feature = "tcp", feature = "udp"))] - DevId::VIRTIO_DEV_ID_NET => { + virtio_spec::Id::Net => { match VirtioNetDriver::init(dev_id, registers, irq_no) { Ok(virt_net_drv) => { info!("Virtio network driver initialized."); diff --git a/virtio-spec/src/mmio.rs b/virtio-spec/src/mmio.rs index f627de90d9..bd7b1b4181 100644 --- a/virtio-spec/src/mmio.rs +++ b/virtio-spec/src/mmio.rs @@ -7,7 +7,7 @@ use volatile::access::{ReadOnly, ReadWrite, RestrictAccess, WriteOnly}; use volatile::VolatilePtr; use crate::volatile::{OveralignedVolatilePtr, WideVolatilePtr}; -use crate::DeviceStatus; +use crate::{DeviceStatus, Id}; /// MMIO Device Registers #[repr(transparent)] @@ -144,7 +144,7 @@ device_register_impl! { #[doc(alias = "DeviceID")] #[offset(0x008)] #[access(ReadOnly)] - device_id: le32, + device_id: Id, /// Virtio Subsystem Vendor ID #[doc(alias = "VendorID")] From 3efffa31be223822e25ef3e83721590cf6809957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sun, 2 Jun 2024 17:30:27 +0200 Subject: [PATCH 3/3] refactor(virtio/pci): migrate `DevId` to `virtio-spec` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/transport/pci.rs | 99 ++++++----------------------- 1 file changed, 18 insertions(+), 81 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index 0417f0e306..4f1a660d4a 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -32,63 +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 device ID's -/// See Virtio specification v1.1. - 5 -/// and v1.1. - 4.1.2.1 -/// -// WARN: Upon changes in the set of the enum variants -// one MUST adjust the associated From -// 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)] -#[repr(u16)] -pub enum DevId { - INVALID = 0x0, - VIRTIO_TRANS_DEV_ID_NET = 0x1000, - VIRTIO_TRANS_DEV_ID_BLK = 0x1001, - VIRTIO_TRANS_DEV_ID_MEM_BALL = 0x1002, - VIRTIO_TRANS_DEV_ID_CONS = 0x1003, - VIRTIO_TRANS_DEV_ID_SCSI = 0x1004, - VIRTIO_TRANS_DEV_ID_ENTROPY = 0x1005, - VIRTIO_TRANS_DEV_ID_9P = 0x1009, - VIRTIO_DEV_ID_NET = 0x1041, - VIRTIO_DEV_ID_FS = 0x105A, -} - -impl From for u16 { - fn from(val: DevId) -> u16 { - match val { - DevId::VIRTIO_TRANS_DEV_ID_NET => 0x1000, - DevId::VIRTIO_TRANS_DEV_ID_BLK => 0x1001, - DevId::VIRTIO_TRANS_DEV_ID_MEM_BALL => 0x1002, - DevId::VIRTIO_TRANS_DEV_ID_CONS => 0x1003, - DevId::VIRTIO_TRANS_DEV_ID_SCSI => 0x1004, - DevId::VIRTIO_TRANS_DEV_ID_ENTROPY => 0x1005, - DevId::VIRTIO_TRANS_DEV_ID_9P => 0x1009, - DevId::VIRTIO_DEV_ID_NET => 0x1041, - DevId::VIRTIO_DEV_ID_FS => 0x105A, - DevId::INVALID => 0x0, - } - } -} - -impl From for DevId { - fn from(val: u16) -> Self { - match val { - 0x1000 => DevId::VIRTIO_TRANS_DEV_ID_NET, - 0x1001 => DevId::VIRTIO_TRANS_DEV_ID_BLK, - 0x1002 => DevId::VIRTIO_TRANS_DEV_ID_MEM_BALL, - 0x1003 => DevId::VIRTIO_TRANS_DEV_ID_CONS, - 0x1004 => DevId::VIRTIO_TRANS_DEV_ID_SCSI, - 0x1005 => DevId::VIRTIO_TRANS_DEV_ID_ENTROPY, - 0x1009 => DevId::VIRTIO_TRANS_DEV_ID_9P, - 0x1041 => DevId::VIRTIO_DEV_ID_NET, - 0x105A => DevId::VIRTIO_DEV_ID_FS, - _ => DevId::INVALID, - } - } -} - /// Virtio's cfg_type constants; indicating type of structure in capabilities list /// See Virtio specification v1.1 - 4.1.4 // @@ -1260,26 +1203,23 @@ pub(crate) fn init_device( ) -> Result { let device_id = device.device_id(); - let virt_drv = match DevId::from(device_id) { - DevId::VIRTIO_TRANS_DEV_ID_NET - | DevId::VIRTIO_TRANS_DEV_ID_BLK - | DevId::VIRTIO_TRANS_DEV_ID_MEM_BALL - | DevId::VIRTIO_TRANS_DEV_ID_CONS - | DevId::VIRTIO_TRANS_DEV_ID_SCSI - | DevId::VIRTIO_TRANS_DEV_ID_ENTROPY - | DevId::VIRTIO_TRANS_DEV_ID_9P => { - warn!( - "Legacy/transitional Virtio device, with id: {:#x} is NOT supported, skipping!", - device_id - ); + if device_id < 0x1040 { + warn!( + "Legacy/transitional Virtio device, with id: {:#x} is NOT supported, skipping!", + device_id + ); - // Return Driver error inidacting device is not supported - Err(DriverError::InitVirtioDevFail( - VirtioError::DevNotSupported(device_id), - )) - } + // Return Driver error inidacting device is not supported + return Err(DriverError::InitVirtioDevFail( + VirtioError::DevNotSupported(device_id), + )); + } + + let id = virtio_spec::Id::from(u8::try_from(device_id - 0x1040).unwrap()); + + let virt_drv = match id { #[cfg(all(not(feature = "rtl8139"), any(feature = "tcp", feature = "udp")))] - DevId::VIRTIO_DEV_ID_NET => match VirtioNetDriver::init(device) { + virtio_spec::Id::Net => match VirtioNetDriver::init(device) { Ok(virt_net_drv) => { info!("Virtio network driver initialized."); Ok(VirtioDriver::Network(virt_net_drv)) @@ -1293,7 +1233,7 @@ pub(crate) fn init_device( } }, #[cfg(feature = "fuse")] - DevId::VIRTIO_DEV_ID_FS => { + virtio_spec::Id::Fs => { // TODO: check subclass // TODO: proper error handling on driver creation fail match VirtioFsDriver::init(device) { @@ -1310,11 +1250,8 @@ pub(crate) fn init_device( } } } - _ => { - warn!( - "Virtio device with id: {:#x} is NOT supported, skipping!", - device_id - ); + id => { + warn!("Virtio device {id:?} is not supported, skipping!"); // Return Driver error inidacting device is not supported Err(DriverError::InitVirtioDevFail(