44use std:: io:: ErrorKind ;
55
66use libc:: { c_void, iovec, size_t} ;
7- #[ cfg( not( kani) ) ]
87use smallvec:: SmallVec ;
98use vm_memory:: bitmap:: Bitmap ;
109use vm_memory:: {
1110 GuestMemory , GuestMemoryError , ReadVolatile , VolatileMemoryError , VolatileSlice , WriteVolatile ,
1211} ;
1312
14- use super :: iov_deque:: { IovDeque , IovDequeError } ;
1513use crate :: devices:: virtio:: queue:: DescriptorChain ;
1614use crate :: vstate:: memory:: GuestMemoryMmap ;
1715
@@ -25,8 +23,6 @@ pub enum IoVecError {
2523 OverflowedDescriptor ,
2624 /// Guest memory error: {0}
2725 GuestMemory ( #[ from] GuestMemoryError ) ,
28- /// Error with underlying `IovDeque`: {0}
29- IovDeque ( #[ from] IovDequeError ) ,
3026}
3127
3228// Using SmallVec in the kani proofs causes kani to use unbounded amounts of memory
@@ -218,135 +214,64 @@ impl IoVecBuffer {
218214 }
219215}
220216
221- #[ derive( Debug ) ]
222- pub struct ParsedDescriptorChain {
223- pub head_index : u16 ,
224- pub length : u32 ,
225- pub nr_iovecs : u16 ,
226- }
227-
228217/// This is essentially a wrapper of a `Vec<libc::iovec>` which can be passed to `libc::readv`.
229218///
230219/// It describes a write-only buffer passed to us by the guest that is scattered across multiple
231220/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
232221/// of data from that buffer.
233- #[ derive( Debug ) ]
222+ #[ derive( Debug , Default , Clone ) ]
234223pub struct IoVecBufferMut {
235224 // container of the memory regions included in this IO vector
236- vecs : IovDeque ,
225+ vecs : IoVecVec ,
237226 // Total length of the IoVecBufferMut
238- len : usize ,
227+ len : u32 ,
239228}
240229
241230impl IoVecBufferMut {
242- /// Parse a `DescriptorChain` object and append the memory regions it describes in the
243- /// underlying ring buffer.
231+ /// Create an `IoVecBuffer` from a `DescriptorChain`
244232 ///
245233 /// # Safety
246234 ///
247235 /// The descriptor chain cannot be referencing the same memory location as another chain
248- unsafe fn parse_descriptor (
236+ pub unsafe fn load_descriptor_chain (
249237 & mut self ,
250238 mem : & GuestMemoryMmap ,
251239 head : DescriptorChain ,
252- ) -> Result < ParsedDescriptorChain , IoVecError > {
253- let head_index = head. index ;
240+ ) -> Result < ( ) , IoVecError > {
241+ self . clear ( ) ;
242+
254243 let mut next_descriptor = Some ( head) ;
255- let mut length = 0u32 ;
256- let mut nr_iovecs = 0u16 ;
257244 while let Some ( desc) = next_descriptor {
258245 if !desc. is_write_only ( ) {
259- self . vecs . pop_front ( nr_iovecs) ;
260246 return Err ( IoVecError :: ReadOnlyDescriptor ) ;
261247 }
262248
263249 // We use get_slice instead of `get_host_address` here in order to have the whole
264250 // range of the descriptor chain checked, i.e. [addr, addr + len) is a valid memory
265251 // region in the GuestMemoryMmap.
266- let slice = mem. get_slice ( desc. addr , desc. len as usize ) . map_err ( |err| {
267- self . vecs . pop_front ( nr_iovecs) ;
268- err
269- } ) ?;
252+ let slice = mem. get_slice ( desc. addr , desc. len as usize ) ?;
270253
271254 // We need to mark the area of guest memory that will be mutated through this
272255 // IoVecBufferMut as dirty ahead of time, as we loose access to all
273256 // vm-memory related information after converting down to iovecs.
274257 slice. bitmap ( ) . mark_dirty ( 0 , desc. len as usize ) ;
275258
276259 let iov_base = slice. ptr_guard_mut ( ) . as_ptr ( ) . cast :: < c_void > ( ) ;
277- self . vecs . push_back ( iovec {
260+ self . vecs . push ( iovec {
278261 iov_base,
279262 iov_len : desc. len as size_t ,
280263 } ) ;
281- nr_iovecs += 1 ;
282- length = length
264+ self . len = self
265+ . len
283266 . checked_add ( desc. len )
284- . ok_or ( IoVecError :: OverflowedDescriptor )
285- . map_err ( |err| {
286- self . vecs . pop_front ( nr_iovecs) ;
287- err
288- } ) ?;
267+ . ok_or ( IoVecError :: OverflowedDescriptor ) ?;
289268
290269 next_descriptor = desc. next_descriptor ( ) ;
291270 }
292271
293- self . len = self . len . checked_add ( length as usize ) . ok_or_else ( || {
294- self . vecs . pop_front ( nr_iovecs) ;
295- IoVecError :: OverflowedDescriptor
296- } ) ?;
297-
298- Ok ( ParsedDescriptorChain {
299- head_index,
300- length,
301- nr_iovecs,
302- } )
303- }
304-
305- /// Create an empty `IoVecBufferMut`.
306- pub fn new ( ) -> Result < Self , IovDequeError > {
307- let vecs = IovDeque :: new ( ) ?;
308- Ok ( Self { vecs, len : 0 } )
309- }
310-
311- /// Create an `IoVecBufferMut` from a `DescriptorChain`
312- ///
313- /// This will clear any previous `iovec` objects in the buffer and load the new
314- /// [`DescriptorChain`].
315- ///
316- /// # Safety
317- ///
318- /// The descriptor chain cannot be referencing the same memory location as another chain
319- pub unsafe fn load_descriptor_chain (
320- & mut self ,
321- mem : & GuestMemoryMmap ,
322- head : DescriptorChain ,
323- ) -> Result < ( ) , IoVecError > {
324- self . clear ( ) ;
325- let _ = self . parse_descriptor ( mem, head) ?;
326272 Ok ( ( ) )
327273 }
328274
329- /// Append a `DescriptorChain` in this `IoVecBufferMut`
330- ///
331- /// # Safety
332- ///
333- /// The descriptor chain cannot be referencing the same memory location as another chain
334- pub unsafe fn append_descriptor_chain (
335- & mut self ,
336- mem : & GuestMemoryMmap ,
337- head : DescriptorChain ,
338- ) -> Result < ParsedDescriptorChain , IoVecError > {
339- self . parse_descriptor ( mem, head)
340- }
341-
342- /// Drop memory from the `IoVecBufferMut`
343- ///
344- /// This will drop memory described by the `IoVecBufferMut` from the beginning.
345- pub fn drop_descriptor_chain ( & mut self , parse_descriptor : & ParsedDescriptorChain ) {
346- self . vecs . pop_front ( parse_descriptor. nr_iovecs ) ;
347- self . len -= parse_descriptor. length as usize ;
348- }
349-
350275 /// Create an `IoVecBuffer` from a `DescriptorChain`
351276 ///
352277 /// # Safety
@@ -356,29 +281,20 @@ impl IoVecBufferMut {
356281 mem : & GuestMemoryMmap ,
357282 head : DescriptorChain ,
358283 ) -> Result < Self , IoVecError > {
359- let mut new_buffer = Self :: new ( ) ? ;
284+ let mut new_buffer = Self :: default ( ) ;
360285 new_buffer. load_descriptor_chain ( mem, head) ?;
361286 Ok ( new_buffer)
362287 }
363288
364289 /// Get the total length of the memory regions covered by this `IoVecBuffer`
365- ///
366- /// In contrast to the equivalent [`IoVecBuffer::len()`] which returns `u32`, this one returns
367- /// `usize` since the buffer can contain multiple `DescriptorChain` objects, so we don't have
368- /// the limit that the length of a buffer is limited by `u32`.
369- pub ( crate ) fn len ( & self ) -> usize {
290+ pub ( crate ) fn len ( & self ) -> u32 {
370291 self . len
371292 }
372293
373- /// Returns a pointer to the memory keeping the `iovec` structs
374- pub fn as_iovec_mut_slice ( & mut self ) -> & mut [ iovec ] {
375- self . vecs . as_mut_slice ( )
376- }
377-
378294 /// Clears the `iovec` array
379295 pub fn clear ( & mut self ) {
380296 self . vecs . clear ( ) ;
381- self . len = 0 ;
297+ self . len = 0u32 ;
382298 }
383299
384300 /// Writes a number of bytes into the `IoVecBufferMut` starting at a given offset.
@@ -397,7 +313,7 @@ impl IoVecBufferMut {
397313 mut buf : & [ u8 ] ,
398314 offset : usize ,
399315 ) -> Result < ( ) , VolatileMemoryError > {
400- if offset < self . len ( ) {
316+ if offset < self . len ( ) as usize {
401317 let expected = buf. len ( ) ;
402318 let bytes_written = self . write_volatile_at ( & mut buf, offset, expected) ?;
403319
@@ -426,7 +342,7 @@ impl IoVecBufferMut {
426342 ) -> Result < usize , VolatileMemoryError > {
427343 let mut total_bytes_read = 0 ;
428344
429- for iov in self . vecs . as_slice ( ) {
345+ for iov in & self . vecs {
430346 if len == 0 {
431347 break ;
432348 }
@@ -475,7 +391,6 @@ mod tests {
475391 use vm_memory:: VolatileMemoryError ;
476392
477393 use super :: { IoVecBuffer , IoVecBufferMut } ;
478- use crate :: devices:: virtio:: iov_deque:: IovDeque ;
479394 use crate :: devices:: virtio:: queue:: { Queue , VIRTQ_DESC_F_NEXT , VIRTQ_DESC_F_WRITE } ;
480395 use crate :: devices:: virtio:: test_utils:: VirtQueue ;
481396 use crate :: test_utils:: multi_region_mem;
@@ -514,33 +429,14 @@ mod tests {
514429
515430 impl From < & mut [ u8 ] > for IoVecBufferMut {
516431 fn from ( buf : & mut [ u8 ] ) -> Self {
517- let mut vecs = IovDeque :: new ( ) . unwrap ( ) ;
518- vecs. push_back ( iovec {
519- iov_base : buf. as_mut_ptr ( ) . cast :: < c_void > ( ) ,
520- iov_len : buf. len ( ) ,
521- } ) ;
522-
523432 Self {
524- vecs,
525- len : buf. len ( ) ,
526- }
527- }
528- }
529-
530- impl From < Vec < & mut [ u8 ] > > for IoVecBufferMut {
531- fn from ( buffer : Vec < & mut [ u8 ] > ) -> Self {
532- let mut len = 0usize ;
533- let mut vecs = IovDeque :: new ( ) . unwrap ( ) ;
534- for slice in buffer {
535- len += slice. len ( ) ;
536-
537- vecs. push_back ( iovec {
538- iov_base : slice. as_ptr ( ) as * mut c_void ,
539- iov_len : slice. len ( ) ,
540- } ) ;
433+ vecs : vec ! [ iovec {
434+ iov_base: buf. as_mut_ptr( ) . cast:: <c_void>( ) ,
435+ iov_len: buf. len( ) ,
436+ } ]
437+ . into ( ) ,
438+ len : buf. len ( ) . try_into ( ) . unwrap ( ) ,
541439 }
542-
543- Self { vecs, len }
544440 }
545441 }
546442
@@ -632,19 +528,8 @@ mod tests {
632528 let head = q. pop ( ) . unwrap ( ) ;
633529
634530 // SAFETY: This descriptor chain is only loaded once in this test
635- let mut iovec = unsafe { IoVecBufferMut :: from_descriptor_chain ( & mem, head) . unwrap ( ) } ;
531+ let iovec = unsafe { IoVecBufferMut :: from_descriptor_chain ( & mem, head) . unwrap ( ) } ;
636532 assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
637-
638- // We are creating a new queue where we can get descriptors from. Probably, this is not
639- // something that we will ever want to do, as `IoVecBufferMut`s are typically
640- // (concpetually) associated with a single `Queue`. We just do this here to be able to test
641- // the appending logic.
642- let ( mut q, _) = write_only_chain ( & mem) ;
643- let head = q. pop ( ) . unwrap ( ) ;
644- // SAFETY: it is actually unsafe, but we just want to check the length of the
645- // `IoVecBufferMut` after appending.
646- let _ = unsafe { iovec. append_descriptor_chain ( & mem, head) . unwrap ( ) } ;
647- assert_eq ! ( iovec. len( ) , 8 * 64 ) ;
648533 }
649534
650535 #[ test]
@@ -802,7 +687,6 @@ mod verification {
802687 use vm_memory:: VolatileSlice ;
803688
804689 use super :: { IoVecBuffer , IoVecBufferMut , IoVecVec } ;
805- use crate :: devices:: virtio:: iov_deque:: IovDeque ;
806690
807691 // Maximum memory size to use for our buffers. For the time being 1KB.
808692 const GUEST_MEMORY_SIZE : usize = 1 << 10 ;
@@ -818,10 +702,10 @@ mod verification {
818702 let mut vecs: Vec < iovec > = Vec :: with_capacity ( nr_descs) ;
819703 let mut len = 0u32 ;
820704 for _ in 0 ..nr_descs {
821- // The `IoVecBuffer` constructors ensure that the memory region described by every
705+ // The `IoVecBuffer(Mut) ` constructors ensure that the memory region described by every
822706 // `Descriptor` in the chain is a valid, i.e. it is memory with then guest's memory
823707 // mmap. The assumption, here, that the last address is within the memory object's
824- // bound substitutes these checks that `IoVecBuffer::new() performs.`
708+ // bound substitutes these checks that `IoVecBuffer(Mut) ::new() performs.`
825709 let addr: usize = kani:: any ( ) ;
826710 let iov_len: usize =
827711 kani:: any_where ( |& len| matches ! ( addr. checked_add( len) , Some ( x) if x <= size) ) ;
@@ -844,26 +728,6 @@ mod verification {
844728 }
845729 }
846730
847- fn create_iovecs_mut ( mem : * mut u8 , size : usize , nr_descs : usize ) -> ( IovDeque , u32 ) {
848- let mut vecs = IovDeque :: new ( ) . unwrap ( ) ;
849- let mut len = 0u32 ;
850- for _ in 0 ..nr_descs {
851- // The `IoVecBufferMut` constructors ensure that the memory region described by every
852- // `Descriptor` in the chain is a valid, i.e. it is memory with then guest's memory
853- // mmap. The assumption, here, that the last address is within the memory object's
854- // bound substitutes these checks that `IoVecBufferMut::new() performs.`
855- let addr: usize = kani:: any ( ) ;
856- let iov_len: usize =
857- kani:: any_where ( |& len| matches ! ( addr. checked_add( len) , Some ( x) if x <= size) ) ;
858- let iov_base = unsafe { mem. offset ( addr. try_into ( ) . unwrap ( ) ) } as * mut c_void ;
859-
860- vecs. push_back ( iovec { iov_base, iov_len } ) ;
861- len += u32:: try_from ( iov_len) . unwrap ( ) ;
862- }
863-
864- ( vecs, len)
865- }
866-
867731 impl IoVecBufferMut {
868732 fn any_of_length ( nr_descs : usize ) -> Self {
869733 // We only write into `IoVecBufferMut` objects, so we can simply create a guest memory
@@ -875,11 +739,8 @@ mod verification {
875739 ) )
876740 } ;
877741
878- let ( vecs, len) = create_iovecs_mut ( mem, GUEST_MEMORY_SIZE , nr_descs) ;
879- Self {
880- vecs,
881- len : len. try_into ( ) . unwrap ( ) ,
882- }
742+ let ( vecs, len) = create_iovecs ( mem, GUEST_MEMORY_SIZE , nr_descs) ;
743+ Self { vecs, len }
883744 }
884745 }
885746
@@ -959,7 +820,7 @@ mod verification {
959820 let mut iov_mut = IoVecBufferMut :: any_of_length ( nr_descs) ;
960821
961822 let mut buf = kani:: vec:: any_vec :: < u8 , GUEST_MEMORY_SIZE > ( ) ;
962- let offset: usize = kani:: any ( ) ;
823+ let offset: u32 = kani:: any ( ) ;
963824
964825 // We can't really check the contents that the operation here writes into
965826 // `IoVecBufferMut`, because our `IoVecBufferMut` being completely arbitrary
@@ -974,7 +835,11 @@ mod verification {
974835 // Ok(...)
975836 assert_eq ! (
976837 iov_mut
977- . write_volatile_at( & mut KaniBuffer ( & mut buf) , offset, GUEST_MEMORY_SIZE )
838+ . write_volatile_at(
839+ & mut KaniBuffer ( & mut buf) ,
840+ offset as usize ,
841+ GUEST_MEMORY_SIZE
842+ )
978843 . unwrap( ) ,
979844 buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) as usize )
980845 ) ;
0 commit comments