Skip to content

Commit 9f393ab

Browse files
committed
refactor: move descriptor reading into separate method
Move descriptor reading into separate method. This will allow for descriptor preprocessing without actual poping of them. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent 6464004 commit 9f393ab

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

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

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -390,14 +390,22 @@ impl Queue {
390390
fn do_pop_unchecked<'b, M: GuestMemory>(
391391
&mut self,
392392
mem: &'b M,
393+
) -> Option<DescriptorChain<'b, M>> {
394+
self.get_desc_chain(self.next_avail.0, mem).map(|dc| {
395+
self.next_avail += Wrapping(1);
396+
dc
397+
})
398+
}
399+
400+
/// Get descriptor chain from the avail ring at the specified index.
401+
pub fn get_desc_chain<'b, M: GuestMemory>(
402+
&self,
403+
avail_idx: u16,
404+
mem: &'b M,
393405
) -> Option<DescriptorChain<'b, M>> {
394406
// This fence ensures all subsequent reads see the updated driver writes.
395407
fence(Ordering::Acquire);
396408

397-
// We'll need to find the first available descriptor, that we haven't yet popped.
398-
// In a naive notation, that would be:
399-
// `descriptor_table[avail_ring[next_avail]]`.
400-
//
401409
// Avail ring has layout:
402410
// struct AvailRing {
403411
// flags: u16,
@@ -408,20 +416,17 @@ impl Queue {
408416
// We calculate offset into `ring` field.
409417
let desc_index_offset = std::mem::size_of::<u16>()
410418
+ std::mem::size_of::<u16>()
411-
+ std::mem::size_of::<u16>() * usize::from(self.next_avail.0 % self.actual_size());
412-
let desc_index_address = self.avail_ring.unchecked_add(usize_to_u64(desc_index_offset));
419+
+ std::mem::size_of::<u16>() * usize::from(avail_idx % self.actual_size());
420+
let desc_index_address = self
421+
.avail_ring
422+
.unchecked_add(usize_to_u64(desc_index_offset));
413423

414-
// `self.is_valid()` already performed all the bound checks on the descriptor table
415-
// and virtq rings, so it's safe to unwrap guest memory reads and to use unchecked
416-
// offsets.
424+
// SAFETY:
425+
// `desc_index_address` param is bounded by size of the queue as `avail_idx` is
426+
// modded by `actual_size()`.
417427
let desc_index: u16 = mem.read_obj(desc_index_address).unwrap();
418428

419-
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index).map(
420-
|dc| {
421-
self.next_avail += Wrapping(1);
422-
dc
423-
},
424-
)
429+
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index)
425430
}
426431

427432
/// Undo the effects of the last `self.pop()` call.

0 commit comments

Comments
 (0)