@@ -24,6 +24,7 @@ use std::fmt::{self, Debug, Display};
2424use std:: mem:: size_of;
2525use std:: num:: Wrapping ;
2626use std:: sync:: atomic:: { fence, Ordering } ;
27+ use std:: sync:: Arc ;
2728
2829use defs:: {
2930 VIRTQ_AVAIL_ELEMENT_SIZE , VIRTQ_AVAIL_RING_HEADER_SIZE , VIRTQ_AVAIL_RING_META_SIZE ,
@@ -37,6 +38,13 @@ use vm_memory::{
3738
3839use log:: error;
3940
41+ /// Trait for devices with access to data in memory being limited and/or
42+ /// translated.
43+ pub trait AccessPlatform : Debug {
44+ /// Provide a way to translate address ranges.
45+ fn translate ( & self , base : u64 , size : u64 ) -> std:: result:: Result < u64 , std:: io:: Error > ;
46+ }
47+
4048/// Virtio Queue related errors.
4149#[ derive( Debug ) ]
4250pub enum Error {
@@ -153,6 +161,7 @@ pub struct DescriptorChain<M: GuestAddressSpace> {
153161 next_index : u16 ,
154162 ttl : u16 ,
155163 is_indirect : bool ,
164+ access_platform : Option < Arc < dyn AccessPlatform > > ,
156165}
157166
158167impl < M : GuestAddressSpace > DescriptorChain < M > {
@@ -162,6 +171,7 @@ impl<M: GuestAddressSpace> DescriptorChain<M> {
162171 queue_size : u16 ,
163172 ttl : u16 ,
164173 head_index : u16 ,
174+ access_platform : Option < Arc < dyn AccessPlatform > > ,
165175 ) -> Self {
166176 DescriptorChain {
167177 mem,
@@ -171,12 +181,26 @@ impl<M: GuestAddressSpace> DescriptorChain<M> {
171181 next_index : head_index,
172182 ttl,
173183 is_indirect : false ,
184+ access_platform,
174185 }
175186 }
176187
177188 /// Create a new `DescriptorChain` instance.
178- fn new ( mem : M :: T , desc_table : GuestAddress , queue_size : u16 , head_index : u16 ) -> Self {
179- Self :: with_ttl ( mem, desc_table, queue_size, queue_size, head_index)
189+ fn new (
190+ mem : M :: T ,
191+ desc_table : GuestAddress ,
192+ queue_size : u16 ,
193+ head_index : u16 ,
194+ access_platform : Option < Arc < dyn AccessPlatform > > ,
195+ ) -> Self {
196+ Self :: with_ttl (
197+ mem,
198+ desc_table,
199+ queue_size,
200+ queue_size,
201+ head_index,
202+ access_platform,
203+ )
180204 }
181205
182206 /// Get the descriptor index of the chain header
@@ -253,7 +277,14 @@ impl<M: GuestAddressSpace> Iterator for DescriptorChain<M> {
253277 . desc_table
254278 . unchecked_add ( self . next_index as u64 * size_of :: < Descriptor > ( ) as u64 ) ;
255279
256- let desc = self . mem . read_obj :: < Descriptor > ( desc_addr) . ok ( ) ?;
280+ let mut desc = self . mem . read_obj :: < Descriptor > ( desc_addr) . ok ( ) ?;
281+ // When needed, it's very important to translate the decriptor address
282+ // before returning the Descriptor to the consumer.
283+ if let Some ( access_platform) = & self . access_platform {
284+ desc. addr = access_platform
285+ . translate ( desc. addr , u64:: from ( desc. len ) )
286+ . ok ( ) ?;
287+ }
257288
258289 if desc. is_indirect ( ) {
259290 self . process_indirect_descriptor ( desc) . ok ( ) ?;
@@ -325,6 +356,7 @@ pub struct AvailIter<'b, M: GuestAddressSpace> {
325356 last_index : Wrapping < u16 > ,
326357 queue_size : u16 ,
327358 next_avail : & ' b mut Wrapping < u16 > ,
359+ access_platform : & ' b Option < Arc < dyn AccessPlatform > > ,
328360}
329361
330362impl < ' b , M : GuestAddressSpace > Iterator for AvailIter < ' b , M > {
@@ -360,6 +392,7 @@ impl<'b, M: GuestAddressSpace> Iterator for AvailIter<'b, M> {
360392 self . desc_table ,
361393 self . queue_size ,
362394 head_index,
395+ self . access_platform . clone ( ) ,
363396 ) )
364397 }
365398}
@@ -415,6 +448,9 @@ pub struct Queue<M: GuestAddressSpace> {
415448
416449 /// Guest physical address of the used ring
417450 pub used_ring : GuestAddress ,
451+
452+ /// Access platform handler
453+ pub access_platform : Option < Arc < dyn AccessPlatform > > ,
418454}
419455
420456impl < M : GuestAddressSpace > Queue < M > {
@@ -432,6 +468,7 @@ impl<M: GuestAddressSpace> Queue<M> {
432468 next_used : Wrapping ( 0 ) ,
433469 event_idx_enabled : false ,
434470 signalled_used : None ,
471+ access_platform : None ,
435472 }
436473 }
437474
@@ -545,6 +582,7 @@ impl<M: GuestAddressSpace> Queue<M> {
545582 last_index : idx,
546583 queue_size : self . actual_size ( ) ,
547584 next_avail : & mut self . next_avail ,
585+ access_platform : & self . access_platform ,
548586 } )
549587 }
550588
@@ -763,25 +801,29 @@ mod tests {
763801
764802 // index >= queue_size
765803 assert ! (
766- DescriptorChain :: <& GuestMemoryMmap >:: new( m, vq. start( ) , 16 , 16 )
804+ DescriptorChain :: <& GuestMemoryMmap >:: new( m, vq. start( ) , 16 , 16 , None )
767805 . next( )
768806 . is_none( )
769807 ) ;
770808
771809 // desc_table address is way off
772- assert ! (
773- DescriptorChain :: <& GuestMemoryMmap >:: new( m, GuestAddress ( 0x00ff_ffff_ffff ) , 16 , 0 )
774- . next( )
775- . is_none( )
776- ) ;
810+ assert ! ( DescriptorChain :: <& GuestMemoryMmap >:: new(
811+ m,
812+ GuestAddress ( 0x00ff_ffff_ffff ) ,
813+ 16 ,
814+ 0 ,
815+ None
816+ )
817+ . next( )
818+ . is_none( ) ) ;
777819
778820 {
779821 // the first desc has a normal len, and the next_descriptor flag is set
780822 // but the the index of the next descriptor is too large
781823 let desc = Descriptor :: new ( 0x1000 , 0x1000 , VIRTQ_DESC_F_NEXT , 16 ) ;
782824 vq. desc_table ( ) . store ( 0 , desc) ;
783825
784- let mut c = DescriptorChain :: < & GuestMemoryMmap > :: new ( m, vq. start ( ) , 16 , 0 ) ;
826+ let mut c = DescriptorChain :: < & GuestMemoryMmap > :: new ( m, vq. start ( ) , 16 , 0 , None ) ;
785827 c. next ( ) . unwrap ( ) ;
786828 assert ! ( c. next( ) . is_none( ) ) ;
787829 }
@@ -794,7 +836,7 @@ mod tests {
794836 let desc = Descriptor :: new ( 0x2000 , 0x1000 , 0 , 0 ) ;
795837 vq. desc_table ( ) . store ( 1 , desc) ;
796838
797- let mut c = DescriptorChain :: < & GuestMemoryMmap > :: new ( m, vq. start ( ) , 16 , 0 ) ;
839+ let mut c = DescriptorChain :: < & GuestMemoryMmap > :: new ( m, vq. start ( ) , 16 , 0 , None ) ;
798840
799841 assert_eq ! (
800842 c. memory( ) as * const GuestMemoryMmap ,
@@ -830,7 +872,8 @@ mod tests {
830872 let desc = Descriptor :: new ( 0x3000 , 0x1000 , 0 , 0 ) ;
831873 dtable. store ( 2 , desc) ;
832874
833- let mut c: DescriptorChain < & GuestMemoryMmap > = DescriptorChain :: new ( m, vq. start ( ) , 16 , 0 ) ;
875+ let mut c: DescriptorChain < & GuestMemoryMmap > =
876+ DescriptorChain :: new ( m, vq. start ( ) , 16 , 0 , None ) ;
834877
835878 // The chain logic hasn't parsed the indirect descriptor yet.
836879 assert ! ( !c. is_indirect) ;
@@ -874,7 +917,7 @@ mod tests {
874917 vq. desc_table ( ) . store ( 0 , desc) ;
875918
876919 let mut c: DescriptorChain < & GuestMemoryMmap > =
877- DescriptorChain :: new ( m, vq. start ( ) , 16 , 0 ) ;
920+ DescriptorChain :: new ( m, vq. start ( ) , 16 , 0 , None ) ;
878921
879922 assert ! ( c. next( ) . is_none( ) ) ;
880923 }
@@ -888,7 +931,7 @@ mod tests {
888931 vq. desc_table ( ) . store ( 0 , desc) ;
889932
890933 let mut c: DescriptorChain < & GuestMemoryMmap > =
891- DescriptorChain :: new ( m, vq. start ( ) , 16 , 0 ) ;
934+ DescriptorChain :: new ( m, vq. start ( ) , 16 , 0 , None ) ;
892935
893936 assert ! ( c. next( ) . is_none( ) ) ;
894937 }
0 commit comments