@@ -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,27 +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
-
74
50
/// [`GuestMemoryRegion`](trait.GuestMemoryRegion.html) implementation that mmaps the guest's
75
51
/// memory region in the current process.
76
52
///
@@ -339,17 +315,9 @@ impl<B: Bitmap> GuestMemoryRegion for GuestRegionMmap<B> {
339
315
/// Represents the entire physical memory of the guest by tracking all its memory regions.
340
316
/// Each region is an instance of `GuestRegionMmap`, being backed by a mapping in the
341
317
/// 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 > > ;
346
319
347
320
impl < B : NewBitmap > GuestMemoryMmap < B > {
348
- /// Creates an empty `GuestMemoryMmap` instance.
349
- pub fn new ( ) -> Self {
350
- Self :: default ( )
351
- }
352
-
353
321
/// Creates a container and allocates anonymous memory for guest memory regions.
354
322
///
355
323
/// Valid memory regions are specified as a slice of (Address, Size) tuples sorted by Address.
@@ -377,111 +345,6 @@ impl<B: NewBitmap> GuestMemoryMmap<B> {
377
345
}
378
346
}
379
347
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
348
#[ cfg( test) ]
486
349
mod tests {
487
350
#![ allow( clippy:: undocumented_unsafe_blocks) ]
@@ -491,16 +354,17 @@ mod tests {
491
354
492
355
use crate :: bitmap:: tests:: test_guest_memory_and_region;
493
356
use crate :: bitmap:: AtomicBitmap ;
494
- use crate :: GuestAddressSpace ;
357
+ use crate :: { Error , GuestAddressSpace , GuestMemory } ;
495
358
496
359
use std:: io:: Write ;
497
360
use std:: mem;
361
+ use std:: sync:: Arc ;
498
362
#[ cfg( feature = "rawfd" ) ]
499
363
use std:: { fs:: File , path:: Path } ;
500
364
use vmm_sys_util:: tempfile:: TempFile ;
501
365
502
- type GuestMemoryMmap = super :: GuestMemoryMmap < ( ) > ;
503
366
type GuestRegionMmap = super :: GuestRegionMmap < ( ) > ;
367
+ type GuestMemoryMmap = super :: GuestRegionCollection < GuestRegionMmap > ;
504
368
type MmapRegion = super :: MmapRegion < ( ) > ;
505
369
506
370
#[ test]
@@ -525,9 +389,8 @@ mod tests {
525
389
}
526
390
assert_eq ! ( guest_mem. last_addr( ) , last_addr) ;
527
391
}
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 ( ) )
531
394
{
532
395
assert_eq ! ( region_addr, & mmap. guest_base) ;
533
396
assert_eq ! ( region_size, & mmap. mapping. size( ) ) ;
@@ -718,7 +581,7 @@ mod tests {
718
581
let regions_summary = [ ( GuestAddress ( 0 ) , 100_usize ) , ( GuestAddress ( 100 ) , 100_usize ) ] ;
719
582
720
583
let guest_mem = GuestMemoryMmap :: new ( ) ;
721
- assert_eq ! ( guest_mem. regions . len ( ) , 0 ) ;
584
+ assert_eq ! ( guest_mem. num_regions ( ) , 0 ) ;
722
585
723
586
check_guest_memory_mmap ( new_guest_memory_mmap ( & regions_summary) , & regions_summary) ;
724
587
@@ -1056,8 +919,10 @@ mod tests {
1056
919
. map( |x| ( x. 0 , x. 1 ) )
1057
920
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1058
921
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 ) ;
1061
926
}
1062
927
1063
928
#[ test]
@@ -1085,8 +950,10 @@ mod tests {
1085
950
. map( |x| ( x. 0 , x. 1 ) )
1086
951
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1087
952
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 ) ;
1090
957
}
1091
958
1092
959
#[ test]
@@ -1195,11 +1062,13 @@ mod tests {
1195
1062
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1196
1063
assert_eq ! ( gm. num_regions( ) , 5 ) ;
1197
1064
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 ) ) ;
1203
1072
}
1204
1073
1205
1074
#[ test]
@@ -1220,7 +1089,7 @@ mod tests {
1220
1089
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1221
1090
assert_eq ! ( gm. num_regions( ) , 1 ) ;
1222
1091
1223
- assert_eq ! ( gm. regions [ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1092
+ assert_eq ! ( gm. iter ( ) . next ( ) . unwrap ( ) . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1224
1093
assert_eq ! ( region. start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1225
1094
}
1226
1095
0 commit comments