Skip to content

Commit 00bd615

Browse files
committed
Snapshot restore for swiotlb regions
Support restoring VMs with swiotlb regions. For this, untangle the uffd handshake from the actual restoration of memory regions, as we first need to restore and register to the Vm _all_ memory regions, before we can then send a single handshake containing both normal and swiotlb regions to the Uffd handler. While we're here, significantly simplify the jungle of error types. Signed-off-by: Patrick Roy <[email protected]>
1 parent 3196935 commit 00bd615

File tree

8 files changed

+160
-193
lines changed

8 files changed

+160
-193
lines changed

src/vmm/src/arch/aarch64/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ use crate::cpu_config::templates::CustomCpuTemplate;
3030
use crate::initrd::InitrdConfig;
3131
use crate::utils::{align_up, usize_to_u64};
3232
use crate::vmm_config::machine_config::MachineConfig;
33-
use crate::vstate::memory::{
34-
Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap,
35-
};
33+
use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap};
3634
use crate::vstate::vcpu::KvmVcpuError;
3735
use crate::{Vcpu, VcpuConfig, Vmm};
3836

@@ -118,7 +116,9 @@ pub fn configure_system_for_boot(
118116

119117
let swiotlb_region = match vmm.vm.swiotlb_regions().num_regions() {
120118
0 | 1 => vmm.vm.swiotlb_regions().iter().next(),
121-
_ => panic!("Firecracker tried to configure more than one swiotlb region. This is a logic bug.")
119+
_ => panic!(
120+
"Firecracker tried to configure more than one swiotlb region. This is a logic bug."
121+
),
122122
};
123123

124124
let fdt = fdt::create_fdt(

src/vmm/src/builder.rs

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44
//! Enables pre-boot setup, instantiation and booting of a Firecracker VMM.
55
66
use std::fmt::Debug;
7-
use std::io;
7+
use std::io::{self};
88
#[cfg(feature = "gdb")]
99
use std::sync::mpsc;
1010
use std::sync::{Arc, Mutex};
1111

1212
use event_manager::{MutEventSubscriber, SubscriberOps};
1313
use libc::EFD_NONBLOCK;
1414
use linux_loader::cmdline::Cmdline as LoaderKernelCmdline;
15-
use userfaultfd::Uffd;
1615
use utils::time::TimestampUs;
1716
#[cfg(target_arch = "aarch64")]
1817
use vm_superio::Rtc;
@@ -50,14 +49,17 @@ use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend};
5049
use crate::gdb;
5150
use crate::initrd::{InitrdConfig, InitrdError};
5251
use crate::logger::{debug, error};
53-
use crate::persist::{MicrovmState, MicrovmStateError};
52+
use crate::persist::{
53+
MicrovmState, MicrovmStateError, RestoreMemoryError, SnapshotStateFromFileError,
54+
restore_memory, send_uffd_handshake,
55+
};
5456
use crate::resources::VmResources;
5557
use crate::seccomp::BpfThreadMap;
5658
use crate::snapshot::Persist;
5759
use crate::vmm_config::instance_info::InstanceInfo;
5860
use crate::vmm_config::machine_config::MachineConfigError;
61+
use crate::vmm_config::snapshot::{MemBackendConfig, MemBackendType};
5962
use crate::vstate::kvm::Kvm;
60-
use crate::vstate::memory::GuestRegionMmap;
6163
use crate::vstate::vcpu::{Vcpu, VcpuError};
6264
use crate::vstate::vm::Vm;
6365
use crate::{EventManager, Vmm, VmmError, device_manager};
@@ -393,6 +395,8 @@ pub enum BuildMicrovmFromSnapshotError {
393395
SetTsc(#[from] crate::arch::SetTscError),
394396
/// Failed to restore microVM state: {0}
395397
RestoreState(#[from] crate::vstate::vm::ArchVmError),
398+
/// Failed to get snapshot state from file: {0}
399+
LoadState(#[from] SnapshotStateFromFileError),
396400
/// Failed to update microVM configuration: {0}
397401
VmUpdateConfig(#[from] MachineConfigError),
398402
/// Failed to restore MMIO device: {0}
@@ -413,19 +417,19 @@ pub enum BuildMicrovmFromSnapshotError {
413417
ACPIDeviManager(#[from] ACPIDeviceManagerRestoreError),
414418
/// VMGenID update failed: {0}
415419
VMGenIDUpdate(std::io::Error),
420+
/// Failed to restore guest memory: {0}
421+
Memory(#[from] RestoreMemoryError),
416422
}
417423

418424
/// Builds and starts a microVM based on the provided MicrovmState.
419425
///
420426
/// An `Arc` reference of the built `Vmm` is also plugged in the `EventManager`, while another
421427
/// is returned.
422-
#[allow(clippy::too_many_arguments)]
423428
pub fn build_microvm_from_snapshot(
424429
instance_info: &InstanceInfo,
425430
event_manager: &mut EventManager,
426431
microvm_state: MicrovmState,
427-
guest_memory: Vec<GuestRegionMmap>,
428-
uffd: Option<Uffd>,
432+
mem_backend: &MemBackendConfig,
429433
seccomp_filters: &BpfThreadMap,
430434
vm_resources: &mut VmResources,
431435
) -> Result<Arc<Mutex<Vmm>>, BuildMicrovmFromSnapshotError> {
@@ -439,11 +443,61 @@ pub fn build_microvm_from_snapshot(
439443
)
440444
.map_err(StartMicrovmError::Internal)?;
441445

446+
let track_dirty_pages = vm_resources.machine_config.track_dirty_pages;
447+
let huge_pages = vm_resources.machine_config.huge_pages;
448+
449+
let mem_backend_path = &mem_backend.backend_path;
450+
451+
let mem_file = match mem_backend.backend_type {
452+
MemBackendType::File => Some(mem_backend_path),
453+
MemBackendType::Uffd => None,
454+
};
455+
456+
let guest_memory = restore_memory(
457+
&microvm_state.vm_state.memory,
458+
mem_file,
459+
huge_pages,
460+
track_dirty_pages,
461+
)?;
462+
let io_memory = restore_memory(
463+
&microvm_state.vm_state.io_memory,
464+
mem_file,
465+
huge_pages,
466+
track_dirty_pages,
467+
)?;
468+
442469
vmm.vm
443470
.register_memory_regions(guest_memory)
444471
.map_err(VmmError::Vm)
445472
.map_err(StartMicrovmError::Internal)?;
446-
vmm.uffd = uffd;
473+
474+
for region in io_memory {
475+
vmm.vm
476+
.register_swiotlb_region(region)
477+
.map_err(VmmError::Vm)
478+
.map_err(StartMicrovmError::Internal)?;
479+
}
480+
481+
vmm.uffd = match mem_backend.backend_type {
482+
MemBackendType::File => None,
483+
MemBackendType::Uffd => {
484+
let (uffd, mut mappings) = vmm
485+
.vm
486+
.create_uffd()
487+
.map_err(RestoreMemoryError::UffdCreate)?;
488+
489+
#[allow(deprecated)]
490+
mappings.iter_mut().for_each(|mapping| {
491+
mapping.page_size = vm_resources.machine_config.huge_pages.page_size();
492+
mapping.page_size_kib = vm_resources.machine_config.huge_pages.page_size();
493+
});
494+
495+
send_uffd_handshake(mem_backend_path, &mappings, &uffd)
496+
.map_err(RestoreMemoryError::UffdHandshake)?;
497+
498+
Some(uffd)
499+
}
500+
};
447501

448502
#[cfg(target_arch = "x86_64")]
449503
{

0 commit comments

Comments
 (0)