diff --git a/vmm/src/igvm/igvm_loader.rs b/vmm/src/igvm/igvm_loader.rs index 6e256c1ec..444fbcc53 100644 --- a/vmm/src/igvm/igvm_loader.rs +++ b/vmm/src/igvm/igvm_loader.rs @@ -4,12 +4,11 @@ // use std::collections::HashMap; use std::ffi::CString; -use std::io::{Read, Seek, SeekFrom}; use std::mem::size_of; use std::sync::{Arc, Mutex}; use igvm::snp_defs::SevVmsa; -use igvm::{IgvmDirectiveHeader, IgvmFile, IgvmPlatformHeader, IsolationType}; +use igvm::{IgvmDirectiveHeader, IgvmFile, IgvmPlatformHeader}; #[cfg(feature = "sev_snp")] use igvm_defs::{IGVM_VHS_MEMORY_MAP_ENTRY, MemoryMapEntryType}; use igvm_defs::{ @@ -51,6 +50,8 @@ pub enum Error { FailedToDecodeHostData(#[source] hex::FromHexError), #[error("Error allocating address space")] MemoryManager(MemoryManagerError), + #[error("IGVM file not provided")] + MissingIgvm, } #[allow(dead_code)] @@ -135,7 +136,7 @@ fn import_parameter( /// any isolation. #[allow(clippy::needless_pass_by_value)] pub fn load_igvm( - mut file: &std::fs::File, + igvm_file: IgvmFile, memory_manager: Arc>, cpu_manager: Arc>, cmdline: &str, @@ -143,7 +144,6 @@ pub fn load_igvm( ) -> Result, Error> { let mut loaded_info: Box = Box::default(); let command_line = CString::new(cmdline).map_err(Error::InvalidCommandLine)?; - let mut file_contents = Vec::new(); let memory = memory_manager.lock().as_ref().unwrap().guest_memory(); let mut gpas: Vec = Vec::new(); let proc_count = cpu_manager.lock().unwrap().vcpus().len() as u32; @@ -156,12 +156,6 @@ pub fn load_igvm( .map_err(Error::FailedToDecodeHostData)?; } - file.seek(SeekFrom::Start(0)).map_err(Error::Igvm)?; - file.read_to_end(&mut file_contents).map_err(Error::Igvm)?; - - let igvm_file = IgvmFile::new_from_binary(&file_contents, Some(IsolationType::Snp)) - .map_err(Error::InvalidIgvmFile)?; - let mask = match &igvm_file.platforms()[0] { IgvmPlatformHeader::SupportedPlatform(info) => { debug_assert!(info.platform_type == IgvmPlatformType::SEV_SNP); diff --git a/vmm/src/igvm/mod.rs b/vmm/src/igvm/mod.rs index 62c32d4e8..ded102bd3 100644 --- a/vmm/src/igvm/mod.rs +++ b/vmm/src/igvm/mod.rs @@ -27,10 +27,19 @@ pub mod igvm_loader; mod loader; +use std::path::Path; + use igvm::snp_defs::SevVmsa; +use igvm::{IgvmFile, IsolationType}; use igvm_defs::IGVM_VHS_SNP_ID_BLOCK; use zerocopy::FromZeros; +pub fn parse_igvm(igvm_path: &Path) -> Result { + let file_contents = std::fs::read(igvm_path).map_err(igvm_loader::Error::Igvm)?; + IgvmFile::new_from_binary(&file_contents, Some(IsolationType::Snp)) + .map_err(igvm_loader::Error::InvalidIgvmFile) +} + #[derive(Debug, Clone)] pub struct IgvmLoadedInfo { pub gpas: Vec, diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 5dfea07e7..f98c5b725 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -1161,6 +1161,8 @@ impl Vmm { self.console_resize_pipe.clone(), Arc::clone(&self.original_termios_opt), Some(&snapshot), + #[cfg(feature = "igvm")] + None, ) .map_err(|e| { MigratableError::MigrateReceive(anyhow!("Error creating VM from snapshot: {e:?}")) diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index beec204f7..fe74e6a75 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -47,6 +47,8 @@ use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs; #[cfg(target_arch = "aarch64")] use hypervisor::arch::aarch64::regs::AARCH64_PMU_IRQ; use hypervisor::{HypervisorVmConfig, HypervisorVmError, VmOps}; +#[cfg(feature = "igvm")] +use igvm::IgvmFile; #[cfg(feature = "sev_snp")] use igvm_defs::SnpPolicy; use libc::{SIGWINCH, termios}; @@ -333,10 +335,6 @@ pub enum Error { #[error("Error coredumping VM")] Coredump(#[source] GuestDebuggableError), - #[cfg(feature = "igvm")] - #[error("Cannot open igvm file")] - IgvmFile(#[source] io::Error), - #[cfg(feature = "igvm")] #[error("Cannot load the igvm into memory")] IgvmLoad(#[source] igvm_loader::Error), @@ -567,6 +565,7 @@ impl Vm { console_resize_pipe: Option>, original_termios: Arc>>, snapshot: Option<&Snapshot>, + #[cfg(feature = "igvm")] igvm_file: Option, ) -> Result { trace_scoped!("Vm::new_from_memory_manager"); @@ -649,6 +648,8 @@ impl Vm { console_resize_pipe.as_ref(), &original_termios, snapshot, + #[cfg(feature = "igvm")] + igvm_file, )?; // Load kernel and initramfs files @@ -879,6 +880,7 @@ impl Vm { console_resize_pipe: Option<&Arc>, original_termios: &Arc>>, snapshot: Option<&Snapshot>, + #[cfg(feature = "igvm")] igvm_file: Option, ) -> Result>>> { #[cfg(feature = "mshv")] let is_mshv = matches!( @@ -913,6 +915,8 @@ impl Vm { console_resize_pipe, original_termios, snapshot, + #[cfg(feature = "igvm")] + igvm_file, ); } @@ -942,6 +946,8 @@ impl Vm { config, #[cfg(feature = "igvm")] cpu_manager, + #[cfg(feature = "igvm")] + igvm_file, )? } else { None @@ -986,6 +992,7 @@ impl Vm { console_resize_pipe: Option<&Arc>, original_termios: &Arc>>, snapshot: Option<&Snapshot>, + #[cfg(feature = "igvm")] igvm_file: Option, ) -> Result>>> { // Create boot vCPUs before SEV-SNP initialization cpu_manager @@ -1005,6 +1012,8 @@ impl Vm { config, #[cfg(feature = "igvm")] cpu_manager, + #[cfg(feature = "igvm")] + igvm_file, )? } else { None @@ -1306,6 +1315,18 @@ impl Vm { vm_config.lock().unwrap().is_tdx_enabled() }; + #[cfg(feature = "igvm")] + let igvm_file = { + let config = vm_config.lock().unwrap(); + config + .payload + .as_ref() + .and_then(|p| p.igvm.as_ref()) + .map(|igvm_path| crate::igvm::parse_igvm(igvm_path)) + .transpose() + .map_err(Error::IgvmLoad)? + }; + let vm = Self::create_hypervisor_vm( hypervisor.as_ref(), vm_config.as_ref().lock().unwrap().deref().into(), @@ -1366,6 +1387,8 @@ impl Vm { console_resize_pipe, original_termios, snapshot, + #[cfg(feature = "igvm")] + igvm_file, ) } @@ -1484,13 +1507,13 @@ impl Vm { #[cfg(feature = "igvm")] #[allow(clippy::needless_pass_by_value)] fn load_igvm( - igvm: File, + igvm_file: IgvmFile, memory_manager: Arc>, cpu_manager: Arc>, #[cfg(feature = "sev_snp")] host_data: &Option, ) -> Result { let res = igvm_loader::load_igvm( - &igvm, + igvm_file, memory_manager, cpu_manager.clone(), "", @@ -1580,14 +1603,16 @@ impl Vm { payload: &PayloadConfig, memory_manager: Arc>, #[cfg(feature = "igvm")] cpu_manager: Arc>, + #[cfg(feature = "igvm")] igvm_file: Option, ) -> Result { trace_scoped!("load_payload"); #[cfg(feature = "igvm")] { - if let Some(_igvm_file) = &payload.igvm { - let igvm = File::open(_igvm_file).map_err(Error::IgvmFile)?; + if payload.igvm.is_some() { + let igvm_file = + igvm_file.ok_or(Error::IgvmLoad(igvm_loader::Error::MissingIgvm))?; return Self::load_igvm( - igvm, + igvm_file, memory_manager, cpu_manager, #[cfg(feature = "sev_snp")] @@ -1636,6 +1661,7 @@ impl Vm { memory_manager: &Arc>, config: &Arc>, #[cfg(feature = "igvm")] cpu_manager: &Arc>, + #[cfg(feature = "igvm")] igvm_file: Option, ) -> Result>>> { // Kernel with TDX is loaded in a different manner #[cfg(feature = "tdx")] @@ -1662,6 +1688,8 @@ impl Vm { memory_manager, #[cfg(feature = "igvm")] cpu_manager, + #[cfg(feature = "igvm")] + igvm_file, ) }) .map_err(Error::KernelLoadThreadSpawn)