@@ -25,7 +25,7 @@ use crate::vstate::memory::{
2525 Address , GuestMemory , GuestMemoryExtension , GuestMemoryMmap , GuestMemoryRegion , GuestRegionMmap ,
2626} ;
2727use crate :: vstate:: vcpu:: VcpuError ;
28- use crate :: { DirtyBitmap , Vcpu , mem_size_mib} ;
28+ use crate :: { DirtyBitmap , Vcpu , logger , mem_size_mib} ;
2929
3030/// Architecture independent parts of a VM.
3131#[ derive( Debug ) ]
@@ -285,6 +285,20 @@ impl Vm {
285285/// Use `mincore(2)` to overapproximate the dirty bitmap for the given memslot. To be used
286286/// if a diff snapshot is requested, but dirty page tracking wasn't enabled.
287287fn mincore_bitmap ( region : & GuestRegionMmap ) -> Result < Vec < u64 > , vmm_sys_util:: errno:: Error > {
288+ // SAFETY: GuestRegionMmap ensures the pointer+len pair is valid. `flags` has no impact
289+ // on safety from the rust perspective.
290+ let r = unsafe {
291+ libc:: mlock2 (
292+ region. as_ptr ( ) . cast ( ) ,
293+ u64_to_usize ( region. len ( ) ) ,
294+ libc:: MLOCK_ONFAULT ,
295+ )
296+ } ;
297+
298+ if r != 0 {
299+ return vmm_sys_util:: errno:: errno_result ( ) ;
300+ }
301+
288302 // Mincore always works at PAGE_SIZE granularity, even if the VMA we are dealing with
289303 // is a hugetlbfs VMA (e.g. to report a single hugepage as "present", mincore will
290304 // give us 512 4k markers with the lowest bit set).
@@ -314,6 +328,14 @@ fn mincore_bitmap(region: &GuestRegionMmap) -> Result<Vec<u64>, vmm_sys_util::er
314328 bitmap[ page_idx / 64 ] |= ( * b as u64 & 0x1 ) << ( page_idx as u64 % 64 ) ;
315329 }
316330
331+ // SAFETY: GuestRegionMmap ensures the pointer+len pair is valid
332+ let r = unsafe { libc:: munlock ( region. as_ptr ( ) . cast ( ) , u64_to_usize ( region. len ( ) ) ) } ;
333+
334+ if r != 0 {
335+ // Not ideal, but nothing to fail snapshot creation over.
336+ logger:: error!( "Failed to munlock guest memory after mincore snapshot!" ) ;
337+ }
338+
317339 Ok ( bitmap)
318340}
319341
0 commit comments