From b0bbe8db661e3db59ea98584319fae8b65101194 Mon Sep 17 00:00:00 2001 From: Jon Lange Date: Mon, 27 Nov 2023 14:41:57 -0800 Subject: [PATCH] Parse the IGVM memory map Signed-off-by: Jon Lange --- Cargo.lock | 88 ++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + src/config.rs | 2 +- src/igvm_params.rs | 58 ++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1239f8598..a2bf663a39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,6 +43,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bitfield-struct" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48adbf9313c68e023d32f441d19942226212ade3999fb22872c37a70a1b5366a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -149,6 +160,18 @@ dependencies = [ "polyval", ] +[[package]] +name = "igvm_defs" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a5930f41716c295685e466befcd97169e6a00e61b5b037bf32e579b5c932e0a" +dependencies = [ + "bitfield-struct", + "open-enum", + "static_assertions", + "zerocopy 0.7.26", +] + [[package]] name = "igvm_params" version = "0.1.0" @@ -213,12 +236,32 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "open-enum" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba485b94b3e73fa752d98cfcab74647a4a537269682cc1ee5256aa020432506d" +dependencies = [ + "open-enum-derive", +] + +[[package]] +name = "open-enum-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed1c261430059cab8b2b51eec42a3c15750439ec6c013cd8fe41d4a450de776" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "packit" version = "0.1.0" source = "git+https://github.com/coconut-svsm/packit#540b471ee8da1d28fee8d9490888c84a48da04a8" dependencies = [ - "zerocopy", + "zerocopy 0.6.5", ] [[package]] @@ -257,6 +300,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "subtle" version = "2.5.0" @@ -271,6 +320,7 @@ dependencies = [ "bitflags 2.4.1", "gdbstub", "gdbstub_arch", + "igvm_defs", "igvm_params", "intrusive-collections", "log", @@ -279,6 +329,17 @@ dependencies = [ "test", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.38" @@ -329,7 +390,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96f8f25c15a0edc9b07eb66e7e6e97d124c0505435c382fde1ab7ceb188aa956" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.6.5", +] + +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.26", ] [[package]] @@ -340,5 +411,16 @@ checksum = "855e0f6af9cd72b87d8a6c586f3cb583f5cdcc62c2c80869d8cd7e96fdf7ee20" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.38", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", ] diff --git a/Cargo.toml b/Cargo.toml index 3efeab9697..10a75a1e9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ log = { version = "0.4.17", features = ["max_level_info", "release_max_level_inf packit = { git = "https://github.com/coconut-svsm/packit", version = "0.1.0" } aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "alloc"] } igvm_params = { path = "igvm_params" } +igvm_defs = { version = "0.1.0" } [target."x86_64-unknown-none".dev-dependencies] test = { version = "0.1.0", path = "test" } diff --git a/src/config.rs b/src/config.rs index b2763cf563..a0383f210b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -48,7 +48,7 @@ impl<'a> SvsmConfig<'a> { pub fn get_memory_regions(&self) -> Result>, SvsmError> { match self { SvsmConfig::FirmwareConfig(fw_cfg) => fw_cfg.get_memory_regions(), - &SvsmConfig::IgvmConfig(_) => todo!(), + SvsmConfig::IgvmConfig(igvm_params) => igvm_params.get_memory_regions(), } } pub fn load_cpu_info(&self) -> Result, SvsmError> { diff --git a/src/igvm_params.rs b/src/igvm_params.rs index a0863f7350..c71befa921 100644 --- a/src/igvm_params.rs +++ b/src/igvm_params.rs @@ -4,16 +4,32 @@ // // Author: Jon Lange (jlange@microsoft.com) +extern crate alloc; + use crate::address::{PhysAddr, VirtAddr}; use crate::error::SvsmError; +use crate::error::SvsmError::Firmware; +use crate::mm::PAGE_SIZE; use crate::utils::MemoryRegion; +use alloc::vec::Vec; +use core::mem::size_of; +use igvm_defs::{MemoryMapEntryType, IGVM_VHS_MEMORY_MAP_ENTRY}; use igvm_params::{IgvmParamBlock, IgvmParamPage}; +const IGVM_MEMORY_ENTRIES_PER_PAGE: usize = PAGE_SIZE / size_of::(); + +#[derive(Clone, Debug)] +#[repr(C, align(64))] +pub struct IgvmMemoryMap { + memory_map: [IGVM_VHS_MEMORY_MAP_ENTRY; IGVM_MEMORY_ENTRIES_PER_PAGE], +} + #[derive(Clone, Debug)] pub struct IgvmParams<'a> { igvm_param_block: &'a IgvmParamBlock, igvm_param_page: &'a IgvmParamPage, + igvm_memory_map: &'a IgvmMemoryMap, } impl IgvmParams<'_> { @@ -21,10 +37,13 @@ impl IgvmParams<'_> { let param_block = unsafe { &*addr.as_ptr::() }; let param_page_address = addr + param_block.param_page_offset.try_into().unwrap(); let param_page = unsafe { &*param_page_address.as_ptr::() }; + let memory_map_address = addr + param_block.memory_map_offset.try_into().unwrap(); + let memory_map = unsafe { &*memory_map_address.as_ptr::() }; Self { igvm_param_block: param_block, igvm_param_page: param_page, + igvm_memory_map: memory_map, } } @@ -54,4 +73,43 @@ impl IgvmParams<'_> { pub fn get_secrets_page_address(&self) -> u64 { self.igvm_param_block.secrets_page as u64 } + + pub fn get_memory_regions(&self) -> Result>, SvsmError> { + // Count the number of memory entries present. They must be + // non-overlapping and strictly increasing. + let mut number_of_entries = 0; + let mut next_page_number = 0; + for i in 0..IGVM_MEMORY_ENTRIES_PER_PAGE { + let entry = &self.igvm_memory_map.memory_map[i]; + if entry.number_of_pages == 0 { + break; + } + if entry.starting_gpa_page_number < next_page_number { + return Err(Firmware); + } + let next_supplied_page_number = entry.starting_gpa_page_number + entry.number_of_pages; + if next_supplied_page_number < next_page_number { + return Err(Firmware); + } + next_page_number = next_supplied_page_number; + number_of_entries += 1; + } + + // Now loop over the supplied entires and add a region for each + // known type. + let mut regions: Vec> = Vec::new(); + for i in 0..number_of_entries { + let entry = &self.igvm_memory_map.memory_map[i]; + if entry.entry_type == MemoryMapEntryType::MEMORY { + let starting_page: usize = entry.starting_gpa_page_number.try_into().unwrap(); + let number_of_pages: usize = entry.number_of_pages.try_into().unwrap(); + regions.push(MemoryRegion::new( + PhysAddr::new(starting_page * PAGE_SIZE), + number_of_pages * PAGE_SIZE, + )); + } + } + + Ok(regions) + } }