Skip to content
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

RFC: extend Queue to support packed queue #39

Closed
wants to merge 10 commits into from
8 changes: 4 additions & 4 deletions benches/queue/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,11 @@ impl<'a, M: GuestMemory> MockSplitQueue<'a, M> {
self.update_avail_idx(head_idx);
}

pub fn create_queue<A: GuestAddressSpace>(&self, a: A) -> Queue<A> {
pub fn create_queue<A: GuestAddressSpace + Clone>(&self, a: A) -> Queue<A> {
let mut q = Queue::new(a, self.len);
q.desc_table = self.desc_table_addr;
q.avail_ring = self.avail_addr;
q.used_ring = self.used_addr;
q.set_desc_table_address(self.desc_table_addr);
q.set_avail_ring_address(self.avail_addr);
q.set_used_ring_address(self.used_addr);
q
}
}
4 changes: 2 additions & 2 deletions benches/queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod mock;

use criterion::{black_box, BatchSize, Criterion};
use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
use vm_virtio::Queue;
use vm_virtio::{DescriptorChainUsed, Queue};

use mock::MockSplitQueue;

Expand Down Expand Up @@ -86,7 +86,7 @@ pub fn benchmark_queue(c: &mut Criterion) {
|| empty_queue(),
|mut q| {
for _ in 0..128 {
q.add_used(123, 0x1000).unwrap();
q.add_used(123, DescriptorChainUsed::Split(0x1000)).unwrap();
}
},
);
Expand Down
2 changes: 1 addition & 1 deletion coverage_config_x86_64.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"coverage_score": 88.8,
"coverage_score": 90.5,
"exclude_path": "",
"crate_features": "backend-stdio"
}
2 changes: 1 addition & 1 deletion src/block/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ impl Request {

let mut desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;

while desc.has_next() {
while desc_chain.has_next(&desc) {
Request::check_data_desc::<<M>::M>(desc_chain.memory(), desc, request.request_type)?;

request.data.push((desc.addr(), desc.len()));
Expand Down
66 changes: 45 additions & 21 deletions src/device/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub trait VirtioMmioDevice<M: GuestAddressSpace>: WithDriverSelect<M> {
.into(),
0x44 => self
.selected_queue()
.map(|q| q.ready)
.map(|q| q.ready())
.unwrap_or(false)
.into(),
0x60 => self.interrupt_status().load(Ordering::SeqCst).into(),
Expand Down Expand Up @@ -158,8 +158,8 @@ pub trait VirtioMmioDevice<M: GuestAddressSpace>: WithDriverSelect<M> {
// data type specified by the virtio standard (we simply use `as` conversion
// for now).
0x30 => self.set_queue_select(v as u16),
0x38 => update_queue_field(self, |q| q.size = v as u16),
0x44 => update_queue_field(self, |q| q.ready = v == 1),
0x38 => update_queue_field(self, |q| q.set_queue_size(v as u16)),
0x44 => update_queue_field(self, |q| q.set_ready(v == 1)),
0x50 => self.queue_notify(v),
0x64 => {
if self.check_device_status(status::DRIVER_OK, 0) {
Expand All @@ -168,12 +168,36 @@ pub trait VirtioMmioDevice<M: GuestAddressSpace>: WithDriverSelect<M> {
}
}
0x70 => self.ack_device_status(v as u8),
0x80 => update_queue_field(self, |q| set_low(&mut q.desc_table, v)),
0x84 => update_queue_field(self, |q| set_high(&mut q.desc_table, v)),
0x90 => update_queue_field(self, |q| set_low(&mut q.avail_ring, v)),
0x94 => update_queue_field(self, |q| set_high(&mut q.avail_ring, v)),
0xa0 => update_queue_field(self, |q| set_low(&mut q.used_ring, v)),
0xa4 => update_queue_field(self, |q| set_high(&mut q.used_ring, v)),
0x80 => update_queue_field(self, |q| {
let mut addr = q.desc_table_address();
set_low(&mut addr, v);
q.set_desc_table_address(addr);
}),
0x84 => update_queue_field(self, |q| {
let mut addr = q.desc_table_address();
set_high(&mut addr, v);
q.set_desc_table_address(addr);
}),
0x90 => update_queue_field(self, |q| {
let mut addr = q.avail_ring_address();
set_low(&mut addr, v);
q.set_avail_ring_address(addr);
}),
0x94 => update_queue_field(self, |q| {
let mut addr = q.avail_ring_address();
set_high(&mut addr, v);
q.set_avail_ring_address(addr);
}),
0xa0 => update_queue_field(self, |q| {
let mut addr = q.used_ring_address();
set_low(&mut addr, v);
q.set_used_ring_address(addr);
}),
0xa4 => update_queue_field(self, |q| {
let mut addr = q.used_ring_address();
set_high(&mut addr, v);
q.set_used_ring_address(addr);
}),
_ => {
warn!("unknown virtio mmio register write: 0x{:x}", offset);
}
Expand Down Expand Up @@ -257,16 +281,16 @@ mod tests {
// The max size for the queue in `Dummy` is 256.
assert_eq!(mmio_read(&d, 0x34), 256);

assert_eq!(d.cfg.queues[0].size, 256);
assert_eq!(d.cfg.queues[0].queue_size(), 256);
d.write(0x38, &32u32.to_le_bytes());
// Updating the queue field has no effect due to invalid device status.
assert_eq!(d.cfg.queues[0].size, 256);
assert_eq!(d.cfg.queues[0].queue_size(), 256);

d.cfg.device_status |= status::FEATURES_OK;

// Let's try the update again.
d.write(0x38, &32u32.to_le_bytes());
assert_eq!(d.cfg.queues[0].size, 32);
assert_eq!(d.cfg.queues[0].queue_size(), 32);

// The queue in `Dummy` is not ready yet.
assert_eq!(mmio_read(&d, 0x44), 0);
Expand All @@ -280,23 +304,23 @@ mod tests {
d.write(0x50, &2u32.to_le_bytes());
assert_eq!(d.last_queue_notify, 2);

assert_eq!(d.cfg.queues[0].desc_table.0, 0);
assert_eq!(d.cfg.queues[0].desc_table_address().0, 0);
d.write(0x80, &1u32.to_le_bytes());
assert_eq!(d.cfg.queues[0].desc_table.0, 1);
assert_eq!(d.cfg.queues[0].desc_table_address().0, 1);
d.write(0x84, &2u32.to_le_bytes());
assert_eq!(d.cfg.queues[0].desc_table.0, (2 << 32) + 1);
assert_eq!(d.cfg.queues[0].desc_table_address().0, (2 << 32) + 1);

assert_eq!(d.cfg.queues[0].avail_ring.0, 0);
assert_eq!(d.cfg.queues[0].avail_ring_address().0, 0);
d.write(0x90, &1u32.to_le_bytes());
assert_eq!(d.cfg.queues[0].avail_ring.0, 1);
assert_eq!(d.cfg.queues[0].avail_ring_address().0, 1);
d.write(0x94, &2u32.to_le_bytes());
assert_eq!(d.cfg.queues[0].avail_ring.0, (2 << 32) + 1);
assert_eq!(d.cfg.queues[0].avail_ring_address().0, (2 << 32) + 1);

assert_eq!(d.cfg.queues[0].used_ring.0, 0);
assert_eq!(d.cfg.queues[0].used_ring_address().0, 0);
d.write(0xa0, &1u32.to_le_bytes());
assert_eq!(d.cfg.queues[0].used_ring.0, 1);
assert_eq!(d.cfg.queues[0].used_ring_address().0, 1);
d.write(0xa4, &2u32.to_le_bytes());
assert_eq!(d.cfg.queues[0].used_ring.0, (2 << 32) + 1);
assert_eq!(d.cfg.queues[0].used_ring_address().0, (2 << 32) + 1);

// Let's select a non-existent queue.
d.write(0x30, &1u32.to_le_bytes());
Expand Down
4 changes: 2 additions & 2 deletions src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ mod tests {
assert_eq!(d.cfg.device_features & (1 << VIRTIO_F_RING_EVENT_IDX), 0);

for q in d.cfg.queues.iter() {
assert_eq!(q.event_idx_enabled, false);
assert_eq!(q.event_idx(), false);
}

// Revert status.
Expand All @@ -299,7 +299,7 @@ mod tests {
assert_eq!(d.cfg.device_status, status);

for q in d.cfg.queues.iter() {
assert_eq!(q.event_idx_enabled, true);
assert_eq!(q.event_idx(), true);
}
}

Expand Down
Loading