@@ -16,16 +16,13 @@ use std::borrow::Borrow;
16
16
use std:: ops:: Deref ;
17
17
use std:: result;
18
18
use std:: sync:: atomic:: Ordering ;
19
- use std:: sync:: Arc ;
20
19
21
20
use crate :: address:: Address ;
22
21
use crate :: bitmap:: { Bitmap , BS } ;
23
- use crate :: guest_memory:: {
24
- self , FileOffset , GuestAddress , GuestMemory , GuestUsize , MemoryRegionAddress ,
25
- } ;
22
+ use crate :: guest_memory:: { self , FileOffset , GuestAddress , GuestUsize , MemoryRegionAddress } ;
26
23
use crate :: region:: GuestMemoryRegion ;
27
24
use crate :: volatile_memory:: { VolatileMemory , VolatileSlice } ;
28
- use crate :: { AtomicAccess , Bytes , ReadVolatile , WriteVolatile } ;
25
+ use crate :: { AtomicAccess , Bytes , Error , GuestRegionCollection , ReadVolatile , WriteVolatile } ;
29
26
30
27
// re-export for backward compat, as the trait used to be defined in mmap.rs
31
28
pub use crate :: bitmap:: NewBitmap ;
@@ -50,26 +47,6 @@ pub use std::io::Error as MmapRegionError;
50
47
#[ cfg( target_family = "windows" ) ]
51
48
pub use windows:: MmapRegion ;
52
49
53
- /// Errors that can occur when creating a memory map.
54
- #[ derive( Debug , thiserror:: Error ) ]
55
- pub enum Error {
56
- /// Adding the guest base address to the length of the underlying mapping resulted
57
- /// in an overflow.
58
- #[ error( "Adding the guest base address to the length of the underlying mapping resulted in an overflow" ) ]
59
- InvalidGuestRegion ,
60
- /// Error creating a `MmapRegion` object.
61
- #[ error( "{0}" ) ]
62
- MmapRegion ( MmapRegionError ) ,
63
- /// No memory region found.
64
- #[ error( "No memory region found" ) ]
65
- NoMemoryRegion ,
66
- /// Some of the memory regions intersect with each other.
67
- #[ error( "Some of the memory regions intersect with each other" ) ]
68
- MemoryRegionOverlap ,
69
- /// The provided memory regions haven't been sorted.
70
- #[ error( "The provided memory regions haven't been sorted" ) ]
71
- UnsortedMemoryRegions ,
72
- }
73
50
74
51
/// [`GuestMemoryRegion`](trait.GuestMemoryRegion.html) implementation that mmaps the guest's
75
52
/// memory region in the current process.
@@ -339,17 +316,9 @@ impl<B: Bitmap> GuestMemoryRegion for GuestRegionMmap<B> {
339
316
/// Represents the entire physical memory of the guest by tracking all its memory regions.
340
317
/// Each region is an instance of `GuestRegionMmap`, being backed by a mapping in the
341
318
/// virtual address space of the calling process.
342
- #[ derive( Clone , Debug , Default ) ]
343
- pub struct GuestMemoryMmap < B = ( ) > {
344
- regions : Vec < Arc < GuestRegionMmap < B > > > ,
345
- }
319
+ pub type GuestMemoryMmap < B = ( ) > = GuestRegionCollection < GuestRegionMmap < B > > ;
346
320
347
321
impl < B : NewBitmap > GuestMemoryMmap < B > {
348
- /// Creates an empty `GuestMemoryMmap` instance.
349
- pub fn new ( ) -> Self {
350
- Self :: default ( )
351
- }
352
-
353
322
/// Creates a container and allocates anonymous memory for guest memory regions.
354
323
///
355
324
/// Valid memory regions are specified as a slice of (Address, Size) tuples sorted by Address.
@@ -377,111 +346,6 @@ impl<B: NewBitmap> GuestMemoryMmap<B> {
377
346
}
378
347
}
379
348
380
- impl < B : Bitmap > GuestMemoryMmap < B > {
381
- /// Creates a new `GuestMemoryMmap` from a vector of regions.
382
- ///
383
- /// # Arguments
384
- ///
385
- /// * `regions` - The vector of regions.
386
- /// The regions shouldn't overlap and they should be sorted
387
- /// by the starting address.
388
- pub fn from_regions ( mut regions : Vec < GuestRegionMmap < B > > ) -> result:: Result < Self , Error > {
389
- Self :: from_arc_regions ( regions. drain ( ..) . map ( Arc :: new) . collect ( ) )
390
- }
391
-
392
- /// Creates a new `GuestMemoryMmap` from a vector of Arc regions.
393
- ///
394
- /// Similar to the constructor `from_regions()` as it returns a
395
- /// `GuestMemoryMmap`. The need for this constructor is to provide a way for
396
- /// consumer of this API to create a new `GuestMemoryMmap` based on existing
397
- /// regions coming from an existing `GuestMemoryMmap` instance.
398
- ///
399
- /// # Arguments
400
- ///
401
- /// * `regions` - The vector of `Arc` regions.
402
- /// The regions shouldn't overlap and they should be sorted
403
- /// by the starting address.
404
- pub fn from_arc_regions ( regions : Vec < Arc < GuestRegionMmap < B > > > ) -> result:: Result < Self , Error > {
405
- if regions. is_empty ( ) {
406
- return Err ( Error :: NoMemoryRegion ) ;
407
- }
408
-
409
- for window in regions. windows ( 2 ) {
410
- let prev = & window[ 0 ] ;
411
- let next = & window[ 1 ] ;
412
-
413
- if prev. start_addr ( ) > next. start_addr ( ) {
414
- return Err ( Error :: UnsortedMemoryRegions ) ;
415
- }
416
-
417
- if prev. last_addr ( ) >= next. start_addr ( ) {
418
- return Err ( Error :: MemoryRegionOverlap ) ;
419
- }
420
- }
421
-
422
- Ok ( Self { regions } )
423
- }
424
-
425
- /// Insert a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`.
426
- ///
427
- /// # Arguments
428
- /// * `region`: the memory region to insert into the guest memory object.
429
- pub fn insert_region (
430
- & self ,
431
- region : Arc < GuestRegionMmap < B > > ,
432
- ) -> result:: Result < GuestMemoryMmap < B > , Error > {
433
- let mut regions = self . regions . clone ( ) ;
434
- regions. push ( region) ;
435
- regions. sort_by_key ( |x| x. start_addr ( ) ) ;
436
-
437
- Self :: from_arc_regions ( regions)
438
- }
439
-
440
- /// Remove a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`
441
- /// on success, together with the removed region.
442
- ///
443
- /// # Arguments
444
- /// * `base`: base address of the region to be removed
445
- /// * `size`: size of the region to be removed
446
- pub fn remove_region (
447
- & self ,
448
- base : GuestAddress ,
449
- size : GuestUsize ,
450
- ) -> result:: Result < ( GuestMemoryMmap < B > , Arc < GuestRegionMmap < B > > ) , Error > {
451
- if let Ok ( region_index) = self . regions . binary_search_by_key ( & base, |x| x. start_addr ( ) ) {
452
- if self . regions . get ( region_index) . unwrap ( ) . mapping . size ( ) as GuestUsize == size {
453
- let mut regions = self . regions . clone ( ) ;
454
- let region = regions. remove ( region_index) ;
455
- return Ok ( ( Self { regions } , region) ) ;
456
- }
457
- }
458
-
459
- Err ( Error :: InvalidGuestRegion )
460
- }
461
- }
462
-
463
- impl < B : Bitmap + ' static > GuestMemory for GuestMemoryMmap < B > {
464
- type R = GuestRegionMmap < B > ;
465
-
466
- fn num_regions ( & self ) -> usize {
467
- self . regions . len ( )
468
- }
469
-
470
- fn find_region ( & self , addr : GuestAddress ) -> Option < & GuestRegionMmap < B > > {
471
- let index = match self . regions . binary_search_by_key ( & addr, |x| x. start_addr ( ) ) {
472
- Ok ( x) => Some ( x) ,
473
- // Within the closest region with starting address < addr
474
- Err ( x) if ( x > 0 && addr <= self . regions [ x - 1 ] . last_addr ( ) ) => Some ( x - 1 ) ,
475
- _ => None ,
476
- } ;
477
- index. map ( |x| self . regions [ x] . as_ref ( ) )
478
- }
479
-
480
- fn iter ( & self ) -> impl Iterator < Item = & Self :: R > {
481
- self . regions . iter ( ) . map ( AsRef :: as_ref)
482
- }
483
- }
484
-
485
349
#[ cfg( test) ]
486
350
mod tests {
487
351
#![ allow( clippy:: undocumented_unsafe_blocks) ]
@@ -491,16 +355,17 @@ mod tests {
491
355
492
356
use crate :: bitmap:: tests:: test_guest_memory_and_region;
493
357
use crate :: bitmap:: AtomicBitmap ;
494
- use crate :: GuestAddressSpace ;
358
+ use crate :: { Error , GuestAddressSpace , GuestMemory } ;
495
359
496
360
use std:: io:: Write ;
497
361
use std:: mem;
362
+ use std:: sync:: Arc ;
498
363
#[ cfg( feature = "rawfd" ) ]
499
364
use std:: { fs:: File , path:: Path } ;
500
365
use vmm_sys_util:: tempfile:: TempFile ;
501
366
502
- type GuestMemoryMmap = super :: GuestMemoryMmap < ( ) > ;
503
367
type GuestRegionMmap = super :: GuestRegionMmap < ( ) > ;
368
+ type GuestMemoryMmap = super :: GuestRegionCollection < GuestRegionMmap > ;
504
369
type MmapRegion = super :: MmapRegion < ( ) > ;
505
370
506
371
#[ test]
@@ -525,9 +390,8 @@ mod tests {
525
390
}
526
391
assert_eq ! ( guest_mem. last_addr( ) , last_addr) ;
527
392
}
528
- for ( ( region_addr, region_size) , mmap) in expected_regions_summary
529
- . iter ( )
530
- . zip ( guest_mem. regions . iter ( ) )
393
+ for ( ( region_addr, region_size) , mmap) in
394
+ expected_regions_summary. iter ( ) . zip ( guest_mem. iter ( ) )
531
395
{
532
396
assert_eq ! ( region_addr, & mmap. guest_base) ;
533
397
assert_eq ! ( region_size, & mmap. mapping. size( ) ) ;
@@ -718,7 +582,7 @@ mod tests {
718
582
let regions_summary = [ ( GuestAddress ( 0 ) , 100_usize ) , ( GuestAddress ( 100 ) , 100_usize ) ] ;
719
583
720
584
let guest_mem = GuestMemoryMmap :: new ( ) ;
721
- assert_eq ! ( guest_mem. regions . len ( ) , 0 ) ;
585
+ assert_eq ! ( guest_mem. num_regions ( ) , 0 ) ;
722
586
723
587
check_guest_memory_mmap ( new_guest_memory_mmap ( & regions_summary) , & regions_summary) ;
724
588
@@ -1056,8 +920,10 @@ mod tests {
1056
920
. map( |x| ( x. 0 , x. 1 ) )
1057
921
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1058
922
1059
- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1060
- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
923
+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
924
+
925
+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
926
+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1061
927
}
1062
928
1063
929
#[ test]
@@ -1085,8 +951,10 @@ mod tests {
1085
951
. map( |x| ( x. 0 , x. 1 ) )
1086
952
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1087
953
1088
- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1089
- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
954
+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
955
+
956
+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
957
+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1090
958
}
1091
959
1092
960
#[ test]
@@ -1195,11 +1063,13 @@ mod tests {
1195
1063
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1196
1064
assert_eq ! ( gm. num_regions( ) , 5 ) ;
1197
1065
1198
- assert_eq ! ( gm. regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1199
- assert_eq ! ( gm. regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1200
- assert_eq ! ( gm. regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1201
- assert_eq ! ( gm. regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1202
- assert_eq ! ( gm. regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1066
+ let regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
1067
+
1068
+ assert_eq ! ( regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1069
+ assert_eq ! ( regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1070
+ assert_eq ! ( regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1071
+ assert_eq ! ( regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1072
+ assert_eq ! ( regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1203
1073
}
1204
1074
1205
1075
#[ test]
@@ -1220,7 +1090,7 @@ mod tests {
1220
1090
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1221
1091
assert_eq ! ( gm. num_regions( ) , 1 ) ;
1222
1092
1223
- assert_eq ! ( gm. regions [ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1093
+ assert_eq ! ( gm. iter ( ) . next ( ) . unwrap ( ) . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1224
1094
assert_eq ! ( region. start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1225
1095
}
1226
1096
0 commit comments