@@ -18,16 +18,13 @@ use std::io::{Seek, SeekFrom};
1818use std:: ops:: Deref ;
1919use std:: result;
2020use std:: sync:: atomic:: Ordering ;
21- use std:: sync:: Arc ;
2221
2322use crate :: address:: Address ;
2423use crate :: bitmap:: { Bitmap , BS } ;
25- use crate :: guest_memory:: {
26- self , FileOffset , GuestAddress , GuestMemory , GuestUsize , MemoryRegionAddress ,
27- } ;
24+ use crate :: guest_memory:: { self , FileOffset , GuestAddress , GuestUsize , MemoryRegionAddress } ;
2825use crate :: region:: GuestMemoryRegion ;
2926use crate :: volatile_memory:: { VolatileMemory , VolatileSlice } ;
30- use crate :: { AtomicAccess , Bytes , ReadVolatile , WriteVolatile } ;
27+ use crate :: { AtomicAccess , Bytes , Error , GuestRegionCollection , ReadVolatile , WriteVolatile } ;
3128
3229// re-export for backward compat, as the trait used to be defined in mmap.rs
3330pub use crate :: bitmap:: NewBitmap ;
@@ -52,27 +49,6 @@ pub use std::io::Error as MmapRegionError;
5249#[ cfg( target_family = "windows" ) ]
5350pub use windows:: MmapRegion ;
5451
55- /// Errors that can occur when creating a memory map.
56- #[ derive( Debug , thiserror:: Error ) ]
57- pub enum Error {
58- /// Adding the guest base address to the length of the underlying mapping resulted
59- /// in an overflow.
60- #[ error( "Adding the guest base address to the length of the underlying mapping resulted in an overflow" ) ]
61- InvalidGuestRegion ,
62- /// Error creating a `MmapRegion` object.
63- #[ error( "{0}" ) ]
64- MmapRegion ( MmapRegionError ) ,
65- /// No memory region found.
66- #[ error( "No memory region found" ) ]
67- NoMemoryRegion ,
68- /// Some of the memory regions intersect with each other.
69- #[ error( "Some of the memory regions intersect with each other" ) ]
70- MemoryRegionOverlap ,
71- /// The provided memory regions haven't been sorted.
72- #[ error( "The provided memory regions haven't been sorted" ) ]
73- UnsortedMemoryRegions ,
74- }
75-
7652// TODO: use this for Windows as well after we redefine the Error type there.
7753#[ cfg( target_family = "unix" ) ]
7854/// Checks if a mapping of `size` bytes fits at the provided `file_offset`.
@@ -369,17 +345,9 @@ impl<B: Bitmap> GuestMemoryRegion for GuestRegionMmap<B> {
369345/// Represents the entire physical memory of the guest by tracking all its memory regions.
370346/// Each region is an instance of `GuestRegionMmap`, being backed by a mapping in the
371347/// virtual address space of the calling process.
372- #[ derive( Clone , Debug , Default ) ]
373- pub struct GuestMemoryMmap < B = ( ) > {
374- regions : Vec < Arc < GuestRegionMmap < B > > > ,
375- }
348+ pub type GuestMemoryMmap < B = ( ) > = GuestRegionCollection < GuestRegionMmap < B > > ;
376349
377350impl < B : NewBitmap > GuestMemoryMmap < B > {
378- /// Creates an empty `GuestMemoryMmap` instance.
379- pub fn new ( ) -> Self {
380- Self :: default ( )
381- }
382-
383351 /// Creates a container and allocates anonymous memory for guest memory regions.
384352 ///
385353 /// Valid memory regions are specified as a slice of (Address, Size) tuples sorted by Address.
@@ -407,111 +375,6 @@ impl<B: NewBitmap> GuestMemoryMmap<B> {
407375 }
408376}
409377
410- impl < B : Bitmap > GuestMemoryMmap < B > {
411- /// Creates a new `GuestMemoryMmap` from a vector of regions.
412- ///
413- /// # Arguments
414- ///
415- /// * `regions` - The vector of regions.
416- /// The regions shouldn't overlap and they should be sorted
417- /// by the starting address.
418- pub fn from_regions ( mut regions : Vec < GuestRegionMmap < B > > ) -> result:: Result < Self , Error > {
419- Self :: from_arc_regions ( regions. drain ( ..) . map ( Arc :: new) . collect ( ) )
420- }
421-
422- /// Creates a new `GuestMemoryMmap` from a vector of Arc regions.
423- ///
424- /// Similar to the constructor `from_regions()` as it returns a
425- /// `GuestMemoryMmap`. The need for this constructor is to provide a way for
426- /// consumer of this API to create a new `GuestMemoryMmap` based on existing
427- /// regions coming from an existing `GuestMemoryMmap` instance.
428- ///
429- /// # Arguments
430- ///
431- /// * `regions` - The vector of `Arc` regions.
432- /// The regions shouldn't overlap and they should be sorted
433- /// by the starting address.
434- pub fn from_arc_regions ( regions : Vec < Arc < GuestRegionMmap < B > > > ) -> result:: Result < Self , Error > {
435- if regions. is_empty ( ) {
436- return Err ( Error :: NoMemoryRegion ) ;
437- }
438-
439- for window in regions. windows ( 2 ) {
440- let prev = & window[ 0 ] ;
441- let next = & window[ 1 ] ;
442-
443- if prev. start_addr ( ) > next. start_addr ( ) {
444- return Err ( Error :: UnsortedMemoryRegions ) ;
445- }
446-
447- if prev. last_addr ( ) >= next. start_addr ( ) {
448- return Err ( Error :: MemoryRegionOverlap ) ;
449- }
450- }
451-
452- Ok ( Self { regions } )
453- }
454-
455- /// Insert a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`.
456- ///
457- /// # Arguments
458- /// * `region`: the memory region to insert into the guest memory object.
459- pub fn insert_region (
460- & self ,
461- region : Arc < GuestRegionMmap < B > > ,
462- ) -> result:: Result < GuestMemoryMmap < B > , Error > {
463- let mut regions = self . regions . clone ( ) ;
464- regions. push ( region) ;
465- regions. sort_by_key ( |x| x. start_addr ( ) ) ;
466-
467- Self :: from_arc_regions ( regions)
468- }
469-
470- /// Remove a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`
471- /// on success, together with the removed region.
472- ///
473- /// # Arguments
474- /// * `base`: base address of the region to be removed
475- /// * `size`: size of the region to be removed
476- pub fn remove_region (
477- & self ,
478- base : GuestAddress ,
479- size : GuestUsize ,
480- ) -> result:: Result < ( GuestMemoryMmap < B > , Arc < GuestRegionMmap < B > > ) , Error > {
481- if let Ok ( region_index) = self . regions . binary_search_by_key ( & base, |x| x. start_addr ( ) ) {
482- if self . regions . get ( region_index) . unwrap ( ) . mapping . size ( ) as GuestUsize == size {
483- let mut regions = self . regions . clone ( ) ;
484- let region = regions. remove ( region_index) ;
485- return Ok ( ( Self { regions } , region) ) ;
486- }
487- }
488-
489- Err ( Error :: InvalidGuestRegion )
490- }
491- }
492-
493- impl < B : Bitmap + ' static > GuestMemory for GuestMemoryMmap < B > {
494- type R = GuestRegionMmap < B > ;
495-
496- fn num_regions ( & self ) -> usize {
497- self . regions . len ( )
498- }
499-
500- fn find_region ( & self , addr : GuestAddress ) -> Option < & GuestRegionMmap < B > > {
501- let index = match self . regions . binary_search_by_key ( & addr, |x| x. start_addr ( ) ) {
502- Ok ( x) => Some ( x) ,
503- // Within the closest region with starting address < addr
504- Err ( x) if ( x > 0 && addr <= self . regions [ x - 1 ] . last_addr ( ) ) => Some ( x - 1 ) ,
505- _ => None ,
506- } ;
507- index. map ( |x| self . regions [ x] . as_ref ( ) )
508- }
509-
510- fn iter ( & self ) -> impl Iterator < Item = & Self :: R > {
511- self . regions . iter ( ) . map ( AsRef :: as_ref)
512- }
513- }
514-
515378#[ cfg( test) ]
516379mod tests {
517380 #![ allow( clippy:: undocumented_unsafe_blocks) ]
@@ -521,16 +384,17 @@ mod tests {
521384
522385 use crate :: bitmap:: tests:: test_guest_memory_and_region;
523386 use crate :: bitmap:: AtomicBitmap ;
524- use crate :: GuestAddressSpace ;
387+ use crate :: { Error , GuestAddressSpace , GuestMemory } ;
525388
526389 use std:: io:: Write ;
527390 use std:: mem;
391+ use std:: sync:: Arc ;
528392 #[ cfg( feature = "rawfd" ) ]
529393 use std:: { fs:: File , path:: Path } ;
530394 use vmm_sys_util:: tempfile:: TempFile ;
531395
532- type GuestMemoryMmap = super :: GuestMemoryMmap < ( ) > ;
533396 type GuestRegionMmap = super :: GuestRegionMmap < ( ) > ;
397+ type GuestMemoryMmap = super :: GuestRegionCollection < GuestRegionMmap > ;
534398 type MmapRegion = super :: MmapRegion < ( ) > ;
535399
536400 #[ test]
@@ -555,9 +419,8 @@ mod tests {
555419 }
556420 assert_eq ! ( guest_mem. last_addr( ) , last_addr) ;
557421 }
558- for ( ( region_addr, region_size) , mmap) in expected_regions_summary
559- . iter ( )
560- . zip ( guest_mem. regions . iter ( ) )
422+ for ( ( region_addr, region_size) , mmap) in
423+ expected_regions_summary. iter ( ) . zip ( guest_mem. iter ( ) )
561424 {
562425 assert_eq ! ( region_addr, & mmap. guest_base) ;
563426 assert_eq ! ( region_size, & mmap. mapping. size( ) ) ;
@@ -748,7 +611,7 @@ mod tests {
748611 let regions_summary = [ ( GuestAddress ( 0 ) , 100_usize ) , ( GuestAddress ( 100 ) , 100_usize ) ] ;
749612
750613 let guest_mem = GuestMemoryMmap :: new ( ) ;
751- assert_eq ! ( guest_mem. regions . len ( ) , 0 ) ;
614+ assert_eq ! ( guest_mem. num_regions ( ) , 0 ) ;
752615
753616 check_guest_memory_mmap ( new_guest_memory_mmap ( & regions_summary) , & regions_summary) ;
754617
@@ -1086,8 +949,10 @@ mod tests {
1086949 . map( |x| ( x. 0 , x. 1 ) )
1087950 . eq( iterated_regions. iter( ) . copied( ) ) ) ;
1088951
1089- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1090- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
952+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
953+
954+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
955+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1091956 }
1092957
1093958 #[ test]
@@ -1115,8 +980,10 @@ mod tests {
1115980 . map( |x| ( x. 0 , x. 1 ) )
1116981 . eq( iterated_regions. iter( ) . copied( ) ) ) ;
1117982
1118- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1119- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
983+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
984+
985+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
986+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1120987 }
1121988
1122989 #[ test]
@@ -1225,11 +1092,13 @@ mod tests {
12251092 assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
12261093 assert_eq ! ( gm. num_regions( ) , 5 ) ;
12271094
1228- assert_eq ! ( gm. regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1229- assert_eq ! ( gm. regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1230- assert_eq ! ( gm. regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1231- assert_eq ! ( gm. regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1232- assert_eq ! ( gm. regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1095+ let regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
1096+
1097+ assert_eq ! ( regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1098+ assert_eq ! ( regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1099+ assert_eq ! ( regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1100+ assert_eq ! ( regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1101+ assert_eq ! ( regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
12331102 }
12341103
12351104 #[ test]
@@ -1250,7 +1119,7 @@ mod tests {
12501119 assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
12511120 assert_eq ! ( gm. num_regions( ) , 1 ) ;
12521121
1253- assert_eq ! ( gm. regions [ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1122+ assert_eq ! ( gm. iter ( ) . next ( ) . unwrap ( ) . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
12541123 assert_eq ! ( region. start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
12551124 }
12561125
0 commit comments