diff --git a/src/arch/aarch64/kernel/mmio.rs b/src/arch/aarch64/kernel/mmio.rs index 153bde370f..5be786d6f7 100644 --- a/src/arch/aarch64/kernel/mmio.rs +++ b/src/arch/aarch64/kernel/mmio.rs @@ -32,7 +32,7 @@ use crate::drivers::virtio::transport::mmio as mmio_virtio; feature = "virtio-net", feature = "virtio-vsock", ))] -use crate::drivers::virtio::transport::mmio::VirtioDriver; +use crate::drivers::virtio::transport::mmio::{Transport, VirtioDriver}; #[cfg(feature = "virtio-vsock")] use crate::drivers::vsock::VirtioVsockDriver; #[cfg(feature = "virtio-net")] @@ -45,16 +45,16 @@ pub(crate) static MMIO_DRIVERS: InitCell> = InitCell::new(Vec::n #[allow(clippy::enum_variant_names)] pub(crate) enum MmioDriver { #[cfg(feature = "virtio-console")] - VirtioConsole(InterruptTicketMutex), + VirtioConsole(InterruptTicketMutex>), #[cfg(feature = "virtio-fs")] - VirtioFs(InterruptTicketMutex), + VirtioFs(InterruptTicketMutex>), #[cfg(feature = "virtio-vsock")] - VirtioVsock(InterruptTicketMutex), + VirtioVsock(InterruptTicketMutex>), } impl MmioDriver { #[cfg(feature = "virtio-console")] - fn get_console_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_console_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioConsole(drv) => Some(drv), @@ -63,7 +63,7 @@ impl MmioDriver { } #[cfg(feature = "virtio-fs")] - fn get_filesystem_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_filesystem_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioFs(drv) => Some(drv), @@ -72,7 +72,7 @@ impl MmioDriver { } #[cfg(feature = "virtio-vsock")] - fn get_vsock_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_vsock_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioVsock(drv) => Some(drv), @@ -81,16 +81,21 @@ impl MmioDriver { } } -#[cfg(any(feature = "virtio-console", feature = "virtio-fs", feature = "virtio-vsock"))] +#[cfg(any( + feature = "virtio-console", + feature = "virtio-fs", + feature = "virtio-vsock" +))] pub(crate) fn register_driver(drv: MmioDriver) { MMIO_DRIVERS.with(|mmio_drivers| mmio_drivers.unwrap().push(drv)); } #[cfg(feature = "virtio-net")] -pub(crate) type NetworkDevice = VirtioNetDriver; +pub(crate) type NetworkDevice = VirtioNetDriver; #[cfg(feature = "virtio-console")] -pub(crate) fn get_console_driver() -> Option<&'static InterruptTicketMutex> { +pub(crate) fn get_console_driver() +-> Option<&'static InterruptTicketMutex>> { MMIO_DRIVERS .get()? .iter() @@ -98,7 +103,8 @@ pub(crate) fn get_console_driver() -> Option<&'static InterruptTicketMutex Option<&'static InterruptTicketMutex> { +pub(crate) fn get_filesystem_driver() +-> Option<&'static InterruptTicketMutex>> { MMIO_DRIVERS .get()? .iter() @@ -106,7 +112,8 @@ pub(crate) fn get_filesystem_driver() -> Option<&'static InterruptTicketMutex Option<&'static InterruptTicketMutex> { +pub(crate) fn get_vsock_driver() +-> Option<&'static InterruptTicketMutex>> { MMIO_DRIVERS .get()? .iter() @@ -209,15 +216,19 @@ pub fn init_drivers() { } else { panic!("Invalid interrupt type"); }; - gic.set_interrupt_priority(virtio_irqid, Some(cpu_id), 0x00).unwrap(); + gic.set_interrupt_priority(virtio_irqid, Some(cpu_id), 0x00) + .unwrap(); if (irqflags & 0xf) == 4 || (irqflags & 0xf) == 8 { - gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Level).unwrap(); + gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Level) + .unwrap(); } else if (irqflags & 0xf) == 2 || (irqflags & 0xf) == 1 { - gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Edge).unwrap(); + gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Edge) + .unwrap(); } else { panic!("Invalid interrupt level!"); } - gic.enable_interrupt(virtio_irqid, Some(cpu_id), true).unwrap(); + gic.enable_interrupt(virtio_irqid, Some(cpu_id), true) + .unwrap(); match drv { #[cfg(feature = "virtio-console")] @@ -225,9 +236,9 @@ pub fn init_drivers() { InterruptTicketMutex::new(*drv), )), #[cfg(feature = "virtio-fs")] - VirtioDriver::Fs(drv) => register_driver(MmioDriver::VirtioFs( - InterruptTicketMutex::new(*drv), - )), + VirtioDriver::Fs(drv) => { + register_driver(MmioDriver::VirtioFs(InterruptTicketMutex::new(*drv))) + } #[cfg(feature = "virtio-net")] VirtioDriver::Net(drv) => *NETWORK_DEVICE.lock() = Some(*drv), #[cfg(feature = "virtio-vsock")] diff --git a/src/arch/riscv64/kernel/mmio.rs b/src/arch/riscv64/kernel/mmio.rs index 67928a388e..cb1d376cb9 100644 --- a/src/arch/riscv64/kernel/mmio.rs +++ b/src/arch/riscv64/kernel/mmio.rs @@ -15,6 +15,8 @@ use crate::drivers::fs::VirtioFsDriver; use crate::drivers::net::gem::GEMDriver; #[cfg(all(not(feature = "gem-net"), feature = "virtio-net"))] use crate::drivers::net::virtio::VirtioNetDriver; +#[cfg(feature = "virtio")] +use crate::drivers::virtio::transport::mmio::Transport; #[cfg(feature = "virtio-vsock")] use crate::drivers::vsock::VirtioVsockDriver; use crate::init_cell::InitCell; @@ -24,16 +26,16 @@ pub(crate) static MMIO_DRIVERS: InitCell> = InitCell::new(Vec::n #[allow(clippy::enum_variant_names)] pub(crate) enum MmioDriver { #[cfg(feature = "virtio-console")] - VirtioConsole(InterruptSpinMutex), + VirtioConsole(InterruptSpinMutex>), #[cfg(feature = "virtio-fs")] - VirtioFs(InterruptSpinMutex), + VirtioFs(InterruptSpinMutex>), #[cfg(feature = "virtio-vsock")] - VirtioVsock(InterruptSpinMutex), + VirtioVsock(InterruptSpinMutex>), } impl MmioDriver { #[cfg(feature = "virtio-console")] - fn get_console_driver(&self) -> Option<&InterruptSpinMutex> { + fn get_console_driver(&self) -> Option<&InterruptSpinMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioConsole(drv) => Some(drv), @@ -42,7 +44,7 @@ impl MmioDriver { } #[cfg(feature = "virtio-fs")] - fn get_filesystem_driver(&self) -> Option<&InterruptSpinMutex> { + fn get_filesystem_driver(&self) -> Option<&InterruptSpinMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioFs(drv) => Some(drv), @@ -51,7 +53,7 @@ impl MmioDriver { } #[cfg(feature = "virtio-vsock")] - fn get_vsock_driver(&self) -> Option<&InterruptSpinMutex> { + fn get_vsock_driver(&self) -> Option<&InterruptSpinMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioVsock(drv) => Some(drv), @@ -73,10 +75,11 @@ pub(crate) fn register_driver(drv: MmioDriver) { pub(crate) type NetworkDevice = GEMDriver; #[cfg(all(not(feature = "gem-net"), feature = "virtio-net"))] -pub(crate) type NetworkDevice = VirtioNetDriver; +pub(crate) type NetworkDevice = VirtioNetDriver; #[cfg(feature = "virtio-console")] -pub(crate) fn get_console_driver() -> Option<&'static InterruptSpinMutex> { +pub(crate) fn get_console_driver() +-> Option<&'static InterruptSpinMutex>> { MMIO_DRIVERS .get()? .iter() @@ -84,7 +87,8 @@ pub(crate) fn get_console_driver() -> Option<&'static InterruptSpinMutex Option<&'static InterruptSpinMutex> { +pub(crate) fn get_filesystem_driver() +-> Option<&'static InterruptSpinMutex>> { MMIO_DRIVERS .get()? .iter() @@ -92,7 +96,8 @@ pub(crate) fn get_filesystem_driver() -> Option<&'static InterruptSpinMutex Option<&'static InterruptSpinMutex> { +pub(crate) fn get_vsock_driver() -> Option<&'static InterruptSpinMutex>> +{ MMIO_DRIVERS .get()? .iter() diff --git a/src/arch/x86_64/kernel/mmio.rs b/src/arch/x86_64/kernel/mmio.rs index db17b31098..4a6ae80849 100644 --- a/src/arch/x86_64/kernel/mmio.rs +++ b/src/arch/x86_64/kernel/mmio.rs @@ -33,7 +33,7 @@ use crate::drivers::virtio::transport::mmio as mmio_virtio; feature = "virtio-net", feature = "virtio-vsock", ))] -use crate::drivers::virtio::transport::mmio::VirtioDriver; +use crate::drivers::virtio::transport::mmio::{Transport, VirtioDriver}; #[cfg(feature = "virtio-vsock")] use crate::drivers::vsock::VirtioVsockDriver; use crate::env; @@ -49,16 +49,16 @@ static MMIO_DRIVERS: InitCell> = InitCell::new(Vec::new()); #[allow(clippy::enum_variant_names)] pub(crate) enum MmioDriver { #[cfg(feature = "virtio-console")] - VirtioConsole(InterruptTicketMutex), + VirtioConsole(InterruptTicketMutex>), #[cfg(feature = "virtio-fs")] - VirtioFs(InterruptTicketMutex), + VirtioFs(InterruptTicketMutex>), #[cfg(feature = "virtio-vsock")] - VirtioVsock(InterruptTicketMutex), + VirtioVsock(InterruptTicketMutex>), } impl MmioDriver { #[cfg(feature = "virtio-console")] - fn get_console_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_console_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioConsole(drv) => Some(drv), @@ -67,7 +67,7 @@ impl MmioDriver { } #[cfg(feature = "virtio-fs")] - fn get_filesystem_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_filesystem_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioFs(drv) => Some(drv), @@ -76,7 +76,7 @@ impl MmioDriver { } #[cfg(feature = "virtio-vsock")] - fn get_vsock_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_vsock_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioVsock(drv) => Some(drv), @@ -191,10 +191,11 @@ pub(crate) fn register_driver(drv: MmioDriver) { } #[cfg(feature = "virtio-net")] -pub(crate) type NetworkDevice = VirtioNetDriver; +pub(crate) type NetworkDevice = VirtioNetDriver; #[cfg(feature = "virtio-console")] -pub(crate) fn get_console_driver() -> Option<&'static InterruptTicketMutex> { +pub(crate) fn get_console_driver() +-> Option<&'static InterruptTicketMutex>> { MMIO_DRIVERS .get()? .iter() @@ -202,7 +203,8 @@ pub(crate) fn get_console_driver() -> Option<&'static InterruptTicketMutex Option<&'static InterruptTicketMutex> { +pub(crate) fn get_filesystem_driver() +-> Option<&'static InterruptTicketMutex>> { MMIO_DRIVERS .get()? .iter() @@ -210,7 +212,8 @@ pub(crate) fn get_filesystem_driver() -> Option<&'static InterruptTicketMutex Option<&'static InterruptTicketMutex> { +pub(crate) fn get_vsock_driver() +-> Option<&'static InterruptTicketMutex>> { MMIO_DRIVERS .get()? .iter() diff --git a/src/drivers/console/mmio.rs b/src/drivers/console/mmio.rs index 7bef82ea95..4ad5abc6b0 100644 --- a/src/drivers/console/mmio.rs +++ b/src/drivers/console/mmio.rs @@ -5,15 +5,15 @@ use volatile::VolatileRef; use crate::drivers::InterruptLine; use crate::drivers::console::{ConsoleDevCfg, RxQueue, TxQueue, VirtioConsoleDriver}; use crate::drivers::virtio::error::VirtioError; -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg, Transport}; // Backend-dependent interface for Virtio console driver -impl VirtioConsoleDriver { +impl VirtioConsoleDriver { pub fn new( dev_id: u16, mut registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, - ) -> Result { + ) -> Result { let dev_cfg_raw: &'static Config = unsafe { &*registers .borrow_mut() @@ -32,7 +32,7 @@ impl VirtioConsoleDriver { let isr_stat = IsrStatus::new(registers.borrow_mut()); let notif_cfg = NotifCfg::new(registers.borrow_mut()); - Ok(VirtioConsoleDriver { + Ok(Self { dev_cfg, com_cfg: ComCfg::new(registers), isr_stat, @@ -52,7 +52,7 @@ impl VirtioConsoleDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, - ) -> Result { + ) -> Result { let mut drv = VirtioConsoleDriver::new(dev_id, registers, irq)?; drv.init_dev().map_err(VirtioError::ConsoleDriver)?; drv.com_cfg.print_information(); diff --git a/src/drivers/console/mod.rs b/src/drivers/console/mod.rs index 01b0f731e5..94d882fa7d 100644 --- a/src/drivers/console/mod.rs +++ b/src/drivers/console/mod.rs @@ -32,10 +32,7 @@ use crate::drivers::mmio::get_console_driver; use crate::drivers::pci::get_console_driver; use crate::drivers::virtio::ControlRegisters; use crate::drivers::virtio::error::VirtioConsoleError; -#[cfg(not(feature = "pci"))] -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; -#[cfg(feature = "pci")] -use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::{ComCfg, IsrStatus, Transport}; use crate::drivers::virtio::virtqueue::split::SplitVq; use crate::drivers::virtio::virtqueue::{ AvailBufferToken, BufferElem, BufferType, UsedBufferToken, VirtQueue, Virtq, @@ -44,7 +41,7 @@ use crate::drivers::{Driver, InterruptLine}; use crate::errno::Errno; use crate::mm::device_alloc::DeviceAlloc; -fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) { +fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) { for _ in 0..num_packets { let buff_tkn = match AvailBufferToken::new(SmallVec::new(), { let mut vec = SmallVec::new(); @@ -114,12 +111,12 @@ impl Write for VirtioUART { } } -pub(crate) struct RxQueue { - vq: Option, +pub(crate) struct RxQueue { + vq: Option>, packet_size: u32, } -impl RxQueue { +impl RxQueue { pub fn new() -> Self { Self { vq: None, @@ -128,7 +125,7 @@ impl RxQueue { } } - pub fn add(&mut self, mut vq: VirtQueue) { + pub fn add(&mut self, mut vq: VirtQueue) { const BUFF_PER_PACKET: u16 = 2; let num_packets = vq.size() / BUFF_PER_PACKET; fill_queue(&mut vq, num_packets, self.packet_size); @@ -178,14 +175,14 @@ impl RxQueue { } } -pub(crate) struct TxQueue { - vq: Option, +pub(crate) struct TxQueue { + vq: Option>, /// Indicates, whether the Driver/Device are using multiple /// queues for communication. packet_length: u32, } -impl TxQueue { +impl TxQueue { pub fn new() -> Self { Self { vq: None, @@ -193,7 +190,7 @@ impl TxQueue { } } - pub fn add(&mut self, vq: VirtQueue) { + pub fn add(&mut self, vq: VirtQueue) { self.vq = Some(vq); } @@ -257,18 +254,18 @@ pub(crate) struct ConsoleDevCfg { pub features: virtio::console::F, } -pub(crate) struct VirtioConsoleDriver { +pub(crate) struct VirtioConsoleDriver { pub(super) dev_cfg: ConsoleDevCfg, - pub(super) com_cfg: ComCfg, - pub(super) isr_stat: IsrStatus, - pub(super) notif_cfg: NotifCfg, + pub(super) com_cfg: T::ComCfg, + pub(super) isr_stat: T::IsrStatus, + pub(super) notif_cfg: T::NotifCfg, pub(super) irq: InterruptLine, - pub(super) recv_vq: RxQueue, - pub(super) send_vq: TxQueue, + pub(super) recv_vq: RxQueue, + pub(super) send_vq: TxQueue, } -impl Driver for VirtioConsoleDriver { +impl Driver for VirtioConsoleDriver { fn get_interrupt_number(&self) -> InterruptLine { self.irq } @@ -278,7 +275,7 @@ impl Driver for VirtioConsoleDriver { } } -impl VirtioConsoleDriver { +impl VirtioConsoleDriver { pub fn has_packet(&self) -> bool { self.recv_vq.has_packet() } @@ -287,14 +284,9 @@ impl VirtioConsoleDriver { pub fn handle_interrupt(&mut self) { let status = self.isr_stat.acknowledge(); - #[cfg(not(feature = "pci"))] - if status.contains(virtio::mmio::InterruptStatus::CONFIGURATION_CHANGE_NOTIFICATION) { - info!("Configuration changes are not possible! Aborting"); - todo!("Implement possibility to change config on the fly...") - } - - #[cfg(feature = "pci")] - if status.contains(virtio::pci::IsrStatus::DEVICE_CONFIGURATION_INTERRUPT) { + if status & ::CONFIGURATION_CHANGE + == ::CONFIGURATION_CHANGE + { info!("Configuration changes are not possible! Aborting"); todo!("Implement possibility to change config on the fly...") } @@ -379,11 +371,11 @@ impl VirtioConsoleDriver { } } -impl ErrorType for VirtioConsoleDriver { +impl ErrorType for VirtioConsoleDriver { type Error = Errno; } -impl Read for VirtioConsoleDriver { +impl Read for VirtioConsoleDriver { fn read(&mut self, buf: &mut [u8]) -> Result { self.recv_vq .process_packet(|src| { @@ -394,7 +386,7 @@ impl Read for VirtioConsoleDriver { } } -impl Write for VirtioConsoleDriver { +impl Write for VirtioConsoleDriver { fn write(&mut self, buf: &[u8]) -> Result { self.send_vq.send_packet(buf); diff --git a/src/drivers/console/pci.rs b/src/drivers/console/pci.rs index c0422d77b3..9e8d37a478 100644 --- a/src/drivers/console/pci.rs +++ b/src/drivers/console/pci.rs @@ -5,11 +5,11 @@ use volatile::VolatileRef; use crate::drivers::console::{ConsoleDevCfg, RxQueue, TxQueue, VirtioConsoleDriver}; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; -use crate::drivers::virtio::transport::pci::{self, PciCap, UniCapsColl}; +use crate::drivers::virtio::transport::pci::{self, PciCap, Transport, UniCapsColl}; use crate::pci::PciConfigRegion; // Backend-dependent interface for Virtio console driver -impl VirtioConsoleDriver { +impl VirtioConsoleDriver { fn map_cfg(cap: &PciCap) -> Option { let dev_cfg = pci::map_dev_cfg::(cap)?; let dev_cfg = VolatileRef::from_ref(dev_cfg); @@ -56,9 +56,7 @@ impl VirtioConsoleDriver { /// Initializes virtio console device /// /// Returns a driver instance of VirtioConsoleDriver. - pub(crate) fn init( - device: &PciDevice, - ) -> Result { + pub(crate) fn init(device: &PciDevice) -> Result { // enable bus master mode device.set_command(CommandRegister::BUS_MASTER_ENABLE); diff --git a/src/drivers/fs/mmio.rs b/src/drivers/fs/mmio.rs index 3ae8b2db2a..d6941d9165 100644 --- a/src/drivers/fs/mmio.rs +++ b/src/drivers/fs/mmio.rs @@ -7,15 +7,15 @@ use volatile::VolatileRef; use crate::drivers::InterruptLine; use crate::drivers::fs::{FsDevCfg, VirtioFsDriver}; use crate::drivers::virtio::error::VirtioError; -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg, Transport}; // Backend-dependent interface for Virtio fs driver -impl VirtioFsDriver { +impl VirtioFsDriver { pub fn new( dev_id: u16, mut registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, - ) -> Result { + ) -> Result { let dev_cfg_raw: &'static Config = unsafe { &*registers .borrow_mut() @@ -53,7 +53,7 @@ impl VirtioFsDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, - ) -> Result { + ) -> Result { let mut drv = VirtioFsDriver::new(dev_id, registers, irq)?; drv.init_dev().map_err(VirtioError::FsDriver)?; drv.com_cfg.print_information(); diff --git a/src/drivers/fs/mod.rs b/src/drivers/fs/mod.rs index cebad3e144..a8dd02a786 100644 --- a/src/drivers/fs/mod.rs +++ b/src/drivers/fs/mod.rs @@ -33,10 +33,7 @@ use crate::config::VIRTIO_MAX_QUEUE_SIZE; use crate::drivers::Driver; use crate::drivers::virtio::ControlRegisters; use crate::drivers::virtio::error::VirtioFsInitError; -#[cfg(not(feature = "pci"))] -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; -#[cfg(feature = "pci")] -use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::{ComCfg, IsrStatus, Transport}; use crate::drivers::virtio::virtqueue::error::VirtqError; use crate::drivers::virtio::virtqueue::split::SplitVq; use crate::drivers::virtio::virtqueue::{ @@ -60,17 +57,17 @@ pub(crate) struct FsDevCfg { /// Struct allows to control devices virtqueues as also /// the device itself. #[allow(dead_code)] -pub(crate) struct VirtioFsDriver { +pub(crate) struct VirtioFsDriver { pub(super) dev_cfg: FsDevCfg, - pub(super) com_cfg: ComCfg, - pub(super) isr_stat: IsrStatus, - pub(super) notif_cfg: NotifCfg, - pub(super) vqueues: Vec, + pub(super) com_cfg: T::ComCfg, + pub(super) isr_stat: T::IsrStatus, + pub(super) notif_cfg: T::NotifCfg, + pub(super) vqueues: Vec>, pub(super) irq: InterruptLine, } // Backend-independent interface for Virtio network driver -impl VirtioFsDriver { +impl VirtioFsDriver { #[cfg(feature = "pci")] pub fn get_dev_id(&self) -> u16 { self.dev_cfg.dev_id @@ -161,21 +158,16 @@ impl VirtioFsDriver { pub fn handle_interrupt(&mut self) { let status = self.isr_stat.acknowledge(); - #[cfg(not(feature = "pci"))] - if status.contains(virtio::mmio::InterruptStatus::CONFIGURATION_CHANGE_NOTIFICATION) { - info!("Configuration changes are not possible! Aborting"); - todo!("Implement possibility to change config on the fly...") - } - - #[cfg(feature = "pci")] - if status.contains(virtio::pci::IsrStatus::DEVICE_CONFIGURATION_INTERRUPT) { + if status & ::CONFIGURATION_CHANGE + == ::CONFIGURATION_CHANGE + { info!("Configuration changes are not possible! Aborting"); todo!("Implement possibility to change config on the fly...") } } } -impl VirtioFsInterface for VirtioFsDriver { +impl VirtioFsInterface for VirtioFsDriver { fn send_command( &mut self, cmd: virtio_fs::Cmd, @@ -262,7 +254,7 @@ impl VirtioFsInterface for VirtioFsDriver { } } -impl Driver for VirtioFsDriver { +impl Driver for VirtioFsDriver { fn get_interrupt_number(&self) -> InterruptLine { self.irq } diff --git a/src/drivers/fs/pci.rs b/src/drivers/fs/pci.rs index 63843609c2..d08c26fa28 100644 --- a/src/drivers/fs/pci.rs +++ b/src/drivers/fs/pci.rs @@ -7,9 +7,9 @@ use crate::drivers::fs::{FsDevCfg, VirtioFsDriver}; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; use crate::drivers::virtio::transport::pci; -use crate::drivers::virtio::transport::pci::{PciCap, UniCapsColl}; +use crate::drivers::virtio::transport::pci::{PciCap, Transport, UniCapsColl}; -impl VirtioFsDriver { +impl VirtioFsDriver { fn map_cfg(cap: &PciCap) -> Option { let dev_cfg = pci::map_dev_cfg::(cap)?; @@ -54,7 +54,9 @@ impl VirtioFsDriver { } /// Initializes virtio filesystem device - pub fn init(device: &PciDevice) -> Result { + pub fn init( + device: &PciDevice, + ) -> Result, VirtioError> { let mut drv = match pci::map_caps(device) { Ok(caps) => match VirtioFsDriver::new(caps, device) { Ok(driver) => driver, diff --git a/src/drivers/net/virtio/mmio.rs b/src/drivers/net/virtio/mmio.rs index ea21245e3c..b945a882ab 100644 --- a/src/drivers/net/virtio/mmio.rs +++ b/src/drivers/net/virtio/mmio.rs @@ -3,12 +3,12 @@ use virtio::mmio::{DeviceRegisters, DeviceRegistersVolatileFieldAccess}; use volatile::VolatileRef; use crate::drivers::InterruptLine; -use crate::drivers::net::virtio::{Init, NetDevCfg, Uninit, VirtioNetDriver}; +use crate::drivers::net::virtio::{NetDevCfg, Uninit, VirtioNetDriver}; use crate::drivers::virtio::error::VirtioError; -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg, Transport}; // Backend-dependent interface for Virtio network driver -impl VirtioNetDriver { +impl VirtioNetDriver { pub fn new( dev_id: u16, mut registers: VolatileRef<'static, DeviceRegisters>, @@ -53,7 +53,7 @@ impl VirtioNetDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, - ) -> Result, VirtioError> { + ) -> Result, VirtioError> { let drv = VirtioNetDriver::new(dev_id, registers, irq)?; let mut drv = drv.init_dev().map_err(VirtioError::NetDriver)?; drv.print_information(); @@ -61,7 +61,7 @@ impl VirtioNetDriver { } } -impl VirtioNetDriver { +impl VirtioNetDriver { pub fn print_information(&mut self) { self.com_cfg.print_information(); if self.dev_status() == virtio::net::S::LINK_UP { diff --git a/src/drivers/net/virtio/mod.rs b/src/drivers/net/virtio/mod.rs index 03fc66b399..899d0797b4 100644 --- a/src/drivers/net/virtio/mod.rs +++ b/src/drivers/net/virtio/mod.rs @@ -37,10 +37,7 @@ use crate::config::VIRTIO_MAX_QUEUE_SIZE; use crate::drivers::net::virtio::constants::BUFF_PER_PACKET; use crate::drivers::net::{NetworkDriver, mtu}; use crate::drivers::virtio::ControlRegisters; -#[cfg(not(feature = "pci"))] -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; -#[cfg(feature = "pci")] -use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::{ComCfg, IsrStatus, Transport}; use crate::drivers::virtio::virtqueue::packed::PackedVq; use crate::drivers::virtio::virtqueue::split::SplitVq; use crate::drivers::virtio::virtqueue::{ @@ -103,13 +100,13 @@ fn determine_rx_buf_size(dev_cfg: &NetDevCfg) -> u32 { min_buf_size } -pub struct RxQueues { - vqs: Vec, +pub struct RxQueues { + vqs: Vec>, buf_size: u32, } -impl RxQueues { - pub fn new(vqs: Vec, dev_cfg: &NetDevCfg) -> Self { +impl RxQueues { + pub fn new(vqs: Vec>, dev_cfg: &NetDevCfg) -> Self { Self { vqs, buf_size: determine_rx_buf_size(dev_cfg), @@ -119,7 +116,7 @@ impl RxQueues { /// Adds a given queue to the underlying vector and populates the queue with RecvBuffers. /// /// Queues are all populated according to Virtio specification v1.1. - 5.1.6.3.1 - fn add(&mut self, mut vq: VirtQueue) { + fn add(&mut self, mut vq: VirtQueue) { let num_bufs = vq.size() / BUFF_PER_PACKET; fill_queue(&mut vq, num_bufs, self.buf_size); self.vqs.push(vq); @@ -162,7 +159,7 @@ fn buffer_token_from_hdr( .unwrap() } -fn fill_queue(vq: &mut VirtQueue, num_bufs: u16, buf_size: u32) { +fn fill_queue(vq: &mut VirtQueue, num_bufs: u16, buf_size: u32) { for _ in 0..num_bufs { let buff_tkn = buffer_token_from_hdr(Box::::new_uninit_in(DeviceAlloc), buf_size); @@ -178,13 +175,13 @@ fn fill_queue(vq: &mut VirtQueue, num_bufs: u16, buf_size: u32) { /// Structure which handles transmission of packets and delegation /// to the respective queue structures. -pub struct TxQueues { - vqs: Vec, +pub struct TxQueues { + vqs: Vec>, buf_size: u32, } -impl TxQueues { - pub fn new(vqs: Vec, dev_cfg: &NetDevCfg) -> Self { +impl TxQueues { + pub fn new(vqs: Vec>, dev_cfg: &NetDevCfg) -> Self { Self { vqs, buf_size: determine_mtu(dev_cfg).into(), @@ -218,7 +215,7 @@ impl TxQueues { released_buffers } - fn add(&mut self, vq: VirtQueue) { + fn add(&mut self, vq: VirtQueue) { // Currently we are doing nothing with the additional queues. They are inactive and might be used in the // future self.vqs.push(vq); @@ -226,11 +223,11 @@ impl TxQueues { } pub(crate) struct Uninit; -pub(crate) struct Init { +pub(crate) struct Init { pub(super) mtu: u16, - pub(super) ctrl_vq: Option, - pub(super) recv_vqs: RxQueues, - pub(super) send_vqs: TxQueues, + pub(super) ctrl_vq: Option>, + pub(super) recv_vqs: RxQueues, + pub(super) send_vqs: TxQueues, /// Capacity in number of buffer descriptors, not frames. pub(super) send_capacity: u32, } @@ -239,11 +236,11 @@ pub(crate) struct Init { /// /// Struct allows to control devices virtqueues as also /// the device itself. -pub(crate) struct VirtioNetDriver { +pub(crate) struct VirtioNetDriver> { pub(super) dev_cfg: NetDevCfg, - pub(super) com_cfg: ComCfg, - pub(super) isr_stat: IsrStatus, - pub(super) notif_cfg: NotifCfg, + pub(super) com_cfg: Tr::ComCfg, + pub(super) isr_stat: Tr::IsrStatus, + pub(super) notif_cfg: Tr::NotifCfg, pub(super) inner: T, @@ -255,19 +252,19 @@ pub(crate) struct VirtioNetDriver { pub(super) checksums: ChecksumCapabilities, } -pub struct TxToken<'a> { - send_vqs: &'a mut TxQueues, +pub struct TxToken<'a, T: Transport> { + send_vqs: &'a mut TxQueues, checksums: ChecksumCapabilities, send_capacity: &'a mut u32, } -impl Drop for TxToken<'_> { +impl Drop for TxToken<'_, T> { fn drop(&mut self) { *self.send_capacity += u32::from(BUFF_PER_PACKET); } } -impl smoltcp::phy::TxToken for TxToken<'_> { +impl smoltcp::phy::TxToken for TxToken<'_, T> { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, @@ -289,7 +286,7 @@ impl smoltcp::phy::TxToken for TxToken<'_> { // If a checksum calculation by the host is necessary, we have to inform the host within the header // see Virtio specification 5.1.6.2 if let Some((ip_header_len, csum_offset)) = - VirtioNetDriver::should_request_checksum(&token.checksums, &mut packet) + VirtioNetDriver::::should_request_checksum(&token.checksums, &mut packet) { header.flags = HdrF::NEEDS_CSUM; header.csum_start = @@ -311,13 +308,13 @@ impl smoltcp::phy::TxToken for TxToken<'_> { } } -pub struct RxToken<'a> { - recv_vqs: &'a mut RxQueues, +pub struct RxToken<'a, T: Transport> { + recv_vqs: &'a mut RxQueues, is_mrg_rxbuf_enabled: bool, checksums: ChecksumCapabilities, } -impl RxToken<'_> { +impl RxToken<'_, T> { /// If we advertised receive checksum offload to smoltcp, we need to validate the packet /// either by checking its virtio-net headers or checksum. Otherwise, it's smoltcp's responsibility /// to validate the frame and we can pass the frame directly. @@ -417,7 +414,7 @@ impl RxToken<'_> { } } -impl smoltcp::phy::RxToken for RxToken<'_> { +impl smoltcp::phy::RxToken for RxToken<'_, T> { fn consume(self, f: F) -> R where F: FnOnce(&[u8]) -> R, @@ -493,7 +490,7 @@ impl smoltcp::phy::RxToken for RxToken<'_> { } } -impl NetworkDriver for VirtioNetDriver { +impl NetworkDriver for VirtioNetDriver> { /// Returns the mac address of the device. /// If VIRTIO_NET_F_MAC is not set, the function panics currently! fn get_mac_address(&self) -> [u8; 6] { @@ -522,14 +519,9 @@ impl NetworkDriver for VirtioNetDriver { fn handle_interrupt(&mut self) { let status = self.isr_stat.acknowledge(); - #[cfg(not(feature = "pci"))] - if status.contains(virtio::mmio::InterruptStatus::CONFIGURATION_CHANGE_NOTIFICATION) { - info!("Configuration changes are not possible! Aborting"); - todo!("Implement possibility to change config on the fly...") - } - - #[cfg(feature = "pci")] - if status.contains(virtio::pci::IsrStatus::DEVICE_CONFIGURATION_INTERRUPT) { + if status & ::CONFIGURATION_CHANGE + == ::CONFIGURATION_CHANGE + { info!("Configuration changes are not possible! Aborting"); todo!("Implement possibility to change config on the fly...") } @@ -538,9 +530,15 @@ impl NetworkDriver for VirtioNetDriver { } } -impl smoltcp::phy::Device for VirtioNetDriver { - type TxToken<'a> = TxToken<'a>; - type RxToken<'a> = RxToken<'a>; +impl smoltcp::phy::Device for VirtioNetDriver { + type TxToken<'a> + = TxToken<'a, T> + where + T: 'a; + type RxToken<'a> + = RxToken<'a, T> + where + T: 'a; fn capabilities(&self) -> DeviceCapabilities { let mut device_capabilities = DeviceCapabilities::default(); @@ -597,7 +595,7 @@ impl smoltcp::phy::Device for VirtioNetDriver { } } -impl Driver for VirtioNetDriver { +impl Driver for VirtioNetDriver> { fn get_interrupt_number(&self) -> InterruptLine { self.irq } @@ -608,7 +606,7 @@ impl Driver for VirtioNetDriver { } // Backend-independent interface for Virtio network driver -impl VirtioNetDriver { +impl VirtioNetDriver> { #[cfg(feature = "pci")] pub fn get_dev_id(&self) -> u16 { self.dev_cfg.dev_id @@ -751,13 +749,13 @@ impl VirtioNetDriver { } } -impl VirtioNetDriver { +impl VirtioNetDriver { /// Initializes the device in adherence to specification. Returns Some(VirtioNetError) /// upon failure and None in case everything worked as expected. /// /// See Virtio specification v1.1. - 3.1.1. /// and v1.1. - 5.1.5 - pub fn init_dev(mut self) -> Result, VirtioNetError> { + pub fn init_dev(mut self) -> Result>, VirtioNetError> { // Reset self.com_cfg.reset_dev(); @@ -824,11 +822,11 @@ impl VirtioNetDriver { return Err(VirtioNetError::FailFeatureNeg(self.dev_cfg.dev_id)); } - let mut inner = Init { + let mut inner = Init:: { mtu: determine_mtu(&self.dev_cfg), ctrl_vq: None, - recv_vqs: RxQueues::new(Vec::new(), &self.dev_cfg), - send_vqs: TxQueues::new(Vec::new(), &self.dev_cfg), + recv_vqs: RxQueues::::new(Vec::new(), &self.dev_cfg), + send_vqs: TxQueues::::new(Vec::new(), &self.dev_cfg), send_capacity: 0, }; @@ -870,7 +868,7 @@ impl VirtioNetDriver { } /// Device Specific initialization according to Virtio specifictation v1.1. - 5.1.5 - fn dev_spec_init(&mut self, inner: &mut Init) -> Result<(), VirtioNetError> { + fn dev_spec_init(&mut self, inner: &mut Init) -> Result<(), VirtioNetError> { self.virtqueue_init(inner)?; info!("Network driver successfully initialized virtqueues."); @@ -908,7 +906,7 @@ impl VirtioNetDriver { } /// Initialize virtqueues via the queue interface and populates receiving queues - fn virtqueue_init(&mut self, inner: &mut Init) -> Result<(), VirtioNetError> { + fn virtqueue_init(&mut self, inner: &mut Init) -> Result<(), VirtioNetError> { // We are assuming here, that the device single source of truth is the // device specific configuration. Hence we do NOT check if // diff --git a/src/drivers/net/virtio/pci.rs b/src/drivers/net/virtio/pci.rs index 104ab84060..905c70eba6 100644 --- a/src/drivers/net/virtio/pci.rs +++ b/src/drivers/net/virtio/pci.rs @@ -2,16 +2,15 @@ use pci_types::CommandRegister; use smoltcp::phy::ChecksumCapabilities; use volatile::VolatileRef; -use super::{Init, Uninit}; +use super::Uninit; use crate::arch::pci::PciConfigRegion; use crate::drivers::net::virtio::{NetDevCfg, VirtioNetDriver}; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; -use crate::drivers::virtio::transport::pci; -use crate::drivers::virtio::transport::pci::{PciCap, UniCapsColl}; +use crate::drivers::virtio::transport::pci::{self, PciCap, Transport, UniCapsColl}; // Backend-dependent interface for Virtio network driver -impl VirtioNetDriver { +impl VirtioNetDriver { fn map_cfg(cap: &PciCap) -> Option { let dev_cfg = pci::map_dev_cfg::(cap)?; @@ -66,7 +65,7 @@ impl VirtioNetDriver { /// [VirtioNetDriver](structs.virtionetdriver.html) or an [VirtioError](enums.virtioerror.html). pub(crate) fn init( device: &PciDevice, - ) -> Result, VirtioError> { + ) -> Result, VirtioError> { // enable bus master mode device.set_command(CommandRegister::BUS_MASTER_ENABLE); diff --git a/src/drivers/pci.rs b/src/drivers/pci.rs index 8b4cd34621..7fb88f12ac 100644 --- a/src/drivers/pci.rs +++ b/src/drivers/pci.rs @@ -33,6 +33,13 @@ use crate::drivers::net::virtio::VirtioNetDriver; #[cfg(feature = "virtio")] use crate::drivers::virtio::transport::pci as pci_virtio; #[cfg(feature = "virtio")] +#[cfg(any( + feature = "virtio-fs", + feature = "virtio-vsock", + feature = "virtio-console", + feature = "virtio-net" +))] +use crate::drivers::virtio::transport::pci::Transport; #[allow(unused_imports)] use crate::drivers::virtio::transport::pci::VirtioDriver; #[cfg(feature = "virtio-vsock")] @@ -331,16 +338,16 @@ pub(crate) fn print_information() { #[non_exhaustive] pub(crate) enum PciDriver { #[cfg(feature = "virtio-fs")] - VirtioFs(InterruptTicketMutex), + VirtioFs(InterruptTicketMutex>), #[cfg(feature = "virtio-console")] - VirtioConsole(InterruptTicketMutex), + VirtioConsole(InterruptTicketMutex>), #[cfg(feature = "virtio-vsock")] - VirtioVsock(InterruptTicketMutex), + VirtioVsock(InterruptTicketMutex>), } impl PciDriver { #[cfg(feature = "virtio-console")] - fn get_console_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_console_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioConsole(drv) => Some(drv), @@ -349,7 +356,7 @@ impl PciDriver { } #[cfg(feature = "virtio-vsock")] - fn get_vsock_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_vsock_driver(&self) -> Option<&InterruptTicketMutex>> { #[allow(unreachable_patterns)] match self { Self::VirtioVsock(drv) => Some(drv), @@ -358,7 +365,7 @@ impl PciDriver { } #[cfg(feature = "virtio-fs")] - fn get_filesystem_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_filesystem_driver(&self) -> Option<&InterruptTicketMutex>> { match self { Self::VirtioFs(drv) => Some(drv), #[allow(unreachable_patterns)] @@ -450,13 +457,14 @@ pub(crate) fn get_interrupt_handlers() -> HashMap; #[cfg(feature = "rtl8139")] pub(crate) type NetworkDevice = RTL8139Driver; #[cfg(feature = "virtio-console")] -pub(crate) fn get_console_driver() -> Option<&'static InterruptTicketMutex> { +pub(crate) fn get_console_driver() +-> Option<&'static InterruptTicketMutex>> { PCI_DRIVERS .get()? .iter() @@ -464,7 +472,8 @@ pub(crate) fn get_console_driver() -> Option<&'static InterruptTicketMutex Option<&'static InterruptTicketMutex> { +pub(crate) fn get_vsock_driver() +-> Option<&'static InterruptTicketMutex>> { PCI_DRIVERS .get()? .iter() @@ -472,7 +481,8 @@ pub(crate) fn get_vsock_driver() -> Option<&'static InterruptTicketMutex Option<&'static InterruptTicketMutex> { +pub(crate) fn get_filesystem_driver() +-> Option<&'static InterruptTicketMutex>> { PCI_DRIVERS .get()? .iter() diff --git a/src/drivers/virtio/transport/mmio.rs b/src/drivers/virtio/transport/mmio.rs index 27f2147da4..14798a5c2a 100644 --- a/src/drivers/virtio/transport/mmio.rs +++ b/src/drivers/virtio/transport/mmio.rs @@ -13,8 +13,7 @@ use virtio::mmio::{ InterruptStatus, NotificationData, }; use virtio::{DeviceStatus, le32}; -use volatile::access::ReadOnly; -use volatile::{VolatilePtr, VolatileRef}; +use volatile::VolatileRef; use crate::drivers::InterruptLine; #[cfg(feature = "virtio-console")] @@ -42,12 +41,14 @@ impl VqCfgHandler<'_> { .queue_sel() .write(self.vq_index.into()); } +} +impl super::VqCfgHandler for VqCfgHandler<'_> { /// Sets the size of a given virtqueue. In case the provided size exceeds the maximum allowed /// size, the size is set to this maximum instead. Else size is set to the provided value. /// /// Returns the set size in form of a `u16`. - pub fn set_vq_size(&mut self, max_size: u16) -> u16 { + fn set_vq_size(&mut self, max_size: u16) -> u16 { self.select_queue(); let ptr = self.raw.as_mut_ptr(); @@ -57,7 +58,7 @@ impl VqCfgHandler<'_> { size } - pub fn set_ring_addr(&mut self, addr: PhysAddr) { + fn set_ring_addr(&mut self, addr: PhysAddr) { self.select_queue(); self.raw @@ -66,7 +67,7 @@ impl VqCfgHandler<'_> { .write(addr.as_u64().into()); } - pub fn set_drv_ctrl_addr(&mut self, addr: PhysAddr) { + fn set_drv_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); self.raw @@ -75,7 +76,7 @@ impl VqCfgHandler<'_> { .write(addr.as_u64().into()); } - pub fn set_dev_ctrl_addr(&mut self, addr: PhysAddr) { + fn set_dev_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); self.raw @@ -84,7 +85,7 @@ impl VqCfgHandler<'_> { .write(addr.as_u64().into()); } - pub fn enable_queue(&mut self) { + fn enable_queue(&mut self) { self.select_queue(); self.raw.as_mut_ptr().queue_ready().write(true); @@ -107,12 +108,35 @@ impl ComCfg { ComCfg { com_cfg: raw } } - pub fn control_registers(&mut self) -> impl ControlRegisters<'_> { + pub fn get_max_queue_size(&mut self, sel: u16) -> u16 { + let ptr = self.com_cfg.as_mut_ptr(); + ptr.queue_sel().write(sel.into()); + ptr.queue_num_max().read().to_ne() + } + + pub fn print_information(&mut self) { + let ptr = self.com_cfg.as_ptr(); + + infoheader!(" MMIO REGISTER LAYOUT INFORMATION "); + + infoentry!("Device version", "{:#X}", ptr.version().read()); + infoentry!("Device ID", "{:?}", ptr.device_id().read()); + infoentry!("Vendor ID", "{:#X}", ptr.vendor_id().read()); + let ptr = self.com_cfg.as_ptr(); + infoentry!("Interrupt status", "{:#X}", ptr.interrupt_status().read()); + infoentry!("Device status", "{:#X}", ptr.status().read()); + + infofooter!(); + } +} + +impl super::ComCfg for ComCfg { + fn control_registers(&mut self) -> impl ControlRegisters<'_> { self.com_cfg.as_mut_ptr() } #[allow(dead_code)] - pub fn device_config_space(&self) -> VolatilePtr<'_, DeviceRegisters, ReadOnly> { + fn device_config_space(&self) -> impl virtio::DeviceConfigSpace { self.com_cfg.as_ptr() } @@ -120,7 +144,7 @@ impl ComCfg { /// returns `Some(VqCfgHandler)`. /// /// INFO: The queue size is automatically bounded by constant `src::config:VIRTIO_MAX_QUEUE_SIZE`. - pub fn select_vq(&mut self, index: u16) -> Option> { + fn select_vq(&mut self, index: u16) -> Option> { if self.get_max_queue_size(index) == 0 { return None; } @@ -131,14 +155,8 @@ impl ComCfg { }) } - pub fn get_max_queue_size(&mut self, sel: u16) -> u16 { - let ptr = self.com_cfg.as_mut_ptr(); - ptr.queue_sel().write(sel.into()); - ptr.queue_num_max().read().to_ne() - } - /// Resets the device status field to zero. - pub fn reset_dev(&mut self) { + fn reset_dev(&mut self) { self.com_cfg .as_mut_ptr() .status() @@ -149,7 +167,7 @@ impl ComCfg { /// A driver MUST NOT initialize and use the device any further after this. /// A driver MAY use the device again after a proper reset of the device. #[allow(dead_code)] - pub fn set_failed(&mut self) { + fn set_failed(&mut self) { self.com_cfg .as_mut_ptr() .status() @@ -158,7 +176,7 @@ impl ComCfg { /// Sets the ACKNOWLEDGE bit in the device status field. This indicates, the /// OS has notived the device - pub fn ack_dev(&mut self) { + fn ack_dev(&mut self) { self.com_cfg .as_mut_ptr() .status() @@ -167,7 +185,7 @@ impl ComCfg { /// Sets the DRIVER bit in the device status field. This indicates, the OS /// know how to run this device. - pub fn set_drv(&mut self) { + fn set_drv(&mut self) { self.com_cfg .as_mut_ptr() .status() @@ -177,7 +195,7 @@ impl ComCfg { /// Sets the FEATURES_OK bit in the device status field. /// /// Drivers MUST NOT accept new features after this step. - pub fn features_ok(&mut self) { + fn features_ok(&mut self) { self.com_cfg .as_mut_ptr() .status() @@ -185,12 +203,12 @@ impl ComCfg { } /// In order to correctly check feature negotiaten, this function - /// MUST be called after [self.features_ok()](ComCfg::features_ok()) in order to check + /// MUST be called after [self.features_ok()](super::ComCfg::features_ok()) in order to check /// if features have been accepted by the device after negotiation. /// /// Re-reads device status to ensure the FEATURES_OK bit is still set: /// otherwise, the device does not support our subset of features and the device is unusable. - pub fn check_features(&self) -> bool { + fn check_features(&self) -> bool { self.com_cfg .as_ptr() .status() @@ -201,27 +219,12 @@ impl ComCfg { /// Sets the DRIVER_OK bit in the device status field. /// /// After this call, the device is "live"! - pub fn drv_ok(&mut self) { + fn drv_ok(&mut self) { self.com_cfg .as_mut_ptr() .status() .update(|status| status | DeviceStatus::DRIVER_OK); } - - pub fn print_information(&mut self) { - let ptr = self.com_cfg.as_ptr(); - - infoheader!(" MMIO REGISTER LAYOUT INFORMATION "); - - infoentry!("Device version", "{:#X}", ptr.version().read()); - infoentry!("Device ID", "{:?}", ptr.device_id().read()); - infoentry!("Vendor ID", "{:#X}", ptr.vendor_id().read()); - let ptr = self.com_cfg.as_ptr(); - infoentry!("Interrupt status", "{:#X}", ptr.interrupt_status().read()); - infoentry!("Device status", "{:#X}", ptr.status().read()); - - infofooter!(); - } } /// Notification Structure to handle virtqueue notification settings. @@ -240,8 +243,10 @@ impl NotifCfg { NotifCfg { queue_notify: raw } } +} - pub fn notification_location(&self, _vq_cfg_handler: &mut VqCfgHandler<'_>) -> *mut le32 { +impl super::NotifCfg for NotifCfg { + fn notification_location(&self, _vq_cfg_handler: &mut VqCfgHandler<'_>) -> *mut le32 { self.queue_notify } } @@ -258,10 +263,12 @@ pub struct NotifCtrl { // FIXME: make `notif_addr` implement `Send` instead unsafe impl Send for NotifCtrl {} -impl NotifCtrl { +impl super::NotifCtrl for NotifCtrl { + type NotificationData = NotificationData; + /// Returns a new controller. By default MSI-X capabilities and VIRTIO_F_NOTIFICATION_DATA /// are disabled. - pub fn new(notif_addr: *mut le32) -> Self { + fn new(notif_addr: *mut le32) -> Self { NotifCtrl { f_notif_data: false, notif_addr, @@ -269,11 +276,11 @@ impl NotifCtrl { } /// Enables VIRTIO_F_NOTIFICATION_DATA. This changes which data is provided to the device. ONLY a good idea if Feature has been negotiated. - pub fn enable_notif_data(&mut self) { + fn enable_notif_data(&mut self) { self.f_notif_data = true; } - pub fn notify_dev(&self, data: NotificationData) { + fn notify_dev(&self, data: NotificationData) { let notification_data = if self.f_notif_data { data.into_bits() } else { @@ -286,6 +293,28 @@ impl NotifCtrl { } } +impl super::NotificationData for NotificationData { + fn new() -> Self { + NotificationData::new() + } + + fn with_next_idx(self, value: u16) -> Self { + self.with_next_idx(value) + } + + fn with_next_off(self, value: u16) -> Self { + self.with_next_off(value) + } + + fn with_next_wrap(self, value: u8) -> Self { + self.with_next_wrap(value) + } + + fn with_vqn(self, value: u16) -> Self { + self.with_vqn(value) + } +} + /// Wraps a [`DeviceRegisters`] in order to preserve /// the original structure and allow interaction with the device via /// the structure. @@ -303,8 +332,14 @@ impl IsrStatus { unsafe { mem::transmute::, VolatileRef<'static, _>>(registers) }; Self { raw } } +} + +impl super::IsrStatus for IsrStatus { + type Status = InterruptStatus; + const CONFIGURATION_CHANGE: InterruptStatus = + InterruptStatus::CONFIGURATION_CHANGE_NOTIFICATION; - pub fn acknowledge(&mut self) -> InterruptStatus { + fn acknowledge(&mut self) -> InterruptStatus { let ptr = self.raw.as_mut_ptr(); let status = ptr.interrupt_status().read(); ptr.interrupt_ack().write(status); @@ -314,13 +349,13 @@ impl IsrStatus { pub(crate) enum VirtioDriver { #[cfg(feature = "virtio-console")] - Console(alloc::boxed::Box), + Console(alloc::boxed::Box>), #[cfg(feature = "virtio-fs")] - Fs(alloc::boxed::Box), + Fs(alloc::boxed::Box>), #[cfg(feature = "virtio-net")] - Net(alloc::boxed::Box), + Net(alloc::boxed::Box>), #[cfg(feature = "virtio-vsock")] - Vsock(alloc::boxed::Box), + Vsock(alloc::boxed::Box>), } #[allow(unused_variables)] @@ -417,3 +452,13 @@ pub(crate) fn init_device( } } } + +pub struct Transport {} + +impl super::Transport for Transport { + type ComCfg = ComCfg; + type NotifCfg = NotifCfg; + type IsrStatus = IsrStatus; + type VqCfgHandler<'a> = VqCfgHandler<'a>; + type NotifCtrl = NotifCtrl; +} diff --git a/src/drivers/virtio/transport/mod.rs b/src/drivers/virtio/transport/mod.rs index 81fb06af41..3d14569078 100644 --- a/src/drivers/virtio/transport/mod.rs +++ b/src/drivers/virtio/transport/mod.rs @@ -1,4 +1,67 @@ +use core::ops::BitAnd; + +use memory_addresses::PhysAddr; +use virtio::{DeviceConfigSpace, le32}; + #[cfg(not(feature = "pci"))] pub mod mmio; #[cfg(feature = "pci")] pub mod pci; + +pub trait Transport: Sized { + type ComCfg: ComCfg; + type NotifCfg: NotifCfg; + type IsrStatus: IsrStatus; + type VqCfgHandler<'a>: VqCfgHandler; + type NotifCtrl: NotifCtrl + Send; +} + +pub trait ComCfg { + fn reset_dev(&mut self); + fn ack_dev(&mut self); + fn set_drv(&mut self); + fn control_registers(&mut self) -> impl super::ControlRegisters<'_>; + fn features_ok(&mut self); + fn check_features(&self) -> bool; + fn select_vq(&mut self, index: u16) -> Option>; + fn drv_ok(&mut self); + #[allow(dead_code)] + fn set_failed(&mut self); + #[allow(dead_code)] + fn device_config_space(&self) -> impl DeviceConfigSpace; +} + +pub trait NotifCfg { + fn notification_location(&self, vq_cfg_handler: &mut T::VqCfgHandler<'_>) -> *mut le32; +} + +pub trait IsrStatus { + type Status: BitAnd + PartialEq + Copy; + const CONFIGURATION_CHANGE: Self::Status; + + fn acknowledge(&mut self) -> Self::Status; +} + +pub trait VqCfgHandler { + fn enable_queue(&mut self); + fn set_dev_ctrl_addr(&mut self, addr: PhysAddr); + fn set_drv_ctrl_addr(&mut self, addr: PhysAddr); + fn set_ring_addr(&mut self, addr: PhysAddr); + fn set_vq_size(&mut self, max_size: u16) -> u16; +} + +pub trait NotifCtrl { + type NotificationData: NotificationData; + + fn new(notif_addr: *mut le32) -> Self; + fn notify_dev(&self, data: Self::NotificationData); + fn enable_notif_data(&mut self); +} + +pub trait NotificationData { + fn new() -> Self; + fn with_next_idx(self, value: u16) -> Self; + fn with_next_off(self, value: u16) -> Self; + fn with_next_wrap(self, value: u8) -> Self; + fn with_vqn(self, value: u16) -> Self; +} diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index babe017063..fe9a64de0e 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -15,8 +15,7 @@ use virtio::pci::{ IsrStatus as IsrStatusRaw, NotificationData, }; use virtio::{DeviceStatus, le16, le32}; -use volatile::access::ReadOnly; -use volatile::{VolatilePtr, VolatileRef}; +use volatile::VolatileRef; use crate::arch::pci::PciConfigRegion; #[cfg(feature = "virtio-console")] @@ -212,12 +211,14 @@ impl VqCfgHandler<'_> { .queue_select() .write(self.vq_index.into()); } +} +impl super::VqCfgHandler for VqCfgHandler<'_> { /// Sets the size of a given virtqueue. In case the provided size exceeds the maximum allowed /// size, the size is set to this maximum instead. Else size is set to the provided value. /// /// Returns the set size in form of a `u16`. - pub fn set_vq_size(&mut self, max_size: u16) -> u16 { + fn set_vq_size(&mut self, max_size: u16) -> u16 { self.select_queue(); let queue_size = self.raw.as_mut_ptr().queue_size(); @@ -231,7 +232,7 @@ impl VqCfgHandler<'_> { } } - pub fn set_ring_addr(&mut self, addr: PhysAddr) { + fn set_ring_addr(&mut self, addr: PhysAddr) { self.select_queue(); self.raw .as_mut_ptr() @@ -239,7 +240,7 @@ impl VqCfgHandler<'_> { .write(addr.as_u64().into()); } - pub fn set_drv_ctrl_addr(&mut self, addr: PhysAddr) { + fn set_drv_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); self.raw .as_mut_ptr() @@ -247,7 +248,7 @@ impl VqCfgHandler<'_> { .write(addr.as_u64().into()); } - pub fn set_dev_ctrl_addr(&mut self, addr: PhysAddr) { + fn set_dev_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); self.raw .as_mut_ptr() @@ -255,20 +256,22 @@ impl VqCfgHandler<'_> { .write(addr.as_u64().into()); } - pub fn notif_off(&mut self) -> u16 { + fn enable_queue(&mut self) { self.select_queue(); - self.raw.as_mut_ptr().queue_notify_off().read().to_ne() + self.raw.as_mut_ptr().queue_enable().write(1.into()); } +} - pub fn enable_queue(&mut self) { +impl VqCfgHandler<'_> { + fn notif_off(&mut self) -> u16 { self.select_queue(); - self.raw.as_mut_ptr().queue_enable().write(1.into()); + self.raw.as_mut_ptr().queue_notify_off().read().to_ne() } } // Public Interface of ComCfg -impl ComCfg { - pub fn control_registers(&mut self) -> impl ControlRegisters<'_> { +impl super::ComCfg for ComCfg { + fn control_registers(&mut self) -> impl ControlRegisters<'_> { self.com_cfg.as_mut_ptr() } @@ -276,7 +279,7 @@ impl ComCfg { /// returns `Some(VqCfgHandler)`. /// /// INFO: The queue size is automatically bounded by constant `src::config:VIRTIO_MAX_QUEUE_SIZE`. - pub fn select_vq(&mut self, index: u16) -> Option> { + fn select_vq(&mut self, index: u16) -> Option> { self.com_cfg.as_mut_ptr().queue_select().write(index.into()); if self.com_cfg.as_mut_ptr().queue_size().read().to_ne() == 0 { @@ -290,12 +293,12 @@ impl ComCfg { } #[allow(dead_code)] - pub fn device_config_space(&self) -> VolatilePtr<'_, CommonCfg, ReadOnly> { + fn device_config_space(&self) -> impl virtio::DeviceConfigSpace { self.com_cfg.as_ptr() } /// Resets the device status field to zero. - pub fn reset_dev(&mut self) { + fn reset_dev(&mut self) { self.com_cfg .as_mut_ptr() .device_status() @@ -306,7 +309,7 @@ impl ComCfg { /// A driver MUST NOT initialize and use the device any further after this. /// A driver MAY use the device again after a proper reset of the device. #[allow(dead_code)] - pub fn set_failed(&mut self) { + fn set_failed(&mut self) { self.com_cfg .as_mut_ptr() .device_status() @@ -315,7 +318,7 @@ impl ComCfg { /// Sets the ACKNOWLEDGE bit in the device status field. This indicates, the /// OS has notived the device - pub fn ack_dev(&mut self) { + fn ack_dev(&mut self) { self.com_cfg .as_mut_ptr() .device_status() @@ -324,7 +327,7 @@ impl ComCfg { /// Sets the DRIVER bit in the device status field. This indicates, the OS /// know how to run this device. - pub fn set_drv(&mut self) { + fn set_drv(&mut self) { self.com_cfg .as_mut_ptr() .device_status() @@ -334,7 +337,7 @@ impl ComCfg { /// Sets the FEATURES_OK bit in the device status field. /// /// Drivers MUST NOT accept new features after this step. - pub fn features_ok(&mut self) { + fn features_ok(&mut self) { self.com_cfg .as_mut_ptr() .device_status() @@ -342,12 +345,12 @@ impl ComCfg { } /// In order to correctly check feature negotiaten, this function - /// MUST be called after [self.features_ok()](ComCfg::features_ok()) in order to check + /// MUST be called after [self.features_ok()](super::ComCfg::features_ok()) in order to check /// if features have been accepted by the device after negotiation. /// /// Re-reads device status to ensure the FEATURES_OK bit is still set: /// otherwise, the device does not support our subset of features and the device is unusable. - pub fn check_features(&self) -> bool { + fn check_features(&self) -> bool { let status = self.com_cfg.as_ptr().device_status().read(); status.contains(DeviceStatus::FEATURES_OK) } @@ -355,7 +358,7 @@ impl ComCfg { /// Sets the DRIVER_OK bit in the device status field. /// /// After this call, the device is "live"! - pub fn drv_ok(&mut self) { + fn drv_ok(&mut self) { self.com_cfg .as_mut_ptr() .device_status() @@ -403,8 +406,10 @@ impl NotifCfg { length: cap.len(), }) } +} - pub fn notification_location(&self, vq_cfg_handler: &mut VqCfgHandler<'_>) -> *mut le32 { +impl super::NotifCfg for NotifCfg { + fn notification_location(&self, vq_cfg_handler: &mut VqCfgHandler<'_>) -> *mut le32 { let addend = u32::from(vq_cfg_handler.notif_off()) * self.notify_off_multiplier; // TODO: This should be @@ -431,10 +436,12 @@ pub struct NotifCtrl { // FIXME: make `notif_addr` implement `Send` instead unsafe impl Send for NotifCtrl {} -impl NotifCtrl { +impl super::NotifCtrl for NotifCtrl { + type NotificationData = NotificationData; + /// Returns a new controller. By default MSI-X capabilities and VIRTIO_F_NOTIFICATION_DATA /// are disabled. - pub fn new(notif_addr: *mut le32) -> Self { + fn new(notif_addr: *mut le32) -> Self { NotifCtrl { f_notif_data: false, notif_addr, @@ -442,11 +449,11 @@ impl NotifCtrl { } /// Enables VIRTIO_F_NOTIFICATION_DATA. This changes which data is provided to the device. ONLY a good idea if Feature has been negotiated. - pub fn enable_notif_data(&mut self) { + fn enable_notif_data(&mut self) { self.f_notif_data = true; } - pub fn notify_dev(&self, data: NotificationData) { + fn notify_dev(&self, data: NotificationData) { // See Virtio specification v.1.1. - 4.1.5.2 // Depending in the feature negotiation, we write either only the // virtqueue index or the index and the next position inside the queue. @@ -465,6 +472,28 @@ impl NotifCtrl { } } +impl super::NotificationData for NotificationData { + fn new() -> Self { + NotificationData::new() + } + + fn with_next_idx(self, value: u16) -> Self { + self.with_next_idx(value) + } + + fn with_next_off(self, value: u16) -> Self { + self.with_next_off(value) + } + + fn with_next_wrap(self, value: u8) -> Self { + self.with_next_wrap(value) + } + + fn with_vqn(self, value: u16) -> Self { + self.with_vqn(value) + } +} + /// Wraps a [IsrStatusRaw] in order to preserve /// the original structure and allow interaction with the device via /// the structure. @@ -481,8 +510,13 @@ impl IsrStatus { fn new(raw: VolatileRef<'static, IsrStatusRaw>) -> Self { IsrStatus { isr_stat: raw } } +} + +impl super::IsrStatus for IsrStatus { + type Status = IsrStatusRaw; + const CONFIGURATION_CHANGE: IsrStatusRaw = IsrStatusRaw::DEVICE_CONFIGURATION_INTERRUPT; - pub fn acknowledge(&mut self) -> IsrStatusRaw { + fn acknowledge(&mut self) -> IsrStatusRaw { self.isr_stat.as_ptr().read() } } @@ -642,7 +676,7 @@ pub(crate) fn init_device( match id { #[cfg(feature = "virtio-console")] - virtio::Id::Console => match VirtioConsoleDriver::init(device) { + virtio::Id::Console => match VirtioConsoleDriver::::init(device) { Ok(virt_console_drv) => { info!("Virtio console driver initialized."); @@ -663,7 +697,7 @@ pub(crate) fn init_device( virtio::Id::Fs => { // TODO: check subclass // TODO: proper error handling on driver creation fail - match VirtioFsDriver::init(device) { + match VirtioFsDriver::::init(device) { Ok(virt_fs_drv) => { info!("Virtio filesystem driver initialized."); let irq = device.get_irq().unwrap(); @@ -683,7 +717,7 @@ pub(crate) fn init_device( not(feature = "rtl8139"), feature = "virtio-net", ))] - virtio::Id::Net => match VirtioNetDriver::init(device) { + virtio::Id::Net => match VirtioNetDriver::::init(device) { Ok(virt_net_drv) => { info!("Virtio network driver initialized."); @@ -701,7 +735,7 @@ pub(crate) fn init_device( } }, #[cfg(feature = "virtio-vsock")] - virtio::Id::Vsock => match VirtioVsockDriver::init(device) { + virtio::Id::Vsock => match VirtioVsockDriver::::init(device) { Ok(virt_sock_drv) => { info!("Virtio sock driver initialized."); @@ -734,15 +768,25 @@ pub(crate) fn init_device( pub(crate) enum VirtioDriver { #[cfg(feature = "virtio-console")] - Console(alloc::boxed::Box), + Console(alloc::boxed::Box>), #[cfg(feature = "virtio-fs")] - Fs(alloc::boxed::Box), + Fs(alloc::boxed::Box>), #[cfg(all( not(all(target_arch = "riscv64", feature = "gem-net", not(feature = "pci"))), not(feature = "rtl8139"), feature = "virtio-net", ))] - Net(alloc::boxed::Box), + Net(alloc::boxed::Box>), #[cfg(feature = "virtio-vsock")] - Vsock(alloc::boxed::Box), + Vsock(alloc::boxed::Box>), +} + +pub struct Transport {} + +impl super::Transport for Transport { + type ComCfg = ComCfg; + type IsrStatus = IsrStatus; + type NotifCfg = NotifCfg; + type NotifCtrl = NotifCtrl; + type VqCfgHandler<'a> = VqCfgHandler<'a>; } diff --git a/src/drivers/virtio/virtqueue/mod.rs b/src/drivers/virtio/virtqueue/mod.rs index 592882e301..3099e4109b 100644 --- a/src/drivers/virtio/virtqueue/mod.rs +++ b/src/drivers/virtio/virtqueue/mod.rs @@ -22,6 +22,7 @@ use smallvec::SmallVec; use virtio::{le32, le64, pvirtq, virtq}; use self::error::VirtqError; +use crate::drivers::virtio::transport::Transport; use crate::drivers::virtio::virtqueue::packed::PackedVq; use crate::drivers::virtio::virtqueue::split::SplitVq; use crate::mm::device_alloc::DeviceAlloc; @@ -226,9 +227,9 @@ trait VirtqPrivate { } #[enum_dispatch(Virtq)] -pub(crate) enum VirtQueue { - Split(SplitVq), - Packed(PackedVq), +pub(crate) enum VirtQueue { + Split(SplitVq), + Packed(PackedVq), } trait VirtqDescriptor { diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index c73773de32..c2e402deba 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -14,22 +14,17 @@ use core::ops; use core::sync::atomic::{Ordering, fence}; use align_address::Align; -#[cfg(not(feature = "pci"))] -use virtio::mmio::NotificationData; -#[cfg(feature = "pci")] -use virtio::pci::NotificationData; use virtio::pvirtq::{EventSuppressDesc, EventSuppressFlags}; use virtio::virtq::DescF; use virtio::{RingEventFlags, pvirtq}; -#[cfg(not(feature = "pci"))] -use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl}; -#[cfg(feature = "pci")] -use super::super::transport::pci::{ComCfg, NotifCfg, NotifCtrl}; use super::error::VirtqError; use super::index_alloc::IndexAlloc; use super::{AvailBufferToken, BufferType, TransferToken, UsedBufferToken, Virtq, VirtqPrivate}; use crate::arch::mm::paging::{BasePageSize, PageSize}; +use crate::drivers::virtio::transport::{ + ComCfg, NotifCfg, NotifCtrl, NotificationData, Transport, VqCfgHandler, +}; use crate::mm::device_alloc::DeviceAlloc; trait RingIndexRange { @@ -92,7 +87,7 @@ impl DescriptorRing { let poll_index = write_index; - DescriptorRing { + Self { ring, tkn_ref_ring, write_index, @@ -113,7 +108,7 @@ impl DescriptorRing { .ok_or(VirtqError::NoNewUsed) } - fn push_batch( + fn push_batch( &mut self, tkn_lst: impl IntoIterator>, ) -> Result { @@ -126,7 +121,7 @@ impl DescriptorRing { return Err(VirtqError::BufferNotSpecified); }; - let mut ctrl = self.push_without_making_available(&first_tkn)?; + let mut ctrl = self.push_without_making_available::(&first_tkn)?; let first_ctrl_settings = (ctrl.start, ctrl.buff_id, ctrl.first_flags); let first_buffer = first_tkn; @@ -148,11 +143,14 @@ impl DescriptorRing { Ok(self.write_index) } - fn push(&mut self, tkn: TransferToken) -> Result { - self.push_batch([tkn]) + fn push( + &mut self, + tkn: TransferToken, + ) -> Result { + self.push_batch::([tkn]) } - fn push_without_making_available( + fn push_without_making_available( &mut self, tkn: &TransferToken, ) -> Result, VirtqError> { @@ -170,10 +168,10 @@ impl DescriptorRing { // The buffer uses indirect descriptors if the ctrl_desc field is Some. if let Some(ctrl_desc) = tkn.ctrl_desc.as_ref() { - let desc = PackedVq::indirect_desc(ctrl_desc.as_ref()); + let desc = PackedVq::::indirect_desc(ctrl_desc.as_ref()); ctrl.write_desc(desc); } else { - for incomplete_desc in PackedVq::descriptor_iter(&tkn.buff_tkn)? { + for incomplete_desc in PackedVq::::descriptor_iter(&tkn.buff_tkn)? { ctrl.write_desc(incomplete_desc); } } @@ -484,7 +482,7 @@ impl DevNotif { /// Packed virtqueue which provides the functionilaty as described in the /// virtio specification v1.1. - 2.7 -pub struct PackedVq { +pub struct PackedVq { /// Ring which allows easy access to the raw ring structure of the /// specification descr_ring: DescriptorRing, @@ -493,7 +491,7 @@ pub struct PackedVq { /// Allows to check, if the device wants a notification dev_event: DevNotif, /// Actually notify device about avail buffers - notif_ctrl: NotifCtrl, + notif_ctrl: T::NotifCtrl, /// The size of the queue, equals the number of descriptors which can /// be used size: u16, @@ -505,7 +503,7 @@ pub struct PackedVq { // Public interface of PackedVq // This interface is also public in order to allow people to use the PackedVq directly! -impl Virtq for PackedVq { +impl Virtq for PackedVq { fn enable_notifs(&mut self) { self.drv_event.enable_notif(); } @@ -530,7 +528,7 @@ impl Virtq for PackedVq { Self::transfer_token_from_buffer_token(buffer_tkn, buffer_type) }); - let next_idx = self.descr_ring.push_batch(transfer_tkns)?; + let next_idx = self.descr_ring.push_batch::(transfer_tkns)?; if notif { self.drv_event.enable_specific(next_idx); @@ -543,7 +541,7 @@ impl Virtq for PackedVq { .is_some_and(|idx| range.wrapping_contains(&idx)); if self.dev_event.is_notif() || notif_specific { - let notification_data = NotificationData::new() + let notification_data = ::NotificationData::new() .with_vqn(self.index) .with_next_off(next_idx.desc_event_off()) .with_next_wrap(next_idx.desc_event_wrap()); @@ -565,7 +563,7 @@ impl Virtq for PackedVq { Self::transfer_token_from_buffer_token(buffer_tkn, buffer_type) }); - let next_idx = self.descr_ring.push_batch(transfer_tkns)?; + let next_idx = self.descr_ring.push_batch::(transfer_tkns)?; if notif { self.drv_event.enable_specific(next_idx); @@ -578,7 +576,7 @@ impl Virtq for PackedVq { .is_some_and(|idx| range.wrapping_contains(&idx)); if self.dev_event.is_notif() | notif_specific { - let notification_data = NotificationData::new() + let notification_data = ::NotificationData::new() .with_vqn(self.index) .with_next_off(next_idx.desc_event_off()) .with_next_wrap(next_idx.desc_event_wrap()); @@ -595,7 +593,7 @@ impl Virtq for PackedVq { buffer_type: BufferType, ) -> Result<(), VirtqError> { let transfer_tkn = Self::transfer_token_from_buffer_token(buffer_tkn, buffer_type); - let next_idx = self.descr_ring.push(transfer_tkn)?; + let next_idx = self.descr_ring.push::(transfer_tkn)?; if notif { self.drv_event.enable_specific(next_idx); @@ -609,7 +607,7 @@ impl Virtq for PackedVq { == Some(self.last_next.get().into_bits()); if self.dev_event.is_notif() || notif_specific { - let notification_data = NotificationData::new() + let notification_data = ::NotificationData::new() .with_vqn(self.index) .with_next_off(next_idx.desc_event_off()) .with_next_wrap(next_idx.desc_event_wrap()); @@ -633,7 +631,7 @@ impl Virtq for PackedVq { } } -impl VirtqPrivate for PackedVq { +impl VirtqPrivate for PackedVq { type Descriptor = pvirtq::Desc; fn create_indirect_ctrl( @@ -645,11 +643,11 @@ impl VirtqPrivate for PackedVq { } } -impl PackedVq { +impl PackedVq { #[allow(dead_code)] pub(crate) fn new( - com_cfg: &mut ComCfg, - notif_cfg: &NotifCfg, + com_cfg: &mut T::ComCfg, + notif_cfg: &T::NotifCfg, max_size: u16, index: u16, features: virtio::F, @@ -709,7 +707,7 @@ impl PackedVq { raw: dev_event, }; - let mut notif_ctrl = NotifCtrl::new(notif_cfg.notification_location(&mut vq_handler)); + let mut notif_ctrl = T::NotifCtrl::new(notif_cfg.notification_location(&mut vq_handler)); if features.contains(virtio::F::NOTIFICATION_DATA) { notif_ctrl.enable_notif_data(); diff --git a/src/drivers/virtio/virtqueue/split.rs b/src/drivers/virtio/virtqueue/split.rs index cc584053bb..5a49715b44 100644 --- a/src/drivers/virtio/virtqueue/split.rs +++ b/src/drivers/virtio/virtqueue/split.rs @@ -13,19 +13,14 @@ use core::cell::UnsafeCell; use core::mem::{self, MaybeUninit}; use mem_barrier::BarrierType; -#[cfg(not(feature = "pci"))] -use virtio::mmio::NotificationData; -#[cfg(feature = "pci")] -use virtio::pci::NotificationData; use virtio::{le16, virtq}; -#[cfg(not(feature = "pci"))] -use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl}; -#[cfg(feature = "pci")] -use super::super::transport::pci::{ComCfg, NotifCfg, NotifCtrl}; use super::error::VirtqError; use super::index_alloc::IndexAlloc; use super::{AvailBufferToken, BufferType, TransferToken, UsedBufferToken, Virtq, VirtqPrivate}; +use crate::drivers::virtio::transport::{ + ComCfg, NotifCfg, NotifCtrl, NotificationData, Transport, VqCfgHandler, +}; use crate::mm::device_alloc::DeviceAlloc; struct DescrRing { @@ -54,15 +49,15 @@ impl DescrRing { unsafe { &*self.used_ring_cell.get() } } - fn push(&mut self, tkn: TransferToken) -> Result { + fn push(&mut self, tkn: TransferToken) -> Result { let mut index; if let Some(ctrl_desc) = tkn.ctrl_desc.as_ref() { - let descriptor = SplitVq::indirect_desc(ctrl_desc.as_ref()); + let descriptor = SplitVq::::indirect_desc(ctrl_desc.as_ref()); index = self.indexes.allocate().ok_or(VirtqError::NoDescrAvail)?; self.descr_table_mut()[index] = MaybeUninit::new(descriptor); } else { - let mut rev_all_desc_iter = SplitVq::descriptor_iter(&tkn.buff_tkn)?.rev(); + let mut rev_all_desc_iter = SplitVq::::descriptor_iter(&tkn.buff_tkn)?.rev(); // We need to handle the last descriptor (the first for the reversed iterator) specially to not set the next flag. { @@ -151,15 +146,15 @@ impl DescrRing { } /// Virtio's split virtqueue structure -pub struct SplitVq { +pub struct SplitVq { ring: DescrRing, size: u16, index: u16, - notif_ctrl: NotifCtrl, + notif_ctrl: T::NotifCtrl, } -impl Virtq for SplitVq { +impl Virtq for SplitVq { fn enable_notifs(&mut self) { self.ring.drv_enable_notif(); } @@ -195,7 +190,7 @@ impl Virtq for SplitVq { buffer_type: BufferType, ) -> Result<(), VirtqError> { let transfer_tkn = Self::transfer_token_from_buffer_token(buffer_tkn, buffer_type); - let next_idx = self.ring.push(transfer_tkn)?; + let next_idx = self.ring.push::(transfer_tkn)?; if notif { // TODO: Check whether the splitvirtquue has notifications for specific descriptors @@ -204,7 +199,7 @@ impl Virtq for SplitVq { } if self.ring.dev_is_notif() { - let notification_data = NotificationData::new() + let notification_data = ::NotificationData::new() .with_vqn(self.index) .with_next_idx(next_idx); self.notif_ctrl.notify_dev(notification_data); @@ -225,7 +220,7 @@ impl Virtq for SplitVq { } } -impl VirtqPrivate for SplitVq { +impl VirtqPrivate for SplitVq { type Descriptor = virtq::Desc; fn create_indirect_ctrl( buffer_tkn: &AvailBufferToken, @@ -241,10 +236,10 @@ impl VirtqPrivate for SplitVq { } } -impl SplitVq { +impl SplitVq { pub(crate) fn new( - com_cfg: &mut ComCfg, - notif_cfg: &NotifCfg, + com_cfg: &mut T::ComCfg, + notif_cfg: &T::NotifCfg, max_size: u16, index: u16, features: virtio::F, @@ -309,7 +304,7 @@ impl SplitVq { order_platform, }; - let mut notif_ctrl = NotifCtrl::new(notif_cfg.notification_location(&mut vq_handler)); + let mut notif_ctrl = T::NotifCtrl::new(notif_cfg.notification_location(&mut vq_handler)); if features.contains(virtio::F::NOTIFICATION_DATA) { notif_ctrl.enable_notif_data(); diff --git a/src/drivers/vsock/mmio.rs b/src/drivers/vsock/mmio.rs index 071d1735c7..83ef312b17 100644 --- a/src/drivers/vsock/mmio.rs +++ b/src/drivers/vsock/mmio.rs @@ -1,19 +1,19 @@ -use virtio::vsock::Config; use virtio::mmio::{DeviceRegisters, DeviceRegistersVolatileFieldAccess}; +use virtio::vsock::Config; use volatile::VolatileRef; use crate::drivers::InterruptLine; -use crate::drivers::vsock::{EventQueue, RxQueue, TxQueue, VirtioVsockDriver, VsockDevCfg}; use crate::drivers::virtio::error::VirtioError; -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg, Transport}; +use crate::drivers::vsock::{EventQueue, RxQueue, TxQueue, VirtioVsockDriver, VsockDevCfg}; // Backend-dependent interface for Virtio vsock driver -impl VirtioVsockDriver { +impl VirtioVsockDriver { pub fn new( dev_id: u16, mut registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, - ) -> Result { + ) -> Result { let dev_cfg_raw: &'static Config = unsafe { &*registers .borrow_mut() @@ -53,7 +53,7 @@ impl VirtioVsockDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, - ) -> Result { + ) -> Result { let mut drv = VirtioVsockDriver::new(dev_id, registers, irq)?; drv.init_dev().map_err(VirtioError::VsockDriver)?; drv.com_cfg.print_information(); diff --git a/src/drivers/vsock/mod.rs b/src/drivers/vsock/mod.rs index 77588be9d1..77340c3157 100644 --- a/src/drivers/vsock/mod.rs +++ b/src/drivers/vsock/mod.rs @@ -23,17 +23,14 @@ use crate::config::VIRTIO_MAX_QUEUE_SIZE; use crate::drivers::Driver; use crate::drivers::virtio::ControlRegisters; use crate::drivers::virtio::error::VirtioVsockError; -#[cfg(not(feature = "pci"))] -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; -#[cfg(feature = "pci")] -use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg}; +use crate::drivers::virtio::transport::{ComCfg, IsrStatus, Transport}; use crate::drivers::virtio::virtqueue::split::SplitVq; use crate::drivers::virtio::virtqueue::{ AvailBufferToken, BufferElem, BufferType, UsedBufferToken, Virtq, }; use crate::mm::device_alloc::DeviceAlloc; -fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) { +fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) { for _ in 0..num_packets { let buff_tkn = match AvailBufferToken::new( SmallVec::new(), @@ -62,12 +59,12 @@ fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) { } } -pub(crate) struct RxQueue { - vq: Option, +pub(crate) struct RxQueue { + vq: Option>, packet_size: u32, } -impl RxQueue { +impl RxQueue { pub fn new() -> Self { Self { vq: None, @@ -76,7 +73,7 @@ impl RxQueue { } } - pub fn add(&mut self, mut vq: VirtQueue) { + pub fn add(&mut self, mut vq: VirtQueue) { const BUFF_PER_PACKET: u16 = 2; let num_packets = vq.size() / BUFF_PER_PACKET; info!("num_packets {num_packets}"); @@ -127,14 +124,14 @@ impl RxQueue { } } -pub(crate) struct TxQueue { - vq: Option, +pub(crate) struct TxQueue { + vq: Option>, /// Indicates, whether the Driver/Device are using multiple /// queues for communication. packet_length: u32, } -impl TxQueue { +impl TxQueue { pub fn new() -> Self { Self { vq: None, @@ -142,7 +139,7 @@ impl TxQueue { } } - pub fn add(&mut self, vq: VirtQueue) { + pub fn add(&mut self, vq: VirtQueue) { self.vq = Some(vq); } @@ -206,12 +203,12 @@ impl TxQueue { } } -pub(crate) struct EventQueue { - vq: Option, +pub(crate) struct EventQueue { + vq: Option>, packet_size: u32, } -impl EventQueue { +impl EventQueue { pub fn new() -> Self { Self { vq: None, @@ -222,7 +219,7 @@ impl EventQueue { /// Adds a given queue to the underlying vector and populates the queue with RecvBuffers. /// /// Queues are all populated according to Virtio specification v1.1. - 5.1.6.3.1 - fn add(&mut self, mut vq: VirtQueue) { + fn add(&mut self, mut vq: VirtQueue) { const BUFF_PER_PACKET: u16 = 2; let num_packets = vq.size() / BUFF_PER_PACKET; fill_queue(&mut vq, num_packets, self.packet_size); @@ -255,19 +252,19 @@ pub(crate) struct VsockDevCfg { pub features: virtio::vsock::F, } -pub(crate) struct VirtioVsockDriver { +pub(crate) struct VirtioVsockDriver { pub(super) dev_cfg: VsockDevCfg, - pub(super) com_cfg: ComCfg, - pub(super) isr_stat: IsrStatus, - pub(super) notif_cfg: NotifCfg, + pub(super) com_cfg: T::ComCfg, + pub(super) isr_stat: T::IsrStatus, + pub(super) notif_cfg: T::NotifCfg, pub(super) irq: InterruptLine, - pub(super) event_vq: EventQueue, - pub(super) recv_vq: RxQueue, - pub(super) send_vq: TxQueue, + pub(super) event_vq: EventQueue, + pub(super) recv_vq: RxQueue, + pub(super) send_vq: TxQueue, } -impl Driver for VirtioVsockDriver { +impl Driver for VirtioVsockDriver { fn get_interrupt_number(&self) -> InterruptLine { self.irq } @@ -277,7 +274,7 @@ impl Driver for VirtioVsockDriver { } } -impl VirtioVsockDriver { +impl VirtioVsockDriver { #[cfg(feature = "pci")] pub fn get_dev_id(&self) -> u16 { self.dev_cfg.dev_id @@ -308,14 +305,9 @@ impl VirtioVsockDriver { pub fn handle_interrupt(&mut self) { let status = self.isr_stat.acknowledge(); - #[cfg(not(feature = "pci"))] - if status.contains(virtio::mmio::InterruptStatus::CONFIGURATION_CHANGE_NOTIFICATION) { - info!("Configuration changes are not possible! Aborting"); - todo!("Implement possibility to change config on the fly...") - } - - #[cfg(feature = "pci")] - if status.contains(virtio::pci::IsrStatus::DEVICE_CONFIGURATION_INTERRUPT) { + if status & ::CONFIGURATION_CHANGE + == ::CONFIGURATION_CHANGE + { info!("Configuration changes are not possible! Aborting"); todo!("Implement possibility to change config on the fly...") } diff --git a/src/drivers/vsock/pci.rs b/src/drivers/vsock/pci.rs index 6b3c64c9ed..dedb7ddc7d 100644 --- a/src/drivers/vsock/pci.rs +++ b/src/drivers/vsock/pci.rs @@ -4,10 +4,10 @@ use crate::arch::pci::PciConfigRegion; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; use crate::drivers::virtio::transport::pci; -use crate::drivers::virtio::transport::pci::{PciCap, UniCapsColl}; +use crate::drivers::virtio::transport::pci::{PciCap, Transport, UniCapsColl}; use crate::drivers::vsock::{EventQueue, RxQueue, TxQueue, VirtioVsockDriver, VsockDevCfg}; -impl VirtioVsockDriver { +impl VirtioVsockDriver { fn map_cfg(cap: &PciCap) -> Option { let dev_cfg = pci::map_dev_cfg::(cap)?; @@ -58,7 +58,7 @@ impl VirtioVsockDriver { /// Returns a driver instance of VirtioVsockDriver. pub(crate) fn init( device: &PciDevice, - ) -> Result { + ) -> Result, VirtioError> { let mut drv = match pci::map_caps(device) { Ok(caps) => match VirtioVsockDriver::new(caps, device) { Ok(driver) => driver,