diff options
author | Zide Chen <zide.chen@intel.corp-partner.google.com> | 2019-10-15 14:32:23 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-25 23:59:45 +0000 |
commit | 8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb (patch) | |
tree | 67764e974ad0e28021f7e7352ab6e1e759e650cc | |
parent | 3185ae95dd58f556a836f9e146dfe7b8450749b2 (diff) | |
download | crosvm-8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb.tar crosvm-8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb.tar.gz crosvm-8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb.tar.bz2 crosvm-8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb.tar.lz crosvm-8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb.tar.xz crosvm-8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb.tar.zst crosvm-8a7e4e902a4950b060ea23b40c0dfce7bfa1b2cb.zip |
devices: implement dedicated Interrupt struct for virtio Worker
The code to inject interrupt to the guest can be generic to all virtio devices. This patch: - move those guest interrupt related fields out of Worker structure and put in a separate file, making the worker code cleaner. - remove redandant functions across virtio devices: signal_used_queue(), signal_config_changed(), etc. BUG=chromium:854765 TEST=sanity test on eve and Linux TEST=cargo test -p devices Change-Id: I8e9f760f2057f192fdc74d16a59fea2e6b08c194 Signed-off-by: Zide Chen <zide.chen@intel.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1869553 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
-rw-r--r-- | devices/src/virtio/balloon.rs | 55 | ||||
-rw-r--r-- | devices/src/virtio/block.rs | 51 | ||||
-rw-r--r-- | devices/src/virtio/gpu/mod.rs | 53 | ||||
-rw-r--r-- | devices/src/virtio/input/mod.rs | 36 | ||||
-rw-r--r-- | devices/src/virtio/interrupt.rs | 83 | ||||
-rw-r--r-- | devices/src/virtio/mod.rs | 2 | ||||
-rw-r--r-- | devices/src/virtio/net.rs | 45 | ||||
-rw-r--r-- | devices/src/virtio/p9.rs | 35 | ||||
-rw-r--r-- | devices/src/virtio/pmem.rs | 36 | ||||
-rw-r--r-- | devices/src/virtio/rng.rs | 34 | ||||
-rw-r--r-- | devices/src/virtio/tpm.rs | 35 | ||||
-rw-r--r-- | devices/src/virtio/vhost/worker.rs | 42 | ||||
-rw-r--r-- | devices/src/virtio/wl.rs | 55 |
13 files changed, 266 insertions, 296 deletions
diff --git a/devices/src/virtio/balloon.rs b/devices/src/virtio/balloon.rs index 460aba5..eef70fb 100644 --- a/devices/src/virtio/balloon.rs +++ b/devices/src/virtio/balloon.rs @@ -19,8 +19,7 @@ use sys_util::{ use vm_control::{BalloonControlCommand, BalloonControlResponseSocket}; use super::{ - copy_config, Queue, Reader, VirtioDevice, INTERRUPT_STATUS_CONFIG_CHANGED, - INTERRUPT_STATUS_USED_RING, TYPE_BALLOON, VIRTIO_F_VERSION_1, + copy_config, Interrupt, Queue, Reader, VirtioDevice, TYPE_BALLOON, VIRTIO_F_VERSION_1, }; #[derive(Debug)] @@ -73,12 +72,10 @@ struct BalloonConfig { } struct Worker { + interrupt: Interrupt, mem: GuestMemory, inflate_queue: Queue, deflate_queue: Queue, - interrupt_status: Arc<AtomicUsize>, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, config: Arc<BalloonConfig>, command_socket: BalloonControlResponseSocket, } @@ -144,18 +141,6 @@ impl Worker { needs_interrupt } - fn signal_used_queue(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - - fn signal_config_changed(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_CONFIG_CHANGED as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - fn run(&mut self, mut queue_evts: Vec<EventFd>, kill_evt: EventFd) { #[derive(PartialEq, PollToken)] enum Token { @@ -173,7 +158,7 @@ impl Worker { (&inflate_queue_evt, Token::Inflate), (&deflate_queue_evt, Token::Deflate), (&self.command_socket, Token::CommandSocket), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -192,7 +177,8 @@ impl Worker { } }; - let mut needs_interrupt = false; + let mut needs_interrupt_inflate = false; + let mut needs_interrupt_deflate = false; for event in events.iter_readable() { match event.token() { Token::Inflate => { @@ -200,14 +186,14 @@ impl Worker { error!("failed reading inflate queue EventFd: {}", e); break 'poll; } - needs_interrupt |= self.process_inflate_deflate(true); + needs_interrupt_inflate |= self.process_inflate_deflate(true); } Token::Deflate => { if let Err(e) = deflate_queue_evt.read() { error!("failed reading deflate queue EventFd: {}", e); break 'poll; } - needs_interrupt |= self.process_inflate_deflate(false); + needs_interrupt_deflate |= self.process_inflate_deflate(false); } Token::CommandSocket => { if let Ok(req) = self.command_socket.recv() { @@ -218,16 +204,13 @@ impl Worker { info!("ballon config changed to consume {} pages", num_pages); self.config.num_pages.store(num_pages, Ordering::Relaxed); - self.signal_config_changed(); + self.interrupt.signal_config_changed(); } }; } } Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => break 'poll, } @@ -239,8 +222,13 @@ impl Worker { let _ = poll_ctx.delete(&self.command_socket); } } - if needs_interrupt { - self.signal_used_queue(); + + if needs_interrupt_inflate { + self.interrupt.signal_used_queue(self.inflate_queue.vector); + } + + if needs_interrupt_deflate { + self.interrupt.signal_used_queue(self.deflate_queue.vector); } } } @@ -334,7 +322,7 @@ impl VirtioDevice for Balloon { mem: GuestMemory, interrupt_evt: EventFd, interrupt_resample_evt: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, status: Arc<AtomicUsize>, mut queues: Vec<Queue>, queue_evts: Vec<EventFd>, @@ -358,12 +346,15 @@ impl VirtioDevice for Balloon { .name("virtio_balloon".to_string()) .spawn(move || { let mut worker = Worker { + interrupt: Interrupt::new( + status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), mem, inflate_queue: queues.remove(0), deflate_queue: queues.remove(0), - interrupt_status: status, - interrupt_evt, - interrupt_resample_evt, command_socket, config, }; diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs index 26be384..a2a1d3d 100644 --- a/devices/src/virtio/block.rs +++ b/devices/src/virtio/block.rs @@ -7,7 +7,7 @@ use std::io::{self, Seek, SeekFrom, Write}; use std::mem::size_of; use std::os::unix::io::{AsRawFd, RawFd}; use std::result; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use std::time::Duration; @@ -24,8 +24,8 @@ use sys_util::{error, info, warn, EventFd, GuestMemory, PollContext, PollToken, use vm_control::{DiskControlCommand, DiskControlResponseSocket, DiskControlResult}; use super::{ - copy_config, DescriptorChain, DescriptorError, Queue, Reader, VirtioDevice, Writer, - INTERRUPT_STATUS_CONFIG_CHANGED, INTERRUPT_STATUS_USED_RING, TYPE_BLOCK, VIRTIO_F_VERSION_1, + copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, + TYPE_BLOCK, VIRTIO_F_VERSION_1, }; const QUEUE_SIZE: u16 = 256; @@ -272,15 +272,12 @@ impl ExecuteError { } struct Worker { + interrupt: Interrupt, queues: Vec<Queue>, mem: GuestMemory, disk_image: Box<dyn DiskFile>, disk_size: Arc<Mutex<u64>>, read_only: bool, - interrupt_status: Arc<AtomicUsize>, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, - msix_config: Option<Arc<Mutex<MsixConfig>>>, } impl Worker { @@ -383,25 +380,6 @@ impl Worker { DiskControlResult::Ok } - fn signal_used_queue(&self, vector: u16) { - if let Some(msix_config) = &self.msix_config { - let mut msix_config = msix_config.lock(); - if msix_config.enabled() { - msix_config.trigger(vector); - return; - } - } - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - - fn signal_config_changed(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_CONFIG_CHANGED as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - fn run( &mut self, queue_evt: EventFd, @@ -430,7 +408,7 @@ impl Worker { (&flush_timer, Token::FlushTimer), (&queue_evt, Token::QueueAvailable), (&control_socket, Token::ControlRequest), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -468,7 +446,7 @@ impl Worker { break 'poll; } if self.process_queue(0, &mut flush_timer, &mut flush_timer_armed) { - self.signal_used_queue(self.queues[0].vector); + self.interrupt.signal_used_queue(self.queues[0].vector); } } Token::ControlRequest => { @@ -493,16 +471,13 @@ impl Worker { } } Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => break 'poll, } } if needs_config_interrupt { - self.signal_config_changed(); + self.interrupt.signal_config_changed(); } } } @@ -818,15 +793,17 @@ impl VirtioDevice for Block { .name("virtio_blk".to_string()) .spawn(move || { let mut worker = Worker { + interrupt: Interrupt::new( + status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), queues, mem, disk_image, disk_size, read_only, - interrupt_status: status, - interrupt_evt, - interrupt_resample_evt, - msix_config, }; worker.run(queue_evts.remove(0), kill_evt, control_socket); }); diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs index 1e545eb..210f815 100644 --- a/devices/src/virtio/gpu/mod.rs +++ b/devices/src/virtio/gpu/mod.rs @@ -14,7 +14,7 @@ use std::num::NonZeroU8; use std::os::unix::io::{AsRawFd, RawFd}; use std::path::PathBuf; use std::rc::Rc; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use std::time::Duration; @@ -32,8 +32,8 @@ use gpu_renderer::{Renderer, RendererFlags}; use resources::Alloc; use super::{ - copy_config, resource_bridge::*, DescriptorChain, Queue, Reader, VirtioDevice, Writer, - INTERRUPT_STATUS_USED_RING, TYPE_GPU, VIRTIO_F_VERSION_1, + copy_config, resource_bridge::*, DescriptorChain, Interrupt, Queue, Reader, VirtioDevice, + Writer, TYPE_GPU, VIRTIO_F_VERSION_1, }; use self::backend::Backend; @@ -475,11 +475,9 @@ impl Frontend { } struct Worker { + interrupt: Interrupt, exit_evt: EventFd, mem: GuestMemory, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, - interrupt_status: Arc<AtomicUsize>, ctrl_queue: Queue, ctrl_evt: EventFd, cursor_queue: Queue, @@ -490,12 +488,6 @@ struct Worker { } impl Worker { - fn signal_used_queue(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - let _ = self.interrupt_evt.write(1); - } - fn run(&mut self) { #[derive(PollToken)] enum Token { @@ -511,7 +503,7 @@ impl Worker { (&self.ctrl_evt, Token::CtrlQueue), (&self.cursor_evt, Token::CursorQueue), (&*self.state.display().borrow(), Token::Display), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&self.kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -552,7 +544,8 @@ impl Worker { break; } }; - let mut signal_used = false; + let mut signal_used_cursor = false; + let mut signal_used_ctrl = false; let mut ctrl_available = false; // Clear the old values and re-initialize with false. @@ -570,7 +563,7 @@ impl Worker { Token::CursorQueue => { let _ = self.cursor_evt.read(); if self.state.process_queue(&self.mem, &mut self.cursor_queue) { - signal_used = true; + signal_used_cursor = true; } } Token::Display => { @@ -581,10 +574,7 @@ impl Worker { } Token::ResourceBridge { index } => process_resource_bridge[index] = true, Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => { break 'poll; @@ -595,18 +585,18 @@ impl Worker { // All cursor commands go first because they have higher priority. while let Some(desc) = self.state.return_cursor() { self.cursor_queue.add_used(&self.mem, desc.index, desc.len); - signal_used = true; + signal_used_cursor = true; } if ctrl_available && self.state.process_queue(&self.mem, &mut self.ctrl_queue) { - signal_used = true; + signal_used_ctrl = true; } self.state.fence_poll(); while let Some(desc) = self.state.return_ctrl() { self.ctrl_queue.add_used(&self.mem, desc.index, desc.len); - signal_used = true; + signal_used_ctrl = true; } // Process the entire control queue before the resource bridge in case a resource is @@ -623,8 +613,12 @@ impl Worker { } } - if signal_used { - self.signal_used_queue(); + if signal_used_ctrl { + self.interrupt.signal_used_queue(self.ctrl_queue.vector); + } + + if signal_used_cursor { + self.interrupt.signal_used_queue(self.cursor_queue.vector); } } } @@ -830,7 +824,7 @@ impl VirtioDevice for Gpu { mem: GuestMemory, interrupt_evt: EventFd, interrupt_resample_evt: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, interrupt_status: Arc<AtomicUsize>, mut queues: Vec<Queue>, mut queue_evts: Vec<EventFd>, @@ -877,11 +871,14 @@ impl VirtioDevice for Gpu { }; Worker { + interrupt: Interrupt::new( + interrupt_status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), exit_evt, mem, - interrupt_evt, - interrupt_resample_evt, - interrupt_status, ctrl_queue, ctrl_evt, cursor_queue, diff --git a/devices/src/virtio/input/mod.rs b/devices/src/virtio/input/mod.rs index 706a563..a4561e5 100644 --- a/devices/src/virtio/input/mod.rs +++ b/devices/src/virtio/input/mod.rs @@ -17,15 +17,15 @@ use sys_util::{error, warn, EventFd, GuestMemory, PollContext, PollToken}; use self::event_source::{input_event, EvdevEventSource, EventSource, SocketEventSource}; use super::{ - copy_config, DescriptorChain, DescriptorError, Queue, Reader, VirtioDevice, Writer, - INTERRUPT_STATUS_USED_RING, TYPE_INPUT, + copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, + TYPE_INPUT, }; use std::collections::BTreeMap; use std::fmt::{self, Display}; use std::io::Read; use std::io::Write; use std::mem::size_of; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use sync::Mutex; @@ -363,22 +363,14 @@ impl virtio_input_event { } struct Worker<T: EventSource> { + interrupt: Interrupt, event_source: T, event_queue: Queue, status_queue: Queue, guest_memory: GuestMemory, - interrupt_status: Arc<AtomicUsize>, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, } impl<T: EventSource> Worker<T> { - fn signal_used_queue(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - // Fills a virtqueue with events from the source. Returns the number of bytes written. fn fill_event_virtqueue( event_source: &mut T, @@ -499,7 +491,7 @@ impl<T: EventSource> Worker<T> { (&event_queue_evt_fd, Token::EventQAvailable), (&status_queue_evt_fd, Token::StatusQAvailable), (&self.event_source, Token::InputEventsAvailable), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(poll_ctx) => poll_ctx, @@ -543,10 +535,7 @@ impl<T: EventSource> Worker<T> { Ok(_cnt) => needs_interrupt |= self.send_events(), }, Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => { let _ = kill_evt.read(); @@ -555,7 +544,7 @@ impl<T: EventSource> Worker<T> { } } if needs_interrupt { - self.signal_used_queue(); + self.interrupt.signal_used_queue(self.event_queue.vector); } } @@ -620,7 +609,7 @@ where mem: GuestMemory, interrupt_evt: EventFd, interrupt_resample_evt: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, status: Arc<AtomicUsize>, mut queues: Vec<Queue>, mut queue_evts: Vec<EventFd>, @@ -650,13 +639,16 @@ where .name(String::from("virtio_input")) .spawn(move || { let mut worker = Worker { + interrupt: Interrupt::new( + status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), event_source: source, event_queue, status_queue, guest_memory: mem, - interrupt_status: status, - interrupt_evt, - interrupt_resample_evt, }; worker.run(event_queue_evt_fd, status_queue_evt_fd, kill_evt); }); diff --git a/devices/src/virtio/interrupt.rs b/devices/src/virtio/interrupt.rs new file mode 100644 index 0000000..3a3d7e2 --- /dev/null +++ b/devices/src/virtio/interrupt.rs @@ -0,0 +1,83 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use super::{INTERRUPT_STATUS_CONFIG_CHANGED, INTERRUPT_STATUS_USED_RING}; +use crate::pci::MsixConfig; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use sync::Mutex; +use sys_util::EventFd; + +pub struct Interrupt { + interrupt_status: Arc<AtomicUsize>, + interrupt_evt: EventFd, + interrupt_resample_evt: EventFd, + msix_config: Option<Arc<Mutex<MsixConfig>>>, +} + +impl Interrupt { + pub fn new( + interrupt_status: Arc<AtomicUsize>, + interrupt_evt: EventFd, + interrupt_resample_evt: EventFd, + msix_config: Option<Arc<Mutex<MsixConfig>>>, + ) -> Interrupt { + Interrupt { + interrupt_status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + } + } + + /// Virtqueue Interrupts From The Device + /// + /// If MSI-X is enabled in this device, MSI-X interrupt is preferred. + /// Write to the irqfd to VMM to deliver virtual interrupt to the guest + pub fn signal_used_queue(&self, vector: u16) { + // Don't need to set ISR for MSI-X interrupts + if let Some(msix_config) = &self.msix_config { + let mut msix_config = msix_config.lock(); + if msix_config.enabled() { + msix_config.trigger(vector); + return; + } + } + + // Don't need to inject the interrupt if the guest hasn't processed it. + if self + .interrupt_status + .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst) + & INTERRUPT_STATUS_USED_RING as usize + == 0 + { + // Set BIT0 in ISR and write to irqfd to inject INTx interrupt + self.interrupt_status + .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); + self.interrupt_evt.write(1).unwrap(); + } + } + + /// Notification of Device Configuration Changes + /// Set BIT1 in ISR and write to irqfd + pub fn signal_config_changed(&self) { + self.interrupt_status + .fetch_or(INTERRUPT_STATUS_CONFIG_CHANGED as usize, Ordering::SeqCst); + self.interrupt_evt.write(1).unwrap(); + } + + /// Handle interrupt resampling event + pub fn interrupt_resample(&self) { + let _ = self.interrupt_resample_evt.read(); + 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) -> &EventFd { + &self.interrupt_resample_evt + } +} diff --git a/devices/src/virtio/mod.rs b/devices/src/virtio/mod.rs index 49f4355..ca3511f 100644 --- a/devices/src/virtio/mod.rs +++ b/devices/src/virtio/mod.rs @@ -10,6 +10,7 @@ mod descriptor_utils; #[cfg(feature = "gpu")] mod gpu; mod input; +mod interrupt; mod net; mod p9; mod pmem; @@ -32,6 +33,7 @@ pub use self::descriptor_utils::*; #[cfg(feature = "gpu")] pub use self::gpu::*; pub use self::input::*; +pub use self::interrupt::*; pub use self::net::*; pub use self::p9::*; pub use self::pmem::*; diff --git a/devices/src/virtio/net.rs b/devices/src/virtio/net.rs index 51d2039..abbaa98 100644 --- a/devices/src/virtio/net.rs +++ b/devices/src/virtio/net.rs @@ -7,7 +7,7 @@ use std::io::{self, Read, Write}; use std::mem; use std::net::Ipv4Addr; use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use sync::Mutex; @@ -21,7 +21,7 @@ use sys_util::{error, warn, EventFd, GuestMemory, PollContext, PollToken}; use virtio_sys::virtio_net::virtio_net_hdr_v1; use virtio_sys::{vhost, virtio_net}; -use super::{Queue, Reader, VirtioDevice, Writer, INTERRUPT_STATUS_USED_RING, TYPE_NET}; +use super::{Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_NET}; /// The maximum buffer size when segmentation offload is enabled. This /// includes the 12-byte virtio net header. @@ -88,14 +88,11 @@ impl Display for NetError { } struct Worker<T: TapT> { + interrupt: Interrupt, mem: GuestMemory, rx_queue: Queue, tx_queue: Queue, tap: T, - interrupt_status: Arc<AtomicUsize>, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, - msix_config: Option<Arc<Mutex<MsixConfig>>>, rx_buf: [u8; MAX_BUFFER_SIZE], rx_count: usize, deferred_rx: bool, @@ -109,19 +106,6 @@ impl<T> Worker<T> where T: TapT, { - fn signal_used_queue(&self, vector: u16) { - if let Some(msix_config) = &self.msix_config { - let mut msix_config = msix_config.lock(); - if msix_config.enabled() { - msix_config.trigger(vector); - return; - } - } - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - // Copies a single frame from `self.rx_buf` into the guest. Returns true // if a buffer was used, and false if the frame must be deferred until a buffer // is made available by the driver. @@ -174,7 +158,7 @@ where self.deferred_rx = true; break; } else if first_frame { - self.signal_used_queue(self.rx_queue.vector); + self.interrupt.signal_used_queue(self.rx_queue.vector); first_frame = false; } else { needs_interrupt = true; @@ -234,7 +218,7 @@ where self.tx_queue.add_used(&self.mem, index, 0); } - self.signal_used_queue(self.tx_queue.vector); + self.interrupt.signal_used_queue(self.tx_queue.vector); } fn run( @@ -261,7 +245,7 @@ where (&self.tap, Token::RxTap), (&rx_queue_evt, Token::RxQueue), (&tx_queue_evt, Token::TxQueue), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) .map_err(NetError::CreatePollContext)?; @@ -319,16 +303,13 @@ where self.process_tx(); } Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => break 'poll, } if needs_interrupt_rx { - self.signal_used_queue(self.rx_queue.vector); + self.interrupt.signal_used_queue(self.rx_queue.vector); } } } @@ -528,14 +509,16 @@ where let rx_queue = queues.remove(0); let tx_queue = queues.remove(0); let mut worker = Worker { + interrupt: Interrupt::new( + status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), mem, rx_queue, tx_queue, tap, - interrupt_status: status, - interrupt_evt, - msix_config, - interrupt_resample_evt, rx_buf: [0u8; MAX_BUFFER_SIZE], rx_count: 0, deferred_rx: false, diff --git a/devices/src/virtio/p9.rs b/devices/src/virtio/p9.rs index 83aa84e..d891d22 100644 --- a/devices/src/virtio/p9.rs +++ b/devices/src/virtio/p9.rs @@ -8,7 +8,7 @@ use std::mem; use std::os::unix::io::RawFd; use std::path::{Path, PathBuf}; use std::result; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use sync::Mutex; @@ -19,8 +19,7 @@ use sys_util::{error, warn, Error as SysError, EventFd, GuestMemory, PollContext use virtio_sys::vhost::VIRTIO_F_VERSION_1; use super::{ - copy_config, DescriptorError, Queue, Reader, VirtioDevice, Writer, INTERRUPT_STATUS_USED_RING, - TYPE_9P, + copy_config, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_9P, }; const QUEUE_SIZE: u16 = 128; @@ -89,21 +88,13 @@ impl Display for P9Error { pub type P9Result<T> = result::Result<T, P9Error>; struct Worker { + interrupt: Interrupt, mem: GuestMemory, queue: Queue, server: p9::Server, - irq_status: Arc<AtomicUsize>, - irq_evt: EventFd, - interrupt_resample_evt: EventFd, } impl Worker { - fn signal_used_queue(&self) -> P9Result<()> { - self.irq_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.irq_evt.write(1).map_err(P9Error::SignalUsedQueue) - } - fn process_queue(&mut self) -> P9Result<()> { while let Some(avail_desc) = self.queue.pop(&self.mem) { let mut reader = Reader::new(&self.mem, avail_desc.clone()) @@ -119,7 +110,7 @@ impl Worker { .add_used(&self.mem, avail_desc.index, writer.bytes_written() as u32); } - self.signal_used_queue()?; + self.interrupt.signal_used_queue(self.queue.vector); Ok(()) } @@ -137,7 +128,7 @@ impl Worker { let poll_ctx: PollContext<Token> = PollContext::build_with(&[ (&queue_evt, Token::QueueReady), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) .map_err(P9Error::CreatePollContext)?; @@ -151,10 +142,7 @@ impl Worker { self.process_queue()?; } Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.irq_status.load(Ordering::SeqCst) != 0 { - self.irq_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => return Ok(()), } @@ -241,7 +229,7 @@ impl VirtioDevice for P9 { guest_mem: GuestMemory, interrupt_evt: EventFd, interrupt_resample_evt: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, status: Arc<AtomicUsize>, mut queues: Vec<Queue>, mut queue_evts: Vec<EventFd>, @@ -265,12 +253,15 @@ impl VirtioDevice for P9 { .name("virtio_9p".to_string()) .spawn(move || { let mut worker = Worker { + interrupt: Interrupt::new( + status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), mem: guest_mem, queue: queues.remove(0), server, - irq_status: status, - irq_evt: interrupt_evt, - interrupt_resample_evt, }; worker.run(queue_evts.remove(0), kill_evt) diff --git a/devices/src/virtio/pmem.rs b/devices/src/virtio/pmem.rs index bc96f94..07ed137 100644 --- a/devices/src/virtio/pmem.rs +++ b/devices/src/virtio/pmem.rs @@ -6,7 +6,7 @@ use std::fmt::{self, Display}; use std::fs::File; use std::io; use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use sync::Mutex; @@ -19,8 +19,8 @@ use data_model::{DataInit, Le32, Le64}; use crate::pci::MsixConfig; use super::{ - copy_config, DescriptorChain, DescriptorError, Queue, Reader, VirtioDevice, Writer, - INTERRUPT_STATUS_USED_RING, TYPE_PMEM, VIRTIO_F_VERSION_1, + copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, + TYPE_PMEM, VIRTIO_F_VERSION_1, }; const QUEUE_SIZE: u16 = 256; @@ -85,12 +85,10 @@ impl ::std::error::Error for Error {} type Result<T> = ::std::result::Result<T, Error>; struct Worker { + interrupt: Interrupt, queue: Queue, memory: GuestMemory, disk_image: File, - interrupt_status: Arc<AtomicUsize>, - interrupt_event: EventFd, - interrupt_resample_event: EventFd, } impl Worker { @@ -149,12 +147,6 @@ impl Worker { needs_interrupt } - fn signal_used_queue(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.interrupt_event.write(1).unwrap(); - } - fn run(&mut self, queue_evt: EventFd, kill_evt: EventFd) { #[derive(PollToken)] enum Token { @@ -165,7 +157,7 @@ impl Worker { let poll_ctx: PollContext<Token> = match PollContext::build_with(&[ (&queue_evt, Token::QueueAvailable), - (&self.interrupt_resample_event, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -195,16 +187,13 @@ impl Worker { needs_interrupt |= self.process_queue(); } Token::InterruptResample => { - let _ = self.interrupt_resample_event.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_event.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => break 'poll, } } if needs_interrupt { - self.signal_used_queue(); + self.interrupt.signal_used_queue(self.queue.vector); } } } @@ -281,7 +270,7 @@ impl VirtioDevice for Pmem { memory: GuestMemory, interrupt_event: EventFd, interrupt_resample_event: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, status: Arc<AtomicUsize>, mut queues: Vec<Queue>, mut queue_events: Vec<EventFd>, @@ -308,12 +297,15 @@ impl VirtioDevice for Pmem { .name("virtio_pmem".to_string()) .spawn(move || { let mut worker = Worker { + interrupt: Interrupt::new( + status, + interrupt_event, + interrupt_resample_event, + msix_config, + ), memory, disk_image, queue, - interrupt_status: status, - interrupt_event, - interrupt_resample_event, }; worker.run(queue_event, kill_event); }); diff --git a/devices/src/virtio/rng.rs b/devices/src/virtio/rng.rs index 41e1b4b..9fa2e59 100644 --- a/devices/src/virtio/rng.rs +++ b/devices/src/virtio/rng.rs @@ -7,14 +7,14 @@ use std::fmt::{self, Display}; use std::fs::File; use std::io; use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use sync::Mutex; use sys_util::{error, warn, EventFd, GuestMemory, PollContext, PollToken}; -use super::{Queue, VirtioDevice, Writer, INTERRUPT_STATUS_USED_RING, TYPE_RNG}; +use super::{Interrupt, Queue, VirtioDevice, Writer, TYPE_RNG}; use crate::pci::MsixConfig; @@ -39,12 +39,10 @@ impl Display for RngError { } struct Worker { + interrupt: Interrupt, queue: Queue, mem: GuestMemory, random_file: File, - interrupt_status: Arc<AtomicUsize>, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, } impl Worker { @@ -73,12 +71,6 @@ impl Worker { needs_interrupt } - fn signal_used_queue(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - fn run(&mut self, queue_evt: EventFd, kill_evt: EventFd) { #[derive(PollToken)] enum Token { @@ -89,7 +81,7 @@ impl Worker { let poll_ctx: PollContext<Token> = match PollContext::build_with(&[ (&queue_evt, Token::QueueAvailable), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -119,16 +111,13 @@ impl Worker { needs_interrupt |= self.process_queue(); } Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => break 'poll, } } if needs_interrupt { - self.signal_used_queue(); + self.interrupt.signal_used_queue(self.queue.vector); } } } @@ -190,7 +179,7 @@ impl VirtioDevice for Rng { mem: GuestMemory, interrupt_evt: EventFd, interrupt_resample_evt: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, status: Arc<AtomicUsize>, mut queues: Vec<Queue>, mut queue_evts: Vec<EventFd>, @@ -216,12 +205,15 @@ impl VirtioDevice for Rng { .name("virtio_rng".to_string()) .spawn(move || { let mut worker = Worker { + interrupt: Interrupt::new( + status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), queue, mem, random_file, - interrupt_status: status, - interrupt_evt, - interrupt_resample_evt, }; worker.run(queue_evts.remove(0), kill_evt); }); diff --git a/devices/src/virtio/tpm.rs b/devices/src/virtio/tpm.rs index f5637d3..22d39a2 100644 --- a/devices/src/virtio/tpm.rs +++ b/devices/src/virtio/tpm.rs @@ -9,7 +9,7 @@ use std::io::{self, Read, Write}; use std::ops::BitOrAssign; use std::os::unix::io::RawFd; use std::path::PathBuf; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; @@ -19,8 +19,7 @@ use sys_util::{error, EventFd, GuestMemory, PollContext, PollToken}; use tpm2; use super::{ - DescriptorChain, DescriptorError, Queue, Reader, VirtioDevice, Writer, - INTERRUPT_STATUS_USED_RING, TYPE_TPM, + DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_TPM, }; // A single queue of size 2. The guest kernel driver will enqueue a single @@ -35,13 +34,11 @@ const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE]; const TPM_BUFSIZE: usize = 4096; struct Worker { + interrupt: Interrupt, queue: Queue, mem: GuestMemory, - interrupt_status: Arc<AtomicUsize>, queue_evt: EventFd, kill_evt: EventFd, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, device: Device, } @@ -107,12 +104,6 @@ impl Worker { NeedsInterrupt::Yes } - fn signal_used_queue(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - let _ = self.interrupt_evt.write(1); - } - fn run(mut self) { #[derive(PollToken, Debug)] enum Token { @@ -126,7 +117,7 @@ impl Worker { let poll_ctx = match PollContext::build_with(&[ (&self.queue_evt, Token::QueueAvailable), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&self.kill_evt, Token::Kill), ]) { Ok(pc) => pc, @@ -156,16 +147,13 @@ impl Worker { needs_interrupt |= self.process_queue(); } Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - let _ = self.interrupt_evt.write(1); - } + self.interrupt.interrupt_resample(); } Token::Kill => break 'poll, } } if needs_interrupt == NeedsInterrupt::Yes { - self.signal_used_queue(); + self.interrupt.signal_used_queue(self.queue.vector); } } } @@ -218,7 +206,7 @@ impl VirtioDevice for Tpm { mem: GuestMemory, interrupt_evt: EventFd, interrupt_resample_evt: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, interrupt_status: Arc<AtomicUsize>, mut queues: Vec<Queue>, mut queue_evts: Vec<EventFd>, @@ -249,12 +237,15 @@ impl VirtioDevice for Tpm { self.kill_evt = Some(self_kill_evt); let worker = Worker { + interrupt: Interrupt::new( + interrupt_status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), queue, mem, - interrupt_status, queue_evt, - interrupt_evt, - interrupt_resample_evt, kill_evt, device: Device { simulator }, }; diff --git a/devices/src/virtio/vhost/worker.rs b/devices/src/virtio/vhost/worker.rs index 26c1449..e88b929 100644 --- a/devices/src/virtio/vhost/worker.rs +++ b/devices/src/virtio/vhost/worker.rs @@ -3,7 +3,7 @@ // found in the LICENSE file. use std::os::raw::c_ulonglong; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use sync::Mutex; @@ -12,20 +12,17 @@ use vhost::Vhost; use super::{Error, Result}; use crate::pci::MsixConfig; -use crate::virtio::{Queue, INTERRUPT_STATUS_USED_RING}; +use crate::virtio::{Interrupt, Queue}; /// Worker that takes care of running the vhost device. This mainly involves forwarding interrupts /// from the vhost driver to the guest VM because crosvm only supports the virtio-mmio transport, /// which requires a bit to be set in the interrupt status register before triggering the interrupt /// and the vhost driver doesn't do this for us. pub struct Worker<T: Vhost> { + interrupt: Interrupt, queues: Vec<Queue>, vhost_handle: T, vhost_interrupt: Vec<EventFd>, - interrupt_status: Arc<AtomicUsize>, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, - msix_config: Option<Arc<Mutex<MsixConfig>>>, acked_features: u64, } @@ -41,31 +38,19 @@ impl<T: Vhost> Worker<T> { acked_features: u64, ) -> Worker<T> { Worker { + interrupt: Interrupt::new( + interrupt_status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), queues, vhost_handle, vhost_interrupt, - interrupt_status, - interrupt_evt, - interrupt_resample_evt, - msix_config, acked_features, } } - fn signal_used_queue(&self, vector: u16) { - if let Some(msix_config) = &self.msix_config { - let mut msix_config = msix_config.lock(); - if msix_config.enabled() { - msix_config.trigger(vector); - return; - } - } - - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - self.interrupt_evt.write(1).unwrap(); - } - pub fn run<F>( &mut self, queue_evts: Vec<EventFd>, @@ -133,7 +118,7 @@ impl<T: Vhost> Worker<T> { } let poll_ctx: PollContext<Token> = PollContext::build_with(&[ - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) .map_err(Error::CreatePollContext)?; @@ -153,13 +138,10 @@ impl<T: Vhost> Worker<T> { self.vhost_interrupt[index] .read() .map_err(Error::VhostIrqRead)?; - self.signal_used_queue(self.queues[index].vector); + self.interrupt.signal_used_queue(self.queues[index].vector); } Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } Token::Kill => break 'poll, } diff --git a/devices/src/virtio/wl.rs b/devices/src/virtio/wl.rs index 4531511..319d70e 100644 --- a/devices/src/virtio/wl.rs +++ b/devices/src/virtio/wl.rs @@ -44,7 +44,7 @@ use std::os::unix::net::UnixStream; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::result; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::thread; use std::time::Duration; @@ -71,9 +71,7 @@ use sys_util::{ use sys_util::ioctl_with_ref; use super::resource_bridge::*; -use super::{ - DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_WL, VIRTIO_F_VERSION_1, -}; +use super::{DescriptorChain, Interrupt, Queue, VirtioDevice, TYPE_WL, VIRTIO_F_VERSION_1}; use crate::pci::MsixConfig; use vm_control::{MaybeOwnedFd, VmMemoryControlRequestSocket, VmMemoryRequest, VmMemoryResponse}; @@ -1472,10 +1470,8 @@ impl WlState { } struct Worker { + interrupt: Interrupt, mem: GuestMemory, - interrupt_evt: EventFd, - interrupt_resample_evt: EventFd, - interrupt_status: Arc<AtomicUsize>, in_queue: Queue, out_queue: Queue, state: WlState, @@ -1488,6 +1484,7 @@ impl Worker { interrupt_evt: EventFd, interrupt_resample_evt: EventFd, interrupt_status: Arc<AtomicUsize>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, in_queue: Queue, out_queue: Queue, wayland_path: PathBuf, @@ -1496,10 +1493,13 @@ impl Worker { resource_bridge: Option<ResourceRequestSocket>, ) -> Worker { Worker { + interrupt: Interrupt::new( + interrupt_status, + interrupt_evt, + interrupt_resample_evt, + msix_config, + ), mem, - interrupt_evt, - interrupt_resample_evt, - interrupt_status, in_queue, out_queue, state: WlState::new( @@ -1512,12 +1512,6 @@ impl Worker { } } - fn signal_used_queue(&self) { - self.interrupt_status - .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst); - let _ = self.interrupt_evt.write(1); - } - fn run(&mut self, mut queue_evts: Vec<EventFd>, kill_evt: EventFd) { let in_queue_evt = queue_evts.remove(0); let out_queue_evt = queue_evts.remove(0); @@ -1535,7 +1529,7 @@ impl Worker { (&out_queue_evt, Token::OutQueue), (&kill_evt, Token::Kill), (&self.state.poll_ctx, Token::State), - (&self.interrupt_resample_evt, Token::InterruptResample), + (self.interrupt.get_resample_evt(), Token::InterruptResample), ]) { Ok(pc) => pc, Err(e) => { @@ -1545,7 +1539,8 @@ impl Worker { }; 'poll: loop { - let mut signal_used = false; + let mut signal_used_in = false; + let mut signal_used_out = false; let events = match poll_ctx.wait() { Ok(v) => v, Err(e) => { @@ -1578,7 +1573,7 @@ impl Worker { } })); for &reject in &rejects[..rejects_len] { - signal_used = true; + signal_used_in = true; self.in_queue.add_used(&self.mem, reject, 0); } } @@ -1609,24 +1604,21 @@ impl Worker { encode_resp(resp_mem, resp).unwrap_or_default(); self.out_queue.add_used(&self.mem, desc.index, used_len); - signal_used = true; + signal_used_out = true; } } } else { // Chains that are unusable get sent straight back to the used // queue. self.out_queue.add_used(&self.mem, desc.index, 0); - signal_used = true; + signal_used_out = true; } } } Token::Kill => break 'poll, Token::State => self.state.process_poll_context(), Token::InterruptResample => { - let _ = self.interrupt_resample_evt.read(); - if self.interrupt_status.load(Ordering::SeqCst) != 0 { - self.interrupt_evt.write(1).unwrap(); - } + self.interrupt.interrupt_resample(); } } } @@ -1652,7 +1644,7 @@ impl Worker { 0 } }; - signal_used = true; + signal_used_in = true; self.in_queue.add_used(&self.mem, index, len); } else { break; @@ -1662,8 +1654,12 @@ impl Worker { } } - if signal_used { - self.signal_used_queue(); + if signal_used_in { + self.interrupt.signal_used_queue(self.in_queue.vector); + } + + if signal_used_out { + self.interrupt.signal_used_queue(self.out_queue.vector); } } } @@ -1745,7 +1741,7 @@ impl VirtioDevice for Wl { mem: GuestMemory, interrupt_evt: EventFd, interrupt_resample_evt: EventFd, - _msix_config: Option<Arc<Mutex<MsixConfig>>>, + msix_config: Option<Arc<Mutex<MsixConfig>>>, status: Arc<AtomicUsize>, mut queues: Vec<Queue>, queue_evts: Vec<EventFd>, @@ -1776,6 +1772,7 @@ impl VirtioDevice for Wl { interrupt_evt, interrupt_resample_evt, status, + msix_config, queues.remove(0), queues.remove(0), wayland_path, |