mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: parse IGVM file early and thread it through VM setup
Move IGVM file parsing from load_igvm() into a dedicated parse_igvm() helper in igvm/mod.rs, and parse the file upfront in Vm::new() so the resulting IgvmFile struct is available throughout VM initialization. This is a prerequisite for extracting VMSA SEV features from the parsed IGVM before issuing KVM_SEV_INIT2, which needs sev_features. Signed-off-by: Ruben Hakobyan <hruben@meta.com>
This commit is contained in:
committed by
Rob Bradford
parent
4f1119a788
commit
425609a8b5
@@ -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<Mutex<MemoryManager>>,
|
||||
cpu_manager: Arc<Mutex<CpuManager>>,
|
||||
cmdline: &str,
|
||||
@@ -143,7 +144,6 @@ pub fn load_igvm(
|
||||
) -> Result<Box<IgvmLoadedInfo>, Error> {
|
||||
let mut loaded_info: Box<IgvmLoadedInfo> = 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<GpaPages> = 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);
|
||||
|
||||
@@ -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<IgvmFile, igvm_loader::Error> {
|
||||
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<u64>,
|
||||
|
||||
@@ -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:?}"))
|
||||
|
||||
@@ -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<Arc<File>>,
|
||||
original_termios: Arc<Mutex<Option<termios>>>,
|
||||
snapshot: Option<&Snapshot>,
|
||||
#[cfg(feature = "igvm")] igvm_file: Option<IgvmFile>,
|
||||
) -> Result<Self> {
|
||||
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<File>>,
|
||||
original_termios: &Arc<Mutex<Option<termios>>>,
|
||||
snapshot: Option<&Snapshot>,
|
||||
#[cfg(feature = "igvm")] igvm_file: Option<IgvmFile>,
|
||||
) -> Result<Option<thread::JoinHandle<Result<EntryPoint>>>> {
|
||||
#[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<File>>,
|
||||
original_termios: &Arc<Mutex<Option<termios>>>,
|
||||
snapshot: Option<&Snapshot>,
|
||||
#[cfg(feature = "igvm")] igvm_file: Option<IgvmFile>,
|
||||
) -> Result<Option<thread::JoinHandle<Result<EntryPoint>>>> {
|
||||
// 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<Mutex<MemoryManager>>,
|
||||
cpu_manager: Arc<Mutex<cpu::CpuManager>>,
|
||||
#[cfg(feature = "sev_snp")] host_data: &Option<String>,
|
||||
) -> Result<EntryPoint> {
|
||||
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<Mutex<MemoryManager>>,
|
||||
#[cfg(feature = "igvm")] cpu_manager: Arc<Mutex<cpu::CpuManager>>,
|
||||
#[cfg(feature = "igvm")] igvm_file: Option<IgvmFile>,
|
||||
) -> Result<EntryPoint> {
|
||||
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<Mutex<MemoryManager>>,
|
||||
config: &Arc<Mutex<VmConfig>>,
|
||||
#[cfg(feature = "igvm")] cpu_manager: &Arc<Mutex<cpu::CpuManager>>,
|
||||
#[cfg(feature = "igvm")] igvm_file: Option<IgvmFile>,
|
||||
) -> Result<Option<thread::JoinHandle<Result<EntryPoint>>>> {
|
||||
// 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)
|
||||
|
||||
Reference in New Issue
Block a user