@@ -9,11 +9,31 @@ use std::cmp::min;
99use std:: num:: Wrapping ;
1010use std:: sync:: atomic:: { fence, Ordering } ;
1111
12- use memory_model:: { GuestAddress , GuestMemory } ;
12+ use memory_model:: { DataInit , GuestAddress , GuestMemory } ;
1313
1414pub ( super ) const VIRTQ_DESC_F_NEXT : u16 = 0x1 ;
1515pub ( 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.
1838pub 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