summary refs log tree commit diff
path: root/devices/src/virtio/virtio_pci_device.rs
diff options
context:
space:
mode:
authorChuanxiao Dong <chuanxiao.dong@intel.corp-partner.google.com>2019-12-06 10:01:32 +0800
committerCommit Bot <commit-bot@chromium.org>2019-12-09 03:06:47 +0000
commit39087b289a3278bd02d28c1318d3cfb40c94e6db (patch)
tree2ea70f3065d5122326cf345a9b475311669322bf /devices/src/virtio/virtio_pci_device.rs
parentd62df4aa6e58c85119077105ebfb81cf6dc617f2 (diff)
downloadcrosvm-39087b289a3278bd02d28c1318d3cfb40c94e6db.tar
crosvm-39087b289a3278bd02d28c1318d3cfb40c94e6db.tar.gz
crosvm-39087b289a3278bd02d28c1318d3cfb40c94e6db.tar.bz2
crosvm-39087b289a3278bd02d28c1318d3cfb40c94e6db.tar.lz
crosvm-39087b289a3278bd02d28c1318d3cfb40c94e6db.tar.xz
crosvm-39087b289a3278bd02d28c1318d3cfb40c94e6db.tar.zst
crosvm-39087b289a3278bd02d28c1318d3cfb40c94e6db.zip
devices: clone the EventFds before activate
The interrupt_evt/interrupt_resample_evt/queue_evts were move to activate
so the reset method has to return them back (although there is no virtio
device implemented the reset method yet).

Instead of move, another way is just clone these EventFds so that they
don't need needed to be returned.

The advantage of doing this can avoid changing every virtio device reset
method (again, currently there is no virtio device implemented the reset
method yet, but this method is going to used when needs to support the
reset of a virtio device) for returning them, which can simplify the code.
And reset method just needs to take care their own specific resources.

The disadvantage is that, the clone of an EventFd is try_clone which might
return error code (although this shouldn't happen). If in such case, the virtio
device won't be activated.

BUG=None
TEST=launch crosvm guest with virtio devices(rng/balloon/blk/net).

Change-Id: I6e55782c3ecc46bfa878aff24b85a58a7ed66365
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.corp-partner.google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1925682
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'devices/src/virtio/virtio_pci_device.rs')
-rw-r--r--devices/src/virtio/virtio_pci_device.rs54
1 files changed, 46 insertions, 8 deletions
diff --git a/devices/src/virtio/virtio_pci_device.rs b/devices/src/virtio/virtio_pci_device.rs
index 9ace795..91e139b 100644
--- a/devices/src/virtio/virtio_pci_device.rs
+++ b/devices/src/virtio/virtio_pci_device.rs
@@ -12,7 +12,7 @@ use data_model::{DataInit, Le32};
 use kvm::Datamatch;
 use libc::ERANGE;
 use resources::{Alloc, MmioType, SystemAllocator};
-use sys_util::{EventFd, GuestMemory, Result};
+use sys_util::{warn, EventFd, GuestMemory, Result};
 
 use super::*;
 use crate::pci::{
@@ -318,6 +318,10 @@ impl VirtioPciDevice {
         self.settings_bar = settings_bar;
         Ok(())
     }
+
+    fn clone_queue_evts(&self) -> Result<Vec<EventFd>> {
+        self.queue_evts.iter().map(|e| e.try_clone()).collect()
+    }
 }
 
 impl PciDevice for VirtioPciDevice {
@@ -573,8 +577,31 @@ impl PciDevice for VirtioPciDevice {
 
         if !self.device_activated && self.is_driver_ready() && self.are_queues_valid() {
             if let Some(interrupt_evt) = self.interrupt_evt.take() {
+                self.interrupt_evt = match interrupt_evt.try_clone() {
+                    Ok(evt) => Some(evt),
+                    Err(e) => {
+                        warn!(
+                            "{} failed to clone interrupt_evt: {}",
+                            self.debug_label(),
+                            e
+                        );
+                        None
+                    }
+                };
                 if let Some(interrupt_resample_evt) = self.interrupt_resample_evt.take() {
+                    self.interrupt_resample_evt = match interrupt_resample_evt.try_clone() {
+                        Ok(evt) => Some(evt),
+                        Err(e) => {
+                            warn!(
+                                "{} failed to clone interrupt_resample_evt: {}",
+                                self.debug_label(),
+                                e
+                            );
+                            None
+                        }
+                    };
                     if let Some(mem) = self.mem.take() {
+                        self.mem = Some(mem.clone());
                         let interrupt = Interrupt::new(
                             self.interrupt_status.clone(),
                             interrupt_evt,
@@ -583,13 +610,24 @@ impl PciDevice for VirtioPciDevice {
                             self.common_config.msix_config,
                         );
 
-                        self.device.activate(
-                            mem,
-                            interrupt,
-                            self.queues.clone(),
-                            self.queue_evts.split_off(0),
-                        );
-                        self.device_activated = true;
+                        match self.clone_queue_evts() {
+                            Ok(queue_evts) => {
+                                self.device.activate(
+                                    mem,
+                                    interrupt,
+                                    self.queues.clone(),
+                                    queue_evts,
+                                );
+                                self.device_activated = true;
+                            }
+                            Err(e) => {
+                                warn!(
+                                    "{} not activate due to failed to clone queue_evts: {}",
+                                    self.debug_label(),
+                                    e
+                                );
+                            }
+                        }
                     }
                 }
             }