diff --git a/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs b/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs index 4ec817c..c4fd3fd 100644 --- a/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs +++ b/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs @@ -1,4 +1,5 @@ use std::sync::Arc; +use std::sync::Mutex; use tokio::sync::Notify; use vm_core::arch::irq::InterruptController; @@ -81,7 +82,7 @@ where &self, queue: usize, notifier: Arc, - dev: VirtioDev, + dev: Arc>>, ) -> Option> { match VirtioBalloonTranditionalVirtqueue::from_repr(queue) { Some(virtq) => match virtq { diff --git a/crates/vm-device/src/device/virtio/virtio_blk.rs b/crates/vm-device/src/device/virtio/virtio_blk.rs index 92e6a54..1e46450 100644 --- a/crates/vm-device/src/device/virtio/virtio_blk.rs +++ b/crates/vm-device/src/device/virtio/virtio_blk.rs @@ -1,4 +1,5 @@ use std::sync::Arc; +use std::sync::Mutex; use tokio::sync::Notify; use vm_core::arch::irq::InterruptController; @@ -110,7 +111,7 @@ where &self, queue_sel: usize, notifier: Arc, - dev: VirtioDev, + dev: Arc>>, ) -> Option> { if queue_sel != 0 { return None; diff --git a/crates/vm-device/src/device/virtio/virtio_mmio_kbd.rs b/crates/vm-device/src/device/virtio/virtio_mmio_kbd.rs index 4f27fad..baba78c 100644 --- a/crates/vm-device/src/device/virtio/virtio_mmio_kbd.rs +++ b/crates/vm-device/src/device/virtio/virtio_mmio_kbd.rs @@ -28,7 +28,7 @@ use vm_virtio::types::device_features::VIRTIO_F_VERSION_1; use vm_virtio::types::driver_features::DriverFeatures; use vm_virtio::types::interrupt::InterruptStatus; use vm_virtio::types::status::Status; -use vm_virtio::types::virtqueue::split_virtqueue::VirtQueue; +use vm_virtio::types::virtqueue::split_virtqueue::Virtqueue; fn bit_to_index(bit: usize) -> (usize, usize) { (bit / 8, bit % 8) @@ -157,7 +157,7 @@ struct VirtIOMmioKbdInternal { driver_features: DriverFeatures, driver_feature_sel: Option, queue_sel: Option, - virtqueues: [VirtQueue; VIRTIO_INPUT_VIRT_QUEUE as usize], + virtqueues: [Virtqueue; VIRTIO_INPUT_VIRT_QUEUE as usize], interrupt_status: InterruptStatus, status: Status, config_generation: u32, diff --git a/crates/vm-machine/src/device.rs b/crates/vm-machine/src/device.rs index acaa136..5249f71 100644 --- a/crates/vm-machine/src/device.rs +++ b/crates/vm-machine/src/device.rs @@ -12,6 +12,7 @@ use vm_mm::allocator::MemoryContainer; use vm_mm::manager::MemoryAddressSpace; use vm_pci::root_complex::mmio::PciRootComplexMmio; use vm_virtio::device::pci::VirtioPciDevice; +use vm_virtio::transport::VirtioDev; use crate::error::Error; @@ -74,7 +75,7 @@ impl InitDevice for DeviceManager { { let virtio_mmio_blk = VirtioMmioBlkDevice::new( - VirtioBlkDevice::new(2, irq_chip.clone(), mm.clone()), + VirtioDev::new(VirtioBlkDevice::new(2, irq_chip.clone(), mm.clone())), MmioRange { start: 0x0900_1000, len: 0x1000, @@ -89,7 +90,11 @@ impl InitDevice for DeviceManager { Device::VirtioMmioBalloon => { // TODO: use mmio allocator let virtio_mmio_balloon = VirtioMmioBalloonDevice::new( - VirtioBalloonTranditional::new(3, irq_chip.clone(), mm.clone()), + VirtioDev::new(VirtioBalloonTranditional::new( + 3, + irq_chip.clone(), + mm.clone(), + )), MmioRange { start: 0x0900_2000, len: 0x1000, diff --git a/crates/vm-virtio/src/device.rs b/crates/vm-virtio/src/device.rs index cd916f9..1c61cfc 100644 --- a/crates/vm-virtio/src/device.rs +++ b/crates/vm-virtio/src/device.rs @@ -1,4 +1,5 @@ use std::sync::Arc; +use std::sync::Mutex; use tokio::sync::Notify; use vm_core::arch::irq::InterruptController; @@ -7,15 +8,14 @@ use vm_mm::manager::MemoryAddressSpace; use crate::result::Result; use crate::transport::VirtioDev; -use crate::transport::VirtioDevInternal; use crate::types::interrupt_status::InterruptStatus; -use crate::virt_queue::virtq_desc_table::VirtqDescTableRef; +use crate::virtqueue::virtq_desc_table::VirtqDescTableRef; pub mod blk; pub mod pci; pub type VirtqueueHandlerFn = Box< - dyn Fn(&MemoryAddressSpace, &mut VirtioDevInternal, &VirtqDescTableRef, u16) -> u32 + dyn Fn(&MemoryAddressSpace, &mut VirtioDev, &VirtqDescTableRef, u16) -> u32 + Send + Sync, >; @@ -23,7 +23,7 @@ pub type VirtqueueHandlerFn = Box< pub struct VirtqueueHandler { pub queue_sel: usize, pub notifier: Arc, - pub dev: VirtioDev, + pub dev: Arc>>, pub mm: Arc>, pub irq_chip: Arc, pub irq_line: u32, @@ -114,7 +114,7 @@ pub trait VirtioDevice: Sized + Send + Sync + 'static { &self, queue: usize, notifier: Arc, - dev: VirtioDev, + dev: Arc>>, ) -> Option>; fn read_config(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<()>; diff --git a/crates/vm-virtio/src/device/pci.rs b/crates/vm-virtio/src/device/pci.rs index 355a2be..18f46b0 100644 --- a/crates/vm-virtio/src/device/pci.rs +++ b/crates/vm-virtio/src/device/pci.rs @@ -3,6 +3,7 @@ use vm_pci::device::function::type0::Type0Function; use vm_pci::device::pci_device::PciDevice; use crate::device::VirtioDevice; +use crate::transport::VirtioDev; use crate::transport::pci::VirtioPciFunction; pub trait VirtioPciDevice: VirtioDevice @@ -14,7 +15,9 @@ where const IRQ_PIN: u8; fn into_pci_device(self) -> PciDevice { - let virtio_function = VirtioPciFunction:: { dev: self.into() }; + let virtio_function = VirtioPciFunction:: { + dev: VirtioDev::new(self), + }; let function = Type0Function::new(virtio_function).unwrap(); PciDevice::from_single_function(Box::new(function)) } diff --git a/crates/vm-virtio/src/lib.rs b/crates/vm-virtio/src/lib.rs index 0d986fd..7dd06a0 100644 --- a/crates/vm-virtio/src/lib.rs +++ b/crates/vm-virtio/src/lib.rs @@ -4,4 +4,4 @@ pub mod device; pub mod result; pub mod transport; pub mod types; -pub mod virt_queue; +pub mod virtqueue; diff --git a/crates/vm-virtio/src/transport.rs b/crates/vm-virtio/src/transport.rs index 612eb43..a8f24a1 100644 --- a/crates/vm-virtio/src/transport.rs +++ b/crates/vm-virtio/src/transport.rs @@ -1,8 +1,6 @@ use std::marker::PhantomData; use std::sync::Arc; -use std::sync::LockResult; use std::sync::Mutex; -use std::sync::MutexGuard; use bitflags::Flags; use tokio::sync::Notify; @@ -14,32 +12,34 @@ use crate::result::Result; use crate::transport::control_register::ControlRegister; use crate::types::interrupt_status::InterruptStatus; use crate::types::status::Status; -use crate::virt_queue::VirtQueue; +use crate::virtqueue::Virtqueue; pub mod control_register; pub mod mmio; pub mod pci; -pub struct VirtioDev(Arc>>); +pub struct VirtioDev { + device: D, -impl Clone for VirtioDev { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} + device_feature_sel: Option, + driver_features: u64, + driver_feature_sel: Option, + queue_sel: Option, + virtqueues: Vec>, + virtqueue_notifiers: Vec>>, + interrupt_status: InterruptStatus, + status: Status, + config_generation: u32, -impl VirtioDev { - pub fn lock(&self) -> LockResult>> { - self.0.lock() - } + _mark: PhantomData, } -impl From for VirtioDev +impl VirtioDev where C: MemoryContainer, D: VirtioDevice, { - fn from(device: D) -> Self { + pub fn new(device: D) -> Arc> { let virtqueues_size_max = device.virtqueues_size_max(); let virtqueue_notifiers = virtqueues_size_max @@ -49,10 +49,10 @@ where let virtqueues = virtqueues_size_max .iter() - .map(|size_max| size_max.map(VirtQueue::new)) + .map(|size_max| size_max.map(Virtqueue::new)) .collect(); - let internal = Arc::new(Mutex::new(VirtioDevInternal { + let virtio_dev = Arc::new(Mutex::new(VirtioDev { device, device_feature_sel: Default::default(), driver_features: Default::default(), @@ -66,8 +66,6 @@ where _mark: PhantomData, })); - let virtio_dev = VirtioDev(internal); - { let dev = virtio_dev.lock().unwrap(); @@ -94,23 +92,7 @@ where } } -pub struct VirtioDevInternal { - device: D, - - device_feature_sel: Option, - driver_features: u64, - driver_feature_sel: Option, - queue_sel: Option, - virtqueues: Vec>, - virtqueue_notifiers: Vec>>, - interrupt_status: InterruptStatus, - status: Status, - config_generation: u32, - - _mark: PhantomData, -} - -impl VirtioDevInternal +impl VirtioDev where D: VirtioDevice, { @@ -322,11 +304,11 @@ where self.device.write_config(offset, len, buf) } - pub fn get_virtqueue(&self, queue_sel: usize) -> Option<&VirtQueue> { + pub fn get_virtqueue(&self, queue_sel: usize) -> Option<&Virtqueue> { self.virtqueues.get(queue_sel).unwrap().as_ref() } - pub fn get_virtqueue_mut(&mut self, queue_sel: usize) -> Option<&mut VirtQueue> { + pub fn get_virtqueue_mut(&mut self, queue_sel: usize) -> Option<&mut Virtqueue> { self.virtqueues.get_mut(queue_sel).unwrap().as_mut() } diff --git a/crates/vm-virtio/src/transport/mmio.rs b/crates/vm-virtio/src/transport/mmio.rs index d6aa99d..ccbb954 100644 --- a/crates/vm-virtio/src/transport/mmio.rs +++ b/crates/vm-virtio/src/transport/mmio.rs @@ -1,3 +1,6 @@ +use std::sync::Arc; +use std::sync::Mutex; + use vm_core::device::Device; use vm_core::device::mmio::MmioRange; use vm_core::device::mmio::mmio_device::MmioDevice; @@ -14,6 +17,9 @@ mod control_register; const CONFIGURATION_SPACE_OFFSET: usize = 0x100; mod handler { + use std::sync::Arc; + use std::sync::Mutex; + use tracing::debug; use tracing::error; use tracing::warn; @@ -24,7 +30,6 @@ mod handler { use crate::device::VirtioDevice; use crate::result::Result as VirtioResult; use crate::transport::VirtioDev; - use crate::transport::VirtioDevInternal; use crate::transport::control_register::ControlRegister; use crate::transport::mmio::CONFIGURATION_SPACE_OFFSET; use crate::transport::mmio::control_register::MmioControlRegister; @@ -32,21 +37,21 @@ mod handler { pub struct Handler { mmio_range: MmioRange, - transport: VirtioDev, + transport: Arc>>, } impl Handler where D: VirtioDevice, { - pub fn new(mmio_range: MmioRange, transport: VirtioDev) -> Self { + pub fn new(mmio_range: MmioRange, transport: Arc>>) -> Self { Handler { mmio_range, transport, } } - fn read_reg(&self, transport: &VirtioDevInternal, reg: MmioControlRegister) -> u32 { + fn read_reg(&self, transport: &VirtioDev, reg: MmioControlRegister) -> u32 { match reg { MmioControlRegister::MagicValue => u32::from_le_bytes(*b"virt"), MmioControlRegister::Version => 0x2, @@ -73,7 +78,7 @@ mod handler { fn write_reg( &self, - transport: &mut VirtioDevInternal, + transport: &mut VirtioDev, reg: MmioControlRegister, val: u32, ) -> VirtioResult<()> { @@ -218,8 +223,7 @@ mod handler { pub struct VirtioMmioTransport { mmio_range: MmioRange, - irq: Option, - dev: VirtioDev, + dev: Arc>>, } impl VirtioMmioTransport @@ -227,10 +231,9 @@ where C: MemoryContainer, D: VirtioDevice, { - pub fn new(device: D, mmio_range: MmioRange) -> Self { + pub fn new(device: Arc>>, mmio_range: MmioRange) -> Self { VirtioMmioTransport { mmio_range, - irq: device.irq(), dev: device.into(), } } @@ -260,11 +263,13 @@ where } fn generate_dt(&self, fdt: &mut FdtWriter) -> Result<(), vm_fdt::Error> { + let dev = self.dev.lock().unwrap(); + let node = fdt.begin_node(&format!("{}@{:x}", self.name(), self.mmio_range.start))?; fdt.property_string("compatible", "virtio,mmio")?; fdt.property_array_u64("reg", &[self.mmio_range.start, self.mmio_range.len as u64])?; - if let Some(_irq) = self.irq { + if let Some(_irq) = dev.device.irq() { #[cfg(target_arch = "aarch64")] { use vm_core::arch::aarch64::irq::GIC_SPI; diff --git a/crates/vm-virtio/src/transport/pci.rs b/crates/vm-virtio/src/transport/pci.rs index f7c7843..b36732c 100644 --- a/crates/vm-virtio/src/transport/pci.rs +++ b/crates/vm-virtio/src/transport/pci.rs @@ -1,3 +1,6 @@ +use std::sync::Arc; +use std::sync::Mutex; + use vm_mm::allocator::MemoryContainer; use vm_pci::device::function::BarHandler; use vm_pci::device::function::PciTypeFunctionCommon; @@ -25,7 +28,7 @@ where C: MemoryContainer, D: VirtioPciDevice, { - dev: VirtioDev, + dev: Arc>>, } impl BarHandler for NotifyHandler @@ -40,9 +43,8 @@ where fn write(&self, _offset: u64, data: &[u8]) { assert_eq!(data.len(), 2); let queue_index = u16::from_le_bytes(data.try_into().unwrap()); - let mut transport = self.dev.lock().unwrap(); - transport - .write_reg(ControlRegister::QueueNotify, queue_index.into()) + let mut dev = self.dev.lock().unwrap(); + dev.write_reg(ControlRegister::QueueNotify, queue_index.into()) .unwrap(); } } @@ -52,7 +54,7 @@ where C: MemoryContainer, D: VirtioPciDevice, { - transport: VirtioDev, + dev: Arc>>, } impl BarHandler for IsrHandler @@ -61,19 +63,17 @@ where D: VirtioPciDevice, { fn read(&self, _offset: u64, data: &mut [u8]) { - let mut transport = self.transport.lock().unwrap(); + let mut dev = self.dev.lock().unwrap(); - let isr = transport.read_reg(ControlRegister::InterruptStatus); + let isr = dev.read_reg(ControlRegister::InterruptStatus); data[0] = isr as u8; /* * From `4.1.4.5.1 Device Requirements: ISR status capability` * - The device MUST reset ISR status to 0 on driver read. */ - transport - .write_reg(ControlRegister::InterruptStatus, 0) - .unwrap(); - transport.device.trigger_irq(false); + dev.write_reg(ControlRegister::InterruptStatus, 0).unwrap(); + dev.device.trigger_irq(false); } fn write(&self, _offset: u64, _data: &[u8]) { @@ -86,7 +86,7 @@ where C: MemoryContainer, D: VirtioPciDevice, { - transport: VirtioDev, + dev: Arc>>, } impl BarHandler for DeviceHandler @@ -95,18 +95,16 @@ where D: VirtioPciDevice, { fn read(&self, offset: u64, data: &mut [u8]) { - let transport = self.transport.lock().unwrap(); + let dev = self.dev.lock().unwrap(); - transport - .read_config(offset.try_into().unwrap(), data.len(), data) + dev.read_config(offset.try_into().unwrap(), data.len(), data) .unwrap(); } fn write(&self, offset: u64, data: &[u8]) { - let mut transport = self.transport.lock().unwrap(); + let mut dev = self.dev.lock().unwrap(); - transport - .write_config(offset.try_into().unwrap(), data.len(), data) + dev.write_config(offset.try_into().unwrap(), data.len(), data) .unwrap(); } } @@ -116,7 +114,7 @@ where C: MemoryContainer, D: VirtioPciDevice, { - pub dev: VirtioDev, + pub dev: Arc>>, } impl PciTypeFunctionCommon for VirtioPciFunction @@ -222,16 +220,16 @@ where fn bar_handler(&self, bar: Bar) -> Option> { match bar { Bar::Bar0 => Some(Box::new(CommonConfigHandler { - transport: self.dev.clone(), + dev: self.dev.clone(), })), Bar::Bar1 => Some(Box::new(NotifyHandler { dev: self.dev.clone(), })), Bar::Bar2 => Some(Box::new(IsrHandler { - transport: self.dev.clone(), + dev: self.dev.clone(), })), Bar::Bar3 => Some(Box::new(DeviceHandler { - transport: self.dev.clone(), + dev: self.dev.clone(), })), _ => None, } diff --git a/crates/vm-virtio/src/transport/pci/common_config_handler.rs b/crates/vm-virtio/src/transport/pci/common_config_handler.rs index 418f427..b8161dd 100644 --- a/crates/vm-virtio/src/transport/pci/common_config_handler.rs +++ b/crates/vm-virtio/src/transport/pci/common_config_handler.rs @@ -1,3 +1,6 @@ +use std::sync::Arc; +use std::sync::Mutex; + use strum_macros::FromRepr; use tracing::warn; use vm_mm::allocator::MemoryContainer; @@ -43,7 +46,7 @@ where C: MemoryContainer, D: VirtioPciDevice, { - pub transport: VirtioDev, + pub dev: Arc>>, } impl BarHandler for CommonConfigHandler @@ -57,13 +60,13 @@ where return; }; - let transport = self.transport.lock().unwrap(); + let dev = self.dev.lock().unwrap(); match offset { CommonCfgOffset::DeviceFeatureSelect => todo!(), CommonCfgOffset::DeviceFeature => { assert_eq!(data.len(), 4); - let feat = transport.read_reg(ControlRegister::DeviceFeatures); + let feat = dev.read_reg(ControlRegister::DeviceFeatures); data.copy_from_slice(&feat.to_le_bytes()); } CommonCfgOffset::DriverFeatureSelect => todo!(), @@ -71,16 +74,16 @@ where CommonCfgOffset::ConfigMsixVector => todo!(), CommonCfgOffset::NumQueues => { assert_eq!(data.len(), 2); - let num_queues = transport.device.num_queues(); + let num_queues = dev.device.num_queues(); data.copy_from_slice(&num_queues.to_le_bytes()); } CommonCfgOffset::DeviceStatus => { assert_eq!(data.len(), 1); - let status = transport.read_reg(ControlRegister::Status); + let status = dev.read_reg(ControlRegister::Status); data[0] = status.try_into().unwrap(); } CommonCfgOffset::ConfigGeneration => { - let cfg_generation: u8 = transport + let cfg_generation: u8 = dev .read_reg(ControlRegister::ConfigGeneration) .try_into() .unwrap(); @@ -89,16 +92,13 @@ where CommonCfgOffset::QueueSelect => todo!(), CommonCfgOffset::QueueSize => { assert_eq!(data.len(), 2); - let queue_size: u16 = transport - .read_reg(ControlRegister::QueueSize) - .try_into() - .unwrap(); + let queue_size: u16 = dev.read_reg(ControlRegister::QueueSize).try_into().unwrap(); data.copy_from_slice(&queue_size.to_le_bytes()); } CommonCfgOffset::QueueMsixVector => todo!(), CommonCfgOffset::QueueEnable => { assert_eq!(data.len(), 2); - let queue_ready = transport.read_reg(ControlRegister::QueueReady) as u16; + let queue_ready = dev.read_reg(ControlRegister::QueueReady) as u16; data.copy_from_slice(&queue_ready.to_le_bytes()); } CommonCfgOffset::QueueNotifyOff => { @@ -124,94 +124,75 @@ where return; }; - let mut transport = self.transport.lock().unwrap(); + let mut dev = self.dev.lock().unwrap(); match offset { CommonCfgOffset::DeviceFeatureSelect => { assert_eq!(data.len(), 4); let sel = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::DeviceFeaturesSel, sel) + dev.write_reg(ControlRegister::DeviceFeaturesSel, sel) .unwrap(); } CommonCfgOffset::DriverFeatureSelect => { assert_eq!(data.len(), 4); let sel = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::DriverFeaturesSel, sel) + dev.write_reg(ControlRegister::DriverFeaturesSel, sel) .unwrap(); } CommonCfgOffset::DriverFeature => { assert_eq!(data.len(), 4); let sel = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::DriverFeatures, sel) - .unwrap(); + dev.write_reg(ControlRegister::DriverFeatures, sel).unwrap(); } CommonCfgOffset::ConfigMsixVector => todo!(), CommonCfgOffset::DeviceStatus => { assert_eq!(data.len(), 1); let status = data[0]; - transport - .write_reg(ControlRegister::Status, status as u32) + dev.write_reg(ControlRegister::Status, status as u32) .unwrap(); } CommonCfgOffset::QueueSelect => { assert_eq!(data.len(), 2); let sel = u16::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueSel, sel as u32) + dev.write_reg(ControlRegister::QueueSel, sel as u32) .unwrap(); } CommonCfgOffset::QueueSize => { assert_eq!(data.len(), 2); let queue_size = u16::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueSize, queue_size as u32) + dev.write_reg(ControlRegister::QueueSize, queue_size as u32) .unwrap(); } CommonCfgOffset::QueueMsixVector => todo!(), CommonCfgOffset::QueueEnable => { let queue_enable = u16::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueReady, queue_enable as u32) + dev.write_reg(ControlRegister::QueueReady, queue_enable as u32) .unwrap(); } CommonCfgOffset::QueueDescLow => { let addr = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueDescLow, addr) - .unwrap(); + dev.write_reg(ControlRegister::QueueDescLow, addr).unwrap(); } CommonCfgOffset::QueueDescHigh => { let addr = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueDescHigh, addr) - .unwrap(); + dev.write_reg(ControlRegister::QueueDescHigh, addr).unwrap(); } CommonCfgOffset::QueueDriverLow => { let addr = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueAvailLow, addr) - .unwrap(); + dev.write_reg(ControlRegister::QueueAvailLow, addr).unwrap(); } CommonCfgOffset::QueueDriverHigh => { let addr = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueAvailHigh, addr) + dev.write_reg(ControlRegister::QueueAvailHigh, addr) .unwrap(); } CommonCfgOffset::QueueDeviceLow => { let addr = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueUsedLow, addr) - .unwrap(); + dev.write_reg(ControlRegister::QueueUsedLow, addr).unwrap(); } CommonCfgOffset::QueueDeviceHigh => { let addr = u32::from_le_bytes(data.try_into().unwrap()); - transport - .write_reg(ControlRegister::QueueUsedHigh, addr) - .unwrap(); + dev.write_reg(ControlRegister::QueueUsedHigh, addr).unwrap(); } _ => { warn!(?offset, "write to a RO cfg"); diff --git a/crates/vm-virtio/src/virt_queue.rs b/crates/vm-virtio/src/virtqueue.rs similarity index 73% rename from crates/vm-virtio/src/virt_queue.rs rename to crates/vm-virtio/src/virtqueue.rs index a3ab91f..7833237 100644 --- a/crates/vm-virtio/src/virt_queue.rs +++ b/crates/vm-virtio/src/virtqueue.rs @@ -1,14 +1,11 @@ -use std::cell::OnceCell; - -use tracing::warn; use vm_mm::allocator::MemoryContainer; use vm_mm::manager::MemoryAddressSpace; use crate::result::Result; use crate::result::VirtioError; -use crate::virt_queue::virtq_avail_ring::VirtqAvail; -use crate::virt_queue::virtq_desc_table::VirtqDescTableRef; -use crate::virt_queue::virtq_used_ring::VirtqUsed; +use crate::virtqueue::virtq_avail_ring::VirtqAvail; +use crate::virtqueue::virtq_desc_table::VirtqDescTableRef; +use crate::virtqueue::virtq_used_ring::VirtqUsed; pub mod virtq_avail_ring; pub mod virtq_desc_table; @@ -24,22 +21,22 @@ fn to_gpa(high: Option<&u32>, low: Option<&u32>) -> Option { } } -pub struct VirtQueue { +pub struct Virtqueue { queue_size_max: u32, queue_size: u16, queue_ready: bool, - queue_desc_low: OnceCell, - queue_desc_high: OnceCell, - queue_available_low: OnceCell, - queue_available_high: OnceCell, - queue_used_low: OnceCell, - queue_used_high: OnceCell, + queue_desc_low: Option, + queue_desc_high: Option, + queue_available_low: Option, + queue_available_high: Option, + queue_used_low: Option, + queue_used_high: Option, last_available_idx: u16, } -impl VirtQueue { +impl Virtqueue { pub fn new(queue_size_max: u32) -> Self { - VirtQueue { + Virtqueue { queue_size_max, queue_size: queue_size_max.try_into().unwrap(), // virtio-pci uses it as maximal queue size, does it work on mmio? queue_ready: Default::default(), @@ -86,39 +83,27 @@ impl VirtQueue { } pub fn write_queue_desc_low(&mut self, addr: u32) { - if self.queue_desc_low.set(addr).is_err() { - warn!("repeated writes to queue_desc_low are ignored") - } + self.queue_desc_low = Some(addr); } pub fn write_queue_desc_high(&mut self, addr: u32) { - if self.queue_desc_high.set(addr).is_err() { - warn!("repeated writes to queue_desc_high are ignored") - } + self.queue_desc_high = Some(addr); } pub fn write_queue_available_low(&mut self, addr: u32) { - if self.queue_available_low.set(addr).is_err() { - warn!("repeated writes to queue_available_low are ignored") - } + self.queue_available_low = Some(addr); } pub fn write_queue_available_high(&mut self, addr: u32) { - if self.queue_available_high.set(addr).is_err() { - warn!("repeated writes to queue_available_high are ignored") - } + self.queue_available_high = Some(addr); } pub fn write_queue_used_low(&mut self, addr: u32) { - if self.queue_used_low.set(addr).is_err() { - warn!("repeated writes to queue_used_low are ignored") - } + self.queue_used_low = Some(addr); } pub fn write_queue_used_high(&mut self, addr: u32) { - if self.queue_used_high.set(addr).is_err() { - warn!("repeated writes to queue_used_high are ignored") - } + self.queue_used_high = Some(addr); } pub fn desc_table_ref(&self, mm: &MemoryAddressSpace) -> Result @@ -172,17 +157,17 @@ impl VirtQueue { } fn queue_desc_table_gpa(&self) -> Option { - to_gpa(self.queue_desc_high.get(), self.queue_desc_low.get()) + to_gpa(self.queue_desc_high.as_ref(), self.queue_desc_low.as_ref()) } fn queue_available_ring_gpa(&self) -> Option { to_gpa( - self.queue_available_high.get(), - self.queue_available_low.get(), + self.queue_available_high.as_ref(), + self.queue_available_low.as_ref(), ) } fn queue_used_ring_gpa(&self) -> Option { - to_gpa(self.queue_used_high.get(), self.queue_used_low.get()) + to_gpa(self.queue_used_high.as_ref(), self.queue_used_low.as_ref()) } } diff --git a/crates/vm-virtio/src/virt_queue/virtq_avail_ring.rs b/crates/vm-virtio/src/virtqueue/virtq_avail_ring.rs similarity index 100% rename from crates/vm-virtio/src/virt_queue/virtq_avail_ring.rs rename to crates/vm-virtio/src/virtqueue/virtq_avail_ring.rs diff --git a/crates/vm-virtio/src/virt_queue/virtq_desc_table.rs b/crates/vm-virtio/src/virtqueue/virtq_desc_table.rs similarity index 100% rename from crates/vm-virtio/src/virt_queue/virtq_desc_table.rs rename to crates/vm-virtio/src/virtqueue/virtq_desc_table.rs diff --git a/crates/vm-virtio/src/virt_queue/virtq_used_ring.rs b/crates/vm-virtio/src/virtqueue/virtq_used_ring.rs similarity index 100% rename from crates/vm-virtio/src/virt_queue/virtq_used_ring.rs rename to crates/vm-virtio/src/virtqueue/virtq_used_ring.rs