diff options
-rw-r--r-- | arch/src/lib.rs | 6 | ||||
-rw-r--r-- | kvm/src/lib.rs | 119 | ||||
-rw-r--r-- | src/plugin/mod.rs | 12 | ||||
-rw-r--r-- | src/plugin/process.rs | 18 | ||||
-rw-r--r-- | vm_control/src/lib.rs | 4 |
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), } |