diff --git a/devices/src/virtio/balloon.rs b/devices/src/virtio/balloon.rs index f3c3f56cbf..a76765d475 100644 --- a/devices/src/virtio/balloon.rs +++ b/devices/src/virtio/balloon.rs @@ -19,8 +19,8 @@ use vm_control::{BalloonControlCommand, BalloonControlResult, BalloonStats}; use vm_memory::{GuestAddress, GuestMemory}; use super::{ - copy_config, descriptor_utils, DescriptorChain, Interrupt, Queue, Reader, VirtioDevice, - TYPE_BALLOON, + copy_config, descriptor_utils, DescriptorChain, Interrupt, Queue, Reader, SignalableInterrupt, + VirtioDevice, TYPE_BALLOON, }; #[sorted] @@ -276,14 +276,20 @@ async fn handle_command_tube( // Async task that resamples the status of the interrupt when the guest sends a request by // signalling the resample event associated with the interrupt. async fn handle_irq_resample(ex: &Executor, interrupt: Rc>) { - let resample_evt = interrupt - .borrow_mut() - .get_resample_evt() - .try_clone() - .unwrap(); - let resample_evt = EventAsync::new(resample_evt.0, ex).unwrap(); - while resample_evt.next_val().await.is_ok() { - interrupt.borrow_mut().do_interrupt_resample(); + let resample_evt = if let Some(resample_evt) = interrupt.borrow_mut().get_resample_evt() { + let resample_evt = resample_evt.try_clone().unwrap(); + let resample_evt = EventAsync::new(resample_evt.0, ex).unwrap(); + Some(resample_evt) + } else { + None + }; + if let Some(resample_evt) = resample_evt { + while resample_evt.next_val().await.is_ok() { + interrupt.borrow_mut().do_interrupt_resample(); + } + } else { + // no resample event, park the future. + let () = futures::future::pending().await; } } diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs index 72181ad646..e9a2024273 100644 --- a/devices/src/virtio/block.rs +++ b/devices/src/virtio/block.rs @@ -26,8 +26,8 @@ use vm_control::{DiskControlCommand, DiskControlResult}; use vm_memory::GuestMemory; use super::{ - copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, - TYPE_BLOCK, + copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, + VirtioDevice, Writer, TYPE_BLOCK, }; const QUEUE_SIZE: u16 = 256; @@ -397,9 +397,14 @@ impl Worker { let wait_ctx: WaitContext = match WaitContext::build_with(&[ (&flush_timer, Token::FlushTimer), (&queue_evt, Token::QueueAvailable), - (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) + .and_then(|wc| { + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + wc.add(resample_evt, Token::InterruptResample)?; + } + Ok(wc) + }) .and_then(|pc| { if let Some(control_tube) = self.control_tube.as_ref() { pc.add(control_tube, Token::ControlRequest)? diff --git a/devices/src/virtio/block_async.rs b/devices/src/virtio/block_async.rs index 38e771ef99..dc04227c75 100644 --- a/devices/src/virtio/block_async.rs +++ b/devices/src/virtio/block_async.rs @@ -33,8 +33,8 @@ use vm_control::{DiskControlCommand, DiskControlResult}; use vm_memory::GuestMemory; use super::{ - copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, - TYPE_BLOCK, + copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, + VirtioDevice, Writer, TYPE_BLOCK, }; const QUEUE_SIZE: u16 = 256; @@ -306,7 +306,7 @@ async fn process_one_request_task( let mut queue = queue.borrow_mut(); queue.add_used(&mem, descriptor_index, len as u32); - queue.trigger_interrupt(&mem, &interrupt.borrow()); + queue.trigger_interrupt(&mem, &*interrupt.borrow()); queue.update_int_required(&mem); } @@ -347,19 +347,28 @@ async fn handle_irq_resample( ex: &Executor, interrupt: Rc>, ) -> result::Result<(), OtherError> { - let resample_evt = interrupt - .borrow_mut() - .get_resample_evt() - .try_clone() - .map_err(OtherError::CloneResampleEvent)?; - let resample_evt = - EventAsync::new(resample_evt.0, ex).map_err(OtherError::AsyncResampleCreate)?; - loop { - let _ = resample_evt - .next_val() - .await - .map_err(OtherError::ReadResampleEvent)?; - interrupt.borrow_mut().do_interrupt_resample(); + let resample_evt = if let Some(resample_evt) = interrupt.borrow().get_resample_evt() { + let resample_evt = resample_evt + .try_clone() + .map_err(OtherError::CloneResampleEvent)?; + let resample_evt = + EventAsync::new(resample_evt.0, ex).map_err(OtherError::AsyncResampleCreate)?; + Some(resample_evt) + } else { + None + }; + if let Some(resample_evt) = resample_evt { + loop { + let _ = resample_evt + .next_val() + .await + .map_err(OtherError::ReadResampleEvent)?; + interrupt.borrow().do_interrupt_resample(); + } + } else { + // no resample event, park the future. + let () = futures::future::pending().await; + Ok(()) } } diff --git a/devices/src/virtio/console.rs b/devices/src/virtio/console.rs index 5eb7cbcf42..9aa789a5d9 100644 --- a/devices/src/virtio/console.rs +++ b/devices/src/virtio/console.rs @@ -11,7 +11,8 @@ use data_model::{DataInit, Le16, Le32}; use vm_memory::GuestMemory; use super::{ - base_features, copy_config, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_CONSOLE, + base_features, copy_config, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice, + Writer, TYPE_CONSOLE, }; use crate::{ProtectionType, SerialDevice}; @@ -239,7 +240,6 @@ impl Worker { (&transmit_evt, Token::TransmitQueueAvailable), (&receive_evt, Token::ReceiveQueueAvailable), (&in_avail_evt, Token::InputAvailable), - (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -248,6 +248,15 @@ impl Worker { return; } }; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + if wait_ctx + .add(resample_evt, Token::InterruptResample) + .is_err() + { + error!("failed adding resample event to WaitContext."); + return; + } + } let mut output: Box = match self.output.take() { Some(o) => o, diff --git a/devices/src/virtio/fs/worker.rs b/devices/src/virtio/fs/worker.rs index 893da5c3bd..19fec1159c 100644 --- a/devices/src/virtio/fs/worker.rs +++ b/devices/src/virtio/fs/worker.rs @@ -14,7 +14,7 @@ use vm_control::{FsMappingRequest, VmResponse}; use vm_memory::GuestMemory; use crate::virtio::fs::{Error, Result}; -use crate::virtio::{Interrupt, Queue, Reader, Writer}; +use crate::virtio::{Interrupt, Queue, Reader, SignalableInterrupt, Writer}; impl fuse::Reader for Reader {} @@ -217,9 +217,11 @@ impl Worker { .map_err(Error::CreateWaitContext)?; if watch_resample_event { - wait_ctx - .add(self.irq.get_resample_evt(), Token::InterruptResample) - .map_err(Error::CreateWaitContext)?; + if let Some(resample_evt) = self.irq.get_resample_evt() { + wait_ctx + .add(resample_evt, Token::InterruptResample) + .map_err(Error::CreateWaitContext)?; + } } loop { diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs index 99c0fa38cc..d9f9c704c7 100644 --- a/devices/src/virtio/gpu/mod.rs +++ b/devices/src/virtio/gpu/mod.rs @@ -37,8 +37,8 @@ use sync::Mutex; use vm_memory::{GuestAddress, GuestMemory}; use super::{ - copy_config, resource_bridge::*, DescriptorChain, Interrupt, Queue, Reader, VirtioDevice, - Writer, TYPE_GPU, + copy_config, resource_bridge::*, DescriptorChain, Interrupt, Queue, Reader, + SignalableInterrupt, VirtioDevice, Writer, TYPE_GPU, }; use super::{PciCapabilityType, VirtioPciShmCap}; @@ -703,7 +703,6 @@ impl Worker { (&self.ctrl_evt, Token::CtrlQueue), (&self.cursor_evt, Token::CursorQueue), (&*self.state.display().borrow(), Token::Display), - (self.interrupt.get_resample_evt(), Token::InterruptResample), (&self.kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -712,6 +711,15 @@ impl Worker { return; } }; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + if wait_ctx + .add(resample_evt, Token::InterruptResample) + .is_err() + { + error!("failed creating WaitContext"); + return; + } + } for (index, bridge) in self.resource_bridges.iter().enumerate() { if let Err(e) = wait_ctx.add(bridge, Token::ResourceBridge { index }) { diff --git a/devices/src/virtio/input/mod.rs b/devices/src/virtio/input/mod.rs index 193e5475fa..30cd724b28 100644 --- a/devices/src/virtio/input/mod.rs +++ b/devices/src/virtio/input/mod.rs @@ -16,8 +16,8 @@ use vm_memory::GuestMemory; use self::event_source::{EvdevEventSource, EventSource, SocketEventSource}; use super::{ - copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, - TYPE_INPUT, + copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, + VirtioDevice, Writer, TYPE_INPUT, }; use linux_input_sys::{virtio_input_event, InputEventDecoder}; use std::collections::BTreeMap; @@ -463,7 +463,6 @@ impl Worker { (&event_queue_evt, Token::EventQAvailable), (&status_queue_evt, Token::StatusQAvailable), (&self.event_source, Token::InputEventsAvailable), - (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(wait_ctx) => wait_ctx, @@ -472,6 +471,15 @@ impl Worker { return; } }; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + if wait_ctx + .add(resample_evt, Token::InterruptResample) + .is_err() + { + error!("failed adding resample event to WaitContext."); + return; + } + } 'wait: loop { let wait_events = match wait_ctx.wait() { diff --git a/devices/src/virtio/interrupt.rs b/devices/src/virtio/interrupt.rs index dac8aaad0c..5b52dc5056 100644 --- a/devices/src/virtio/interrupt.rs +++ b/devices/src/virtio/interrupt.rs @@ -9,6 +9,26 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use sync::Mutex; +pub trait SignalableInterrupt { + /// Writes to the irqfd to VMM to deliver virtual interrupt to the guest. + fn signal(&self, vector: u16, interrupt_status_mask: u32); + + /// Notify the driver that buffers have been placed in the used queue. + fn signal_used_queue(&self, vector: u16) { + self.signal(vector, INTERRUPT_STATUS_USED_RING) + } + + /// Notify the driver that the device configuration has changed. + fn signal_config_changed(&self); + + /// Get the event to signal resampling is needed if it exists. + fn get_resample_evt(&self) -> Option<&Event>; + + /// Reads the status and writes to the interrupt event. Doesn't read the resample event, it + /// assumes the resample has been requested. + fn do_interrupt_resample(&self); +} + pub struct Interrupt { interrupt_status: Arc, interrupt_evt: Event, @@ -17,23 +37,7 @@ pub struct Interrupt { config_msix_vector: u16, } -impl Interrupt { - pub fn new( - interrupt_status: Arc, - interrupt_evt: Event, - interrupt_resample_evt: Event, - msix_config: Option>>, - config_msix_vector: u16, - ) -> Interrupt { - Interrupt { - interrupt_status, - interrupt_evt, - interrupt_resample_evt, - msix_config, - config_msix_vector, - } - } - +impl SignalableInterrupt for Interrupt { /// Virtqueue Interrupts From The Device /// /// If MSI-X is enabled in this device, MSI-X interrupt is preferred. @@ -62,14 +66,36 @@ impl Interrupt { } } - /// Notify the driver that buffers have been placed in the used queue. - pub fn signal_used_queue(&self, vector: u16) { - self.signal(vector, INTERRUPT_STATUS_USED_RING) + fn signal_config_changed(&self) { + self.signal(self.config_msix_vector, INTERRUPT_STATUS_CONFIG_CHANGED) } - /// Notify the driver that the device configuration has changed. - pub fn signal_config_changed(&self) { - self.signal(self.config_msix_vector, INTERRUPT_STATUS_CONFIG_CHANGED) + fn get_resample_evt(&self) -> Option<&Event> { + Some(&self.interrupt_resample_evt) + } + + fn do_interrupt_resample(&self) { + if self.interrupt_status.load(Ordering::SeqCst) != 0 { + self.interrupt_evt.write(1).unwrap(); + } + } +} + +impl Interrupt { + pub fn new( + interrupt_status: Arc, + interrupt_evt: Event, + interrupt_resample_evt: Event, + msix_config: Option>>, + config_msix_vector: u16, + ) -> Interrupt { + Interrupt { + interrupt_status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + config_msix_vector, + } } /// Handle interrupt resampling event, reading the value from the event and doing the resample. @@ -78,20 +104,6 @@ impl Interrupt { self.do_interrupt_resample(); } - /// Read the status and write to the interrupt event. Don't read the resample event, assume the - /// resample has been requested. - pub fn do_interrupt_resample(&self) { - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } - } - - /// Return the reference of interrupt_resample_evt - /// To keep the interface clean, this member is private. - pub fn get_resample_evt(&self) -> &Event { - &self.interrupt_resample_evt - } - /// Get a reference to the msix configuration pub fn get_msix_config(&self) -> &Option>> { &self.msix_config diff --git a/devices/src/virtio/net.rs b/devices/src/virtio/net.rs index b88dc44ae9..d1f35dca55 100644 --- a/devices/src/virtio/net.rs +++ b/devices/src/virtio/net.rs @@ -23,7 +23,8 @@ use virtio_sys::virtio_net::{ use vm_memory::GuestMemory; use super::{ - copy_config, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_NET, + copy_config, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice, + Writer, TYPE_NET, }; const QUEUE_SIZE: u16 = 256; @@ -351,9 +352,11 @@ where .add(ctrl_evt, Token::CtrlQueue) .map_err(NetError::CreateWaitContext)?; // Let CtrlQueue's thread handle InterruptResample also. - wait_ctx - .add(self.interrupt.get_resample_evt(), Token::InterruptResample) - .map_err(NetError::CreateWaitContext)?; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + wait_ctx + .add(resample_evt, Token::InterruptResample) + .map_err(NetError::CreateWaitContext)?; + } } let mut tap_polling_enabled = true; diff --git a/devices/src/virtio/p9.rs b/devices/src/virtio/p9.rs index a082afa062..670645d887 100644 --- a/devices/src/virtio/p9.rs +++ b/devices/src/virtio/p9.rs @@ -12,7 +12,8 @@ use base::{error, warn, Error as SysError, Event, PollToken, RawDescriptor, Wait use vm_memory::GuestMemory; use super::{ - copy_config, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_9P, + copy_config, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice, + Writer, TYPE_9P, }; const QUEUE_SIZE: u16 = 128; @@ -115,12 +116,14 @@ impl Worker { Kill, } - let wait_ctx: WaitContext = WaitContext::build_with(&[ - (&queue_evt, Token::QueueReady), - (self.interrupt.get_resample_evt(), Token::InterruptResample), - (&kill_evt, Token::Kill), - ]) - .map_err(P9Error::CreateWaitContext)?; + let wait_ctx: WaitContext = + WaitContext::build_with(&[(&queue_evt, Token::QueueReady), (&kill_evt, Token::Kill)]) + .map_err(P9Error::CreateWaitContext)?; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + wait_ctx + .add(resample_evt, Token::InterruptResample) + .map_err(P9Error::CreateWaitContext)?; + } loop { let events = wait_ctx.wait().map_err(P9Error::WaitError)?; diff --git a/devices/src/virtio/pmem.rs b/devices/src/virtio/pmem.rs index fb7a46da24..9a3ca39cbb 100644 --- a/devices/src/virtio/pmem.rs +++ b/devices/src/virtio/pmem.rs @@ -14,8 +14,8 @@ use vm_control::{MemSlot, VmMsyncRequest, VmMsyncResponse}; use vm_memory::{GuestAddress, GuestMemory}; use super::{ - copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, - TYPE_PMEM, + copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, + VirtioDevice, Writer, TYPE_PMEM, }; const QUEUE_SIZE: u16 = 256; @@ -173,7 +173,6 @@ impl Worker { let wait_ctx: WaitContext = match WaitContext::build_with(&[ (&queue_evt, Token::QueueAvailable), - (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -182,6 +181,15 @@ impl Worker { return; } }; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + if wait_ctx + .add(resample_evt, Token::InterruptResample) + .is_err() + { + error!("failed adding resample event to WaitContext."); + return; + } + } 'wait: loop { let events = match wait_ctx.wait() { diff --git a/devices/src/virtio/queue.rs b/devices/src/virtio/queue.rs index 3f48ad64a4..537abaeeef 100644 --- a/devices/src/virtio/queue.rs +++ b/devices/src/virtio/queue.rs @@ -11,7 +11,7 @@ use cros_async::{AsyncError, EventAsync}; use virtio_sys::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use vm_memory::{GuestAddress, GuestMemory}; -use super::{Interrupt, VIRTIO_MSI_NO_VECTOR}; +use super::{SignalableInterrupt, VIRTIO_MSI_NO_VECTOR}; const VIRTQ_DESC_F_NEXT: u16 = 0x1; const VIRTQ_DESC_F_WRITE: u16 = 0x2; @@ -536,7 +536,11 @@ impl Queue { /// inject interrupt into guest on this queue /// return true: interrupt is injected into guest for this queue /// false: interrupt isn't injected - pub fn trigger_interrupt(&mut self, mem: &GuestMemory, interrupt: &Interrupt) -> bool { + pub fn trigger_interrupt( + &mut self, + mem: &GuestMemory, + interrupt: &dyn SignalableInterrupt, + ) -> bool { if self.available_interrupt_enabled(mem) { self.last_used = self.next_used; interrupt.signal_used_queue(self.vector); @@ -554,6 +558,7 @@ impl Queue { #[cfg(test)] mod tests { + use super::super::Interrupt; use super::*; use base::Event; use data_model::{DataInit, Le16, Le32, Le64}; diff --git a/devices/src/virtio/rng.rs b/devices/src/virtio/rng.rs index 466ffd247f..65d671e6ae 100644 --- a/devices/src/virtio/rng.rs +++ b/devices/src/virtio/rng.rs @@ -10,7 +10,7 @@ use std::thread; use base::{error, warn, AsRawDescriptor, Event, PollToken, RawDescriptor, WaitContext}; use vm_memory::GuestMemory; -use super::{Interrupt, Queue, VirtioDevice, Writer, TYPE_RNG}; +use super::{Interrupt, Queue, SignalableInterrupt, VirtioDevice, Writer, TYPE_RNG}; const QUEUE_SIZE: u16 = 256; const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE]; @@ -75,7 +75,6 @@ impl Worker { let wait_ctx: WaitContext = match WaitContext::build_with(&[ (&queue_evt, Token::QueueAvailable), - (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -84,6 +83,15 @@ impl Worker { return; } }; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + if wait_ctx + .add(resample_evt, Token::InterruptResample) + .is_err() + { + error!("failed adding resample event to WaitContext."); + return; + } + } 'wait: loop { let events = match wait_ctx.wait() { diff --git a/devices/src/virtio/tpm.rs b/devices/src/virtio/tpm.rs index ee68ea1ea9..e9e07c90a4 100644 --- a/devices/src/virtio/tpm.rs +++ b/devices/src/virtio/tpm.rs @@ -14,7 +14,8 @@ use base::{error, Event, PollToken, RawDescriptor, WaitContext}; use vm_memory::GuestMemory; use super::{ - DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_TPM, + DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice, + Writer, TYPE_TPM, }; // A single queue of size 2. The guest kernel driver will enqueue a single @@ -112,9 +113,14 @@ impl Worker { let wait_ctx = match WaitContext::build_with(&[ (&self.queue_evt, Token::QueueAvailable), - (self.interrupt.get_resample_evt(), Token::InterruptResample), (&self.kill_evt, Token::Kill), - ]) { + ]) + .and_then(|wc| { + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + wc.add(resample_evt, Token::InterruptResample)?; + } + Ok(wc) + }) { Ok(pc) => pc, Err(e) => { error!("vtpm failed creating WaitContext: {}", e); diff --git a/devices/src/virtio/vhost/user/worker.rs b/devices/src/virtio/vhost/user/worker.rs index 4cf2e5d40c..0015a158c4 100644 --- a/devices/src/virtio/vhost/user/worker.rs +++ b/devices/src/virtio/vhost/user/worker.rs @@ -8,6 +8,7 @@ use futures::pin_mut; use thiserror::Error as ThisError; use vm_memory::GuestMemory; +use crate::virtio::interrupt::SignalableInterrupt; use crate::virtio::{Interrupt, Queue}; #[derive(ThisError, Debug)] @@ -49,6 +50,7 @@ impl Worker { pub fn run(&mut self, ex: &Executor, interrupt: Interrupt) -> Result<(), String> { let resample_evt = interrupt .get_resample_evt() + .expect("resample event required") .try_clone() .expect("failed to clone resample event"); let async_resample_evt = diff --git a/devices/src/virtio/vhost/worker.rs b/devices/src/virtio/vhost/worker.rs index 225d880e12..9d7822ebfa 100644 --- a/devices/src/virtio/vhost/worker.rs +++ b/devices/src/virtio/vhost/worker.rs @@ -9,7 +9,7 @@ use vhost::Vhost; use super::control_socket::{VhostDevRequest, VhostDevResponse}; use super::{Error, Result}; -use crate::virtio::{Interrupt, Queue}; +use crate::virtio::{Interrupt, Queue, SignalableInterrupt}; use libc::EIO; /// Worker that takes care of running the vhost device. @@ -105,11 +105,9 @@ impl Worker { ControlNotify, } - let wait_ctx: WaitContext = WaitContext::build_with(&[ - (self.interrupt.get_resample_evt(), Token::InterruptResample), - (&self.kill_evt, Token::Kill), - ]) - .map_err(Error::CreateWaitContext)?; + let wait_ctx: WaitContext = + WaitContext::build_with(&[(&self.kill_evt, Token::Kill)]) + .map_err(Error::CreateWaitContext)?; for (index, vhost_int) in self.vhost_interrupt.iter().enumerate() { wait_ctx @@ -121,6 +119,11 @@ impl Worker { .add(socket, Token::ControlNotify) .map_err(Error::CreateWaitContext)?; } + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + wait_ctx + .add(resample_evt, Token::InterruptResample) + .map_err(Error::CreateWaitContext)?; + } 'wait: loop { let events = wait_ctx.wait().map_err(Error::WaitError)?; diff --git a/devices/src/virtio/video/worker.rs b/devices/src/virtio/video/worker.rs index 3fc9e4a78a..f7a3a32146 100644 --- a/devices/src/virtio/video/worker.rs +++ b/devices/src/virtio/video/worker.rs @@ -18,7 +18,7 @@ use crate::virtio::video::device::{ use crate::virtio::video::event::{self, EvtType, VideoEvt}; use crate::virtio::video::response::{self, Response}; use crate::virtio::video::{Error, Result}; -use crate::virtio::{Interrupt, Reader, Writer}; +use crate::virtio::{Interrupt, Reader, SignalableInterrupt, Writer}; pub struct Worker { pub interrupt: Interrupt, @@ -275,8 +275,13 @@ impl Worker { (&self.cmd_evt, Token::CmdQueue), (&self.event_evt, Token::EventQueue), (&self.kill_evt, Token::Kill), - (self.interrupt.get_resample_evt(), Token::InterruptResample), ]) + .and_then(|wc| { + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + wc.add(resample_evt, Token::InterruptResample)?; + } + Ok(wc) + }) .map_err(Error::WaitContextCreationFailed)?; // Stores descriptors in which responses for asynchronous commands will be written. diff --git a/devices/src/virtio/wl.rs b/devices/src/virtio/wl.rs index c86fe671eb..9eee5ea875 100644 --- a/devices/src/virtio/wl.rs +++ b/devices/src/virtio/wl.rs @@ -67,7 +67,9 @@ use vm_control::GpuMemoryDesc; use super::resource_bridge::{ get_resource_info, BufferInfo, ResourceBridgeError, ResourceInfo, ResourceRequest, }; -use super::{DescriptorChain, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_WL}; +use super::{ + DescriptorChain, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice, Writer, TYPE_WL, +}; use vm_control::{MemSlot, VmMemoryRequest, VmMemoryResponse}; const VIRTWL_SEND_MAX_ALLOCS: usize = 28; @@ -1514,7 +1516,6 @@ impl Worker { (&out_queue_evt, Token::OutQueue), (&kill_evt, Token::Kill), (&self.state.wait_ctx, Token::State), - (self.interrupt.get_resample_evt(), Token::InterruptResample), ]) { Ok(pc) => pc, Err(e) => { @@ -1522,6 +1523,15 @@ impl Worker { return; } }; + if let Some(resample_evt) = self.interrupt.get_resample_evt() { + if wait_ctx + .add(resample_evt, Token::InterruptResample) + .is_err() + { + error!("failed adding resample event to WaitContext."); + return; + } + } 'wait: loop { let mut signal_used_in = false;