@@ -461,6 +461,43 @@ impl GuestMemoryMmap {
461
461
462
462
Ok ( Self { regions } )
463
463
}
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
+ }
464
501
}
465
502
466
503
impl GuestMemory for GuestMemoryMmap {
@@ -1204,4 +1241,64 @@ mod tests {
1204
1241
assert ! ( region. file_offset( ) . is_some( ) ) ;
1205
1242
assert_eq ! ( region. file_offset( ) . unwrap( ) . start( ) , offset) ;
1206
1243
}
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
+ }
1207
1304
}
0 commit comments