Repository: firecracker-microvm/firecracker
File: src/vmm/src/builder.rs (Rust)

Code before:
    /// Could not set TSC scaling within the snapshot: {0}
    SetTsc(#[from] crate::vstate::vcpu::SetTscError),
    /// Failed to restore microVM state: {0}
    RestoreState(#[from] crate::vstate::vm::RestoreStateError),
    /// Failed to update microVM configuration: {0}
    VmUpdateConfig(#[from] VmConfigError),
    /// Failed to restore MMIO device: {0}
    RestoreMmioDevice(#[from] MicrovmStateError),
    /// Failed to emulate MMIO serial: {0}
    EmulateSerialInit(#[from] crate::EmulateSerialInitError),
    /// Failed to start vCPUs as no vCPU seccomp filter found.
    MissingVcpuSeccompFilters,
    /// Failed to start vCPUs: {0}
    StartVcpus(#[from] crate::StartVcpusError),
    /// Failed to restore vCPUs: {0}
    RestoreVcpus(#[from] VcpuError),
    /// Failed to apply VMM secccomp filter as none found.
    MissingVmmSeccompFilters,
    /// Failed to apply VMM secccomp filter: {0}
    SeccompFiltersInternal(#[from] seccompiler::InstallationError),
    /// Failed to restore ACPI device manager: {0}
    ACPIDeviManager(#[from] ACPIDeviceManagerRestoreError),
    /// VMGenID update failed: {0}
    VMGenIDUpdate(std::io::Error),
    /// Unknown Network Device.
    UnknownNetworkDevice,
}

/// 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.
#[allow(clippy::too_many_arguments)]
pub fn build_microvm_from_snapshot(
    instance_info: &InstanceInfo,
    event_manager: &mut EventManager,
    microvm_state: MicrovmState,
    guest_memory: GuestMemoryMmap,
    uffd: Option<Uffd>,
    seccomp_filters: &BpfThreadMap,
    vm_resources: &mut VmResources,
) -> Result<Arc<Mutex<Vmm>>, BuildMicrovmFromSnapshotError> {
    // Build Vmm.
    debug!("event_start: build microvm from snapshot");
    let (mut vmm, mut vcpus) = create_vmm_and_vcpus(
        instance_info,
        event_manager,
        guest_memory.clone(),
        uffd,
        vm_resources.vm_config.track_dirty_pages,
        vm_resources.vm_config.vcpu_count,

Review comment (suggestion):
I don't believe this error variant belongs here. I admit that our error handling structure is not the most intuitive, but I believe this error belongs in the `SnasphotStateFromFileError` inside `src/vmm/src/persist.rs`, which is where you emit the error from as well. I _think_ that if you plug it in there everything should propagate upwards nicely.

Code after:
    /// Failed to restore microVM state: {0}
    RestoreState(#[from] crate::vstate::vm::ArchVmError),
    /// Failed to update microVM configuration: {0}
    VmUpdateConfig(#[from] MachineConfigError),
    /// Failed to restore MMIO device: {0}
    RestoreMmioDevice(#[from] MicrovmStateError),
    /// Failed to emulate MMIO serial: {0}
    EmulateSerialInit(#[from] crate::EmulateSerialInitError),
    /// Failed to start vCPUs as no vCPU seccomp filter found.
    MissingVcpuSeccompFilters,
    /// Failed to start vCPUs: {0}
    StartVcpus(#[from] crate::StartVcpusError),
    /// Failed to restore vCPUs: {0}
    RestoreVcpus(#[from] VcpuError),
    /// Failed to apply VMM secccomp filter as none found.
    MissingVmmSeccompFilters,
    /// Failed to apply VMM secccomp filter: {0}
    SeccompFiltersInternal(#[from] crate::seccomp::InstallationError),
    /// Failed to restore ACPI device manager: {0}
    ACPIDeviManager(#[from] ACPIDeviceManagerRestoreError),
    /// VMGenID update failed: {0}
    VMGenIDUpdate(std::io::Error),
}

/// 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.
#[allow(clippy::too_many_arguments)]
pub fn build_microvm_from_snapshot(
    instance_info: &InstanceInfo,
    event_manager: &mut EventManager,
    microvm_state: MicrovmState,
    guest_memory: GuestMemoryMmap,
    uffd: Option<Uffd>,
    seccomp_filters: &BpfThreadMap,
    vm_resources: &mut VmResources,
) -> Result<Arc<Mutex<Vmm>>, BuildMicrovmFromSnapshotError> {
    // Build Vmm.
    debug!("event_start: build microvm from snapshot");
    let (mut vmm, mut vcpus) = create_vmm_and_vcpus(
        instance_info,
        event_manager,
        guest_memory,
        uffd,
        vm_resources.machine_config.vcpu_count,
        microvm_state.kvm_state.kvm_cap_modifiers.clone(),
    )?;

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