From 9b151d06ca935c1ab1244a585a8407276ecc7765 Mon Sep 17 00:00:00 2001 From: Jinank Jain Date: Mon, 11 Dec 2023 06:09:05 +0000 Subject: [PATCH] vmm: igvm: Generate memory map for SEV-SNP guests For SEV-SNP guests we need to provide the extended memory. It follows a very simple layout and very similar to other x86 guests. First segment: [HIGH_RAM_START - MEM_32BIT_RESERVED_START] PCI hole: [MEM_32BIT_RESERVED_START - RAM_64BIT_START] Second segment: [RAM_64BIT_START - RAM_END] Fixes #5993 Signed-off-by: Jinank Jain --- vmm/src/igvm/igvm_loader.rs | 50 +++++++++++++++++++++++++++++++++++++ vmm/src/vm.rs | 2 -- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/vmm/src/igvm/igvm_loader.rs b/vmm/src/igvm/igvm_loader.rs index bfd35a93d..685f3aab5 100644 --- a/vmm/src/igvm/igvm_loader.rs +++ b/vmm/src/igvm/igvm_loader.rs @@ -30,6 +30,11 @@ use std::mem::size_of; use std::sync::{Arc, Mutex}; use thiserror::Error; +#[cfg(feature = "sev_snp")] +use crate::GuestMemoryMmap; +#[cfg(feature = "sev_snp")] +use igvm_defs::{MemoryMapEntryType, IGVM_VHS_MEMORY_MAP_ENTRY}; + #[derive(Debug, Error)] pub enum Error { #[error("command line is not a valid C string")] @@ -38,6 +43,8 @@ pub enum Error { Igvm(#[source] std::io::Error), #[error("invalid igvm file")] InvalidIgvmFile(#[source] igvm_parser::Error), + #[error("invalid guest memory map")] + InvalidGuestMemmap(#[source] arch::Error), #[error("loader error")] Loader(#[source] crate::igvm::loader::Error), #[error("parameter too large for parameter area")] @@ -64,6 +71,41 @@ enum ParameterAreaState { Inserted, } +#[cfg(feature = "sev_snp")] +fn igvm_memmap_from_ram_range(ram_range: (u64, u64)) -> IGVM_VHS_MEMORY_MAP_ENTRY { + assert!(ram_range.0 % HV_PAGE_SIZE == 0); + assert!((ram_range.1 - ram_range.0) % HV_PAGE_SIZE == 0); + + IGVM_VHS_MEMORY_MAP_ENTRY { + starting_gpa_page_number: ram_range.0 / HV_PAGE_SIZE, + number_of_pages: (ram_range.1 - ram_range.0) / HV_PAGE_SIZE, + entry_type: MemoryMapEntryType::MEMORY, + flags: 0, + reserved: 0, + } +} + +#[cfg(feature = "sev_snp")] +fn generate_memory_map( + guest_mem: &GuestMemoryMmap, +) -> Result, Error> { + let mut memory_map = Vec::new(); + + // Get usable physical memory ranges + let (first_ram_range, second_ram_range) = + arch::generate_ram_ranges(guest_mem).map_err(Error::InvalidGuestMemmap)?; + + // Create the memory map entry for memory region before the gap + memory_map.push(igvm_memmap_from_ram_range(first_ram_range)); + + // Create the memory map entry for memory region after the gap if any + if let Some(second_ram_range) = second_ram_range { + memory_map.push(igvm_memmap_from_ram_range(second_ram_range)); + } + + Ok(memory_map) +} + // Import a parameter to the given parameter area. fn import_parameter( parameter_areas: &mut HashMap, @@ -245,6 +287,14 @@ pub fn load_igvm( todo!("unsupported IgvmPageDataType"); } IgvmDirectiveHeader::MemoryMap(_info) => { + #[cfg(feature = "sev_snp")] + { + let guest_mem = memory_manager.lock().unwrap().boot_guest_memory(); + let memory_map = generate_memory_map(&guest_mem)?; + import_parameter(&mut parameter_areas, _info, memory_map.as_bytes())?; + } + + #[cfg(not(feature = "sev_snp"))] todo!("Not implemented"); } IgvmDirectiveHeader::CommandLine(info) => { diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index fc42202ec..fe2caa097 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -998,8 +998,6 @@ impl Vm { memory_manager: Arc>, cpu_manager: Arc>, ) -> Result { - //TODO: see issue https://github.com/cloud-hypervisor/cloud-hypervisor/issues/5993 - let res = igvm_loader::load_igvm(&igvm, memory_manager, cpu_manager, "") .map_err(Error::IgvmLoad)?;