pub fn build_microvm_from_snapshot(
    instance_info: &InstanceInfo,
    event_manager: &mut EventManager,
    microvm_state: MicrovmState,
    guest_memory: GuestMemoryMmap,
    track_dirty_pages: bool,
    seccomp_filters: &BpfThreadMap,
) -> std::result::Result<Arc<Mutex<Vmm>>, StartMicrovmError> {
    use self::StartMicrovmError::*;
    let vcpu_count = u8::try_from(microvm_state.vcpu_states.len())
        .map_err(|_| MicrovmStateError::InvalidInput)
        .map_err(RestoreMicrovmState)?;

    // Build Vmm.
    let (mut vmm, vcpus) = create_vmm_and_vcpus(
        instance_info,
        event_manager,
        guest_memory.clone(),
        track_dirty_pages,
        vcpu_count,
    )?;

    #[cfg(target_arch = "x86_64")]
    // Check if we need to scale the TSC.
    // We start by checking if the CPU model in the snapshot is
    // the same as this host's. If they are the same, we don't
    // need to do anything else.
    if !is_same_model(&microvm_state.vcpu_states[0].cpuid) {
        // Extract the TSC freq from the state.
        // No TSC freq in snapshot means we have to fail-fast.
        let state_tsc = microvm_state.vcpu_states[0]
            .tsc_khz
            .ok_or_else(|| {
                MicrovmStateError::IncompatibleState(
                    "Error configuring the TSC, frequency not \
                    present in snapshot."
                        .to_string(),
                )
            })
            .map_err(RestoreMicrovmState)?;

        // Scale the TSC frequency for all VCPUs, if needed.
        if vcpus[0]
            .kvm_vcpu
            .is_tsc_scaling_required(state_tsc)
            .map_err(|e| MicrovmStateError::IncompatibleState(e.to_string()))
            .map_err(RestoreMicrovmState)?
        {
            for vcpu in &vcpus {
                vcpu.kvm_vcpu
                    .set_tsc_khz(state_tsc)
                    .map_err(|e| MicrovmStateError::IncompatibleState(e.to_string()))
                    .map_err(RestoreMicrovmState)?;
            }
        }
    }

    #[cfg(target_arch = "aarch64")]
    {
        let mpidrs = construct_kvm_mpidrs(&microvm_state.vcpu_states);
        // Restore kvm vm state.
        vmm.vm
            .restore_state(&mpidrs, &microvm_state.vm_state)
            .map_err(MicrovmStateError::RestoreVmState)
            .map_err(RestoreMicrovmState)?;
    }

    // Restore kvm vm state.
    #[cfg(target_arch = "x86_64")]
    vmm.vm
        .restore_state(&microvm_state.vm_state)
        .map_err(MicrovmStateError::RestoreVmState)
        .map_err(RestoreMicrovmState)?;

    // Restore devices states.
    let mmio_ctor_args = MMIODevManagerConstructorArgs {
        mem: guest_memory,
        vm: vmm.vm.fd(),
        event_manager,
    };
    vmm.mmio_device_manager =
        MMIODeviceManager::restore(mmio_ctor_args, &microvm_state.device_states)
            .map_err(MicrovmStateError::RestoreDevices)
            .map_err(RestoreMicrovmState)?;

    // Move vcpus to their own threads and start their state machine in the 'Paused' state.
    vmm.start_vcpus(
        vcpus,
        seccomp_filters
            .get("vcpu")
            .ok_or_else(|| MissingSeccompFilters("vcpu".to_string()))?
            .clone(),
    )
    .map_err(Internal)?;

    // Restore vcpus kvm state.
    vmm.restore_vcpu_states(microvm_state.vcpu_states)
        .map_err(RestoreMicrovmState)?;

    let vmm = Arc::new(Mutex::new(vmm));
    event_manager.add_subscriber(vmm.clone());

    // Load seccomp filters for the VMM thread.
    // Keep this as the last step of the building process.
    seccompiler::apply_filter(
        seccomp_filters
            .get("vmm")
            .ok_or_else(|| MissingSeccompFilters("vmm".to_string()))?,
    )
    .map_err(Error::SeccompFilters)
    .map_err(StartMicrovmError::Internal)?;

    Ok(vmm)
}
/// Builds and starts a microVM based on the provided MicrovmState.
///
/// An `Arc` reference of the built `Vmm` is also plugged in the `EventManager`, while another
/// is returned.
Builds and starts a microVM based on the provided MicrovmState.
Builds and starts a microVM based on the provided MicrovmState .
pub fn build_microvm_from_snapshot(
    instance_info: &InstanceInfo,
    event_manager: &mut EventManager,
    microvm_state: MicrovmState,
    guest_memory: GuestMemoryMmap,
    track_dirty_pages: bool,
    seccomp_filters: &BpfThreadMap,
) -> std::result::Result<Arc<Mutex<Vmm>>, StartMicrovmError> {
    use self::StartMicrovmError::*;
    let vcpu_count = u8::try_from(microvm_state.vcpu_states.len())
        .map_err(|_| MicrovmStateError::InvalidInput)
        .map_err(RestoreMicrovmState)?;
    // Build Vmm.
    let (mut vmm, vcpus) = create_vmm_and_vcpus(
        instance_info,
        event_manager,
        guest_memory.clone(),
        track_dirty_pages,
        vcpu_count,
    )?;
    #[cfg(target_arch = "x86_64")]
    // Check if we need to scale the TSC.
    // We start by checking if the CPU model in the snapshot is
    // the same as this host's. If they are the same, we don't
    // need to do anything else.
    if !is_same_model(&microvm_state.vcpu_states[0].cpuid) {
        // Extract the TSC freq from the state.
        // No TSC freq in snapshot means we have to fail-fast.
        let state_tsc = microvm_state.vcpu_states[0]
            .tsc_khz
            .ok_or_else(|| {
                MicrovmStateError::IncompatibleState(
                    "Error configuring the TSC, frequency not \
                    present in snapshot."
                        .to_string(),
                )
            })
            .map_err(RestoreMicrovmState)?;
        // Scale the TSC frequency for all VCPUs, if needed.
        if vcpus[0]
            .kvm_vcpu
            .is_tsc_scaling_required(state_tsc)
            .map_err(|e| MicrovmStateError::IncompatibleState(e.to_string()))
            .map_err(RestoreMicrovmState)?
        {
            for vcpu in &vcpus {
                vcpu.kvm_vcpu
                    .set_tsc_khz(state_tsc)
                    .map_err(|e| MicrovmStateError::IncompatibleState(e.to_string()))
                    .map_err(RestoreMicrovmState)?;
            }
        }
    }
    #[cfg(target_arch = "aarch64")]
    {
        let mpidrs = construct_kvm_mpidrs(&microvm_state.vcpu_states);
        // Restore kvm vm state.
        vmm.vm
            .restore_state(&mpidrs, &microvm_state.vm_state)
            .map_err(MicrovmStateError::RestoreVmState)
            .map_err(RestoreMicrovmState)?;
    }
    // Restore kvm vm state.
    #[cfg(target_arch = "x86_64")]
    vmm.vm
        .restore_state(&microvm_state.vm_state)
        .map_err(MicrovmStateError::RestoreVmState)
        .map_err(RestoreMicrovmState)?;
    // Restore devices states.
    let mmio_ctor_args = MMIODevManagerConstructorArgs {
        mem: guest_memory,
        vm: vmm.vm.fd(),
        event_manager,
    };
    vmm.mmio_device_manager =
        MMIODeviceManager::restore(mmio_ctor_args, &microvm_state.device_states)
            .map_err(MicrovmStateError::RestoreDevices)
            .map_err(RestoreMicrovmState)?;
    // Move vcpus to their own threads and start their state machine in the 'Paused' state.
    vmm.start_vcpus(
        vcpus,
        seccomp_filters
            .get("vcpu")
            .ok_or_else(|| MissingSeccompFilters("vcpu".to_string()))?
            .clone(),
    )
    .map_err(Internal)?;
    // Restore vcpus kvm state.
    vmm.restore_vcpu_states(microvm_state.vcpu_states)
        .map_err(RestoreMicrovmState)?;
    let vmm = Arc::new(Mutex::new(vmm));
    event_manager.add_subscriber(vmm.clone());
    // Load seccomp filters for the VMM thread.
    // Keep this as the last step of the building process.
    seccompiler::apply_filter(
        seccomp_filters
            .get("vmm")
            .ok_or_else(|| MissingSeccompFilters("vmm".to_string()))?,
    )
    .map_err(Error::SeccompFilters)
    .map_err(StartMicrovmError::Internal)?;
    Ok(vmm)
}
pub fn build_microvm_from_snapshot ( instance_info : & InstanceInfo , event_manager : & mut EventManager , microvm_state : MicrovmState , guest_memory : GuestMemoryMmap , track_dirty_pages : bool , seccomp_filters : & BpfThreadMap , ) -> std :: result :: Result < Arc < Mutex < Vmm > > , StartMicrovmError > { use self :: StartMicrovmError :: * ; let vcpu_count = u8 :: try_from ( microvm_state . vcpu_states . len ( ) ) . map_err ( | _ | MicrovmStateError :: InvalidInput ) . map_err ( RestoreMicrovmState ) ? ; // Build Vmm. let ( mut vmm , vcpus ) = create_vmm_and_vcpus ( instance_info , event_manager , guest_memory . clone ( ) , track_dirty_pages , vcpu_count , ) ? ; # [ cfg ( target_arch " " ) ] // Check if we need to scale the TSC. // We start by checking if the CPU model in the snapshot is // the same as this host's. If they are the same, we don't // need to do anything else. if ! is_same_model ( & microvm_state . vcpu_states [ 0 ] . cpuid ) { // Extract the TSC freq from the state. // No TSC freq in snapshot means we have to fail-fast. let state_tsc = microvm_state . vcpu_states [ 0 ] . tsc_khz . ok_or_else ( | | { MicrovmStateError :: IncompatibleState ( " \
 " . to_string ( ) , ) } ) . map_err ( RestoreMicrovmState ) ? ; // Scale the TSC frequency for all VCPUs, if needed. if vcpus [ 0 ] . kvm_vcpu . is_tsc_scaling_required ( state_tsc ) . map_err ( | e | MicrovmStateError :: IncompatibleState ( e . to_string ( ) ) ) . map_err ( RestoreMicrovmState ) ? { for vcpu in & vcpus { vcpu . kvm_vcpu . set_tsc_khz ( state_tsc ) . map_err ( | e | MicrovmStateError :: IncompatibleState ( e . to_string ( ) ) ) . map_err ( RestoreMicrovmState ) ? ; } } } # [ cfg ( target_arch " " ) ] { let mpidrs = construct_kvm_mpidrs ( & microvm_state . vcpu_states ) ; // Restore kvm vm state. vmm . vm . restore_state ( & mpidrs , & microvm_state . vm_state ) . map_err ( MicrovmStateError :: RestoreVmState ) . map_err ( RestoreMicrovmState ) ? ; } // Restore kvm vm state. # [ cfg ( target_arch " " ) ] vmm . vm . restore_state ( & microvm_state . vm_state ) . map_err ( MicrovmStateError :: RestoreVmState ) . map_err ( RestoreMicrovmState ) ? ; // Restore devices states. let mmio_ctor_args = MMIODevManagerConstructorArgs { mem : guest_memory , vm : vmm . vm . fd ( ) , event_manager , } ; vmm . mmio_device_manager = MMIODeviceManager :: restore ( mmio_ctor_args , & microvm_state . device_states ) . map_err ( MicrovmStateError :: RestoreDevices ) . map_err ( RestoreMicrovmState ) ? ; // Move vcpus to their own threads and start their state machine in the 'Paused' state. vmm . start_vcpus ( vcpus , seccomp_filters . get ( " " ) . ok_or_else ( | | MissingSeccompFilters ( " " . to_string ( ) ) ) ? . clone ( ) , ) . map_err ( Internal ) ? ; // Restore vcpus kvm state. vmm . restore_vcpu_states ( microvm_state . vcpu_states ) . map_err ( RestoreMicrovmState ) ? ; let vmm = Arc :: new ( Mutex :: new ( vmm ) ) ; event_manager . add_subscriber ( vmm . clone ( ) ) ; // Load seccomp filters for the VMM thread. // Keep this as the last step of the building process. seccompiler :: apply_filter ( seccomp_filters . get ( " " ) . ok_or_else ( | | MissingSeccompFilters ( " " . to_string ( ) ) ) ? , ) . map_err ( Error :: SeccompFilters ) . map_err ( StartMicrovmError :: Internal ) ? ; Ok ( vmm ) }
Builds and starts a microVM based on the provided MicrovmState.
Builds and starts a microVM based on the provided MicrovmState .
instance_info
&InstanceInfo
event_manager
&mut EventManager
microvm_state
MicrovmState
guest_memory
GuestMemoryMmap
track_dirty_pages
bool
seccomp_filters
&BpfThreadMap
instance_info
&InstanceInfo
event_manager
&mut EventManager
microvm_state
MicrovmState
guest_memory
GuestMemoryMmap
track_dirty_pages
bool
seccomp_filters
&BpfThreadMap