/// The trait for virtio device operations. pubtraitVirtioDevice: Send { /// Realize low level device. fnrealize(&mutself) -> Result<()>;
/// Unrealize low level device fnunrealize(&mutself) -> Result<()> { bail!("Unrealize of the virtio device is not implemented"); }
/// Get the virtio device type, refer to Virtio Spec. fndevice_type(&self) -> u32;
/// Get the count of virtio device queues. fnqueue_num(&self) -> usize;
/// Get the queue size of virtio device. fnqueue_size(&self) -> u16;
/// Get device features from host. fnget_device_features(&self, features_select: u32) -> u32;
/// Set driver features by guest. fnset_driver_features(&mutself, page: u32, value: u32);
/// Read data of config from guest. fnread_config(&self, offset: u64, data: &mut [u8]) -> Result<()>;
/// Write data to config from guest. fnwrite_config(&mutself, offset: u64, data: &[u8]) -> Result<()>;
/// Activate the virtio device, this function is called by vcpu thread when frontend /// virtio driver is ready and write `DRIVER_OK` to backend. /// /// # Arguments /// /// * `mem_space` - System mem. /// * `interrupt_evt` - The eventfd used to send interrupt to guest. /// * `interrupt_status` - The interrupt status present to guest. /// * `queues` - The virtio queues. /// * `queue_evts` - The notifier events from guest. fnactivate( &mutself, mem_space: Arc<AddressSpace>, interrupt_cb: Arc<VirtioInterrupt>, queues: &[Arc<Mutex<Queue>>], queue_evts: Vec<EventFd>, ) -> Result<()>;
/// Deactivate virtio device, this function remove event fd /// of device out of the event loop. fndeactivate(&mutself) -> Result<()> { bail!( "Reset this device is not supported, virtio dev type is {}", self.device_type() ); }
virtio 设备可以有一个或多个队列,每个队列有描述符表、available ring、used ring 三个部分。当前 StratoVirt 的 virtio 设备均遵循 1.0 规范,队列的内存布局仅支持 Split Vring 的方式。queue.rs 中定义了一系列针对队列操作及查询的接口。所有的 I/O 请求数据信息以描述符的形式存放在描述符表中,前端准备好数据后更新 available ring 告诉后端还有哪些 I/O 待发送,后端执行完 I/O 更新 used ring 通知前端。不同设备的 I/O 处理不尽相同,但是核心的 virtqueue 操作是一样的。
pubstructSplitVring { /// Region cache information. pub cache: Option<RegionCache>, /// Guest physical address of the descriptor table. /// The table is composed of descriptors(SplitVringDesc). pub desc_table: GuestAddress,
/// Guest physical address of the available ring. /// The ring is composed of flags(u16), idx(u16), ring[size](u16) and used_event(u16). pub avail_ring: GuestAddress,
/// Guest physical address of the used ring. /// The ring is composed of flags(u16), idx(u16), used_ring[size](UsedElem) and avail_event(u16). pub used_ring: GuestAddress,
pubstructVirtioMmioDevice { // The entity of low level device. pub device: Arc<Mutex<dyn VirtioDevice>>, // EventFd used to send interrupt to VM interrupt_evt: EventFd, // Interrupt status. interrupt_status: Arc<AtomicU32>, // HostNotifyInfo used for guest notifier host_notify_info: HostNotifyInfo, // The state of virtio mmio device. state: VirtioMmioState, // System address space. mem_space: Arc<AddressSpace>, // Virtio queues. queues: Vec<Arc<Mutex<Queue>>>, // System Resource of device. res: SysRes, }
if region_base >= sysbus.mmio_region.1 { bail!("Mmio region space exhausted."); } self.set_sys_resource(sysbus, region_base, region_size)?; let dev = Arc::new(Mutex::new(self)); sysbus.attach_device(&dev, region_base, region_size)?;
pubstructVirtioPciDevice { /// Name of this device name: String, /// The entity of virtio device device: Arc<Mutex<dyn VirtioDevice>>, /// Device id dev_id: Arc<AtomicU16>, /// Devfn devfn: u8, /// If this device is activated or not. device_activated: Arc<AtomicBool>, /// Memory AddressSpace sys_mem: Arc<AddressSpace>, /// Pci config space. config: PciConfig, /// Virtio common config refer to Virtio Spec. common_config: Arc<Mutex<VirtioPciCommonConfig>>, /// Primary Bus parent_bus: Weak<Mutex<PciBus>>, /// Eventfds used for notifying the guest. notify_eventfds: NotifyEventFds, /// The function for interrupt triggering interrupt_cb: Option<Arc<VirtioInterrupt>>, /// Virtio queues. The vector and Queue will be shared acrossing thread, so all with Arc<Mutex<..>> wrapper. queues: Arc<Mutex<Vec<Arc<Mutex<Queue>>>>>, /// Multi-Function flag. multi_func: bool, }