@@ -461,6 +461,43 @@ impl GuestMemoryMmap {
461461
462462 Ok ( Self { regions } )
463463 }
464+
465+ /// Insert a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`.
466+ ///
467+ /// # Arguments
468+ /// * `region`: the memory region to insert into the guest memory object.
469+ pub fn insert_region (
470+ & self ,
471+ region : Arc < GuestRegionMmap > ,
472+ ) -> result:: Result < GuestMemoryMmap , Error > {
473+ let mut regions = self . regions . clone ( ) ;
474+ regions. push ( region) ;
475+ regions. sort_by_key ( |x| x. start_addr ( ) ) ;
476+
477+ Self :: from_arc_regions ( regions)
478+ }
479+
480+ /// Remove a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`
481+ /// on success, together with the removed region.
482+ ///
483+ /// # Arguments
484+ /// * `base`: base address of the region to be removed
485+ /// * `size`: size of the region to be removed
486+ pub fn remove_region (
487+ & self ,
488+ base : GuestAddress ,
489+ size : GuestUsize ,
490+ ) -> result:: Result < ( GuestMemoryMmap , Arc < GuestRegionMmap > ) , Error > {
491+ if let Ok ( region_index) = self . regions . binary_search_by_key ( & base, |x| x. start_addr ( ) ) {
492+ if self . regions . get ( region_index) . unwrap ( ) . size ( ) as GuestUsize == size {
493+ let mut regions = self . regions . clone ( ) ;
494+ let region = regions. remove ( region_index) ;
495+ return Ok ( ( Self { regions } , region) ) ;
496+ }
497+ }
498+
499+ Err ( Error :: InvalidGuestRegion )
500+ }
464501}
465502
466503impl GuestMemory for GuestMemoryMmap {
@@ -1204,4 +1241,64 @@ mod tests {
12041241 assert ! ( region. file_offset( ) . is_some( ) ) ;
12051242 assert_eq ! ( region. file_offset( ) . unwrap( ) . start( ) , offset) ;
12061243 }
1244+
1245+ #[ test]
1246+ fn test_mmap_insert_region ( ) {
1247+ let region_size = 0x1000 ;
1248+ let regions = vec ! [
1249+ ( GuestAddress ( 0x0 ) , region_size) ,
1250+ ( GuestAddress ( 0x10_0000 ) , region_size) ,
1251+ ] ;
1252+ let gm = Arc :: new ( GuestMemoryMmap :: from_ranges ( & regions) . unwrap ( ) ) ;
1253+ let mem_orig = gm. memory ( ) ;
1254+ assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1255+
1256+ let mmap = Arc :: new (
1257+ GuestRegionMmap :: new ( MmapRegion :: new ( 0x1000 ) . unwrap ( ) , GuestAddress ( 0x8000 ) ) . unwrap ( ) ,
1258+ ) ;
1259+ let gm = gm. insert_region ( mmap) . unwrap ( ) ;
1260+ let mmap = Arc :: new (
1261+ GuestRegionMmap :: new ( MmapRegion :: new ( 0x1000 ) . unwrap ( ) , GuestAddress ( 0x4000 ) ) . unwrap ( ) ,
1262+ ) ;
1263+ let gm = gm. insert_region ( mmap) . unwrap ( ) ;
1264+ let mmap = Arc :: new (
1265+ GuestRegionMmap :: new ( MmapRegion :: new ( 0x1000 ) . unwrap ( ) , GuestAddress ( 0xc000 ) ) . unwrap ( ) ,
1266+ ) ;
1267+ let gm = gm. insert_region ( mmap) . unwrap ( ) ;
1268+ let mmap = Arc :: new (
1269+ GuestRegionMmap :: new ( MmapRegion :: new ( 0x1000 ) . unwrap ( ) , GuestAddress ( 0xc000 ) ) . unwrap ( ) ,
1270+ ) ;
1271+ gm. insert_region ( mmap) . unwrap_err ( ) ;
1272+
1273+ assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1274+ assert_eq ! ( gm. num_regions( ) , 5 ) ;
1275+
1276+ assert_eq ! ( gm. regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1277+ assert_eq ! ( gm. regions[ 1 ] . start_addr( ) , GuestAddress ( 0x4000 ) ) ;
1278+ assert_eq ! ( gm. regions[ 2 ] . start_addr( ) , GuestAddress ( 0x8000 ) ) ;
1279+ assert_eq ! ( gm. regions[ 3 ] . start_addr( ) , GuestAddress ( 0xc000 ) ) ;
1280+ assert_eq ! ( gm. regions[ 4 ] . start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1281+ }
1282+
1283+ #[ test]
1284+ fn test_mmap_remove_region ( ) {
1285+ let region_size = 0x1000 ;
1286+ let regions = vec ! [
1287+ ( GuestAddress ( 0x0 ) , region_size) ,
1288+ ( GuestAddress ( 0x10_0000 ) , region_size) ,
1289+ ] ;
1290+ let gm = Arc :: new ( GuestMemoryMmap :: from_ranges ( & regions) . unwrap ( ) ) ;
1291+ let mem_orig = gm. memory ( ) ;
1292+ assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1293+
1294+ gm. remove_region ( GuestAddress ( 0 ) , 128 ) . unwrap_err ( ) ;
1295+ gm. remove_region ( GuestAddress ( 0x4000 ) , 128 ) . unwrap_err ( ) ;
1296+ let ( gm, region) = gm. remove_region ( GuestAddress ( 0x10_0000 ) , 0x1000 ) . unwrap ( ) ;
1297+
1298+ assert_eq ! ( mem_orig. num_regions( ) , 2 ) ;
1299+ assert_eq ! ( gm. num_regions( ) , 1 ) ;
1300+
1301+ assert_eq ! ( gm. regions[ 0 ] . start_addr( ) , GuestAddress ( 0x0000 ) ) ;
1302+ assert_eq ! ( region. start_addr( ) , GuestAddress ( 0x10_0000 ) ) ;
1303+ }
12071304}
0 commit comments