mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 21:55: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.
|
/// 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() {
|
if desc_index >= self.actual_size() {
|
||||||
error!(
|
error!(
|
||||||
"attempted to add out of bounds descriptor to used ring: {}",
|
"attempted to add out of bounds descriptor to used ring: {}",
|
||||||
desc_index
|
desc_index
|
||||||
);
|
);
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let used_ring = self.used_ring;
|
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))
|
mem.write_obj(self.next_used.0 as u16, used_ring.unchecked_add(2))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
Some(self.next_used.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Goes back one position in the available descriptor chain offered by the driver.
|
/// 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::vhost_user::{Master, VhostUserMaster, VhostUserMasterReqHandler};
|
||||||
use vhost_rs::VhostBackend;
|
use vhost_rs::VhostBackend;
|
||||||
use virtio_bindings::bindings::virtio_blk::*;
|
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_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
||||||
use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
|
use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
@ -57,6 +58,7 @@ impl Blk {
|
|||||||
| 1 << VIRTIO_BLK_F_BLK_SIZE
|
| 1 << VIRTIO_BLK_F_BLK_SIZE
|
||||||
| 1 << VIRTIO_BLK_F_FLUSH
|
| 1 << VIRTIO_BLK_F_FLUSH
|
||||||
| 1 << VIRTIO_BLK_F_TOPOLOGY
|
| 1 << VIRTIO_BLK_F_TOPOLOGY
|
||||||
|
| 1 << VIRTIO_RING_F_EVENT_IDX
|
||||||
| 1 << VIRTIO_F_VERSION_1
|
| 1 << VIRTIO_F_VERSION_1
|
||||||
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user