Skip to content

Improve vqueue encapsulation - prerequisite for vhost work #4312

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/vmm/src/device_manager/mmio.rs
Original file line number Diff line number Diff line change
@@ -467,7 +467,7 @@ mod tests {

use super::*;
use crate::devices::virtio::device::VirtioDevice;
use crate::devices::virtio::queue::Queue;
use crate::devices::virtio::queue::{Queue, QueueIter, QueueIterMut};
use crate::devices::virtio::ActivateError;
use crate::vstate::memory::{GuestAddress, GuestMemoryExtension, GuestMemoryMmap};
use crate::{builder, Vm};
@@ -535,12 +535,12 @@ mod tests {
0
}

fn queues(&self) -> &[Queue] {
&self.queues
fn queues(&self) -> QueueIter {
self.queues.iter()
}

fn queues_mut(&mut self) -> &mut [Queue] {
&mut self.queues
fn queues_mut(&mut self) -> QueueIterMut {
self.queues.iter_mut()
}

fn queue_events(&self) -> &[EventFd] {
10 changes: 5 additions & 5 deletions src/vmm/src/devices/virtio/balloon/device.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@ use utils::eventfd::EventFd;
use utils::u64_to_usize;

use super::super::device::{DeviceState, VirtioDevice};
use super::super::queue::Queue;
use super::super::{ActivateError, TYPE_BALLOON};
use super::metrics::METRICS;
use super::util::{compact_page_frame_numbers, remove_range};
@@ -30,6 +29,7 @@ use super::{
use crate::devices::virtio::balloon::BalloonError;
use crate::devices::virtio::device::{IrqTrigger, IrqType};
use crate::devices::virtio::gen::virtio_blk::VIRTIO_F_VERSION_1;
use crate::devices::virtio::queue::{Queue, QueueIter, QueueIterMut};
use crate::logger::IncMetric;
use crate::vstate::memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemoryMmap};

@@ -573,12 +573,12 @@ impl VirtioDevice for Balloon {
TYPE_BALLOON
}

fn queues(&self) -> &[Queue] {
&self.queues
fn queues(&self) -> QueueIter {
self.queues.iter()
}

fn queues_mut(&mut self) -> &mut [Queue] {
&mut self.queues
fn queues_mut(&mut self) -> QueueIterMut {
self.queues.iter_mut()
}

fn queue_events(&self) -> &[EventFd] {
2 changes: 1 addition & 1 deletion src/vmm/src/devices/virtio/balloon/persist.rs
Original file line number Diff line number Diff line change
@@ -209,7 +209,7 @@ mod tests {
assert_eq!(restored_balloon.acked_features, balloon.acked_features);
assert_eq!(restored_balloon.avail_features, balloon.avail_features);
assert_eq!(restored_balloon.config_space, balloon.config_space);
assert_eq!(restored_balloon.queues(), balloon.queues());
assert!(restored_balloon.queues().eq(balloon.queues()));
assert_eq!(
restored_balloon.interrupt_status().load(Ordering::Relaxed),
balloon.interrupt_status().load(Ordering::Relaxed)
11 changes: 6 additions & 5 deletions src/vmm/src/devices/virtio/device.rs
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@ use std::sync::Arc;
use utils::eventfd::EventFd;

use super::mmio::{VIRTIO_MMIO_INT_CONFIG, VIRTIO_MMIO_INT_VRING};
use super::queue::Queue;
use super::ActivateError;
use crate::devices::virtio::queue::{QueueIter, QueueIterMut};
use crate::devices::virtio::AsAny;
use crate::logger::{error, warn};
use crate::vstate::memory::GuestMemoryMmap;
@@ -111,10 +111,10 @@ pub trait VirtioDevice: AsAny + Send {
fn device_type(&self) -> u32;

/// Returns the device queues.
fn queues(&self) -> &[Queue];
fn queues(&self) -> QueueIter;

/// Returns a mutable reference to the device queues.
fn queues_mut(&mut self) -> &mut [Queue];
fn queues_mut(&mut self) -> QueueIterMut;

/// Returns the device queues event fds.
fn queue_events(&self) -> &[EventFd];
@@ -190,6 +190,7 @@ impl fmt::Debug for dyn VirtioDevice {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::devices::virtio::queue::{QueueIter, QueueIterMut};

impl IrqTrigger {
pub fn has_pending_irq(&self, irq_type: IrqType) -> bool {
@@ -254,11 +255,11 @@ pub(crate) mod tests {
todo!()
}

fn queues(&self) -> &[Queue] {
fn queues(&self) -> QueueIter {
todo!()
}

fn queues_mut(&mut self) -> &mut [Queue] {
fn queues_mut(&mut self) -> QueueIterMut {
todo!()
}

108 changes: 66 additions & 42 deletions src/vmm/src/devices/virtio/mmio.rs
Original file line number Diff line number Diff line change
@@ -97,10 +97,7 @@ impl MmioTransport {
}

fn are_queues_valid(&self) -> bool {
self.locked_device()
.queues()
.iter()
.all(|q| q.is_valid(&self.mem))
self.locked_device().queues().all(|q| q.is_valid(&self.mem))
}

fn with_queue<U, F>(&self, d: U, f: F) -> U
@@ -111,7 +108,7 @@ impl MmioTransport {
match self
.locked_device()
.queues()
.get(self.queue_select as usize)
.nth(self.queue_select as usize)
{
Some(queue) => f(queue),
None => d,
@@ -122,7 +119,7 @@ impl MmioTransport {
if let Some(queue) = self
.locked_device()
.queues_mut()
.get_mut(self.queue_select as usize)
.nth(self.queue_select as usize)
{
f(queue);
true
@@ -158,7 +155,7 @@ impl MmioTransport {
// eventfds, but nothing will happen other than supurious wakeups.
// . Do not reset config_generation and keep it monotonically increasing
for queue in self.locked_device().queues_mut() {
*queue = Queue::new(queue.get_max_size());
*queue = Queue::new(queue.max_size());
}
}

@@ -243,8 +240,8 @@ impl MmioTransport {
}
features
}
0x34 => self.with_queue(0, |q| u32::from(q.get_max_size())),
0x44 => self.with_queue(0, |q| u32::from(q.ready)),
0x34 => self.with_queue(0, |q| u32::from(q.max_size())),
0x44 => self.with_queue(0, |q| u32::from(q.ready())),
0x60 => {
// For vhost-user backed devices we need some additional
// logic to differentiate between `VIRTIO_MMIO_INT_VRING`
@@ -319,20 +316,20 @@ impl MmioTransport {
}
0x24 => self.acked_features_select = v,
0x30 => self.queue_select = v,
0x38 => self.update_queue_field(|q| q.size = (v & 0xffff) as u16),
0x44 => self.update_queue_field(|q| q.ready = v == 1),
0x38 => self.update_queue_field(|q| q.set_size(v as u16)),
0x44 => self.update_queue_field(|q| q.set_ready(v == 1)),
0x64 => {
if self.check_device_status(device_status::DRIVER_OK, 0) {
self.interrupt_status.fetch_and(!v, Ordering::SeqCst);
}
}
0x70 => self.set_device_status(v),
0x80 => self.update_queue_field(|q| lo(&mut q.desc_table, v)),
0x84 => self.update_queue_field(|q| hi(&mut q.desc_table, v)),
0x90 => self.update_queue_field(|q| lo(&mut q.avail_ring, v)),
0x94 => self.update_queue_field(|q| hi(&mut q.avail_ring, v)),
0xa0 => self.update_queue_field(|q| lo(&mut q.used_ring, v)),
0xa4 => self.update_queue_field(|q| hi(&mut q.used_ring, v)),
0x80 => self.update_queue_field(|q| lo(q.desc_table_mut(), v)),
0x84 => self.update_queue_field(|q| hi(q.desc_table_mut(), v)),
0x90 => self.update_queue_field(|q| lo(q.avail_ring_mut(), v)),
0x94 => self.update_queue_field(|q| hi(q.avail_ring_mut(), v)),
0xa0 => self.update_queue_field(|q| lo(q.used_ring_mut(), v)),
0xa4 => self.update_queue_field(|q| hi(q.used_ring_mut(), v)),
_ => {
warn!("unknown virtio mmio register write: 0x{:x}", offset);
}
@@ -363,6 +360,7 @@ pub(crate) mod tests {
use utils::u64_to_usize;

use super::*;
use crate::devices::virtio::queue::{Queue, QueueIter, QueueIterMut};
use crate::devices::virtio::ActivateError;
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap};

@@ -417,12 +415,12 @@ pub(crate) mod tests {
123
}

fn queues(&self) -> &[Queue] {
&self.queues
fn queues(&self) -> QueueIter {
self.queues.iter()
}

fn queues_mut(&mut self) -> &mut [Queue] {
&mut self.queues
fn queues_mut(&mut self) -> QueueIterMut {
self.queues.iter_mut()
}

fn queue_events(&self) -> &[EventFd] {
@@ -479,18 +477,32 @@ pub(crate) mod tests {
assert!(!d.are_queues_valid());

d.queue_select = 0;
assert_eq!(d.with_queue(0, Queue::get_max_size), 16);
assert!(d.with_queue_mut(|q| q.size = 16));
assert_eq!(d.locked_device().queues()[d.queue_select as usize].size, 16);
assert_eq!(d.with_queue(0, |q| q.max_size()), 16);
assert!(d.with_queue_mut(|q| q.set_size(16)));
assert_eq!(
d.locked_device()
.queues()
.nth(d.queue_select as usize)
.unwrap()
.size(),
16
);

d.queue_select = 1;
assert_eq!(d.with_queue(0, Queue::get_max_size), 32);
assert!(d.with_queue_mut(|q| q.size = 16));
assert_eq!(d.locked_device().queues()[d.queue_select as usize].size, 16);
assert_eq!(d.with_queue(0, |q| q.max_size()), 32);
assert!(d.with_queue_mut(|q| q.set_size(16)));
assert_eq!(
d.locked_device()
.queues()
.nth(d.queue_select as usize)
.unwrap()
.size(),
16
);

d.queue_select = 2;
assert_eq!(d.with_queue(0, Queue::get_max_size), 0);
assert!(!d.with_queue_mut(|q| q.size = 16));
assert_eq!(d.with_queue(0, |q| q.max_size()), 0);
assert!(!d.with_queue_mut(|q| q.set_size(16)));

assert!(!d.are_queues_valid());
}
@@ -667,42 +679,54 @@ pub(crate) mod tests {
assert_eq!(d.queue_select, 3);

d.queue_select = 0;
assert_eq!(d.locked_device().queues()[0].size, 0);
assert_eq!(d.locked_device().queues().nth(0).unwrap().size(), 0);
write_le_u32(&mut buf[..], 16);
d.bus_write(0x38, &buf[..]);
assert_eq!(d.locked_device().queues()[0].size, 16);
assert_eq!(d.locked_device().queues().nth(0).unwrap().size(), 16);

assert!(!d.locked_device().queues()[0].ready);
assert!(!d.locked_device().queues().nth(0).unwrap().ready());
write_le_u32(&mut buf[..], 1);
d.bus_write(0x44, &buf[..]);
assert!(d.locked_device().queues()[0].ready);
assert!(d.locked_device().queues().nth(0).unwrap().ready());

assert_eq!(d.locked_device().queues()[0].desc_table.0, 0);
assert_eq!(d.locked_device().queues().nth(0).unwrap().desc_table().0, 0);
write_le_u32(&mut buf[..], 123);
d.bus_write(0x80, &buf[..]);
assert_eq!(d.locked_device().queues()[0].desc_table.0, 123);
assert_eq!(
d.locked_device().queues().nth(0).unwrap().desc_table().0,
123
);
d.bus_write(0x84, &buf[..]);
assert_eq!(
d.locked_device().queues()[0].desc_table.0,
d.locked_device().queues().nth(0).unwrap().desc_table().0,
123 + (123 << 32)
);

assert_eq!(d.locked_device().queues()[0].avail_ring.0, 0);
assert_eq!(d.locked_device().queues().nth(0).unwrap().avail_ring().0, 0);
write_le_u32(&mut buf[..], 124);
d.bus_write(0x90, &buf[..]);
assert_eq!(d.locked_device().queues()[0].avail_ring.0, 124);
assert_eq!(
d.locked_device().queues().nth(0).unwrap().avail_ring().0,
124
);
d.bus_write(0x94, &buf[..]);
assert_eq!(
d.locked_device().queues()[0].avail_ring.0,
d.locked_device().queues().nth(0).unwrap().avail_ring().0,
124 + (124 << 32)
);

assert_eq!(d.locked_device().queues()[0].used_ring.0, 0);
assert_eq!(d.locked_device().queues().nth(0).unwrap().used_ring().0, 0);
write_le_u32(&mut buf[..], 125);
d.bus_write(0xa0, &buf[..]);
assert_eq!(d.locked_device().queues()[0].used_ring.0, 125);
assert_eq!(
d.locked_device().queues().nth(0).unwrap().used_ring().0,
125
);
d.bus_write(0xa4, &buf[..]);
assert_eq!(d.locked_device().queues()[0].used_ring.0, 125 + (125 << 32));
assert_eq!(
d.locked_device().queues().nth(0).unwrap().used_ring().0,
125 + (125 << 32)
);

set_device_status(
&mut d,
24 changes: 11 additions & 13 deletions src/vmm/src/devices/virtio/net/device.rs
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ use crate::devices::virtio::net::tap::Tap;
use crate::devices::virtio::net::{
gen, NetError, NetQueue, MAX_BUFFER_SIZE, NET_QUEUE_SIZES, RX_INDEX, TX_INDEX,
};
use crate::devices::virtio::queue::{DescriptorChain, Queue};
use crate::devices::virtio::queue::{DescriptorChain, Queue, QueueIter, QueueIterMut};
use crate::devices::virtio::{ActivateError, TYPE_NET};
use crate::devices::{report_net_event_fail, DeviceError};
use crate::dumbo::pdu::arp::ETH_IPV4_FRAME_LEN;
@@ -787,12 +787,12 @@ impl VirtioDevice for Net {
TYPE_NET
}

fn queues(&self) -> &[Queue] {
&self.queues
fn queues(&self) -> QueueIter {
self.queues.iter()
}

fn queues_mut(&mut self) -> &mut [Queue] {
&mut self.queues
fn queues_mut(&mut self) -> QueueIterMut {
self.queues.iter_mut()
}

fn queue_events(&self) -> &[EventFd] {
@@ -845,7 +845,7 @@ impl VirtioDevice for Net {
fn activate(&mut self, mem: GuestMemoryMmap) -> Result<(), ActivateError> {
let event_idx = self.has_feature(u64::from(VIRTIO_RING_F_EVENT_IDX));
if event_idx {
for queue in &mut self.queues {
for queue in self.queues_mut() {
queue.enable_notif_suppression();
}
}
@@ -2007,10 +2007,9 @@ pub mod tests {
let net = th.net.lock().unwrap();

// Test queues count (TX and RX).
let queues = net.queues();
assert_eq!(queues.len(), NET_QUEUE_SIZES.len());
assert_eq!(queues[RX_INDEX].size, th.rxq.size());
assert_eq!(queues[TX_INDEX].size, th.txq.size());
assert_eq!(net.queues().count(), NET_QUEUE_SIZES.len());
assert_eq!(net.queues().nth(RX_INDEX).unwrap().size(), th.rxq.size());
assert_eq!(net.queues().nth(TX_INDEX).unwrap().size(), th.txq.size());

// Test corresponding queues events.
assert_eq!(net.queue_events().len(), NET_QUEUE_SIZES.len());
@@ -2028,8 +2027,7 @@ pub mod tests {
th.activate_net();

let net = th.net();
let queues = net.queues();
assert!(queues[RX_INDEX].uses_notif_suppression);
assert!(queues[TX_INDEX].uses_notif_suppression);
assert!(net.queues().nth(RX_INDEX).unwrap().uses_notif_suppression());
assert!(net.queues().nth(TX_INDEX).unwrap().uses_notif_suppression());
}
}
Loading