@@ -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
#[ cfg( all( not( feature = "xen" ) , unix) ) ]
33
30
pub use crate :: mmap_unix:: { Error as MmapRegionError , MmapRegion , MmapRegionBuilder } ;
@@ -50,27 +47,6 @@ impl NewBitmap for () {
50
47
fn with_len ( _len : usize ) -> Self { }
51
48
}
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
// TODO: use this for Windows as well after we redefine the Error type there.
75
51
#[ cfg( unix) ]
76
52
/// Checks if a mapping of `size` bytes fits at the provided `file_offset`.
@@ -367,17 +343,9 @@ impl<B: Bitmap> GuestMemoryRegion for GuestRegionMmap<B> {
367
343
/// Represents the entire physical memory of the guest by tracking all its memory regions.
368
344
/// Each region is an instance of `GuestRegionMmap`, being backed by a mapping in the
369
345
/// virtual address space of the calling process.
370
- #[ derive( Clone , Debug , Default ) ]
371
- pub struct GuestMemoryMmap < B = ( ) > {
372
- regions : Vec < Arc < GuestRegionMmap < B > > > ,
373
- }
346
+ pub type GuestMemoryMmap < B = ( ) > = GuestRegionCollection < GuestRegionMmap < B > > ;
374
347
375
348
impl < B : NewBitmap > GuestMemoryMmap < B > {
376
- /// Creates an empty `GuestMemoryMmap` instance.
377
- pub fn new ( ) -> Self {
378
- Self :: default ( )
379
- }
380
-
381
349
/// Creates a container and allocates anonymous memory for guest memory regions.
382
350
///
383
351
/// Valid memory regions are specified as a slice of (Address, Size) tuples sorted by Address.
@@ -405,111 +373,6 @@ impl<B: NewBitmap> GuestMemoryMmap<B> {
405
373
}
406
374
}
407
375
408
- impl < B : Bitmap > GuestMemoryMmap < B > {
409
- /// Creates a new `GuestMemoryMmap` from a vector of regions.
410
- ///
411
- /// # Arguments
412
- ///
413
- /// * `regions` - The vector of regions.
414
- /// The regions shouldn't overlap and they should be sorted
415
- /// by the starting address.
416
- pub fn from_regions ( mut regions : Vec < GuestRegionMmap < B > > ) -> result:: Result < Self , Error > {
417
- Self :: from_arc_regions ( regions. drain ( ..) . map ( Arc :: new) . collect ( ) )
418
- }
419
-
420
- /// Creates a new `GuestMemoryMmap` from a vector of Arc regions.
421
- ///
422
- /// Similar to the constructor `from_regions()` as it returns a
423
- /// `GuestMemoryMmap`. The need for this constructor is to provide a way for
424
- /// consumer of this API to create a new `GuestMemoryMmap` based on existing
425
- /// regions coming from an existing `GuestMemoryMmap` instance.
426
- ///
427
- /// # Arguments
428
- ///
429
- /// * `regions` - The vector of `Arc` regions.
430
- /// The regions shouldn't overlap and they should be sorted
431
- /// by the starting address.
432
- pub fn from_arc_regions ( regions : Vec < Arc < GuestRegionMmap < B > > > ) -> result:: Result < Self , Error > {
433
- if regions. is_empty ( ) {
434
- return Err ( Error :: NoMemoryRegion ) ;
435
- }
436
-
437
- for window in regions. windows ( 2 ) {
438
- let prev = & window[ 0 ] ;
439
- let next = & window[ 1 ] ;
440
-
441
- if prev. start_addr ( ) > next. start_addr ( ) {
442
- return Err ( Error :: UnsortedMemoryRegions ) ;
443
- }
444
-
445
- if prev. last_addr ( ) >= next. start_addr ( ) {
446
- return Err ( Error :: MemoryRegionOverlap ) ;
447
- }
448
- }
449
-
450
- Ok ( Self { regions } )
451
- }
452
-
453
- /// Insert a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`.
454
- ///
455
- /// # Arguments
456
- /// * `region`: the memory region to insert into the guest memory object.
457
- pub fn insert_region (
458
- & self ,
459
- region : Arc < GuestRegionMmap < B > > ,
460
- ) -> result:: Result < GuestMemoryMmap < B > , Error > {
461
- let mut regions = self . regions . clone ( ) ;
462
- regions. push ( region) ;
463
- regions. sort_by_key ( |x| x. start_addr ( ) ) ;
464
-
465
- Self :: from_arc_regions ( regions)
466
- }
467
-
468
- /// Remove a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`
469
- /// on success, together with the removed region.
470
- ///
471
- /// # Arguments
472
- /// * `base`: base address of the region to be removed
473
- /// * `size`: size of the region to be removed
474
- pub fn remove_region (
475
- & self ,
476
- base : GuestAddress ,
477
- size : GuestUsize ,
478
- ) -> result:: Result < ( GuestMemoryMmap < B > , Arc < GuestRegionMmap < B > > ) , Error > {
479
- if let Ok ( region_index) = self . regions . binary_search_by_key ( & base, |x| x. start_addr ( ) ) {
480
- if self . regions . get ( region_index) . unwrap ( ) . mapping . size ( ) as GuestUsize == size {
481
- let mut regions = self . regions . clone ( ) ;
482
- let region = regions. remove ( region_index) ;
483
- return Ok ( ( Self { regions } , region) ) ;
484
- }
485
- }
486
-
487
- Err ( Error :: InvalidGuestRegion )
488
- }
489
- }
490
-
491
- impl < B : Bitmap + ' static > GuestMemory for GuestMemoryMmap < B > {
492
- type R = GuestRegionMmap < B > ;
493
-
494
- fn num_regions ( & self ) -> usize {
495
- self . regions . len ( )
496
- }
497
-
498
- fn find_region ( & self , addr : GuestAddress ) -> Option < & GuestRegionMmap < B > > {
499
- let index = match self . regions . binary_search_by_key ( & addr, |x| x. start_addr ( ) ) {
500
- Ok ( x) => Some ( x) ,
501
- // Within the closest region with starting address < addr
502
- Err ( x) if ( x > 0 && addr <= self . regions [ x - 1 ] . last_addr ( ) ) => Some ( x - 1 ) ,
503
- _ => None ,
504
- } ;
505
- index. map ( |x| self . regions [ x] . as_ref ( ) )
506
- }
507
-
508
- fn iter ( & self ) -> impl Iterator < Item = & Self :: R > {
509
- self . regions . iter ( ) . map ( AsRef :: as_ref)
510
- }
511
- }
512
-
513
376
#[ cfg( test) ]
514
377
mod tests {
515
378
#![ allow( clippy:: undocumented_unsafe_blocks) ]
@@ -519,16 +382,17 @@ mod tests {
519
382
520
383
use crate :: bitmap:: tests:: test_guest_memory_and_region;
521
384
use crate :: bitmap:: AtomicBitmap ;
522
- use crate :: GuestAddressSpace ;
385
+ use crate :: { Error , GuestAddressSpace , GuestMemory } ;
523
386
524
387
use std:: io:: Write ;
525
388
use std:: mem;
389
+ use std:: sync:: Arc ;
526
390
#[ cfg( feature = "rawfd" ) ]
527
391
use std:: { fs:: File , path:: Path } ;
528
392
use vmm_sys_util:: tempfile:: TempFile ;
529
393
530
- type GuestMemoryMmap = super :: GuestMemoryMmap < ( ) > ;
531
394
type GuestRegionMmap = super :: GuestRegionMmap < ( ) > ;
395
+ type GuestMemoryMmap = super :: GuestRegionCollection < GuestRegionMmap > ;
532
396
type MmapRegion = super :: MmapRegion < ( ) > ;
533
397
534
398
#[ test]
@@ -553,9 +417,8 @@ mod tests {
553
417
}
554
418
assert_eq ! ( guest_mem. last_addr( ) , last_addr) ;
555
419
}
556
- for ( ( region_addr, region_size) , mmap) in expected_regions_summary
557
- . iter ( )
558
- . zip ( guest_mem. regions . iter ( ) )
420
+ for ( ( region_addr, region_size) , mmap) in
421
+ expected_regions_summary. iter ( ) . zip ( guest_mem. iter ( ) )
559
422
{
560
423
assert_eq ! ( region_addr, & mmap. guest_base) ;
561
424
assert_eq ! ( region_size, & mmap. mapping. size( ) ) ;
@@ -746,7 +609,7 @@ mod tests {
746
609
let regions_summary = [ ( GuestAddress ( 0 ) , 100_usize ) , ( GuestAddress ( 100 ) , 100_usize ) ] ;
747
610
748
611
let guest_mem = GuestMemoryMmap :: new ( ) ;
749
- assert_eq ! ( guest_mem. regions . len ( ) , 0 ) ;
612
+ assert_eq ! ( guest_mem. num_regions ( ) , 0 ) ;
750
613
751
614
check_guest_memory_mmap ( new_guest_memory_mmap ( & regions_summary) , & regions_summary) ;
752
615
@@ -1084,8 +947,10 @@ mod tests {
1084
947
. map( |x| ( x. 0 , x. 1 ) )
1085
948
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1086
949
1087
- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1088
- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
950
+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
951
+
952
+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
953
+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1089
954
}
1090
955
1091
956
#[ test]
@@ -1113,8 +978,10 @@ mod tests {
1113
978
. map( |x| ( x. 0 , x. 1 ) )
1114
979
. eq( iterated_regions. iter( ) . copied( ) ) ) ;
1115
980
1116
- assert_eq ! ( gm. regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
1117
- assert_eq ! ( gm. regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
981
+ let mmap_regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
982
+
983
+ assert_eq ! ( mmap_regions[ 0 ] . guest_base, regions[ 0 ] . 0 ) ;
984
+ assert_eq ! ( mmap_regions[ 1 ] . guest_base, regions[ 1 ] . 0 ) ;
1118
985
}
1119
986
1120
987
#[ test]
@@ -1223,11 +1090,13 @@ mod tests {
1223
1090
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1224
1091
assert_eq ! ( gm. num_regions( ) , 5 ) ;
1225
1092
1226
- assert_eq ! ( gm. regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1227
- assert_eq ! ( gm. regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1228
- assert_eq ! ( gm. regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1229
- assert_eq ! ( gm. regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1230
- assert_eq ! ( gm. regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1093
+ let regions = gm. iter ( ) . collect :: < Vec < _ > > ( ) ;
1094
+
1095
+ assert_eq ! ( regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1096
+ assert_eq ! ( regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1097
+ assert_eq ! ( regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1098
+ assert_eq ! ( regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1099
+ assert_eq ! ( regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1231
1100
}
1232
1101
1233
1102
#[ test]
@@ -1248,7 +1117,7 @@ mod tests {
1248
1117
assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1249
1118
assert_eq ! ( gm. num_regions( ) , 1 ) ;
1250
1119
1251
- assert_eq ! ( gm. regions [ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1120
+ assert_eq ! ( gm. iter ( ) . next ( ) . unwrap ( ) . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1252
1121
assert_eq ! ( region. start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1253
1122
}
1254
1123
0 commit comments