44//! Enables pre-boot setup, instantiation and booting of a Firecracker VMM.
55
66use std:: fmt:: Debug ;
7- use std:: io;
7+ use std:: io:: { self } ;
88#[ cfg( feature = "gdb" ) ]
99use std:: sync:: mpsc;
1010use std:: sync:: { Arc , Mutex } ;
1111
1212use event_manager:: { MutEventSubscriber , SubscriberOps } ;
1313use libc:: EFD_NONBLOCK ;
1414use linux_loader:: cmdline:: Cmdline as LoaderKernelCmdline ;
15- use userfaultfd:: Uffd ;
1615use utils:: time:: TimestampUs ;
1716#[ cfg( target_arch = "aarch64" ) ]
1817use vm_superio:: Rtc ;
@@ -50,14 +49,17 @@ use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend};
5049use crate :: gdb;
5150use crate :: initrd:: { InitrdConfig , InitrdError } ;
5251use 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+ } ;
5456use crate :: resources:: VmResources ;
5557use crate :: seccomp:: BpfThreadMap ;
5658use crate :: snapshot:: Persist ;
5759use crate :: vmm_config:: instance_info:: InstanceInfo ;
5860use crate :: vmm_config:: machine_config:: MachineConfigError ;
61+ use crate :: vmm_config:: snapshot:: { MemBackendConfig , MemBackendType } ;
5962use crate :: vstate:: kvm:: Kvm ;
60- use crate :: vstate:: memory:: GuestRegionMmap ;
6163use crate :: vstate:: vcpu:: { Vcpu , VcpuError } ;
6264use crate :: vstate:: vm:: Vm ;
6365use 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) ]
423428pub 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