Skip to content

Commit 27d44cb

Browse files
kornelskimajek
authored andcommitted
Improve vqueue encapsulation: make virtio.Queue fields private, expose as functions
Signed-off-by: Kornel Lesiński <[email protected]>
1 parent da60282 commit 27d44cb

File tree

6 files changed

+136
-79
lines changed

6 files changed

+136
-79
lines changed

src/vmm/src/devices/virtio/mmio.rs

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl MmioTransport {
158158
// eventfds, but nothing will happen other than supurious wakeups.
159159
// . Do not reset config_generation and keep it monotonically increasing
160160
for queue in self.locked_device().queues_mut() {
161-
*queue = Queue::new(queue.get_max_size());
161+
*queue = Queue::new(queue.max_size());
162162
}
163163
}
164164

@@ -243,8 +243,8 @@ impl MmioTransport {
243243
}
244244
features
245245
}
246-
0x34 => self.with_queue(0, |q| u32::from(q.get_max_size())),
247-
0x44 => self.with_queue(0, |q| u32::from(q.ready)),
246+
0x34 => self.with_queue(0, |q| u32::from(q.max_size())),
247+
0x44 => self.with_queue(0, |q| u32::from(q.ready())),
248248
0x60 => {
249249
// For vhost-user backed devices we need some additional
250250
// logic to differentiate between `VIRTIO_MMIO_INT_VRING`
@@ -319,20 +319,20 @@ impl MmioTransport {
319319
}
320320
0x24 => self.acked_features_select = v,
321321
0x30 => self.queue_select = v,
322-
0x38 => self.update_queue_field(|q| q.size = (v & 0xffff) as u16),
323-
0x44 => self.update_queue_field(|q| q.ready = v == 1),
322+
0x38 => self.update_queue_field(|q| q.set_size(v as u16)),
323+
0x44 => self.update_queue_field(|q| q.set_ready(v == 1)),
324324
0x64 => {
325325
if self.check_device_status(device_status::DRIVER_OK, 0) {
326326
self.interrupt_status.fetch_and(!v, Ordering::SeqCst);
327327
}
328328
}
329329
0x70 => self.set_device_status(v),
330-
0x80 => self.update_queue_field(|q| lo(&mut q.desc_table, v)),
331-
0x84 => self.update_queue_field(|q| hi(&mut q.desc_table, v)),
332-
0x90 => self.update_queue_field(|q| lo(&mut q.avail_ring, v)),
333-
0x94 => self.update_queue_field(|q| hi(&mut q.avail_ring, v)),
334-
0xa0 => self.update_queue_field(|q| lo(&mut q.used_ring, v)),
335-
0xa4 => self.update_queue_field(|q| hi(&mut q.used_ring, v)),
330+
0x80 => self.update_queue_field(|q| lo(q.desc_table_mut(), v)),
331+
0x84 => self.update_queue_field(|q| hi(q.desc_table_mut(), v)),
332+
0x90 => self.update_queue_field(|q| lo(q.avail_ring_mut(), v)),
333+
0x94 => self.update_queue_field(|q| hi(q.avail_ring_mut(), v)),
334+
0xa0 => self.update_queue_field(|q| lo(q.used_ring_mut(), v)),
335+
0xa4 => self.update_queue_field(|q| hi(q.used_ring_mut(), v)),
336336
_ => {
337337
warn!("unknown virtio mmio register write: 0x{:x}", offset);
338338
}
@@ -479,18 +479,24 @@ pub(crate) mod tests {
479479
assert!(!d.are_queues_valid());
480480

481481
d.queue_select = 0;
482-
assert_eq!(d.with_queue(0, Queue::get_max_size), 16);
483-
assert!(d.with_queue_mut(|q| q.size = 16));
484-
assert_eq!(d.locked_device().queues()[d.queue_select as usize].size, 16);
482+
assert_eq!(d.with_queue(0, |q| q.max_size()), 16);
483+
assert!(d.with_queue_mut(|q| q.set_size(16)));
484+
assert_eq!(
485+
d.locked_device().queues()[d.queue_select as usize].size(),
486+
16
487+
);
485488

486489
d.queue_select = 1;
487-
assert_eq!(d.with_queue(0, Queue::get_max_size), 32);
488-
assert!(d.with_queue_mut(|q| q.size = 16));
489-
assert_eq!(d.locked_device().queues()[d.queue_select as usize].size, 16);
490+
assert_eq!(d.with_queue(0, |q| q.max_size()), 32);
491+
assert!(d.with_queue_mut(|q| q.set_size(16)));
492+
assert_eq!(
493+
d.locked_device().queues()[d.queue_select as usize].size(),
494+
16
495+
);
490496

491497
d.queue_select = 2;
492-
assert_eq!(d.with_queue(0, Queue::get_max_size), 0);
493-
assert!(!d.with_queue_mut(|q| q.size = 16));
498+
assert_eq!(d.with_queue(0, |q| q.max_size()), 0);
499+
assert!(!d.with_queue_mut(|q| q.set_size(16)));
494500

495501
assert!(!d.are_queues_valid());
496502
}
@@ -667,42 +673,45 @@ pub(crate) mod tests {
667673
assert_eq!(d.queue_select, 3);
668674

669675
d.queue_select = 0;
670-
assert_eq!(d.locked_device().queues()[0].size, 0);
676+
assert_eq!(d.locked_device().queues()[0].size(), 0);
671677
write_le_u32(&mut buf[..], 16);
672678
d.bus_write(0x38, &buf[..]);
673-
assert_eq!(d.locked_device().queues()[0].size, 16);
679+
assert_eq!(d.locked_device().queues()[0].size(), 16);
674680

675-
assert!(!d.locked_device().queues()[0].ready);
681+
assert!(!d.locked_device().queues()[0].ready());
676682
write_le_u32(&mut buf[..], 1);
677683
d.bus_write(0x44, &buf[..]);
678-
assert!(d.locked_device().queues()[0].ready);
684+
assert!(d.locked_device().queues()[0].ready());
679685

680-
assert_eq!(d.locked_device().queues()[0].desc_table.0, 0);
686+
assert_eq!(d.locked_device().queues()[0].desc_table().0, 0);
681687
write_le_u32(&mut buf[..], 123);
682688
d.bus_write(0x80, &buf[..]);
683-
assert_eq!(d.locked_device().queues()[0].desc_table.0, 123);
689+
assert_eq!(d.locked_device().queues()[0].desc_table().0, 123);
684690
d.bus_write(0x84, &buf[..]);
685691
assert_eq!(
686-
d.locked_device().queues()[0].desc_table.0,
692+
d.locked_device().queues()[0].desc_table().0,
687693
123 + (123 << 32)
688694
);
689695

690-
assert_eq!(d.locked_device().queues()[0].avail_ring.0, 0);
696+
assert_eq!(d.locked_device().queues()[0].avail_ring().0, 0);
691697
write_le_u32(&mut buf[..], 124);
692698
d.bus_write(0x90, &buf[..]);
693-
assert_eq!(d.locked_device().queues()[0].avail_ring.0, 124);
699+
assert_eq!(d.locked_device().queues()[0].avail_ring().0, 124);
694700
d.bus_write(0x94, &buf[..]);
695701
assert_eq!(
696-
d.locked_device().queues()[0].avail_ring.0,
702+
d.locked_device().queues()[0].avail_ring().0,
697703
124 + (124 << 32)
698704
);
699705

700-
assert_eq!(d.locked_device().queues()[0].used_ring.0, 0);
706+
assert_eq!(d.locked_device().queues()[0].used_ring().0, 0);
701707
write_le_u32(&mut buf[..], 125);
702708
d.bus_write(0xa0, &buf[..]);
703-
assert_eq!(d.locked_device().queues()[0].used_ring.0, 125);
709+
assert_eq!(d.locked_device().queues()[0].used_ring().0, 125);
704710
d.bus_write(0xa4, &buf[..]);
705-
assert_eq!(d.locked_device().queues()[0].used_ring.0, 125 + (125 << 32));
711+
assert_eq!(
712+
d.locked_device().queues()[0].used_ring().0,
713+
125 + (125 << 32)
714+
);
706715

707716
set_device_status(
708717
&mut d,

src/vmm/src/devices/virtio/net/device.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,8 +2009,8 @@ pub mod tests {
20092009
// Test queues count (TX and RX).
20102010
let queues = net.queues();
20112011
assert_eq!(queues.len(), NET_QUEUE_SIZES.len());
2012-
assert_eq!(queues[RX_INDEX].size, th.rxq.size());
2013-
assert_eq!(queues[TX_INDEX].size, th.txq.size());
2012+
assert_eq!(queues[RX_INDEX].size(), th.rxq.size());
2013+
assert_eq!(queues[TX_INDEX].size(), th.txq.size());
20142014

20152015
// Test corresponding queues events.
20162016
assert_eq!(net.queue_events().len(), NET_QUEUE_SIZES.len());
@@ -2029,7 +2029,7 @@ pub mod tests {
20292029

20302030
let net = th.net();
20312031
let queues = net.queues();
2032-
assert!(queues[RX_INDEX].uses_notif_suppression);
2033-
assert!(queues[TX_INDEX].uses_notif_suppression);
2032+
assert!(queues[RX_INDEX].uses_notif_suppression());
2033+
assert!(queues[TX_INDEX].uses_notif_suppression());
20342034
}
20352035
}

src/vmm/src/devices/virtio/persist.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ impl Persist<'_> for Queue {
6161

6262
fn save(&self) -> Self::State {
6363
QueueState {
64-
max_size: self.max_size,
65-
size: self.size,
66-
ready: self.ready,
67-
desc_table: self.desc_table.0,
68-
avail_ring: self.avail_ring.0,
69-
used_ring: self.used_ring.0,
64+
max_size: self.max_size(),
65+
size: self.size(),
66+
ready: self.ready(),
67+
desc_table: self.desc_table().0,
68+
avail_ring: self.avail_ring().0,
69+
used_ring: self.used_ring().0,
7070
next_avail: self.next_avail,
7171
next_used: self.next_used,
7272
num_added: self.num_added,
@@ -161,7 +161,7 @@ impl VirtioDeviceState {
161161

162162
for q in &queues {
163163
// Sanity check queue size and queue max size.
164-
if q.max_size != expected_queue_max_size || q.size > expected_queue_max_size {
164+
if q.max_size() != expected_queue_max_size || q.size() > expected_queue_max_size {
165165
return Err(PersistError::InvalidInput);
166166
}
167167
// Snapshot can happen at any time, including during device configuration/activation

src/vmm/src/devices/virtio/queue.rs

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -183,19 +183,19 @@ pub struct Queue {
183183
pub(crate) max_size: u16,
184184

185185
/// The queue size in elements the driver selected
186-
pub size: u16,
186+
pub(crate) size: u16,
187187

188188
/// Indicates if the queue is finished with configuration
189-
pub ready: bool,
189+
pub(crate) ready: bool,
190190

191191
/// Guest physical address of the descriptor table
192-
pub desc_table: GuestAddress,
192+
pub(crate) desc_table: GuestAddress,
193193

194194
/// Guest physical address of the available ring
195-
pub avail_ring: GuestAddress,
195+
pub(crate) avail_ring: GuestAddress,
196196

197197
/// Guest physical address of the used ring
198-
pub used_ring: GuestAddress,
198+
pub(crate) used_ring: GuestAddress,
199199

200200
pub(crate) next_avail: Wrapping<u16>,
201201
pub(crate) next_used: Wrapping<u16>,
@@ -225,10 +225,54 @@ impl Queue {
225225
}
226226

227227
/// Maximum size of the queue.
228-
pub fn get_max_size(&self) -> u16 {
228+
pub fn max_size(&self) -> u16 {
229229
self.max_size
230230
}
231231

232+
pub fn size(&self) -> u16 {
233+
self.size
234+
}
235+
236+
pub fn ready(&self) -> bool {
237+
self.ready
238+
}
239+
240+
pub fn desc_table(&self) -> GuestAddress {
241+
self.desc_table
242+
}
243+
244+
pub fn avail_ring(&self) -> GuestAddress {
245+
self.avail_ring
246+
}
247+
248+
pub fn used_ring(&self) -> GuestAddress {
249+
self.used_ring
250+
}
251+
252+
pub fn desc_table_mut(&mut self) -> &mut GuestAddress {
253+
&mut self.desc_table
254+
}
255+
256+
pub fn avail_ring_mut(&mut self) -> &mut GuestAddress {
257+
&mut self.avail_ring
258+
}
259+
260+
pub fn used_ring_mut(&mut self) -> &mut GuestAddress {
261+
&mut self.used_ring
262+
}
263+
264+
pub fn set_max_size(&mut self, val: u16) {
265+
self.max_size = val;
266+
}
267+
268+
pub fn set_size(&mut self, val: u16) {
269+
self.size = val;
270+
}
271+
272+
pub fn set_ready(&mut self, val: bool) {
273+
self.ready = val;
274+
}
275+
232276
/// Return the actual size of the queue, as the driver may not set up a
233277
/// queue as big as the device allows.
234278
pub fn actual_size(&self) -> u16 {
@@ -347,7 +391,7 @@ impl Queue {
347391
&mut self,
348392
mem: &'b M,
349393
) -> Option<DescriptorChain<'b, M>> {
350-
if !self.uses_notif_suppression {
394+
if !self.uses_notif_suppression() {
351395
return self.pop(mem);
352396
}
353397

@@ -499,7 +543,7 @@ impl Queue {
499543

500544
// If the device doesn't use notification suppression, we'll continue to get notifications
501545
// no matter what.
502-
if !self.uses_notif_suppression {
546+
if !self.uses_notif_suppression() {
503547
return true;
504548
}
505549

@@ -533,6 +577,10 @@ impl Queue {
533577
self.uses_notif_suppression = true;
534578
}
535579

580+
pub fn uses_notif_suppression(&self) -> bool {
581+
self.uses_notif_suppression
582+
}
583+
536584
/// Check if we need to kick the guest.
537585
///
538586
/// Please note this method has side effects: once it returns `true`, it considers the
@@ -544,7 +592,7 @@ impl Queue {
544592
debug_assert!(self.is_layout_valid(mem));
545593

546594
// If the device doesn't use notification suppression, always return true
547-
if !self.uses_notif_suppression {
595+
if !self.uses_notif_suppression() {
548596
return true;
549597
}
550598

@@ -959,8 +1007,8 @@ mod verification {
9591007
fn verify_actual_size() {
9601008
let ProofContext(queue, _) = kani::any();
9611009

962-
assert!(queue.actual_size() <= queue.get_max_size());
963-
assert!(queue.actual_size() <= queue.size);
1010+
assert!(queue.actual_size() <= queue.max_size());
1011+
assert!(queue.actual_size() <= queue.size());
9641012
}
9651013

9661014
#[kani::proof]
@@ -1075,7 +1123,7 @@ mod tests {
10751123
impl Queue {
10761124
fn avail_event(&self, mem: &GuestMemoryMmap) -> u16 {
10771125
let avail_event_addr = self
1078-
.used_ring
1126+
.used_ring()
10791127
.unchecked_add(u64::from(4 + 8 * self.actual_size()));
10801128

10811129
mem.read_obj::<u16>(avail_event_addr).unwrap()
@@ -1171,7 +1219,7 @@ mod tests {
11711219
assert!(!q.is_valid(m));
11721220
m.write_obj::<u16>(5_u16, q.avail_ring.unchecked_add(2))
11731221
.unwrap();
1174-
q.max_size = 2;
1222+
q.set_max_size(2);
11751223
assert!(!q.is_valid(m));
11761224

11771225
// reset dirtied values
@@ -1182,23 +1230,23 @@ mod tests {
11821230

11831231
// or if the various addresses are off
11841232

1185-
q.desc_table = GuestAddress(0xffff_ffff);
1233+
*q.desc_table_mut() = GuestAddress(0xffff_ffff);
11861234
assert!(!q.is_valid(m));
1187-
q.desc_table = GuestAddress(0x1001);
1235+
*q.desc_table_mut() = GuestAddress(0x1001);
11881236
assert!(!q.is_valid(m));
1189-
q.desc_table = vq.dtable_start();
1237+
*q.desc_table_mut() = vq.dtable_start();
11901238

1191-
q.avail_ring = GuestAddress(0xffff_ffff);
1239+
*q.avail_ring_mut() = GuestAddress(0xffff_ffff);
11921240
assert!(!q.is_valid(m));
1193-
q.avail_ring = GuestAddress(0x1001);
1241+
*q.avail_ring_mut() = GuestAddress(0x1001);
11941242
assert!(!q.is_valid(m));
1195-
q.avail_ring = vq.avail_start();
1243+
*q.avail_ring_mut() = vq.avail_start();
11961244

1197-
q.used_ring = GuestAddress(0xffff_ffff);
1245+
*q.used_ring_mut() = GuestAddress(0xffff_ffff);
11981246
assert!(!q.is_valid(m));
1199-
q.used_ring = GuestAddress(0x1001);
1247+
*q.used_ring_mut() = GuestAddress(0x1001);
12001248
assert!(!q.is_valid(m));
1201-
q.used_ring = vq.used_start();
1249+
*q.used_ring_mut() = vq.used_start();
12021250
}
12031251

12041252
#[test]
@@ -1351,7 +1399,7 @@ mod tests {
13511399
let vq = VirtQueue::new(GuestAddress(0), m, 4);
13521400
let mut q = vq.create_queue();
13531401

1354-
q.uses_notif_suppression = true;
1402+
q.enable_notif_suppression();
13551403

13561404
// Create 1 descriptor chain of 4.
13571405
for j in 0..4 {
@@ -1476,7 +1524,7 @@ mod tests {
14761524
let vq = VirtQueue::new(GuestAddress(0), m, 16);
14771525
let mut q = vq.create_queue();
14781526

1479-
q.ready = true;
1527+
q.set_ready(true);
14801528

14811529
// We create a simple descriptor chain
14821530
vq.dtable[0].set(0x1000_u64, 0x1000, 0, 0);

0 commit comments

Comments
 (0)