4
4
use std:: io:: ErrorKind ;
5
5
6
6
use libc:: { c_void, iovec, size_t} ;
7
- #[ cfg( not( kani) ) ]
8
7
use smallvec:: SmallVec ;
9
8
use vm_memory:: bitmap:: Bitmap ;
10
9
use vm_memory:: {
11
10
GuestMemory , GuestMemoryError , ReadVolatile , VolatileMemoryError , VolatileSlice , WriteVolatile ,
12
11
} ;
13
12
14
- use super :: iov_deque:: { IovDeque , IovDequeError } ;
15
13
use crate :: devices:: virtio:: queue:: DescriptorChain ;
16
14
use crate :: vstate:: memory:: GuestMemoryMmap ;
17
15
@@ -25,8 +23,6 @@ pub enum IoVecError {
25
23
OverflowedDescriptor ,
26
24
/// Guest memory error: {0}
27
25
GuestMemory ( #[ from] GuestMemoryError ) ,
28
- /// Error with underlying `IovDeque`: {0}
29
- IovDeque ( #[ from] IovDequeError ) ,
30
26
}
31
27
32
28
// Using SmallVec in the kani proofs causes kani to use unbounded amounts of memory
@@ -218,135 +214,64 @@ impl IoVecBuffer {
218
214
}
219
215
}
220
216
221
- #[ derive( Debug ) ]
222
- pub struct ParsedDescriptorChain {
223
- pub head_index : u16 ,
224
- pub length : u32 ,
225
- pub nr_iovecs : u16 ,
226
- }
227
-
228
217
/// This is essentially a wrapper of a `Vec<libc::iovec>` which can be passed to `libc::readv`.
229
218
///
230
219
/// It describes a write-only buffer passed to us by the guest that is scattered across multiple
231
220
/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
232
221
/// of data from that buffer.
233
- #[ derive( Debug ) ]
222
+ #[ derive( Debug , Default , Clone ) ]
234
223
pub struct IoVecBufferMut {
235
224
// container of the memory regions included in this IO vector
236
- vecs : IovDeque ,
225
+ vecs : IoVecVec ,
237
226
// Total length of the IoVecBufferMut
238
- len : usize ,
227
+ len : u32 ,
239
228
}
240
229
241
230
impl 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`
244
232
///
245
233
/// # Safety
246
234
///
247
235
/// 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 (
249
237
& mut self ,
250
238
mem : & GuestMemoryMmap ,
251
239
head : DescriptorChain ,
252
- ) -> Result < ParsedDescriptorChain , IoVecError > {
253
- let head_index = head. index ;
240
+ ) -> Result < ( ) , IoVecError > {
241
+ self . clear ( ) ;
242
+
254
243
let mut next_descriptor = Some ( head) ;
255
- let mut length = 0u32 ;
256
- let mut nr_iovecs = 0u16 ;
257
244
while let Some ( desc) = next_descriptor {
258
245
if !desc. is_write_only ( ) {
259
- self . vecs . pop_front ( nr_iovecs) ;
260
246
return Err ( IoVecError :: ReadOnlyDescriptor ) ;
261
247
}
262
248
263
249
// We use get_slice instead of `get_host_address` here in order to have the whole
264
250
// range of the descriptor chain checked, i.e. [addr, addr + len) is a valid memory
265
251
// 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 ) ?;
270
253
271
254
// We need to mark the area of guest memory that will be mutated through this
272
255
// IoVecBufferMut as dirty ahead of time, as we loose access to all
273
256
// vm-memory related information after converting down to iovecs.
274
257
slice. bitmap ( ) . mark_dirty ( 0 , desc. len as usize ) ;
275
258
276
259
let iov_base = slice. ptr_guard_mut ( ) . as_ptr ( ) . cast :: < c_void > ( ) ;
277
- self . vecs . push_back ( iovec {
260
+ self . vecs . push ( iovec {
278
261
iov_base,
279
262
iov_len : desc. len as size_t ,
280
263
} ) ;
281
- nr_iovecs += 1 ;
282
- length = length
264
+ self . len = self
265
+ . len
283
266
. 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 ) ?;
289
268
290
269
next_descriptor = desc. next_descriptor ( ) ;
291
270
}
292
271
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) ?;
326
272
Ok ( ( ) )
327
273
}
328
274
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
-
350
275
/// Create an `IoVecBuffer` from a `DescriptorChain`
351
276
///
352
277
/// # Safety
@@ -356,29 +281,20 @@ impl IoVecBufferMut {
356
281
mem : & GuestMemoryMmap ,
357
282
head : DescriptorChain ,
358
283
) -> Result < Self , IoVecError > {
359
- let mut new_buffer = Self :: new ( ) ? ;
284
+ let mut new_buffer = Self :: default ( ) ;
360
285
new_buffer. load_descriptor_chain ( mem, head) ?;
361
286
Ok ( new_buffer)
362
287
}
363
288
364
289
/// 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 {
370
291
self . len
371
292
}
372
293
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
-
378
294
/// Clears the `iovec` array
379
295
pub fn clear ( & mut self ) {
380
296
self . vecs . clear ( ) ;
381
- self . len = 0 ;
297
+ self . len = 0u32 ;
382
298
}
383
299
384
300
/// Writes a number of bytes into the `IoVecBufferMut` starting at a given offset.
@@ -397,7 +313,7 @@ impl IoVecBufferMut {
397
313
mut buf : & [ u8 ] ,
398
314
offset : usize ,
399
315
) -> Result < ( ) , VolatileMemoryError > {
400
- if offset < self . len ( ) {
316
+ if offset < self . len ( ) as usize {
401
317
let expected = buf. len ( ) ;
402
318
let bytes_written = self . write_volatile_at ( & mut buf, offset, expected) ?;
403
319
@@ -426,7 +342,7 @@ impl IoVecBufferMut {
426
342
) -> Result < usize , VolatileMemoryError > {
427
343
let mut total_bytes_read = 0 ;
428
344
429
- for iov in self . vecs . as_slice ( ) {
345
+ for iov in & self . vecs {
430
346
if len == 0 {
431
347
break ;
432
348
}
@@ -475,7 +391,6 @@ mod tests {
475
391
use vm_memory:: VolatileMemoryError ;
476
392
477
393
use super :: { IoVecBuffer , IoVecBufferMut } ;
478
- use crate :: devices:: virtio:: iov_deque:: IovDeque ;
479
394
use crate :: devices:: virtio:: queue:: { Queue , VIRTQ_DESC_F_NEXT , VIRTQ_DESC_F_WRITE } ;
480
395
use crate :: devices:: virtio:: test_utils:: VirtQueue ;
481
396
use crate :: test_utils:: multi_region_mem;
@@ -514,33 +429,14 @@ mod tests {
514
429
515
430
impl From < & mut [ u8 ] > for IoVecBufferMut {
516
431
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
-
523
432
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 ( ) ,
541
439
}
542
-
543
- Self { vecs, len }
544
440
}
545
441
}
546
442
@@ -632,19 +528,8 @@ mod tests {
632
528
let head = q. pop ( ) . unwrap ( ) ;
633
529
634
530
// 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 ( ) } ;
636
532
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 ) ;
648
533
}
649
534
650
535
#[ test]
@@ -802,7 +687,6 @@ mod verification {
802
687
use vm_memory:: VolatileSlice ;
803
688
804
689
use super :: { IoVecBuffer , IoVecBufferMut , IoVecVec } ;
805
- use crate :: devices:: virtio:: iov_deque:: IovDeque ;
806
690
807
691
// Maximum memory size to use for our buffers. For the time being 1KB.
808
692
const GUEST_MEMORY_SIZE : usize = 1 << 10 ;
@@ -818,10 +702,10 @@ mod verification {
818
702
let mut vecs: Vec < iovec > = Vec :: with_capacity ( nr_descs) ;
819
703
let mut len = 0u32 ;
820
704
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
822
706
// `Descriptor` in the chain is a valid, i.e. it is memory with then guest's memory
823
707
// 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.`
825
709
let addr: usize = kani:: any ( ) ;
826
710
let iov_len: usize =
827
711
kani:: any_where ( |& len| matches ! ( addr. checked_add( len) , Some ( x) if x <= size) ) ;
@@ -844,26 +728,6 @@ mod verification {
844
728
}
845
729
}
846
730
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
-
867
731
impl IoVecBufferMut {
868
732
fn any_of_length ( nr_descs : usize ) -> Self {
869
733
// We only write into `IoVecBufferMut` objects, so we can simply create a guest memory
@@ -875,11 +739,8 @@ mod verification {
875
739
) )
876
740
} ;
877
741
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 }
883
744
}
884
745
}
885
746
@@ -959,7 +820,7 @@ mod verification {
959
820
let mut iov_mut = IoVecBufferMut :: any_of_length ( nr_descs) ;
960
821
961
822
let mut buf = kani:: vec:: any_vec :: < u8 , GUEST_MEMORY_SIZE > ( ) ;
962
- let offset: usize = kani:: any ( ) ;
823
+ let offset: u32 = kani:: any ( ) ;
963
824
964
825
// We can't really check the contents that the operation here writes into
965
826
// `IoVecBufferMut`, because our `IoVecBufferMut` being completely arbitrary
@@ -974,7 +835,11 @@ mod verification {
974
835
// Ok(...)
975
836
assert_eq ! (
976
837
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
+ )
978
843
. unwrap( ) ,
979
844
buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) as usize )
980
845
) ;
0 commit comments