@@ -18,16 +18,13 @@ use std::io::{Seek, SeekFrom};
18
18
use std:: ops:: Deref ;
19
19
use std:: result;
20
20
use std:: sync:: atomic:: Ordering ;
21
- use std:: sync:: Arc ;
22
21
23
22
use crate :: address:: Address ;
24
23
use 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 } ;
28
25
use crate :: region:: GuestMemoryRegion ;
29
26
use crate :: volatile_memory:: { VolatileMemory , VolatileSlice } ;
30
- use crate :: { AtomicAccess , Bytes , ReadVolatile , WriteVolatile } ;
27
+ use crate :: { AtomicAccess , Bytes , Error , GuestRegionCollection , ReadVolatile , WriteVolatile } ;
31
28
32
29
// re-export for backward compat, as the trait used to be defined in mmap.rs
33
30
pub use crate :: bitmap:: NewBitmap ;
@@ -52,27 +49,6 @@ pub use std::io::Error as MmapRegionError;
52
49
#[ cfg( target_family = "windows" ) ]
53
50
pub use windows:: MmapRegion ;
54
51
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
-
76
52
// TODO: use this for Windows as well after we redefine the Error type there.
77
53
#[ cfg( target_family = "unix" ) ]
78
54
/// Checks if a mapping of `size` bytes fits at the provided `file_offset`.
@@ -369,17 +345,9 @@ impl<B: Bitmap> GuestMemoryRegion for GuestRegionMmap<B> {
369
345
/// Represents the entire physical memory of the guest by tracking all its memory regions.
370
346
/// Each region is an instance of `GuestRegionMmap`, being backed by a mapping in the
371
347
/// 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 > > ;
376
349
377
350
impl < B : NewBitmap > GuestMemoryMmap < B > {
378
- /// Creates an empty `GuestMemoryMmap` instance.
379
- pub fn new ( ) -> Self {
380
- Self :: default ( )
381
- }
382
-
383
351
/// Creates a container and allocates anonymous memory for guest memory regions.
384
352
///
385
353
/// Valid memory regions are specified as a slice of (Address, Size) tuples sorted by Address.
@@ -407,111 +375,6 @@ impl<B: NewBitmap> GuestMemoryMmap<B> {
407
375
}
408
376
}
409
377
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
-
515
378
#[ cfg( test) ]
516
379
mod tests {
517
380
#![ allow( clippy:: undocumented_unsafe_blocks) ]
@@ -521,16 +384,17 @@ mod tests {
521
384
522
385
use crate :: bitmap:: tests:: test_guest_memory_and_region;
523
386
use crate :: bitmap:: AtomicBitmap ;
524
- use crate :: GuestAddressSpace ;
387
+ use crate :: { Error , GuestAddressSpace , GuestMemory } ;
525
388
526
389
use std:: io:: Write ;
527
390
use std:: mem;
391
+ use std:: sync:: Arc ;
528
392
#[ cfg( feature = "rawfd" ) ]
529
393
use std:: { fs:: File , path:: Path } ;
530
394
use vmm_sys_util:: tempfile:: TempFile ;
531
395
532
- type GuestMemoryMmap = super :: GuestMemoryMmap < ( ) > ;
533
396
type GuestRegionMmap = super :: GuestRegionMmap < ( ) > ;
397
+ type GuestMemoryMmap = super :: GuestRegionCollection < GuestRegionMmap > ;
534
398
type MmapRegion = super :: MmapRegion < ( ) > ;
535
399
536
400
#[ test]
@@ -555,9 +419,8 @@ mod tests {
555
419
}
556
420
assert_eq ! ( guest_mem. last_addr( ) , last_addr) ;
557
421
}
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 ( ) )
561
424
{
562
425
assert_eq ! ( region_addr, & mmap. guest_base) ;
563
426
assert_eq ! ( region_size, & mmap. mapping. size( ) ) ;
@@ -748,7 +611,7 @@ mod tests {
748
611
let regions_summary = [ ( GuestAddress ( 0 ) , 100_usize ) , ( GuestAddress ( 100 ) , 100_usize ) ] ;
749
612
750
613
let guest_mem = GuestMemoryMmap :: new ( ) ;
751
- assert_eq ! ( guest_mem. regions . len ( ) , 0 ) ;
614
+ assert_eq ! ( guest_mem. num_regions ( ) , 0 ) ;
752
615
753
616
check_guest_memory_mmap ( new_guest_memory_mmap ( & regions_summary) , & regions_summary) ;
754
617
@@ -1086,8 +949,10 @@ mod tests {
1086
949
. map( |x| ( x. 0 , x. 1 ) )
1087
950
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1088
951
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 ) ;
1091
956
}
1092
957
1093
958
#[ test]
@@ -1115,8 +980,10 @@ mod tests {
1115
980
. map( |x| ( x. 0 , x. 1 ) )
1116
981
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1117
982
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 ) ;
1120
987
}
1121
988
1122
989
#[ test]
@@ -1225,11 +1092,13 @@ mod tests {
1225
1092
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1226
1093
assert_eq ! ( gm. num_regions( ) , 5 ) ;
1227
1094
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 ) ) ;
1233
1102
}
1234
1103
1235
1104
#[ test]
@@ -1250,7 +1119,7 @@ mod tests {
1250
1119
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1251
1120
assert_eq ! ( gm. num_regions( ) , 1 ) ;
1252
1121
1253
- assert_eq ! ( gm. regions [ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1122
+ assert_eq ! ( gm. iter ( ) . next ( ) . unwrap ( ) . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1254
1123
assert_eq ! ( region. start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1255
1124
}
1256
1125
0 commit comments