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 62323fb..cd4040c 100644 --- a/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs +++ b/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use std::sync::Arc; use std::sync::Mutex; @@ -6,8 +7,9 @@ use vm_core::arch::irq::InterruptController; use vm_mm::allocator::MemoryContainer; use vm_mm::manager::MemoryAddressSpace; use vm_virtio::device::VirtioDevice; -use vm_virtio::device::VirtqueueHandler; -use vm_virtio::device::VirtqueueHandlerFn; +use vm_virtio::device::transport::TransportContext; +use vm_virtio::device::virtqueue::VirtqueueHandler; +use vm_virtio::device::virtqueue::VirtqueueHandlerFn; use vm_virtio::result::Result; use vm_virtio::transport::VirtioDev; use vm_virtio::transport::mmio::VirtioMmioTransport; @@ -20,12 +22,50 @@ use zerocopy::IntoBytes; const INFLATEQ_QUEUE_SIZE_MAX: u32 = 512; const DEFLATEQ_QUEUE_SIZE_MAX: u32 = 512; -fn inflateq_handler() -> VirtqueueHandlerFn { - Box::new(|_mm, _dev, _desc_ring, _desc_id| todo!()) +fn inflateq_handler() -> VirtqueueHandlerFn> +where + C: MemoryContainer, +{ + Box::new(|mm, dev, desc_ring, desc_id| { + let desc = desc_ring.get(desc_id); + let len = desc.len; + assert!(len.is_multiple_of(4)); + + let array = desc.addr(mm).unwrap().as_ptr() as *const u32; + + for i in 0..(len / 4) { + let pfn = unsafe { *array.add(i as usize) }; + assert!(dev.device.balloon.insert(pfn)); + let gpa = (pfn as u64) << 12; + let _hva = mm.gpa_to_hva(gpa).unwrap(); + // TODO: mmap + } + + len + }) } -fn deflateq_handler() -> VirtqueueHandlerFn { - Box::new(|_mm, _dev, _desc_ring, _desc_id| todo!()) +fn deflateq_handler() -> VirtqueueHandlerFn> +where + C: MemoryContainer, +{ + Box::new(|mm, dev, desc_ring, desc_id| { + let desc = desc_ring.get(desc_id); + let len = desc.len; + assert!(len.is_multiple_of(4)); + + let array = desc.addr(mm).unwrap().as_ptr() as *const u32; + + for i in 0..(len / 4) { + let pfn = unsafe { *array.add(i as usize) }; + assert!(dev.device.balloon.remove(&pfn)); + let gpa = (pfn as u64) << 12; + let _hva = mm.gpa_to_hva(gpa).unwrap(); + // TODO: mmap + } + + len + }) } pub struct VirtioBalloonTranditional @@ -36,6 +76,7 @@ where irq_chip: Arc, mm: Arc>, cfg: VirtioBalloonTranditionalConfig, + balloon: HashSet, } impl VirtioBalloonTranditional @@ -52,8 +93,15 @@ where irq_chip, mm, cfg: VirtioBalloonTranditionalConfig::default(), + balloon: Default::default(), } } + + pub fn set_num_pages(&mut self, num_pages: u32) { + self.cfg.num_pages = num_pages; + + todo!("notify config generation changes"); + } } impl VirtioDevice for VirtioBalloonTranditional @@ -112,15 +160,43 @@ where } } - fn read_config(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<()> { - buf.copy_from_slice(&self.cfg.as_bytes()[offset..offset + len]); + fn read_config(&self, offset: usize, buf: &mut [u8]) -> Result<()> { + buf.copy_from_slice(&self.cfg.as_bytes()[offset..offset + buf.len()]); Ok(()) } - fn write_config(&mut self, offset: usize, len: usize, buf: &[u8]) -> Result<()> { - self.cfg.as_mut_bytes()[offset..len].copy_from_slice(buf); + fn write_config(&mut self, offset: usize, buf: &[u8]) -> Result<()> { + self.cfg.as_mut_bytes()[offset..offset + buf.len()].copy_from_slice(buf); Ok(()) } + + fn transport_context(&self) -> &dyn TransportContext { + todo!() + } + + fn transport_context_mit(&mut self) -> &mut dyn TransportContext { + todo!() + } +} + +pub trait VirtioBalloonApi { + fn update_num_pages(&mut self, num_pages: u32); +} + +pub type VirtioBalloonDev = VirtioDev>; + +impl VirtioBalloonApi for VirtioBalloonDev +where + C: MemoryContainer, +{ + fn update_num_pages(&mut self, num_pages: u32) { + if self.device.cfg.num_pages == num_pages { + return; + } + + self.device.cfg.num_pages = num_pages; + self.update_config_generation_and_notify(); + } } pub type VirtioMmioBalloonDevice = VirtioMmioTransport>; diff --git a/crates/vm-device/src/device/virtio/virtio_blk.rs b/crates/vm-device/src/device/virtio/virtio_blk.rs index 56ee8eb..ebb14a0 100644 --- a/crates/vm-device/src/device/virtio/virtio_blk.rs +++ b/crates/vm-device/src/device/virtio/virtio_blk.rs @@ -7,15 +7,16 @@ use vm_mm::allocator::MemoryContainer; use vm_mm::manager::MemoryAddressSpace; use vm_pci::device::interrupt::legacy::InterruptPin; use vm_virtio::device::VirtioDevice; -use vm_virtio::device::VirtqueueHandler; -use vm_virtio::device::VirtqueueHandlerFn; -use vm_virtio::device::blk::config::VirtioBlkConfig; -use vm_virtio::device::blk::req::VirtioBlkReq; -use vm_virtio::device::blk::req::VirtioBlkReqType; -use vm_virtio::device::pci::VirtioPciDevice; +use vm_virtio::device::transport::TransportContext; +use vm_virtio::device::virtqueue::VirtqueueHandler; +use vm_virtio::device::virtqueue::VirtqueueHandlerFn; use vm_virtio::result::Result; use vm_virtio::transport::VirtioDev; use vm_virtio::transport::mmio::VirtioMmioTransport; +use vm_virtio::transport::pci::VirtioPciDevice; +use vm_virtio::types::device::blk::config::VirtioBlkConfig; +use vm_virtio::types::device::blk::req::VirtioBlkReq; +use vm_virtio::types::device::blk::req::VirtioBlkReqType; use vm_virtio::types::device_features::VIRTIO_F_VERSION_1; use vm_virtio::types::device_id::DeviceId; use zerocopy::IntoBytes; @@ -128,15 +129,23 @@ where }) } - fn read_config(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<()> { - buf.copy_from_slice(&self.cfg.as_bytes()[offset..offset + len]); + fn read_config(&self, offset: usize, buf: &mut [u8]) -> Result<()> { + buf.copy_from_slice(&self.cfg.as_bytes()[offset..offset + buf.len()]); Ok(()) } - fn write_config(&mut self, offset: usize, len: usize, buf: &[u8]) -> Result<()> { - self.cfg.as_mut_bytes()[offset..len].copy_from_slice(buf); + fn write_config(&mut self, offset: usize, buf: &[u8]) -> Result<()> { + self.cfg.as_mut_bytes()[offset..offset + buf.len()].copy_from_slice(buf); Ok(()) } + + fn transport_context(&self) -> &dyn TransportContext { + todo!() + } + + fn transport_context_mit(&mut self) -> &mut dyn TransportContext { + todo!() + } } impl VirtioPciDevice for VirtioBlkDevice diff --git a/crates/vm-machine/src/device.rs b/crates/vm-machine/src/device.rs index 5249f71..b607c86 100644 --- a/crates/vm-machine/src/device.rs +++ b/crates/vm-machine/src/device.rs @@ -1,9 +1,12 @@ use std::sync::Arc; +use std::thread::sleep; +use std::time::Duration; use vm_core::arch::irq::InterruptController; use vm_core::device::device_manager::DeviceManager; use vm_core::device::mmio::MmioRange; use vm_device::device::Device; +use vm_device::device::virtio::virtio_balloon_traditional::VirtioBalloonApi; use vm_device::device::virtio::virtio_balloon_traditional::VirtioBalloonTranditional; use vm_device::device::virtio::virtio_balloon_traditional::VirtioMmioBalloonDevice; use vm_device::device::virtio::virtio_blk::VirtioBlkDevice; @@ -11,8 +14,8 @@ use vm_device::device::virtio::virtio_blk::VirtioMmioBlkDevice; 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 vm_virtio::transport::pci::VirtioPciDevice; use crate::error::Error; @@ -88,13 +91,41 @@ impl InitDevice for DeviceManager { match device { Device::GicV3 => (), // irq_chip is initialized already Device::VirtioMmioBalloon => { - // TODO: use mmio allocator + let dev = VirtioDev::new(VirtioBalloonTranditional::new( + 3, + irq_chip.clone(), + mm.clone(), + )); + + if false { + std::thread::spawn({ + let dev = dev.clone(); + move || { + let mut i = 0; + loop { + i += 1; + + { + sleep(Duration::from_secs(5)); + + let mut dev = dev.lock().unwrap(); + dev.update_num_pages(i); + } + + { + sleep(Duration::from_secs(5)); + + let mut dev = dev.lock().unwrap(); + dev.update_num_pages(0); + } + } + } + }); + } + + // TODO: use mmio allocator? let virtio_mmio_balloon = VirtioMmioBalloonDevice::new( - VirtioDev::new(VirtioBalloonTranditional::new( - 3, - irq_chip.clone(), - mm.clone(), - )), + dev, MmioRange { start: 0x0900_2000, len: 0x1000, diff --git a/crates/vm-virtio/src/device.rs b/crates/vm-virtio/src/device.rs index 0bbca94..db1f6f0 100644 --- a/crates/vm-virtio/src/device.rs +++ b/crates/vm-virtio/src/device.rs @@ -2,89 +2,14 @@ use std::sync::Arc; use std::sync::Mutex; use tokio::sync::Notify; -use vm_core::arch::irq::InterruptController; -use vm_mm::allocator::MemoryContainer; -use vm_mm::manager::MemoryAddressSpace; +use crate::device::transport::TransportContext; +use crate::device::virtqueue::VirtqueueHandler; use crate::result::Result; use crate::transport::VirtioDev; -use crate::types::interrupt_status::InterruptStatus; -use crate::virtqueue::virtq_desc_table::VirtqDescTableRef; -pub mod blk; -pub mod pci; - -pub type VirtqueueHandlerFn = Box< - dyn Fn(&MemoryAddressSpace, &mut VirtioDev, &VirtqDescTableRef, u16) -> u32 - + Send - + Sync, ->; - -pub struct VirtqueueHandler { - pub queue_sel: usize, - pub notifier: Arc, - pub dev: Arc>>, - pub mm: Arc>, - pub irq_chip: Arc, - pub irq_line: u32, - pub handle_desc: VirtqueueHandlerFn, -} - -impl VirtqueueHandler -where - C: MemoryContainer, - D: VirtioDevice, -{ - pub async fn run(self) { - let mm = self.mm.as_ref(); - - loop { - self.notifier.notified().await; - - let mut dev = self.dev.lock().unwrap(); - - let mut updated = false; - loop { - let (desc_table, desc_id) = { - // fetch desc from avail ring - let q = dev.get_virtqueue_mut(self.queue_sel).unwrap(); - let avail_ring = q.avail_ring(mm).unwrap(); - - if q.last_available_idx() == avail_ring.idx() { - break; - } - - let last_available_idx = q.last_available_idx(); - let desc_id = avail_ring.ring(last_available_idx); - q.incr_last_available_idx(); - (q.desc_table_ref(mm).unwrap(), desc_id) - }; - - let len = (self.handle_desc)(mm, &mut dev, &desc_table, desc_id); - - { - // update used ring - let q = dev.get_virtqueue_mut(self.queue_sel).unwrap(); - - let mut used_ring = q.used_ring(mm).unwrap(); - let used_idx = used_ring.idx(); - let used_entry = used_ring.ring(used_idx); - used_entry.id = desc_id as u32; - used_entry.len = len; - used_ring.incr_idx(); - } - - updated = true; - } - - if updated { - let mut isr = dev.get_interrupt_status(); - isr.insert(InterruptStatus::VIRTIO_MMIO_INT_VRING); - dev.update_interrupt_status(isr); - } - } - } -} +pub mod transport; +pub mod virtqueue; pub trait VirtioDevice: Sized + Send + Sync + 'static { const NAME: &str; @@ -115,7 +40,11 @@ pub trait VirtioDevice: Sized + Send + Sync + 'static { dev: Arc>>, ) -> Option>; - fn read_config(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<()>; + fn read_config(&self, offset: usize, buf: &mut [u8]) -> Result<()>; + + fn write_config(&mut self, offset: usize, buf: &[u8]) -> Result<()>; + + fn transport_context(&self) -> &dyn TransportContext; - fn write_config(&mut self, offset: usize, len: usize, buf: &[u8]) -> Result<()>; + fn transport_context_mit(&mut self) -> &mut dyn TransportContext; } diff --git a/crates/vm-virtio/src/device/pci.rs b/crates/vm-virtio/src/device/pci.rs deleted file mode 100644 index a3cd038..0000000 --- a/crates/vm-virtio/src/device/pci.rs +++ /dev/null @@ -1,24 +0,0 @@ -use vm_mm::allocator::MemoryContainer; -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::VirtioPciTransport; - -pub trait VirtioPciDevice: VirtioDevice -where - C: MemoryContainer, -{ - const DEVICE_SPECIFICATION_CONFIGURATION_LEN: usize; - const CLASS_CODE: u32; - const IRQ_PIN: u8; - - fn into_pci_device(self) -> PciDevice { - let virtio_function = VirtioPciTransport:: { - 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/device/transport.rs b/crates/vm-virtio/src/device/transport.rs new file mode 100644 index 0000000..67999a1 --- /dev/null +++ b/crates/vm-virtio/src/device/transport.rs @@ -0,0 +1,8 @@ +pub enum NotificationEvent { + ConfigurationChange, + AvailableBuffer, +} + +pub trait TransportContext { + fn update_config_generation_and_notify(&self); +} diff --git a/crates/vm-virtio/src/device/virtqueue.rs b/crates/vm-virtio/src/device/virtqueue.rs new file mode 100644 index 0000000..1c67765 --- /dev/null +++ b/crates/vm-virtio/src/device/virtqueue.rs @@ -0,0 +1,84 @@ +use std::sync::Arc; +use std::sync::Mutex; + +use tokio::sync::Notify; +use vm_core::arch::irq::InterruptController; +use vm_mm::allocator::MemoryContainer; +use vm_mm::manager::MemoryAddressSpace; + +use crate::device::VirtioDevice; +use crate::transport::VirtioDev; +use crate::types::interrupt_status::InterruptStatus; +use crate::virtqueue::virtq_desc_table::VirtqDescTableRef; + +pub type VirtqueueHandlerFn = Box< + dyn Fn(&MemoryAddressSpace, &mut VirtioDev, &VirtqDescTableRef, u16) -> u32 + + Send + + Sync, +>; + +pub struct VirtqueueHandler { + pub queue_sel: usize, + pub notifier: Arc, + pub dev: Arc>>, + pub mm: Arc>, + pub irq_chip: Arc, + pub irq_line: u32, + pub handle_desc: VirtqueueHandlerFn, +} + +impl VirtqueueHandler +where + C: MemoryContainer, + D: VirtioDevice, +{ + pub async fn run(self) { + let mm = self.mm.as_ref(); + + loop { + self.notifier.notified().await; + + let mut dev = self.dev.lock().unwrap(); + + let mut updated = false; + loop { + let (desc_table, desc_id) = { + // fetch desc from avail ring + let q = dev.get_virtqueue_mut(self.queue_sel).unwrap(); + let avail_ring = q.avail_ring(mm).unwrap(); + + if q.last_available_idx() == avail_ring.idx() { + break; + } + + let last_available_idx = q.last_available_idx(); + let desc_id = avail_ring.ring(last_available_idx); + q.incr_last_available_idx(); + (q.desc_table_ref(mm).unwrap(), desc_id) + }; + + let len = (self.handle_desc)(mm, &mut dev, &desc_table, desc_id); + + { + // update used ring + let q = dev.get_virtqueue_mut(self.queue_sel).unwrap(); + + let mut used_ring = q.used_ring(mm).unwrap(); + let used_idx = used_ring.idx(); + let used_entry = used_ring.ring(used_idx); + used_entry.id = desc_id as u32; + used_entry.len = len; + used_ring.incr_idx(); + } + + updated = true; + } + + if updated { + let mut isr = dev.get_interrupt_status(); + isr.insert(InterruptStatus::VIRTIO_MMIO_INT_VRING); + dev.update_interrupt_status(isr); + } + } + } +} diff --git a/crates/vm-virtio/src/transport.rs b/crates/vm-virtio/src/transport.rs index 1867c4e..487c1f6 100644 --- a/crates/vm-virtio/src/transport.rs +++ b/crates/vm-virtio/src/transport.rs @@ -20,7 +20,7 @@ pub mod pci; mod control_register; pub struct VirtioDev { - device: D, + pub device: D, device_feature_sel: Option, driver_features: u64, @@ -297,12 +297,12 @@ where Ok(()) } - pub fn read_config(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<()> { - self.device.read_config(offset, len, buf) + pub fn read_config(&self, offset: usize, buf: &mut [u8]) -> Result<()> { + self.device.read_config(offset, buf) } - pub fn write_config(&mut self, offset: usize, len: usize, buf: &[u8]) -> Result<()> { - self.device.write_config(offset, len, buf) + pub fn write_config(&mut self, offset: usize, buf: &[u8]) -> Result<()> { + self.device.write_config(offset, buf) } pub fn get_virtqueue(&self, queue_sel: usize) -> Option<&Virtqueue> { @@ -322,4 +322,12 @@ where self.device.trigger_irq(!self.interrupt_status.is_empty()); } + + pub fn update_config_generation_and_notify(&mut self) { + self.config_generation += 1; + + let mut is = self.get_interrupt_status(); + is.insert(InterruptStatus::VIRTIO_MMIO_INT_CONFIG); + self.update_interrupt_status(is); + } } diff --git a/crates/vm-virtio/src/transport/mmio/mmio_handler.rs b/crates/vm-virtio/src/transport/mmio/mmio_handler.rs index 7fd8c74..3029403 100644 --- a/crates/vm-virtio/src/transport/mmio/mmio_handler.rs +++ b/crates/vm-virtio/src/transport/mmio/mmio_handler.rs @@ -137,7 +137,7 @@ where debug_assert!(false) } - } else if let Err(err) = dev.read_config(offset - CONFIGURATION_SPACE_OFFSET, len, data) { + } else if let Err(err) = dev.read_config(offset - CONFIGURATION_SPACE_OFFSET, data) { error!(name = D::NAME, ?err, "Failed to read device configuration"); debug_assert!(false) @@ -186,7 +186,7 @@ where debug_assert!(false) } - } else if let Err(err) = dev.write_config(offset - CONFIGURATION_SPACE_OFFSET, len, data) { + } else if let Err(err) = dev.write_config(offset - CONFIGURATION_SPACE_OFFSET, data) { error!(name = D::NAME, ?err, "Failed to write device configuration"); debug_assert!(false) diff --git a/crates/vm-virtio/src/transport/pci.rs b/crates/vm-virtio/src/transport/pci.rs index 6a09cfd..25eebcb 100644 --- a/crates/vm-virtio/src/transport/pci.rs +++ b/crates/vm-virtio/src/transport/pci.rs @@ -6,10 +6,12 @@ use vm_pci::device::function::BarHandler; use vm_pci::device::function::PciTypeFunctionCommon; use vm_pci::device::function::type0::Bar; use vm_pci::device::function::type0::PciType0Function; +use vm_pci::device::function::type0::Type0Function; +use vm_pci::device::pci_device::PciDevice; use vm_pci::error::Error; use vm_pci::types::configuration_space::ConfigurationSpace; -use crate::device::pci::VirtioPciDevice; +use crate::device::VirtioDevice; use crate::transport::VirtioDev; use crate::transport::pci::common_config_handler::CommonConfigHandler; use crate::transport::pci::device_handler::DeviceHandler; @@ -41,7 +43,7 @@ where D: VirtioPciDevice, { const VENDOR_ID: u16 = VIRTIO_PCI_VENDOR_ID; - const DEVICE_ID: u16 = 0x1040 + D::DEVICE_ID as u16; + const DEVICE_ID: u16 = 0x1040 + D::DEVICE_ID; const CLASS_CODE: u32 = D::CLASS_CODE; fn legacy_interrupt(&self) -> Option<(u8, u8)> { @@ -160,3 +162,20 @@ where } } } + +pub trait VirtioPciDevice: VirtioDevice +where + C: MemoryContainer, +{ + const DEVICE_SPECIFICATION_CONFIGURATION_LEN: usize; + const CLASS_CODE: u32; + const IRQ_PIN: u8; + + fn into_pci_device(self) -> PciDevice { + let virtio_function = VirtioPciTransport:: { + 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/transport/pci/common_config_handler.rs b/crates/vm-virtio/src/transport/pci/common_config_handler.rs index b8161dd..2763060 100644 --- a/crates/vm-virtio/src/transport/pci/common_config_handler.rs +++ b/crates/vm-virtio/src/transport/pci/common_config_handler.rs @@ -6,9 +6,9 @@ use tracing::warn; use vm_mm::allocator::MemoryContainer; use vm_pci::device::function::BarHandler; -use crate::device::pci::VirtioPciDevice; use crate::transport::VirtioDev; use crate::transport::control_register::ControlRegister; +use crate::transport::pci::VirtioPciDevice; #[derive(Debug, FromRepr)] #[repr(u64)] @@ -56,21 +56,33 @@ where { fn read(&self, offset: u64, data: &mut [u8]) { let Some(offset) = CommonCfgOffset::from_repr(offset) else { - warn!(offset, "invalid offset"); + warn!(name = D::NAME, offset, "invalid offset"); return; }; let dev = self.dev.lock().unwrap(); match offset { - CommonCfgOffset::DeviceFeatureSelect => todo!(), + CommonCfgOffset::DeviceFeatureSelect => { + assert_eq!(data.len(), 4); + let sel = dev.read_reg(ControlRegister::DeviceFeaturesSel); + data.copy_from_slice(&sel.to_le_bytes()); + } CommonCfgOffset::DeviceFeature => { assert_eq!(data.len(), 4); let feat = dev.read_reg(ControlRegister::DeviceFeatures); data.copy_from_slice(&feat.to_le_bytes()); } - CommonCfgOffset::DriverFeatureSelect => todo!(), - CommonCfgOffset::DriverFeature => todo!(), + CommonCfgOffset::DriverFeatureSelect => { + assert_eq!(data.len(), 4); + let sel = dev.read_reg(ControlRegister::DriverFeaturesSel); + data.copy_from_slice(&sel.to_le_bytes()); + } + CommonCfgOffset::DriverFeature => { + assert_eq!(data.len(), 4); + let feat = dev.read_reg(ControlRegister::DriverFeatures); + data.copy_from_slice(&feat.to_le_bytes()); + } CommonCfgOffset::ConfigMsixVector => todo!(), CommonCfgOffset::NumQueues => { assert_eq!(data.len(), 2); @@ -89,7 +101,11 @@ where .unwrap(); data[0] = cfg_generation; } - CommonCfgOffset::QueueSelect => todo!(), + CommonCfgOffset::QueueSelect => { + assert_eq!(data.len(), 2); + let queue_sel: u16 = dev.read_reg(ControlRegister::QueueSel).try_into().unwrap(); + data.copy_from_slice(&queue_sel.to_le_bytes()); + } CommonCfgOffset::QueueSize => { assert_eq!(data.len(), 2); let queue_size: u16 = dev.read_reg(ControlRegister::QueueSize).try_into().unwrap(); @@ -102,25 +118,44 @@ where data.copy_from_slice(&queue_ready.to_le_bytes()); } CommonCfgOffset::QueueNotifyOff => { - // let val: u16 = transport - // .read_reg(ControlRegister::QueueNotify) - // .try_into() - // .unwrap(); - // data.copy_from_slice(&val.to_le_bytes()); - // TODO: What's this - } - CommonCfgOffset::QueueDescLow => todo!(), - CommonCfgOffset::QueueDescHigh => todo!(), - CommonCfgOffset::QueueDriverLow => todo!(), - CommonCfgOffset::QueueDriverHigh => todo!(), - CommonCfgOffset::QueueDeviceLow => todo!(), - CommonCfgOffset::QueueDeviceHigh => todo!(), + // TODO + } + CommonCfgOffset::QueueDescLow => { + assert_eq!(data.len(), 4); + let addr = dev.read_reg(ControlRegister::QueueDescLow); + data.copy_from_slice(&addr.to_le_bytes()); + } + CommonCfgOffset::QueueDescHigh => { + assert_eq!(data.len(), 4); + let addr = dev.read_reg(ControlRegister::QueueDescHigh); + data.copy_from_slice(&addr.to_le_bytes()); + } + CommonCfgOffset::QueueDriverLow => { + assert_eq!(data.len(), 4); + let addr = dev.read_reg(ControlRegister::QueueAvailLow); + data.copy_from_slice(&addr.to_le_bytes()); + } + CommonCfgOffset::QueueDriverHigh => { + assert_eq!(data.len(), 4); + let addr = dev.read_reg(ControlRegister::QueueAvailHigh); + data.copy_from_slice(&addr.to_le_bytes()); + } + CommonCfgOffset::QueueDeviceLow => { + assert_eq!(data.len(), 4); + let addr = dev.read_reg(ControlRegister::QueueUsedLow); + data.copy_from_slice(&addr.to_le_bytes()); + } + CommonCfgOffset::QueueDeviceHigh => { + assert_eq!(data.len(), 4); + let addr = dev.read_reg(ControlRegister::QueueUsedHigh); + data.copy_from_slice(&addr.to_le_bytes()); + } } } fn write(&self, offset: u64, data: &[u8]) { let Some(offset) = CommonCfgOffset::from_repr(offset) else { - warn!(offset, "invalid offset"); + warn!(name = D::NAME, offset, "invalid offset"); return; }; @@ -194,9 +229,7 @@ where let addr = u32::from_le_bytes(data.try_into().unwrap()); dev.write_reg(ControlRegister::QueueUsedHigh, addr).unwrap(); } - _ => { - warn!(?offset, "write to a RO cfg"); - } + _ => warn!(name = D::NAME, ?offset, "write to a RO cfg"), } } } diff --git a/crates/vm-virtio/src/transport/pci/device_handler.rs b/crates/vm-virtio/src/transport/pci/device_handler.rs index b0cce4d..f39e570 100644 --- a/crates/vm-virtio/src/transport/pci/device_handler.rs +++ b/crates/vm-virtio/src/transport/pci/device_handler.rs @@ -4,8 +4,8 @@ use std::sync::Mutex; use vm_mm::allocator::MemoryContainer; use vm_pci::device::function::BarHandler; -use crate::device::pci::VirtioPciDevice; use crate::transport::VirtioDev; +use crate::transport::pci::VirtioPciDevice; pub struct DeviceHandler where @@ -23,14 +23,12 @@ where fn read(&self, offset: u64, data: &mut [u8]) { let dev = self.dev.lock().unwrap(); - dev.read_config(offset.try_into().unwrap(), data.len(), data) - .unwrap(); + dev.read_config(offset.try_into().unwrap(), data).unwrap(); } fn write(&self, offset: u64, data: &[u8]) { let mut dev = self.dev.lock().unwrap(); - dev.write_config(offset.try_into().unwrap(), data.len(), data) - .unwrap(); + dev.write_config(offset.try_into().unwrap(), data).unwrap(); } } diff --git a/crates/vm-virtio/src/transport/pci/isr_handler.rs b/crates/vm-virtio/src/transport/pci/isr_handler.rs index a137d16..81ca507 100644 --- a/crates/vm-virtio/src/transport/pci/isr_handler.rs +++ b/crates/vm-virtio/src/transport/pci/isr_handler.rs @@ -4,9 +4,9 @@ use std::sync::Mutex; use vm_mm::allocator::MemoryContainer; use vm_pci::device::function::BarHandler; -use crate::device::pci::VirtioPciDevice; use crate::transport::VirtioDev; use crate::transport::control_register::ControlRegister; +use crate::transport::pci::VirtioPciDevice; pub struct IsrHandler where diff --git a/crates/vm-virtio/src/transport/pci/notify_handler.rs b/crates/vm-virtio/src/transport/pci/notify_handler.rs index 37d9985..9a744e0 100644 --- a/crates/vm-virtio/src/transport/pci/notify_handler.rs +++ b/crates/vm-virtio/src/transport/pci/notify_handler.rs @@ -4,9 +4,9 @@ use std::sync::Mutex; use vm_mm::allocator::MemoryContainer; use vm_pci::device::function::BarHandler; -use crate::device::pci::VirtioPciDevice; use crate::transport::VirtioDev; use crate::transport::control_register::ControlRegister; +use crate::transport::pci::VirtioPciDevice; pub struct NotifyHandler where diff --git a/crates/vm-virtio/src/types/device.rs b/crates/vm-virtio/src/types/device.rs index 95698be..18ab8b8 100644 --- a/crates/vm-virtio/src/types/device.rs +++ b/crates/vm-virtio/src/types/device.rs @@ -1 +1,2 @@ pub mod balloon_tranditional; +pub mod blk; diff --git a/crates/vm-virtio/src/device/blk.rs b/crates/vm-virtio/src/types/device/blk.rs similarity index 100% rename from crates/vm-virtio/src/device/blk.rs rename to crates/vm-virtio/src/types/device/blk.rs