@@ -16,16 +16,13 @@ use std::borrow::Borrow;
1616use std:: ops:: Deref ;
1717use std:: result;
1818use std:: sync:: atomic:: Ordering ;
19- use std:: sync:: Arc ;
2019
2120use crate :: address:: Address ;
2221use 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 } ;
2623use crate :: region:: GuestMemoryRegion ;
2724use crate :: volatile_memory:: { VolatileMemory , VolatileSlice } ;
28- use crate :: { AtomicAccess , Bytes , ReadVolatile , WriteVolatile } ;
25+ use crate :: { AtomicAccess , Bytes , Error , GuestRegionCollection , ReadVolatile , WriteVolatile } ;
2926
3027// re-export for backward compat, as the trait used to be defined in mmap.rs
3128pub use crate :: bitmap:: NewBitmap ;
@@ -50,27 +47,6 @@ pub use std::io::Error as MmapRegionError;
5047#[ cfg( target_family = "windows" ) ]
5148pub use windows:: MmapRegion ;
5249
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-
7450/// [`GuestMemoryRegion`](trait.GuestMemoryRegion.html) implementation that mmaps the guest's
7551/// memory region in the current process.
7652///
@@ -339,17 +315,9 @@ impl<B: Bitmap> GuestMemoryRegion for GuestRegionMmap<B> {
339315/// Represents the entire physical memory of the guest by tracking all its memory regions.
340316/// Each region is an instance of `GuestRegionMmap`, being backed by a mapping in the
341317/// virtual address space of the calling process.
342- #[ derive( Clone , Debug , Default ) ]
343- pub struct GuestMemoryMmap < B = ( ) > {
344- regions : Vec < Arc < GuestRegionMmap < B > > > ,
345- }
318+ pub type GuestMemoryMmap < B = ( ) > = GuestRegionCollection < GuestRegionMmap < B > > ;
346319
347320impl < B : NewBitmap > GuestMemoryMmap < B > {
348- /// Creates an empty `GuestMemoryMmap` instance.
349- pub fn new ( ) -> Self {
350- Self :: default ( )
351- }
352-
353321 /// Creates a container and allocates anonymous memory for guest memory regions.
354322 ///
355323 /// Valid memory regions are specified as a slice of (Address, Size) tuples sorted by Address.
@@ -377,111 +345,6 @@ impl<B: NewBitmap> GuestMemoryMmap<B> {
377345 }
378346}
379347
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-
485348#[ cfg( test) ]
486349mod tests {
487350 #![ allow( clippy:: undocumented_unsafe_blocks) ]
@@ -491,16 +354,17 @@ mod tests {
491354
492355 use crate :: bitmap:: tests:: test_guest_memory_and_region;
493356 use crate :: bitmap:: AtomicBitmap ;
494- use crate :: GuestAddressSpace ;
357+ use crate :: { Error , GuestAddressSpace , GuestMemory } ;
495358
496359 use std:: io:: Write ;
497360 use std:: mem;
361+ use std:: sync:: Arc ;
498362 #[ cfg( feature = "rawfd" ) ]
499363 use std:: { fs:: File , path:: Path } ;
500364 use vmm_sys_util:: tempfile:: TempFile ;
501365
502- type GuestMemoryMmap = super :: GuestMemoryMmap < ( ) > ;
503366 type GuestRegionMmap = super :: GuestRegionMmap < ( ) > ;
367+ type GuestMemoryMmap = super :: GuestRegionCollection < GuestRegionMmap > ;
504368 type MmapRegion = super :: MmapRegion < ( ) > ;
505369
506370 #[ test]
@@ -525,9 +389,8 @@ mod tests {
525389 }
526390 assert_eq ! ( guest_mem. last_addr( ) , last_addr) ;
527391 }
528- for ( ( region_addr, region_size) , mmap) in expected_regions_summary
529- . iter ( )
530- . zip ( guest_mem. regions . iter ( ) )
392+ for ( ( region_addr, region_size) , mmap) in
393+ expected_regions_summary. iter ( ) . zip ( guest_mem. iter ( ) )
531394 {
532395 assert_eq ! ( region_addr, & mmap. guest_base) ;
533396 assert_eq ! ( region_size, & mmap. mapping. size( ) ) ;
@@ -718,7 +581,7 @@ mod tests {
718581 let regions_summary = [ ( GuestAddress ( 0 ) , 100_usize ) , ( GuestAddress ( 100 ) , 100_usize ) ] ;
719582
720583 let guest_mem = GuestMemoryMmap :: new ( ) ;
721- assert_eq ! ( guest_mem. regions . len ( ) , 0 ) ;
584+ assert_eq ! ( guest_mem. num_regions ( ) , 0 ) ;
722585
723586 check_guest_memory_mmap ( new_guest_memory_mmap ( & regions_summary) , & regions_summary) ;
724587
@@ -1056,8 +919,10 @@ mod tests {
1056919 . map( |x| ( x. 0 , x. 1 ) )
1057920 . eq( iterated_regions. iter( ) . copied( ) ) ) ;
1058921
1059- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1060- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
922+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
923+
924+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
925+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1061926 }
1062927
1063928 #[ test]
@@ -1085,8 +950,10 @@ mod tests {
1085950 . map( |x| ( x. 0 , x. 1 ) )
1086951 . eq( iterated_regions. iter( ) . copied( ) ) ) ;
1087952
1088- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1089- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
953+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
954+
955+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
956+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1090957 }
1091958
1092959 #[ test]
@@ -1195,11 +1062,13 @@ mod tests {
11951062 assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
11961063 assert_eq ! ( gm. num_regions( ) , 5 ) ;
11971064
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 ) ) ;
1065+ let regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
1066+
1067+ assert_eq ! ( regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1068+ assert_eq ! ( regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1069+ assert_eq ! ( regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1070+ assert_eq ! ( regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1071+ assert_eq ! ( regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
12031072 }
12041073
12051074 #[ test]
@@ -1220,7 +1089,7 @@ mod tests {
12201089 assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
12211090 assert_eq ! ( gm. num_regions( ) , 1 ) ;
12221091
1223- assert_eq ! ( gm. regions [ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1092+ assert_eq ! ( gm. iter ( ) . next ( ) . unwrap ( ) . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
12241093 assert_eq ! ( region. start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
12251094 }
12261095
0 commit comments