summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--arch/src/lib.rs6
-rw-r--r--kvm/src/lib.rs119
-rw-r--r--src/plugin/mod.rs12
-rw-r--r--src/plugin/process.rs18
-rw-r--r--vm_control/src/lib.rs4
5 files changed, 94 insertions, 65 deletions
diff --git a/arch/src/lib.rs b/arch/src/lib.rs
index f2c7639..aeb8f6c 100644
--- a/arch/src/lib.rs
+++ b/arch/src/lib.rs
@@ -21,7 +21,7 @@ use devices::{
     Bus, BusError, PciDevice, PciDeviceError, PciInterruptPin, PciRoot, ProxyDevice, Serial,
 };
 use io_jail::Minijail;
-use kvm::{IoeventAddress, Kvm, NoDatamatch, Vcpu, Vm};
+use kvm::{Datamatch, IoeventAddress, Kvm, Vcpu, Vm};
 use resources::SystemAllocator;
 use sys_util::{syslog, EventFd, GuestMemory};
 
@@ -169,7 +169,7 @@ pub fn generate_pci_root(
             .map_err(DeviceRegistrationError::AllocateIoAddrs)?;
         for (event, addr) in device.ioeventfds() {
             let io_addr = IoeventAddress::Mmio(addr);
-            vm.register_ioevent(&event, io_addr, NoDatamatch)
+            vm.register_ioevent(&event, io_addr, Datamatch::AnyLength)
                 .map_err(DeviceRegistrationError::RegisterIoevent)?;
             keep_fds.push(event.as_raw_fd());
         }
@@ -212,7 +212,7 @@ pub fn register_mmio(
         .ok_or(DeviceRegistrationError::AddrsExhausted)?;
     for (i, queue_evt) in mmio_device.queue_evts().iter().enumerate() {
         let io_addr = IoeventAddress::Mmio(mmio_base + devices::virtio::NOTIFY_REG_OFFSET as u64);
-        vm.register_ioevent(&queue_evt, io_addr, i as u32)
+        vm.register_ioevent(&queue_evt, io_addr, Datamatch::U32(Some(i as u32)))
             .map_err(DeviceRegistrationError::RegisterIoevent)?;
         keep_fds.push(queue_evt.as_raw_fd());
     }
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs
index c9c5673..42a58f3 100644
--- a/kvm/src/lib.rs
+++ b/kvm/src/lib.rs
@@ -216,12 +216,13 @@ pub enum IoeventAddress {
     Mmio(u64),
 }
 
-/// Used in `Vm::register_ioevent` to indicate that no datamatch is requested.
-pub struct NoDatamatch;
-impl Into<u64> for NoDatamatch {
-    fn into(self) -> u64 {
-        0
-    }
+/// Used in `Vm::register_ioevent` to indicate a size and optionally value to match.
+pub enum Datamatch {
+    AnyLength,
+    U8(Option<u8>),
+    U16(Option<u16>),
+    U32(Option<u32>),
+    U64(Option<u64>),
 }
 
 /// A source of IRQs in an `IrqRoute`.
@@ -621,53 +622,59 @@ impl Vm {
     ///
     /// In all cases where `evt` is signaled, the ordinary vmexit to userspace that would be
     /// triggered is prevented.
-    pub fn register_ioevent<T: Into<u64>>(
+    pub fn register_ioevent(
         &self,
         evt: &EventFd,
         addr: IoeventAddress,
-        datamatch: T,
+        datamatch: Datamatch,
     ) -> Result<()> {
-        self.ioeventfd(
-            evt,
-            addr,
-            datamatch.into(),
-            std::mem::size_of::<T>() as u32,
-            false,
-        )
+        self.ioeventfd(evt, addr, datamatch, false)
     }
 
     /// Unregisters an event previously registered with `register_ioevent`.
     ///
     /// The `evt`, `addr`, and `datamatch` set must be the same as the ones passed into
     /// `register_ioevent`.
-    pub fn unregister_ioevent<T: Into<u64>>(
+    pub fn unregister_ioevent(
         &self,
         evt: &EventFd,
         addr: IoeventAddress,
-        datamatch: T,
+        datamatch: Datamatch,
     ) -> Result<()> {
-        self.ioeventfd(
-            evt,
-            addr,
-            datamatch.into(),
-            std::mem::size_of::<T>() as u32,
-            true,
-        )
+        self.ioeventfd(evt, addr, datamatch, true)
     }
 
     fn ioeventfd(
         &self,
         evt: &EventFd,
         addr: IoeventAddress,
-        datamatch: u64,
-        datamatch_len: u32,
+        datamatch: Datamatch,
         deassign: bool,
     ) -> Result<()> {
+        let (do_datamatch, datamatch_value, datamatch_len) = match datamatch {
+            Datamatch::AnyLength => (false, 0, 0),
+            Datamatch::U8(v) => match v {
+                Some(u) => (true, u as u64, 1),
+                None => (false, 0, 1),
+            },
+            Datamatch::U16(v) => match v {
+                Some(u) => (true, u as u64, 2),
+                None => (false, 0, 2),
+            },
+            Datamatch::U32(v) => match v {
+                Some(u) => (true, u as u64, 4),
+                None => (false, 0, 4),
+            },
+            Datamatch::U64(v) => match v {
+                Some(u) => (true, u as u64, 8),
+                None => (false, 0, 8),
+            },
+        };
         let mut flags = 0;
         if deassign {
             flags |= 1 << kvm_ioeventfd_flag_nr_deassign;
         }
-        if datamatch_len > 0 {
+        if do_datamatch {
             flags |= 1 << kvm_ioeventfd_flag_nr_datamatch
         }
         match addr {
@@ -675,7 +682,7 @@ impl Vm {
             _ => {}
         };
         let ioeventfd = kvm_ioeventfd {
-            datamatch,
+            datamatch: datamatch_value,
             len: datamatch_len,
             addr: match addr {
                 IoeventAddress::Pio(p) => p as u64,
@@ -1623,24 +1630,34 @@ mod tests {
 
     #[test]
     fn register_ioevent() {
-        assert_eq!(std::mem::size_of::<NoDatamatch>(), 0);
-
         let kvm = Kvm::new().unwrap();
         let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
         let vm = Vm::new(&kvm, gm).unwrap();
         let evtfd = EventFd::new().unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xf4), NoDatamatch)
-            .unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Mmio(0x1000), NoDatamatch)
-            .unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xc1), 0x7fu8)
-            .unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xc2), 0x1337u16)
+        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xf4), Datamatch::AnyLength)
             .unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xc4), 0xdeadbeefu32)
-            .unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xc8), 0xdeadbeefdeadbeefu64)
+        vm.register_ioevent(&evtfd, IoeventAddress::Mmio(0x1000), Datamatch::AnyLength)
             .unwrap();
+        vm.register_ioevent(
+            &evtfd,
+            IoeventAddress::Pio(0xc1),
+            Datamatch::U8(Some(0x7fu8)),
+        ).unwrap();
+        vm.register_ioevent(
+            &evtfd,
+            IoeventAddress::Pio(0xc2),
+            Datamatch::U16(Some(0x1337u16)),
+        ).unwrap();
+        vm.register_ioevent(
+            &evtfd,
+            IoeventAddress::Pio(0xc4),
+            Datamatch::U32(Some(0xdeadbeefu32)),
+        ).unwrap();
+        vm.register_ioevent(
+            &evtfd,
+            IoeventAddress::Pio(0xc8),
+            Datamatch::U64(Some(0xdeadbeefdeadbeefu64)),
+        ).unwrap();
     }
 
     #[test]
@@ -1649,18 +1666,24 @@ mod tests {
         let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
         let vm = Vm::new(&kvm, gm).unwrap();
         let evtfd = EventFd::new().unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xf4), NoDatamatch)
-            .unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Mmio(0x1000), NoDatamatch)
-            .unwrap();
-        vm.register_ioevent(&evtfd, IoeventAddress::Mmio(0x1004), 0x7fu8)
+        vm.register_ioevent(&evtfd, IoeventAddress::Pio(0xf4), Datamatch::AnyLength)
             .unwrap();
-        vm.unregister_ioevent(&evtfd, IoeventAddress::Pio(0xf4), NoDatamatch)
+        vm.register_ioevent(&evtfd, IoeventAddress::Mmio(0x1000), Datamatch::AnyLength)
             .unwrap();
-        vm.unregister_ioevent(&evtfd, IoeventAddress::Mmio(0x1000), NoDatamatch)
+        vm.register_ioevent(
+            &evtfd,
+            IoeventAddress::Mmio(0x1004),
+            Datamatch::U8(Some(0x7fu8)),
+        ).unwrap();
+        vm.unregister_ioevent(&evtfd, IoeventAddress::Pio(0xf4), Datamatch::AnyLength)
             .unwrap();
-        vm.unregister_ioevent(&evtfd, IoeventAddress::Mmio(0x1004), 0x7fu8)
+        vm.unregister_ioevent(&evtfd, IoeventAddress::Mmio(0x1000), Datamatch::AnyLength)
             .unwrap();
+        vm.unregister_ioevent(
+            &evtfd,
+            IoeventAddress::Mmio(0x1004),
+            Datamatch::U8(Some(0x7fu8)),
+        ).unwrap();
     }
 
     #[test]
diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs
index ddff643..8cd81b4 100644
--- a/src/plugin/mod.rs
+++ b/src/plugin/mod.rs
@@ -25,7 +25,7 @@ use libc::{
 use protobuf::ProtobufError;
 
 use io_jail::{self, Minijail};
-use kvm::{IoeventAddress, Kvm, NoDatamatch, Vcpu, VcpuExit, Vm};
+use kvm::{Datamatch, IoeventAddress, Kvm, Vcpu, VcpuExit, Vm};
 use net_util::{Error as TapError, Tap, TapT};
 use sys_util::{
     block_signal, clear_signal, getegid, geteuid, register_signal_handler, Error as SysError,
@@ -303,11 +303,11 @@ impl PluginObject {
                 length,
                 datamatch,
             } => match length {
-                0 => vm.unregister_ioevent(&evt, addr, NoDatamatch),
-                1 => vm.unregister_ioevent(&evt, addr, datamatch as u8),
-                2 => vm.unregister_ioevent(&evt, addr, datamatch as u16),
-                4 => vm.unregister_ioevent(&evt, addr, datamatch as u32),
-                8 => vm.unregister_ioevent(&evt, addr, datamatch as u64),
+                0 => vm.unregister_ioevent(&evt, addr, Datamatch::AnyLength),
+                1 => vm.unregister_ioevent(&evt, addr, Datamatch::U8(Some(datamatch as u8))),
+                2 => vm.unregister_ioevent(&evt, addr, Datamatch::U16(Some(datamatch as u16))),
+                4 => vm.unregister_ioevent(&evt, addr, Datamatch::U32(Some(datamatch as u32))),
+                8 => vm.unregister_ioevent(&evt, addr, Datamatch::U64(Some(datamatch as u64))),
                 _ => Err(SysError::new(EINVAL)),
             },
             PluginObject::Memory { slot, .. } => vm.remove_device_memory(slot).and(Ok(())),
diff --git a/src/plugin/process.rs b/src/plugin/process.rs
index c99e3b6..c46b835 100644
--- a/src/plugin/process.rs
+++ b/src/plugin/process.rs
@@ -23,7 +23,7 @@ use protobuf;
 use protobuf::Message;
 
 use io_jail::Minijail;
-use kvm::{dirty_log_bitmap_size, IoeventAddress, IrqRoute, IrqSource, NoDatamatch, PicId, Vm};
+use kvm::{dirty_log_bitmap_size, Datamatch, IoeventAddress, IrqRoute, IrqSource, PicId, Vm};
 use kvm_sys::{kvm_ioapic_state, kvm_pic_state, kvm_pit_state2};
 use plugin_proto::*;
 use sys_util::{
@@ -289,11 +289,17 @@ impl Process {
             AddressSpace::MMIO => IoeventAddress::Mmio(io_event.address),
         };
         match io_event.length {
-            0 => vm.register_ioevent(&evt, addr, NoDatamatch)?,
-            1 => vm.register_ioevent(&evt, addr, io_event.datamatch as u8)?,
-            2 => vm.register_ioevent(&evt, addr, io_event.datamatch as u16)?,
-            4 => vm.register_ioevent(&evt, addr, io_event.datamatch as u32)?,
-            8 => vm.register_ioevent(&evt, addr, io_event.datamatch as u64)?,
+            0 => vm.register_ioevent(&evt, addr, Datamatch::AnyLength)?,
+            1 => vm.register_ioevent(&evt, addr, Datamatch::U8(Some(io_event.datamatch as u8)))?,
+            2 => {
+                vm.register_ioevent(&evt, addr, Datamatch::U16(Some(io_event.datamatch as u16)))?
+            }
+            4 => {
+                vm.register_ioevent(&evt, addr, Datamatch::U32(Some(io_event.datamatch as u32)))?
+            }
+            8 => {
+                vm.register_ioevent(&evt, addr, Datamatch::U64(Some(io_event.datamatch as u64)))?
+            }
             _ => return Err(SysError::new(EINVAL)),
         };
 
diff --git a/vm_control/src/lib.rs b/vm_control/src/lib.rs
index 47e9d8c..4d1d036 100644
--- a/vm_control/src/lib.rs
+++ b/vm_control/src/lib.rs
@@ -27,7 +27,7 @@ use libc::{EINVAL, ENODEV, ERANGE};
 
 use byteorder::{LittleEndian, WriteBytesExt};
 use data_model::{DataInit, Le32, Le64, VolatileMemory};
-use kvm::{IoeventAddress, Vm};
+use kvm::{Datamatch, IoeventAddress, Vm};
 use resources::{GpuMemoryDesc, GpuMemoryPlaneDesc, SystemAllocator};
 use sys_util::{
     Error as SysError, EventFd, GuestAddress, MemoryMapping, MmapError, Result, ScmSocket,
@@ -248,7 +248,7 @@ impl VmRequest {
                 VmResponse::Ok
             }
             &VmRequest::RegisterIoevent(ref evt, addr, datamatch) => {
-                match vm.register_ioevent(evt, addr, datamatch) {
+                match vm.register_ioevent(evt, addr, Datamatch::U32(Some(datamatch))) {
                     Ok(_) => VmResponse::Ok,
                     Err(e) => VmResponse::Err(e),
                 }