summary refs log tree commit diff
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2018-02-02 18:03:59 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-02-06 21:32:40 -0800
commit3994c3964e117da41bfe263d6e0be0babc861572 (patch)
treeb71a2cbdd9a03a1bb15a6b6b93cb42b07697b4e0
parente0e8e56732801c63f5c836827e473665e1e12c29 (diff)
downloadcrosvm-3994c3964e117da41bfe263d6e0be0babc861572.tar
crosvm-3994c3964e117da41bfe263d6e0be0babc861572.tar.gz
crosvm-3994c3964e117da41bfe263d6e0be0babc861572.tar.bz2
crosvm-3994c3964e117da41bfe263d6e0be0babc861572.tar.lz
crosvm-3994c3964e117da41bfe263d6e0be0babc861572.tar.xz
crosvm-3994c3964e117da41bfe263d6e0be0babc861572.tar.zst
crosvm-3994c3964e117da41bfe263d6e0be0babc861572.zip
kvm: support irqfds with resample eventfds
The plugin process may require resample events to implement a device
properly.

TEST=cargo test -p kvm; ./build_test
BUG=chromium:800626

Change-Id: I47a3336195f212c9f6c49adfaec24757803c3b7f
Reviewed-on: https://chromium-review.googlesource.com/900489
Commit-Ready: Zach Reizner <zachr@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
-rw-r--r--kvm/src/lib.rs40
1 files changed, 38 insertions, 2 deletions
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs
index d6dbea8..8f977af 100644
--- a/kvm/src/lib.rs
+++ b/kvm/src/lib.rs
@@ -474,9 +474,32 @@ impl Vm {
         }
     }
 
-    /// Unregisters an event that was previously registered with `register_irqfd`.
+    /// Registers an event that will, when signalled, trigger the `gsi` irq, and `resample_evt` will
+    /// get triggered when the irqchip is resampled.
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64"))]
+    pub fn register_irqfd_resample(&self,
+                                   evt: &EventFd,
+                                   resample_evt: &EventFd,
+                                   gsi: u32)
+                                   -> Result<()> {
+        let irqfd = kvm_irqfd {
+            flags: KVM_IRQFD_FLAG_RESAMPLE,
+            fd: evt.as_raw_fd() as u32,
+            resamplefd: resample_evt.as_raw_fd() as u32,
+            gsi: gsi,
+            ..Default::default()
+        };
+        // Safe because we know that our file is a VM fd, we know the kernel will only read the
+        // correct amount of memory from our pointer, and we verify the return result.
+        let ret = unsafe { ioctl_with_ref(self, KVM_IRQFD(), &irqfd) };
+        if ret == 0 { Ok(()) } else { errno_result() }
+    }
+
+    /// Unregisters an event that was previously registered with
+    /// `register_irqfd`/`register_irqfd_resample`.
     ///
-    /// The `evt` and `gsi` pair must be the same as the ones passed into `register_irqfd`.
+    /// The `evt` and `gsi` pair must be the same as the ones passed into
+    /// `register_irqfd`/`register_irqfd_resample`.
     #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64"))]
     pub fn unregister_irqfd(&self, evt: &EventFd, gsi: u32) -> Result<()> {
         let irqfd = kvm_irqfd {
@@ -1062,6 +1085,19 @@ mod tests {
     }
 
     #[test]
+    fn irqfd_resample() {
+        let kvm = Kvm::new().unwrap();
+        let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
+        let vm = Vm::new(&kvm, gm).unwrap();
+        let evtfd1 = EventFd::new().unwrap();
+        let evtfd2 = EventFd::new().unwrap();
+        vm.register_irqfd_resample(&evtfd1, &evtfd2, 4).unwrap();
+        vm.unregister_irqfd(&evtfd1, 4).unwrap();
+        // Ensures the ioctl is actually reading the resamplefd.
+        vm.register_irqfd_resample(&evtfd1, unsafe { &EventFd::from_raw_fd(-1) }, 4).unwrap_err();
+    }
+
+    #[test]
     fn set_gsi_routing() {
         let kvm = Kvm::new().unwrap();
         let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();