mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
vm-virtio: Implement support for EVENT_IDX
VIRTIO_RING_F_EVENT_IDX is a virtio feature that allows to avoid device <-> driver notifications under some circunstances, most notably when actively polling the queue. This commit implements support for in in the vm-virtio crate. Consumers of this crate will also need to add support for it by exposing the feature and calling using update_avail_event() and get_used_event() accordingly. Signed-off-by: Sergio Lopez <slp@redhat.com>
This commit is contained in:
parent
793d4e7b8d
commit
d17fa784bc
@ -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::<u16>(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<Wrapping<u16>> {
|
||||
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::<u16>(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<u16> {
|
||||
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.
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user