diff --git a/vm-virtio/src/queue.rs b/vm-virtio/src/queue.rs index 137167f67..aec691350 100644 --- a/vm-virtio/src/queue.rs +++ b/vm-virtio/src/queue.rs @@ -447,14 +447,59 @@ impl Queue { } } + /// Update avail_event on the used ring with the last index in the avail ring. + pub fn update_avail_event(&mut self, mem: &GuestMemoryMmap) { + let index_addr = match mem.checked_offset(self.avail_ring, 2) { + Some(ret) => ret, + None => { + // TODO log address + warn!("Invalid offset"); + return; + } + }; + // Note that last_index has no invalid values + let last_index: u16 = match mem.read_obj::(index_addr) { + Ok(ret) => ret, + Err(_) => return, + }; + + match mem.checked_offset(self.used_ring, (4 + self.actual_size() * 8) as usize) { + Some(a) => { + mem.write_obj(last_index, a).unwrap(); + } + None => warn!("Can't update avail_event"), + } + + // This fence ensures all descriptor writes are visible before the index update is. + fence(Ordering::Release); + } + + /// Return the value present in the used_event field of the avail ring. + pub fn get_used_event(&self, mem: &GuestMemoryMmap) -> Option> { + let avail_ring = self.avail_ring; + let used_event_addr = + match mem.checked_offset(avail_ring, (4 + self.actual_size() * 2) as usize) { + Some(a) => a, + None => { + warn!("Invalid offset looking for used_event"); + return None; + } + }; + + match mem.read_obj::(used_event_addr) { + Ok(ret) => Some(Wrapping(ret)), + Err(_) => None, + } + } + /// Puts an available descriptor head into the used ring for use by the guest. - pub fn add_used(&mut self, mem: &GuestMemoryMmap, desc_index: u16, len: u32) { + pub fn add_used(&mut self, mem: &GuestMemoryMmap, desc_index: u16, len: u32) -> Option { if desc_index >= self.actual_size() { error!( "attempted to add out of bounds descriptor to used ring: {}", desc_index ); - return; + return None; } let used_ring = self.used_ring; @@ -473,6 +518,8 @@ impl Queue { mem.write_obj(self.next_used.0 as u16, used_ring.unchecked_add(2)) .unwrap(); + + Some(self.next_used.0) } /// Goes back one position in the available descriptor chain offered by the driver. diff --git a/vm-virtio/src/vhost_user/blk.rs b/vm-virtio/src/vhost_user/blk.rs index a5b4d7036..c658e1f46 100644 --- a/vm-virtio/src/vhost_user/blk.rs +++ b/vm-virtio/src/vhost_user/blk.rs @@ -24,6 +24,7 @@ use vhost_rs::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFe use vhost_rs::vhost_user::{Master, VhostUserMaster, VhostUserMasterReqHandler}; use vhost_rs::VhostBackend; use virtio_bindings::bindings::virtio_blk::*; +use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use vm_device::{Migratable, MigratableError, Pausable, Snapshotable}; use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap}; use vmm_sys_util::eventfd::EventFd; @@ -57,6 +58,7 @@ impl Blk { | 1 << VIRTIO_BLK_F_BLK_SIZE | 1 << VIRTIO_BLK_F_FLUSH | 1 << VIRTIO_BLK_F_TOPOLOGY + | 1 << VIRTIO_RING_F_EVENT_IDX | 1 << VIRTIO_F_VERSION_1 | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();