Skip to content

Commit 31dc205

Browse files
committed
tmp: swap in memory before taking snapshot
Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent 8f6641c commit 31dc205

File tree

4 files changed

+37
-1
lines changed

4 files changed

+37
-1
lines changed

resources/seccomp/aarch64-unknown-linux-musl.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
{
3232
"syscall": "mincore"
3333
},
34+
{
35+
"syscall": "mlock2"
36+
},
37+
{
38+
"syscall": "munlock"
39+
},
3440
{
3541
"syscall": "writev",
3642
"comment": "Used by the VirtIO net device to write to tap"

resources/seccomp/x86_64-unknown-linux-musl.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
{
3232
"syscall": "mincore"
3333
},
34+
{
35+
"syscall": "mlock2"
36+
},
37+
{
38+
"syscall": "munlock"
39+
},
3440
{
3541
"syscall": "writev",
3642
"comment": "Used by the VirtIO net device to write to tap"

src/vmm/src/persist.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ pub enum CreateSnapshotError {
145145
SerializeMicrovmState(#[from] crate::snapshot::SnapshotError),
146146
/// Cannot perform {0} on the snapshot backing file: {1}
147147
SnapshotBackingFile(&'static str, io::Error),
148+
/// Error locking memory into RAM for snapshotting
149+
Mlock(#[from] io::Error),
148150
}
149151

150152
/// Snapshot version

src/vmm/src/vstate/vm.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::vstate::memory::{
2525
Address, GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryRegion, GuestRegionMmap,
2626
};
2727
use 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.
287287
fn 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

Comments
 (0)