From bed6bd9d22fe12e7f6c77c2498b32f5c20e35116 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Thu, 5 Mar 2026 23:37:56 +0800 Subject: [PATCH 1/4] refine: Refine irq for virtio-mmio --- crates/vm-virtio/src/device.rs | 4 +--- crates/vm-virtio/src/transport.rs | 4 +++- crates/vm-virtio/src/transport/mmio/mmio_handler.rs | 11 +++-------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/crates/vm-virtio/src/device.rs b/crates/vm-virtio/src/device.rs index 1c61cfc..78b3ef1 100644 --- a/crates/vm-virtio/src/device.rs +++ b/crates/vm-virtio/src/device.rs @@ -78,11 +78,9 @@ where } if updated { - // update irq let mut isr = dev.get_interrupt_status(); isr.insert(InterruptStatus::VIRTIO_MMIO_INT_VRING); - dev.set_interrupt_status(isr); - self.irq_chip.trigger_irq(self.irq_line, true); + dev.update_interrupt_status(isr); } } } diff --git a/crates/vm-virtio/src/transport.rs b/crates/vm-virtio/src/transport.rs index a8f24a1..9e1cff7 100644 --- a/crates/vm-virtio/src/transport.rs +++ b/crates/vm-virtio/src/transport.rs @@ -316,7 +316,9 @@ where self.interrupt_status } - pub fn set_interrupt_status(&mut self, is: InterruptStatus) { + pub fn update_interrupt_status(&mut self, is: InterruptStatus) { self.interrupt_status = is; + + self.device.trigger_irq(!self.interrupt_status.is_empty()); } } diff --git a/crates/vm-virtio/src/transport/mmio/mmio_handler.rs b/crates/vm-virtio/src/transport/mmio/mmio_handler.rs index b7c4eb0..6f13362 100644 --- a/crates/vm-virtio/src/transport/mmio/mmio_handler.rs +++ b/crates/vm-virtio/src/transport/mmio/mmio_handler.rs @@ -66,14 +66,9 @@ where MmioControlRegister::QueueReady => dev.write_reg(ControlRegister::QueueReady, val), MmioControlRegister::QueueNotify => dev.write_reg(ControlRegister::QueueNotify, val), MmioControlRegister::InterruptAck => { - // TODO - - dev.interrupt_status - .remove(InterruptStatus::from_bits_truncate(val)); - - if dev.interrupt_status.is_empty() { - dev.device.trigger_irq(false); - } + let mut is = dev.get_interrupt_status(); + is.remove(InterruptStatus::from_bits_truncate(val)); + dev.update_interrupt_status(is); Ok(()) } From 2913b7a45f5b3ef1140090b958906c033253c310 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Thu, 5 Mar 2026 23:41:28 +0800 Subject: [PATCH 2/4] refine: Reduce the visibility of virtio transport --- crates/vm-virtio/src/transport.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/vm-virtio/src/transport.rs b/crates/vm-virtio/src/transport.rs index 9e1cff7..1867c4e 100644 --- a/crates/vm-virtio/src/transport.rs +++ b/crates/vm-virtio/src/transport.rs @@ -14,10 +14,11 @@ use crate::types::interrupt_status::InterruptStatus; use crate::types::status::Status; use crate::virtqueue::Virtqueue; -pub mod control_register; pub mod mmio; pub mod pci; +mod control_register; + pub struct VirtioDev { device: D, From 9a1c5f462d30d570736bb1c0dbdfb8234c391339 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Fri, 6 Mar 2026 00:51:32 +0800 Subject: [PATCH 3/4] refine: Refine virtio-pci --- .../virtio/virtio_balloon_traditional.rs | 2 +- .../vm-device/src/device/virtio/virtio_blk.rs | 2 +- crates/vm-virtio/src/device.rs | 2 +- crates/vm-virtio/src/device/pci.rs | 4 +- .../src/transport/mmio/mmio_handler.rs | 2 +- crates/vm-virtio/src/transport/pci.rs | 109 +++--------------- .../src/transport/pci/device_handler.rs | 36 ++++++ .../src/transport/pci/isr_handler.rs | 41 +++++++ .../src/transport/pci/notify_handler.rs | 35 ++++++ .../vm-virtio/src/transport/pci/pci_header.rs | 8 -- 10 files changed, 133 insertions(+), 108 deletions(-) create mode 100644 crates/vm-virtio/src/transport/pci/device_handler.rs create mode 100644 crates/vm-virtio/src/transport/pci/isr_handler.rs create mode 100644 crates/vm-virtio/src/transport/pci/notify_handler.rs delete mode 100644 crates/vm-virtio/src/transport/pci/pci_header.rs 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 c4fd3fd..62323fb 100644 --- a/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs +++ b/crates/vm-device/src/device/virtio/virtio_balloon_traditional.rs @@ -61,7 +61,7 @@ where C: MemoryContainer, { const NAME: &str = "virtio-balloon-tranditional"; - const DEVICE_ID: u32 = DeviceId::Balloon as u32; + const DEVICE_ID: u16 = DeviceId::Balloon as u16; const DEVICE_FEATURES: u64 = (1 << VIRTIO_F_VERSION_1); fn virtqueues_size_max(&self) -> Vec> { diff --git a/crates/vm-device/src/device/virtio/virtio_blk.rs b/crates/vm-device/src/device/virtio/virtio_blk.rs index 1e46450..56ee8eb 100644 --- a/crates/vm-device/src/device/virtio/virtio_blk.rs +++ b/crates/vm-device/src/device/virtio/virtio_blk.rs @@ -90,7 +90,7 @@ where C: MemoryContainer, { const NAME: &str = "virtio-blk"; - const DEVICE_ID: u32 = DeviceId::Blk as u32; + const DEVICE_ID: u16 = DeviceId::Blk as u16; const DEVICE_FEATURES: u64 = (1 << VIRTIO_F_VERSION_1); fn virtqueues_size_max(&self) -> Vec> { diff --git a/crates/vm-virtio/src/device.rs b/crates/vm-virtio/src/device.rs index 78b3ef1..0bbca94 100644 --- a/crates/vm-virtio/src/device.rs +++ b/crates/vm-virtio/src/device.rs @@ -88,7 +88,7 @@ where pub trait VirtioDevice: Sized + Send + Sync + 'static { const NAME: &str; - const DEVICE_ID: u32; + const DEVICE_ID: u16; const DEVICE_FEATURES: u64; fn virtqueues_size_max(&self) -> Vec>; diff --git a/crates/vm-virtio/src/device/pci.rs b/crates/vm-virtio/src/device/pci.rs index 18f46b0..a3cd038 100644 --- a/crates/vm-virtio/src/device/pci.rs +++ b/crates/vm-virtio/src/device/pci.rs @@ -4,7 +4,7 @@ use vm_pci::device::pci_device::PciDevice; use crate::device::VirtioDevice; use crate::transport::VirtioDev; -use crate::transport::pci::VirtioPciFunction; +use crate::transport::pci::VirtioPciTransport; pub trait VirtioPciDevice: VirtioDevice where @@ -15,7 +15,7 @@ where const IRQ_PIN: u8; fn into_pci_device(self) -> PciDevice { - let virtio_function = VirtioPciFunction:: { + let virtio_function = VirtioPciTransport:: { dev: VirtioDev::new(self), }; let function = Type0Function::new(virtio_function).unwrap(); diff --git a/crates/vm-virtio/src/transport/mmio/mmio_handler.rs b/crates/vm-virtio/src/transport/mmio/mmio_handler.rs index 6f13362..7fd8c74 100644 --- a/crates/vm-virtio/src/transport/mmio/mmio_handler.rs +++ b/crates/vm-virtio/src/transport/mmio/mmio_handler.rs @@ -27,7 +27,7 @@ where match reg { MmioControlRegister::MagicValue => VIRTIO_MMIO_MAGIC_VALUE, MmioControlRegister::Version => VIRTIO_MMIO_VERSION, - MmioControlRegister::DeviceId => D::DEVICE_ID, + MmioControlRegister::DeviceId => D::DEVICE_ID as u32, MmioControlRegister::VendorId => VIRTIO_MMIO_VENDOR_ID, MmioControlRegister::DeviceFeatures => dev.read_reg(ControlRegister::DeviceFeatures), MmioControlRegister::QueueSizeMax => dev.read_reg(ControlRegister::QueueSizeMax), diff --git a/crates/vm-virtio/src/transport/pci.rs b/crates/vm-virtio/src/transport/pci.rs index b36732c..4dcff9b 100644 --- a/crates/vm-virtio/src/transport/pci.rs +++ b/crates/vm-virtio/src/transport/pci.rs @@ -11,105 +11,23 @@ use vm_pci::types::configuration_space::ConfigurationSpace; use crate::device::pci::VirtioPciDevice; use crate::transport::VirtioDev; -use crate::transport::control_register::ControlRegister; use crate::transport::pci::common_config_handler::CommonConfigHandler; -use crate::transport::pci::pci_header::VENDOR_ID; +use crate::transport::pci::device_handler::DeviceHandler; +use crate::transport::pci::isr_handler::IsrHandler; +use crate::transport::pci::notify_handler::NotifyHandler; use crate::types::pci::VirtioPciCap; use crate::types::pci::VirtioPciCapCfgType; use crate::types::pci::VirtioPciCommonCfg; use crate::types::pci::VirtioPciNotifyCap; -pub mod pci_header; - mod common_config_handler; +mod device_handler; +mod isr_handler; +mod notify_handler; -struct NotifyHandler -where - C: MemoryContainer, - D: VirtioPciDevice, -{ - dev: Arc>>, -} +const VIRTIO_PCI_VENDOR_ID: u16 = 0x1AF4; -impl BarHandler for NotifyHandler -where - C: MemoryContainer, - D: VirtioPciDevice, -{ - fn read(&self, _offset: u64, _data: &mut [u8]) { - unreachable!() - } - - 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 dev = self.dev.lock().unwrap(); - dev.write_reg(ControlRegister::QueueNotify, queue_index.into()) - .unwrap(); - } -} - -struct IsrHandler -where - C: MemoryContainer, - D: VirtioPciDevice, -{ - dev: Arc>>, -} - -impl BarHandler for IsrHandler -where - C: MemoryContainer, - D: VirtioPciDevice, -{ - fn read(&self, _offset: u64, data: &mut [u8]) { - let mut dev = self.dev.lock().unwrap(); - - 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. - */ - dev.write_reg(ControlRegister::InterruptStatus, 0).unwrap(); - dev.device.trigger_irq(false); - } - - fn write(&self, _offset: u64, _data: &[u8]) { - unreachable!() - } -} - -struct DeviceHandler -where - C: MemoryContainer, - D: VirtioPciDevice, -{ - dev: Arc>>, -} - -impl BarHandler for DeviceHandler -where - C: MemoryContainer, - D: VirtioPciDevice, -{ - 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(); - } - - 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(); - } -} - -pub struct VirtioPciFunction +pub struct VirtioPciTransport where C: MemoryContainer, D: VirtioPciDevice, @@ -117,12 +35,12 @@ where pub dev: Arc>>, } -impl PciTypeFunctionCommon for VirtioPciFunction +impl PciTypeFunctionCommon for VirtioPciTransport where C: MemoryContainer, D: VirtioPciDevice, { - const VENDOR_ID: u16 = VENDOR_ID; + const VENDOR_ID: u16 = VIRTIO_PCI_VENDOR_ID; const DEVICE_ID: u16 = 0x1040 + D::DEVICE_ID as u16; const CLASS_CODE: u32 = D::CLASS_CODE; @@ -190,7 +108,10 @@ where length: 0x1000, ..Default::default() }; - assert!(D::DEVICE_SPECIFICATION_CONFIGURATION_LEN <= 0x1000); + + if D::DEVICE_SPECIFICATION_CONFIGURATION_LEN > 0x1000 { + return Err(Error::CapTooLarge); + } cfg.alloc_capability(virtio_pci_device_cfg_cap.into())?; } @@ -199,7 +120,7 @@ where } } -impl PciType0Function for VirtioPciFunction +impl PciType0Function for VirtioPciTransport where C: MemoryContainer, D: VirtioPciDevice, diff --git a/crates/vm-virtio/src/transport/pci/device_handler.rs b/crates/vm-virtio/src/transport/pci/device_handler.rs new file mode 100644 index 0000000..b0cce4d --- /dev/null +++ b/crates/vm-virtio/src/transport/pci/device_handler.rs @@ -0,0 +1,36 @@ +use std::sync::Arc; +use std::sync::Mutex; + +use vm_mm::allocator::MemoryContainer; +use vm_pci::device::function::BarHandler; + +use crate::device::pci::VirtioPciDevice; +use crate::transport::VirtioDev; + +pub struct DeviceHandler +where + C: MemoryContainer, + D: VirtioPciDevice, +{ + pub dev: Arc>>, +} + +impl BarHandler for DeviceHandler +where + C: MemoryContainer, + D: VirtioPciDevice, +{ + 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(); + } + + 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(); + } +} diff --git a/crates/vm-virtio/src/transport/pci/isr_handler.rs b/crates/vm-virtio/src/transport/pci/isr_handler.rs new file mode 100644 index 0000000..a137d16 --- /dev/null +++ b/crates/vm-virtio/src/transport/pci/isr_handler.rs @@ -0,0 +1,41 @@ +use std::sync::Arc; +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; + +pub struct IsrHandler +where + C: MemoryContainer, + D: VirtioPciDevice, +{ + pub dev: Arc>>, +} + +impl BarHandler for IsrHandler +where + C: MemoryContainer, + D: VirtioPciDevice, +{ + fn read(&self, _offset: u64, data: &mut [u8]) { + let mut dev = self.dev.lock().unwrap(); + + 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. + */ + dev.write_reg(ControlRegister::InterruptStatus, 0).unwrap(); + dev.device.trigger_irq(false); + } + + fn write(&self, _offset: u64, _data: &[u8]) { + unreachable!() + } +} diff --git a/crates/vm-virtio/src/transport/pci/notify_handler.rs b/crates/vm-virtio/src/transport/pci/notify_handler.rs new file mode 100644 index 0000000..37d9985 --- /dev/null +++ b/crates/vm-virtio/src/transport/pci/notify_handler.rs @@ -0,0 +1,35 @@ +use std::sync::Arc; +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; + +pub struct NotifyHandler +where + C: MemoryContainer, + D: VirtioPciDevice, +{ + pub dev: Arc>>, +} + +impl BarHandler for NotifyHandler +where + C: MemoryContainer, + D: VirtioPciDevice, +{ + fn read(&self, _offset: u64, _data: &mut [u8]) { + unreachable!() + } + + 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 dev = self.dev.lock().unwrap(); + dev.write_reg(ControlRegister::QueueNotify, queue_index.into()) + .unwrap(); + } +} diff --git a/crates/vm-virtio/src/transport/pci/pci_header.rs b/crates/vm-virtio/src/transport/pci/pci_header.rs deleted file mode 100644 index efc8fc0..0000000 --- a/crates/vm-virtio/src/transport/pci/pci_header.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::types::device_id::DeviceId; - -pub const VENDOR_ID: u16 = 0x1AF4; - -#[repr(u16)] -pub enum VirtioPciDeviceId { - Blk = 0x1040 + DeviceId::Blk as u16, -} From 22f8f8a89a02d5ca80c0f56f3b7cb12a2ff4d309 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Fri, 6 Mar 2026 01:01:39 +0800 Subject: [PATCH 4/4] refine: Refine error handling --- crates/vm-virtio/src/transport/pci.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/vm-virtio/src/transport/pci.rs b/crates/vm-virtio/src/transport/pci.rs index 4dcff9b..6a09cfd 100644 --- a/crates/vm-virtio/src/transport/pci.rs +++ b/crates/vm-virtio/src/transport/pci.rs @@ -62,7 +62,9 @@ where bar: 0, id: 0, offset: 0, - length: size_of::().try_into().unwrap(), + length: size_of::() + .try_into() + .map_err(|_| Error::CapTooLarge)?, ..Default::default() }; @@ -72,7 +74,9 @@ where { let virtio_pci_notify_cap = VirtioPciNotifyCap { cap: VirtioPciCap { - cap_len: size_of::().try_into().unwrap(), + cap_len: size_of::() + .try_into() + .map_err(|_| Error::CapTooLarge)?, cfg_type: VirtioPciCapCfgType::VirtioPciCapNotifyCfg as u8, bar: 1, id: 0,