Skip to content

Commit ca901e9

Browse files
committed
queue: introduce traits queue state operations
Abstract queue state operations as `trait QueueStateT`, so we could provide different implementations for single-threaded context and multi-threaded context. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
1 parent fd58387 commit ca901e9

File tree

4 files changed

+307
-156
lines changed

4 files changed

+307
-156
lines changed

crates/virtio-device/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ mod tests {
284284
assert_eq!(d.cfg.device_features & (1 << VIRTIO_F_RING_EVENT_IDX), 0);
285285

286286
for q in d.cfg.queues.iter() {
287-
assert_eq!(q.event_idx_enabled, false);
287+
assert_eq!(q.state.event_idx_enabled, false);
288288
}
289289

290290
// Revert status.
@@ -302,7 +302,7 @@ mod tests {
302302
assert_eq!(d.cfg.device_status, status);
303303

304304
for q in d.cfg.queues.iter() {
305-
assert_eq!(q.event_idx_enabled, true);
305+
assert_eq!(q.state.event_idx_enabled, true);
306306
}
307307
}
308308

crates/virtio-device/src/mmio.rs

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::convert::TryInto;
1010
use std::sync::atomic::Ordering;
1111

1212
use log::warn;
13-
use vm_memory::{GuestAddress, GuestAddressSpace};
13+
use vm_memory::GuestAddressSpace;
1414

1515
use crate::{status, WithDriverSelect};
1616
use virtio_queue::Queue;
@@ -51,16 +51,6 @@ where
5151
}
5252
}
5353

54-
// Helper function that rewrites the most significant 4 bytes of the provided `GuestAddress`.
55-
fn set_high(v: &mut GuestAddress, hi: u32) {
56-
*v = (*v & 0xffff_ffff) | (u64::from(hi) << 32)
57-
}
58-
59-
// Helper function that rewrites the least significant 4 bytes of the provided `GuestAddress`.
60-
fn set_low(v: &mut GuestAddress, lo: u32) {
61-
*v = (*v & !0xffff_ffff) | u64::from(lo)
62-
}
63-
6454
/// A common interface for Virtio devices that use the MMIO transport, which also provides a
6555
/// default implementation of read and write operations from/to the device registers and
6656
/// configuration space.
@@ -99,7 +89,7 @@ pub trait VirtioMmioDevice<M: GuestAddressSpace>: WithDriverSelect<M> {
9989
.into(),
10090
0x44 => self
10191
.selected_queue()
102-
.map(|q| q.ready)
92+
.map(|q| q.ready())
10393
.unwrap_or(false)
10494
.into(),
10595
0x60 => self.interrupt_status().load(Ordering::SeqCst).into(),
@@ -159,8 +149,8 @@ pub trait VirtioMmioDevice<M: GuestAddressSpace>: WithDriverSelect<M> {
159149
// data type specified by the virtio standard (we simply use `as` conversion
160150
// for now).
161151
0x30 => self.set_queue_select(v as u16),
162-
0x38 => update_queue_field(self, |q| q.size = v as u16),
163-
0x44 => update_queue_field(self, |q| q.ready = v == 1),
152+
0x38 => update_queue_field(self, |q| q.set_size(v as u16)),
153+
0x44 => update_queue_field(self, |q| q.set_ready(v == 1)),
164154
0x50 => self.queue_notify(v),
165155
0x64 => {
166156
if self.check_device_status(status::DRIVER_OK, 0) {
@@ -169,12 +159,12 @@ pub trait VirtioMmioDevice<M: GuestAddressSpace>: WithDriverSelect<M> {
169159
}
170160
}
171161
0x70 => self.ack_device_status(v as u8),
172-
0x80 => update_queue_field(self, |q| set_low(&mut q.desc_table, v)),
173-
0x84 => update_queue_field(self, |q| set_high(&mut q.desc_table, v)),
174-
0x90 => update_queue_field(self, |q| set_low(&mut q.avail_ring, v)),
175-
0x94 => update_queue_field(self, |q| set_high(&mut q.avail_ring, v)),
176-
0xa0 => update_queue_field(self, |q| set_low(&mut q.used_ring, v)),
177-
0xa4 => update_queue_field(self, |q| set_high(&mut q.used_ring, v)),
162+
0x80 => update_queue_field(self, |q| q.set_desc_table_address(Some(v), None)),
163+
0x84 => update_queue_field(self, |q| q.set_desc_table_address(None, Some(v))),
164+
0x90 => update_queue_field(self, |q| q.set_avail_ring_address(Some(v), None)),
165+
0x94 => update_queue_field(self, |q| q.set_avail_ring_address(None, Some(v))),
166+
0xa0 => update_queue_field(self, |q| q.set_used_ring_address(Some(v), None)),
167+
0xa4 => update_queue_field(self, |q| q.set_used_ring_address(None, Some(v))),
178168
_ => {
179169
warn!("unknown virtio mmio register write: 0x{:x}", offset);
180170
}
@@ -258,16 +248,16 @@ mod tests {
258248
// The max size for the queue in `Dummy` is 256.
259249
assert_eq!(mmio_read(&d, 0x34), 256);
260250

261-
assert_eq!(d.cfg.queues[0].size, 256);
251+
assert_eq!(d.cfg.queues[0].state.size, 256);
262252
d.write(0x38, &32u32.to_le_bytes());
263253
// Updating the queue field has no effect due to invalid device status.
264-
assert_eq!(d.cfg.queues[0].size, 256);
254+
assert_eq!(d.cfg.queues[0].state.size, 256);
265255

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

268258
// Let's try the update again.
269259
d.write(0x38, &32u32.to_le_bytes());
270-
assert_eq!(d.cfg.queues[0].size, 32);
260+
assert_eq!(d.cfg.queues[0].state.size, 32);
271261

272262
// The queue in `Dummy` is not ready yet.
273263
assert_eq!(mmio_read(&d, 0x44), 0);
@@ -281,23 +271,23 @@ mod tests {
281271
d.write(0x50, &2u32.to_le_bytes());
282272
assert_eq!(d.last_queue_notify, 2);
283273

284-
assert_eq!(d.cfg.queues[0].desc_table.0, 0);
274+
assert_eq!(d.cfg.queues[0].state.desc_table.0, 0);
285275
d.write(0x80, &1u32.to_le_bytes());
286-
assert_eq!(d.cfg.queues[0].desc_table.0, 1);
276+
assert_eq!(d.cfg.queues[0].state.desc_table.0, 1);
287277
d.write(0x84, &2u32.to_le_bytes());
288-
assert_eq!(d.cfg.queues[0].desc_table.0, (2 << 32) + 1);
278+
assert_eq!(d.cfg.queues[0].state.desc_table.0, (2 << 32) + 1);
289279

290-
assert_eq!(d.cfg.queues[0].avail_ring.0, 0);
280+
assert_eq!(d.cfg.queues[0].state.avail_ring.0, 0);
291281
d.write(0x90, &1u32.to_le_bytes());
292-
assert_eq!(d.cfg.queues[0].avail_ring.0, 1);
282+
assert_eq!(d.cfg.queues[0].state.avail_ring.0, 1);
293283
d.write(0x94, &2u32.to_le_bytes());
294-
assert_eq!(d.cfg.queues[0].avail_ring.0, (2 << 32) + 1);
284+
assert_eq!(d.cfg.queues[0].state.avail_ring.0, (2 << 32) + 1);
295285

296-
assert_eq!(d.cfg.queues[0].used_ring.0, 0);
286+
assert_eq!(d.cfg.queues[0].state.used_ring.0, 0);
297287
d.write(0xa0, &1u32.to_le_bytes());
298-
assert_eq!(d.cfg.queues[0].used_ring.0, 1);
288+
assert_eq!(d.cfg.queues[0].state.used_ring.0, 1);
299289
d.write(0xa4, &2u32.to_le_bytes());
300-
assert_eq!(d.cfg.queues[0].used_ring.0, (2 << 32) + 1);
290+
assert_eq!(d.cfg.queues[0].state.used_ring.0, (2 << 32) + 1);
301291

302292
// Let's select a non-existent queue.
303293
d.write(0x30, &1u32.to_le_bytes());

0 commit comments

Comments
 (0)