Skip to content

Commit da21ac0

Browse files
jiangliuandreeaflorescu
authored andcommitted
virtio: optimize the way to fetch VirtIO descriptor
Fetch the entire VirtIO descriptor all at once instead of fetching each field one by one. Signed-off-by: Liu Jiang <[email protected]>
1 parent f0a08a9 commit da21ac0

File tree

1 file changed

+27
-31
lines changed

1 file changed

+27
-31
lines changed

devices/src/virtio/queue.rs

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,31 @@ use std::cmp::min;
99
use std::num::Wrapping;
1010
use std::sync::atomic::{fence, Ordering};
1111

12-
use memory_model::{GuestAddress, GuestMemory};
12+
use memory_model::{DataInit, GuestAddress, GuestMemory};
1313

1414
pub(super) const VIRTQ_DESC_F_NEXT: u16 = 0x1;
1515
pub(super) const VIRTQ_DESC_F_WRITE: u16 = 0x2;
1616

17+
// GuestMemory::read_obj_from_addr() will be used to fetch the descriptor,
18+
// which has an explicit constraint that the entire descriptor doesn't
19+
// cross the page boundary. Otherwise the descriptor may be splitted into
20+
// two mmap regions which causes failure of GuestMemory::read_obj_from_addr().
21+
//
22+
// The Virtio Spec 1.0 defines the alignment of VirtIO descriptor is 16 bytes,
23+
// which fulfills the explicit constraint of GuestMemory::read_obj_from_addr().
24+
25+
/// A virtio descriptor constraints with C representive.
26+
#[repr(C)]
27+
#[derive(Default, Clone, Copy)]
28+
struct Descriptor {
29+
addr: u64,
30+
len: u32,
31+
flags: u16,
32+
next: u16,
33+
}
34+
35+
unsafe impl DataInit for Descriptor {}
36+
1737
/// A virtio descriptor chain.
1838
pub struct DescriptorChain<'a> {
1939
mem: &'a GuestMemory,
@@ -53,35 +73,11 @@ impl<'a> DescriptorChain<'a> {
5373
Some(a) => a,
5474
None => return None,
5575
};
56-
// These reads can't fail unless Guest memory is hopelessly broken.
57-
let addr = match mem.read_obj_from_addr::<u64>(desc_head) {
58-
Ok(ret) => GuestAddress(ret as usize),
59-
Err(_) => {
60-
// TODO log address
61-
error!("Failed to read from memory");
62-
return None;
63-
}
64-
};
6576
if mem.checked_offset(desc_head, 16).is_none() {
6677
return None;
6778
}
68-
let len: u32 = match mem.read_obj_from_addr(desc_head.unchecked_add(8)) {
69-
Ok(ret) => ret,
70-
Err(_) => {
71-
// TODO log address
72-
error!("Failed to read from memory");
73-
return None;
74-
}
75-
};
76-
let flags: u16 = match mem.read_obj_from_addr(desc_head.unchecked_add(12)) {
77-
Ok(ret) => ret,
78-
Err(_) => {
79-
// TODO log address
80-
error!("Failed to read from memory");
81-
return None;
82-
}
83-
};
84-
let next: u16 = match mem.read_obj_from_addr(desc_head.unchecked_add(14)) {
79+
// These reads can't fail unless Guest memory is hopelessly broken.
80+
let desc = match mem.read_obj_from_addr::<Descriptor>(desc_head) {
8581
Ok(ret) => ret,
8682
Err(_) => {
8783
// TODO log address
@@ -95,10 +91,10 @@ impl<'a> DescriptorChain<'a> {
9591
queue_size: queue_size,
9692
ttl: queue_size,
9793
index: index,
98-
addr: addr,
99-
len: len,
100-
flags: flags,
101-
next: next,
94+
addr: GuestAddress(desc.addr as usize),
95+
len: desc.len,
96+
flags: desc.flags,
97+
next: desc.next,
10298
};
10399

104100
if chain.is_valid() {

0 commit comments

Comments
 (0)