66// found in the THIRD-PARTY file.
77
88use std:: fs:: File ;
9+ use std:: io;
910use std:: io:: SeekFrom ;
1011use std:: ops:: Deref ;
1112use std:: sync:: { Arc , Mutex } ;
@@ -22,12 +23,12 @@ pub use vm_memory::{
2223} ;
2324use vm_memory:: { GuestMemoryError , GuestMemoryRegionBytes , VolatileSlice , WriteVolatile } ;
2425
25- use crate :: DirtyBitmap ;
2626use crate :: arch:: host_page_size;
2727use crate :: logger:: error;
2828use crate :: utils:: u64_to_usize;
2929use crate :: vmm_config:: machine_config:: HugePageConfig ;
3030use crate :: vstate:: vm:: { KvmVm , VmError } ;
31+ use crate :: { DirtyBitmap , warn_unrestricted} ;
3132
3233/// Type of GuestRegionMmap.
3334pub type GuestRegionMmap = vm_memory:: GuestRegionMmap < Option < AtomicBitmap > > ;
@@ -528,6 +529,7 @@ pub fn create(
528529 mmap_flags : libc:: c_int ,
529530 file : Option < File > ,
530531 track_dirty_pages : bool ,
532+ madvise_flags : libc:: c_int ,
531533) -> Result < Vec < GuestRegionMmap > , MemoryError > {
532534 let mut offset = 0 ;
533535 let file = file. map ( Arc :: new) ;
@@ -559,6 +561,18 @@ pub fn create(
559561 start,
560562 )
561563 . ok_or ( MemoryError :: VmMemoryError )
564+ . inspect ( |region| {
565+ if madvise_flags != libc:: MADV_NORMAL {
566+ // SAFETY: The referenced memory was just mapped.
567+ let ret = unsafe {
568+ libc:: madvise ( region. as_ptr ( ) . cast ( ) , region. size ( ) , madvise_flags)
569+ } ;
570+ if ret != 0 {
571+ let e = io:: Error :: last_os_error ( ) ;
572+ warn_unrestricted ! ( "Madvise call failed for guest memory: {e}" ) ;
573+ }
574+ }
575+ } )
562576 } )
563577 . collect :: < Result < Vec < _ > , _ > > ( )
564578}
@@ -577,6 +591,7 @@ pub fn memfd_backed(
577591 libc:: MAP_SHARED | huge_pages. mmap_flags ( ) ,
578592 Some ( memfd_file) ,
579593 track_dirty_pages,
594+ huge_pages. madvise_flags ( ) ,
580595 )
581596}
582597
@@ -591,6 +606,7 @@ pub fn anonymous(
591606 libc:: MAP_PRIVATE | libc:: MAP_ANONYMOUS | huge_pages. mmap_flags ( ) ,
592607 None ,
593608 track_dirty_pages,
609+ huge_pages. madvise_flags ( ) ,
594610 )
595611}
596612
@@ -600,6 +616,7 @@ pub fn snapshot_file(
600616 file : File ,
601617 regions : impl Iterator < Item = ( GuestAddress , usize ) > ,
602618 track_dirty_pages : bool ,
619+ huge_pages : HugePageConfig ,
603620) -> Result < Vec < GuestRegionMmap > , MemoryError > {
604621 let regions: Vec < _ > = regions. collect ( ) ;
605622 let memory_size = regions
@@ -619,6 +636,7 @@ pub fn snapshot_file(
619636 libc:: MAP_PRIVATE ,
620637 Some ( file) ,
621638 track_dirty_pages,
639+ huge_pages. madvise_flags ( ) ,
622640 )
623641}
624642
@@ -951,8 +969,13 @@ mod tests {
951969 file. write_all ( & vec ! [ 0x42u8 ; page_size] ) . unwrap ( ) ;
952970
953971 let regions = vec ! [ ( GuestAddress ( 0 ) , page_size) ] ;
954- let guest_regions =
955- snapshot_file ( file, regions. into_iter ( ) , dirty_page_tracking) . unwrap ( ) ;
972+ let guest_regions = snapshot_file (
973+ file,
974+ regions. into_iter ( ) ,
975+ dirty_page_tracking,
976+ HugePageConfig :: None ,
977+ )
978+ . unwrap ( ) ;
956979 assert_eq ! ( guest_regions. len( ) , 1 ) ;
957980 guest_regions. iter ( ) . for_each ( |region| {
958981 assert_eq ! ( region. bitmap( ) . is_some( ) , dirty_page_tracking) ;
@@ -973,7 +996,8 @@ mod tests {
973996 ( GuestAddress ( 0x10000 ) , page_size) ,
974997 ( GuestAddress ( 0x20000 ) , page_size) ,
975998 ] ;
976- let guest_regions = snapshot_file ( file, regions. into_iter ( ) , false ) . unwrap ( ) ;
999+ let guest_regions =
1000+ snapshot_file ( file, regions. into_iter ( ) , false , HugePageConfig :: None ) . unwrap ( ) ;
9771001 assert_eq ! ( guest_regions. len( ) , 3 ) ;
9781002 }
9791003
@@ -985,7 +1009,7 @@ mod tests {
9851009 file. write_all ( & vec ! [ 0x42u8 ; page_size] ) . unwrap ( ) ;
9861010
9871011 let regions = vec ! [ ( GuestAddress ( 0 ) , 2 * page_size) ] ;
988- let result = snapshot_file ( file, regions. into_iter ( ) , false ) ;
1012+ let result = snapshot_file ( file, regions. into_iter ( ) , false , HugePageConfig :: None ) ;
9891013 assert ! ( matches!( result. unwrap_err( ) , MemoryError :: OffsetTooLarge ) ) ;
9901014 }
9911015
@@ -1175,8 +1199,15 @@ mod tests {
11751199 let mut memory_file = TempFile :: new ( ) . unwrap ( ) . into_file ( ) ;
11761200 guest_memory. dump ( & mut memory_file) . unwrap ( ) ;
11771201
1178- let restored_guest_memory =
1179- into_region_ext ( snapshot_file ( memory_file, memory_state. regions ( ) , false ) . unwrap ( ) ) ;
1202+ let restored_guest_memory = into_region_ext (
1203+ snapshot_file (
1204+ memory_file,
1205+ memory_state. regions ( ) ,
1206+ false ,
1207+ HugePageConfig :: None ,
1208+ )
1209+ . unwrap ( ) ,
1210+ ) ;
11801211
11811212 // Check that the region contents are the same.
11821213 let mut restored_region = vec ! [ 0u8 ; page_size * 2 ] ;
@@ -1240,8 +1271,9 @@ mod tests {
12401271 . unwrap ( ) ;
12411272
12421273 // We can restore from this because this is the first dirty dump.
1243- let restored_guest_memory =
1244- into_region_ext ( snapshot_file ( file, memory_state. regions ( ) , false ) . unwrap ( ) ) ;
1274+ let restored_guest_memory = into_region_ext (
1275+ snapshot_file ( file, memory_state. regions ( ) , false , HugePageConfig :: None ) . unwrap ( ) ,
1276+ ) ;
12451277
12461278 // Check that the region contents are the same.
12471279 let mut restored_region = vec ! [ 0u8 ; region_size] ;
@@ -1465,6 +1497,7 @@ mod tests {
14651497 memory_file,
14661498 std:: iter:: once ( ( GuestAddress ( 0 ) , 2 * page_size) ) ,
14671499 false ,
1500+ HugePageConfig :: None ,
14681501 )
14691502 . unwrap ( ) ,
14701503 ) ;
0 commit comments