From 6956d369a1ee3e29c23b3b75f5e8af1357da2786 Mon Sep 17 00:00:00 2001 From: Chris Oo Date: Tue, 12 Nov 2024 23:08:10 +0000 Subject: [PATCH 1/3] loader: move snp specific pages to new vtl2 reserved region --- openhcl/bootloader_fdt_parser/src/lib.rs | 36 ++++++++++ openhcl/openhcl_boot/src/dt.rs | 1 + openhcl/openhcl_boot/src/host_params/dt.rs | 5 ++ openhcl/openhcl_boot/src/host_params/mod.rs | 6 +- .../src/host_params/shim_params.rs | 19 ++++-- openhcl/openhcl_boot/src/main.rs | 9 +++ .../src/loader/vtl2_config/mod.rs | 22 +++++++ vm/loader/loader_defs/src/paravisor.rs | 65 +++++++++---------- vm/loader/loader_defs/src/shim.rs | 9 +++ vm/loader/src/paravisor.rs | 33 +++++++--- 10 files changed, 156 insertions(+), 49 deletions(-) diff --git a/openhcl/bootloader_fdt_parser/src/lib.rs b/openhcl/bootloader_fdt_parser/src/lib.rs index bb99a5813..ffc6561f5 100644 --- a/openhcl/bootloader_fdt_parser/src/lib.rs +++ b/openhcl/bootloader_fdt_parser/src/lib.rs @@ -158,6 +158,8 @@ pub struct ParsedBootDtInfo { /// The ranges config regions are stored at. #[inspect(iter_by_index)] pub config_ranges: Vec, + /// The VTL2 reserved range. + pub vtl2_reserved_range: MemoryRange, /// The ranges that were accepted at load time by the host on behalf of the /// guest. #[inspect(iter_by_index)] @@ -201,6 +203,7 @@ struct OpenhclInfo { config_ranges: Vec, partition_memory_map: Vec, accepted_memory: Vec, + vtl2_reserved_range: MemoryRange, vtl0_alias_map: Option, memory_allocation_mode: MemoryAllocationMode, isolation: IsolationType, @@ -352,6 +355,25 @@ fn parse_openhcl(node: &Node<'_>) -> anyhow::Result { }) .collect(); + // Report the reserved range. There should only be one. + let vtl2_reserved_range = { + let mut reserved_range_iter = memory.iter().filter_map(|entry| { + if entry.vtl_usage() == MemoryVtlType::VTL2_RESERVED { + Some(*entry.range()) + } else { + None + } + }); + + let reserved_range = reserved_range_iter.next().unwrap_or(MemoryRange::EMPTY); + + if reserved_range_iter.next().is_some() { + bail!("multiple VTL2 reserved ranges found"); + } + + reserved_range + }; + let vtl0_alias_map = try_find_property(node, "vtl0-alias-map") .map(|prop| prop.read_u64(0).map_err(err_to_owned)) .transpose() @@ -374,6 +396,7 @@ fn parse_openhcl(node: &Node<'_>) -> anyhow::Result { config_ranges, partition_memory_map: memory, accepted_memory, + vtl2_reserved_range, vtl0_alias_map, memory_allocation_mode, isolation, @@ -469,6 +492,7 @@ impl ParsedBootDtInfo { let mut vtl0_alias_map = None; let mut memory_allocation_mode = MemoryAllocationMode::Host; let mut isolation = IsolationType::None; + let mut vtl2_reserved_range = MemoryRange::EMPTY; let parser = Parser::new(raw) .map_err(err_to_owned) @@ -497,6 +521,7 @@ impl ParsedBootDtInfo { vtl0_mmio: n_vtl0_mmio, config_ranges: n_config_ranges, partition_memory_map: n_partition_memory_map, + vtl2_reserved_range: n_vtl2_reserved_range, accepted_memory: n_accepted_memory, vtl0_alias_map: n_vtl0_alias_map, memory_allocation_mode: n_memory_allocation_mode, @@ -509,6 +534,7 @@ impl ParsedBootDtInfo { vtl0_alias_map = n_vtl0_alias_map; memory_allocation_mode = n_memory_allocation_mode; isolation = n_isolation; + vtl2_reserved_range = n_vtl2_reserved_range; } _ if child.name.starts_with("memory@") => { @@ -540,6 +566,7 @@ impl ParsedBootDtInfo { gic, memory_allocation_mode, isolation, + vtl2_reserved_range, }) } } @@ -854,6 +881,14 @@ mod tests { vtl_usage: MemoryVtlType::VTL2_CONFIG, igvm_type: MemoryMapEntryType::VTL2_PROTECTABLE, }), + AddressRange::Memory(Memory { + range: MemoryRangeWithNode { + range: MemoryRange::new(0x40000..0x50000), + vnode: 1, + }, + vtl_usage: MemoryVtlType::VTL2_RESERVED, + igvm_type: MemoryMapEntryType::VTL2_PROTECTABLE, + }), AddressRange::Memory(Memory { range: MemoryRangeWithNode { range: MemoryRange::new(0x1000000..0x2000000), @@ -890,6 +925,7 @@ mod tests { mmio_size: Some(0x2000), }, isolation: IsolationType::Vbs, + vtl2_reserved_range: MemoryRange::new(0x40000..0x50000), }; let dt = build_dt(&orig_info).unwrap(); diff --git a/openhcl/openhcl_boot/src/dt.rs b/openhcl/openhcl_boot/src/dt.rs index d0d8f925f..6db6aab00 100644 --- a/openhcl/openhcl_boot/src/dt.rs +++ b/openhcl/openhcl_boot/src/dt.rs @@ -509,6 +509,7 @@ pub fn write_dt( ReservedMemoryType::Vtl2Config => MemoryVtlType::VTL2_CONFIG, ReservedMemoryType::SidecarImage => MemoryVtlType::VTL2_SIDECAR_IMAGE, ReservedMemoryType::SidecarNode => MemoryVtlType::VTL2_SIDECAR_NODE, + ReservedMemoryType::Vtl2Reserved => MemoryVtlType::VTL2_RESERVED, }, ) }), diff --git a/openhcl/openhcl_boot/src/host_params/dt.rs b/openhcl/openhcl_boot/src/host_params/dt.rs index a2387db42..0f460e6eb 100644 --- a/openhcl/openhcl_boot/src/host_params/dt.rs +++ b/openhcl/openhcl_boot/src/host_params/dt.rs @@ -444,6 +444,7 @@ impl PartitionInfo { vtl2_ram: _, vtl2_full_config_region: vtl2_config_region, vtl2_config_region_reclaim: vtl2_config_region_reclaim_struct, + vtl2_reserved_region, partition_ram: _, isolation, bsp_reg, @@ -466,6 +467,10 @@ impl PartitionInfo { ); *vtl2_config_region_reclaim_struct = vtl2_config_region_reclaim; assert!(vtl2_config_region.contains(&vtl2_config_region_reclaim)); + *vtl2_reserved_region = MemoryRange::new( + params.vtl2_reserved_region_start + ..(params.vtl2_reserved_region_start + params.vtl2_reserved_region_size), + ); *bsp_reg = parsed.boot_cpuid_phys; cpus.extend(parsed.cpus.iter().copied()); *com3_serial = parsed.com3_serial; diff --git a/openhcl/openhcl_boot/src/host_params/mod.rs b/openhcl/openhcl_boot/src/host_params/mod.rs index 5d1a9bea6..8b34a7b4a 100644 --- a/openhcl/openhcl_boot/src/host_params/mod.rs +++ b/openhcl/openhcl_boot/src/host_params/mod.rs @@ -53,7 +53,10 @@ pub struct PartitionInfo { /// Additional ram that can be reclaimed from the parameter region. Today, /// this is the whole device tree provided by the host. pub vtl2_config_region_reclaim: MemoryRange, - /// The full memory map provided by the host. + /// The vtl2 reserved region, that is reserved to both the kernel and + /// usermode. + pub vtl2_reserved_region: MemoryRange, + /// The full memory map provided by the host. pub partition_ram: ArrayVec, /// The partiton's isolation type. pub isolation: IsolationType, @@ -87,6 +90,7 @@ impl PartitionInfo { vtl2_ram: ArrayVec::new_const(), vtl2_full_config_region: MemoryRange::EMPTY, vtl2_config_region_reclaim: MemoryRange::EMPTY, + vtl2_reserved_region: MemoryRange::EMPTY, partition_ram: ArrayVec::new_const(), isolation: IsolationType::None, bsp_reg: 0, diff --git a/openhcl/openhcl_boot/src/host_params/shim_params.rs b/openhcl/openhcl_boot/src/host_params/shim_params.rs index f8a0d0d9c..ed1bb9073 100644 --- a/openhcl/openhcl_boot/src/host_params/shim_params.rs +++ b/openhcl/openhcl_boot/src/host_params/shim_params.rs @@ -95,6 +95,10 @@ pub struct ShimParams { pub parameter_region_start: u64, /// The size of the parameter region. pub parameter_region_size: u64, + /// The base address of the VTL2 reserved region. + pub vtl2_reserved_region_start: u64, + /// The size of the VTL2 reserved region. + pub vtl2_reserved_region_size: u64, /// Isolation type supported by the boot shim. pub isolation_type: IsolationType, pub sidecar_entry_address: u64, @@ -120,6 +124,8 @@ impl ShimParams { memory_size, parameter_region_offset, parameter_region_size, + vtl2_reserved_region_offset, + vtl2_reserved_region_size, sidecar_offset, sidecar_size, sidecar_entry_offset, @@ -148,6 +154,9 @@ impl ShimParams { memory_size, parameter_region_start: shim_base_address.wrapping_add_signed(parameter_region_offset), parameter_region_size, + vtl2_reserved_region_start: shim_base_address + .wrapping_add_signed(vtl2_reserved_region_offset), + vtl2_reserved_region_size, isolation_type, sidecar_entry_address: shim_base_address.wrapping_add_signed(sidecar_entry_offset), sidecar_base: shim_base_address.wrapping_add_signed(sidecar_offset), @@ -163,15 +172,17 @@ impl ShimParams { /// Get the base address of the secrets page. #[cfg(target_arch = "x86_64")] pub fn secrets_start(&self) -> u64 { - self.parameter_region_start - + loader_defs::paravisor::PARAVISOR_CONFIG_SECRETS_PAGE_INDEX * hvdef::HV_PAGE_SIZE + self.vtl2_reserved_region_start + + loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_SECRETS_PAGE_INDEX + * hvdef::HV_PAGE_SIZE } /// Get the size of the CPUID page. #[cfg(target_arch = "x86_64")] pub fn cpuid_start(&self) -> u64 { - self.parameter_region_start - + loader_defs::paravisor::PARAVISOR_CONFIG_CPUID_PAGE_INDEX * hvdef::HV_PAGE_SIZE + self.vtl2_reserved_region_start + + loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_CPUID_PAGE_INDEX + * hvdef::HV_PAGE_SIZE } /// Get the base address of the host provided device tree. diff --git a/openhcl/openhcl_boot/src/main.rs b/openhcl/openhcl_boot/src/main.rs index 24bc37b29..c7a863c61 100644 --- a/openhcl/openhcl_boot/src/main.rs +++ b/openhcl/openhcl_boot/src/main.rs @@ -296,6 +296,7 @@ pub const MAX_RESERVED_MEM_RANGES: usize = 3 + sidecar_defs::MAX_NODES; #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum ReservedMemoryType { Vtl2Config, + Vtl2Reserved, SidecarImage, SidecarNode, } @@ -322,6 +323,13 @@ fn reserved_memory_regions( ) })); } + + // Add the VTL2 reserved region. + reserved.push(( + partition_info.vtl2_reserved_region, + ReservedMemoryType::Vtl2Reserved, + )); + reserved .as_mut() .sort_unstable_by_key(|(r, _typ)| r.start()); @@ -855,6 +863,7 @@ mod test { vtl2_ram: ArrayVec::new(), vtl2_full_config_region: MemoryRange::EMPTY, vtl2_config_region_reclaim: MemoryRange::EMPTY, + vtl2_reserved_region: MemoryRange::EMPTY, partition_ram: ArrayVec::new(), isolation: IsolationType::None, bsp_reg: cpus[0].reg as u32, diff --git a/openhcl/underhill_core/src/loader/vtl2_config/mod.rs b/openhcl/underhill_core/src/loader/vtl2_config/mod.rs index 27beefd27..f5ae4c292 100644 --- a/openhcl/underhill_core/src/loader/vtl2_config/mod.rs +++ b/openhcl/underhill_core/src/loader/vtl2_config/mod.rs @@ -166,6 +166,28 @@ impl Drop for Vtl2ParamsMap<'_> { } } +/// Map that reads the VTL 2 reserved region, that should not be zeroed after +/// reading. +struct Vtl2ReservedMap { + mapping: SparseMapping, +} + +impl Vtl2ReservedMap { + fn new(reserved_range: MemoryRange) -> anyhow::Result { + let size = reserved_range.len() as usize; + + let mapping = SparseMapping::new(size).context("failed to create a sparse mapping")?; + + let dev_mem = fs_err::OpenOptions::new().read(true).open("/dev/mem")?; + + mapping + .map_file(0, size, dev_mem.file(), reserved_range.start(), false) + .context("failed to memory map reserved region")?; + + Ok(Self { mapping }) + } +} + /// Reads the VTL 2 parameters from the vtl-boot-data region. pub fn read_vtl2_params() -> anyhow::Result<(RuntimeParameters, MeasuredVtl2Info)> { let parsed_openhcl_boot = ParsedBootDtInfo::new().context("failed to parse openhcl_boot dt")?; diff --git a/vm/loader/loader_defs/src/paravisor.rs b/vm/loader/loader_defs/src/paravisor.rs index b2f064b15..b00ce6ca4 100644 --- a/vm/loader/loader_defs/src/paravisor.rs +++ b/vm/loader/loader_defs/src/paravisor.rs @@ -9,7 +9,6 @@ use hvdef::HV_PAGE_SIZE; #[cfg(feature = "inspect")] use inspect::Inspect; use open_enum::open_enum; -use static_assertions::const_assert; use static_assertions::const_assert_eq; use zerocopy::AsBytes; use zerocopy::FromBytes; @@ -23,36 +22,13 @@ pub const PARAVISOR_CONFIG_SLIT_SIZE_PAGES: u64 = 20; pub const PARAVISOR_CONFIG_PPTT_SIZE_PAGES: u64 = 20; /// Size in pages for the device tree. pub const PARAVISOR_CONFIG_DEVICE_TREE_SIZE_PAGES: u64 = 64; -/// Size in pages for the secrets page. -pub const PARAVISOR_CONFIG_SECRETS_SIZE_PAGES: u64 = 1; -/// Size in pages for the CPUID pages. -pub const PARAVISOR_CONFIG_CPUID_SIZE_PAGES: u64 = 2; -/// Size in pages for the VMSA page. -pub const PARAVISOR_CONFIG_VMSA_SIZE_PAGES: u64 = 1; -/// Count for unmeasured config region size on different isolation types. -pub const PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_COMMON: u64 = +/// The maximum size in pages of the unmeasured vtl 2 config region. +pub const PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_MAX: u64 = PARAVISOR_CONFIG_SLIT_SIZE_PAGES + PARAVISOR_CONFIG_PPTT_SIZE_PAGES + PARAVISOR_CONFIG_DEVICE_TREE_SIZE_PAGES; -/// Size in pages for VSM isolation. -pub const PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_VSM: u64 = - PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_COMMON; -/// Size in pages for AMD SEV-SNP isolation. -pub const PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_SNP: u64 = - PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_COMMON - + PARAVISOR_CONFIG_SECRETS_SIZE_PAGES - + PARAVISOR_CONFIG_CPUID_SIZE_PAGES - + PARAVISOR_CONFIG_VMSA_SIZE_PAGES; -const_assert!( - PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_SNP - >= PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_VSM -); -/// The maximum size in pages of the unmeasured vtl 2 config region out of all isolation architectures. -pub const PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_MAX: u64 = - PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_SNP; // TODO: const fn max or macro possible? - // Page indices for different parameters within the unmeasured vtl 2 config region. /// The page index to the SLIT. pub const PARAVISOR_CONFIG_SLIT_PAGE_INDEX: u64 = 0; @@ -62,19 +38,38 @@ pub const PARAVISOR_CONFIG_PPTT_PAGE_INDEX: u64 = /// The page index to the device tree. pub const PARAVISOR_CONFIG_DEVICE_TREE_PAGE_INDEX: u64 = PARAVISOR_CONFIG_PPTT_PAGE_INDEX + PARAVISOR_CONFIG_PPTT_SIZE_PAGES; -/// The page index to the secrets page. -pub const PARAVISOR_CONFIG_SECRETS_PAGE_INDEX: u64 = - PARAVISOR_CONFIG_DEVICE_TREE_PAGE_INDEX + PARAVISOR_CONFIG_DEVICE_TREE_SIZE_PAGES; -/// The page index to the first CPUID page. -pub const PARAVISOR_CONFIG_CPUID_PAGE_INDEX: u64 = - PARAVISOR_CONFIG_SECRETS_PAGE_INDEX + PARAVISOR_CONFIG_SECRETS_SIZE_PAGES; -/// The page index to the VMSA page. -pub const PARAVISOR_CONFIG_VMSA_PAGE_INDEX: u64 = - PARAVISOR_CONFIG_CPUID_PAGE_INDEX + PARAVISOR_CONFIG_CPUID_SIZE_PAGES; /// Base index for the unmeasured vtl 2 config region pub const PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_BASE_INDEX: u64 = PARAVISOR_CONFIG_SLIT_PAGE_INDEX; +/// Size in pages for the SNP CPUID pages. +pub const PARAVISOR_RESERVED_VTL2_SNP_CPUID_SIZE_PAGES: u64 = 2; +/// Size in pages for the VMSA page. +pub const PARAVISOR_RESERVED_VTL2_SNP_VMSA_SIZE_PAGES: u64 = 1; +/// Size in pages for the secrets page. +pub const PARAVISOR_RESERVED_VTL2_SNP_SECRETS_SIZE_PAGES: u64 = 1; + +/// Total size of the reserved vtl2 range. +pub const PARAVISOR_RESERVED_VTL2_PAGE_COUNT_MAX: u64 = PARAVISOR_RESERVED_VTL2_SNP_CPUID_SIZE_PAGES + + PARAVISOR_RESERVED_VTL2_SNP_VMSA_SIZE_PAGES + + PARAVISOR_RESERVED_VTL2_SNP_SECRETS_SIZE_PAGES; + +// Page indices for reserved vtl2 ranges, ranges that are marked as reserved to +// both the kernel and usermode. Today, these are SNP specific pages. +// +// TODO SNP: Does the kernel require that the CPUID and secrets pages are +// persisted, or after the kernel boots, and usermode reads them, can we discard +// them? +// +/// The page index to the SNP VMSA page. +pub const PARAVISOR_RESERVED_VTL2_SNP_VMSA_PAGE_INDEX: u64 = 0; +/// The page index to the first SNP CPUID page. +pub const PARAVISOR_RESERVED_VTL2_SNP_CPUID_PAGE_INDEX: u64 = + PARAVISOR_RESERVED_VTL2_SNP_VMSA_PAGE_INDEX + PARAVISOR_RESERVED_VTL2_SNP_VMSA_SIZE_PAGES; +/// The page index to the first SNP secrets page. +pub const PARAVISOR_RESERVED_VTL2_SNP_SECRETS_PAGE_INDEX: u64 = + PARAVISOR_RESERVED_VTL2_SNP_CPUID_PAGE_INDEX + PARAVISOR_RESERVED_VTL2_SNP_CPUID_SIZE_PAGES; + // Number of pages for each type of parameter in the vtl 2 measured config // region. /// Size in pages the list of accepted memory diff --git a/vm/loader/loader_defs/src/shim.rs b/vm/loader/loader_defs/src/shim.rs index e54080c5c..1294e9ba8 100644 --- a/vm/loader/loader_defs/src/shim.rs +++ b/vm/loader/loader_defs/src/shim.rs @@ -34,6 +34,10 @@ pub struct ShimParamsRaw { pub parameter_region_offset: i64, /// The size of the parameter region. pub parameter_region_size: u64, + /// The offset to the VTL2 reserved region. + pub vtl2_reserved_region_offset: i64, + /// The size of the VTL2 reserved region. + pub vtl2_reserved_region_size: u64, /// The offset to the sidecar memory region. pub sidecar_offset: i64, /// The size of the sidecar memory region. @@ -88,6 +92,10 @@ open_enum! { VTL0_MMIO = 5, /// This range is mmio for VTL2. VTL2_MMIO = 6, + /// This memory holds VTL2 data which should be preserved by the kernel + /// and usermode. Today, this is only used for SNP: VMSA, CPUID pages, + /// and secrets pages. + VTL2_RESERVED = 7, } } @@ -101,6 +109,7 @@ impl MemoryVtlType { | MemoryVtlType::VTL2_CONFIG | MemoryVtlType::VTL2_SIDECAR_IMAGE | MemoryVtlType::VTL2_SIDECAR_NODE + | MemoryVtlType::VTL2_RESERVED ) } } diff --git a/vm/loader/src/paravisor.rs b/vm/loader/src/paravisor.rs index 7aefc1ad9..5b4a334a4 100644 --- a/vm/loader/src/paravisor.rs +++ b/vm/loader/src/paravisor.rs @@ -130,12 +130,13 @@ where let memory_size = memory_page_count * HV_PAGE_SIZE; - // Underhill is laid out as the following: + // OpenHCL is laid out as the following: // --- High Memory, 2MB aligned --- // free space // // page tables // IGVM parameters + // reserved vtl2 ranges // initrd // openhcl_boot // sidecar, if configured @@ -283,7 +284,6 @@ where None }; - // Determine the initial memory layout. let gdt_base_address = offset; let gdt_size = HV_PAGE_SIZE; offset += gdt_size; @@ -321,6 +321,13 @@ where offset += HV_PAGE_SIZE; + // Reserve space for the VTL2 reserved region. + let reserved_region_size = PARAVISOR_RESERVED_VTL2_PAGE_COUNT_MAX * HV_PAGE_SIZE; + let reserved_region_start = offset; + offset += reserved_region_size; + + tracing::debug!(reserved_region_start); + let parameter_region_size = PARAVISOR_VTL2_CONFIG_REGION_PAGE_COUNT_MAX * HV_PAGE_SIZE; let parameter_region_start = offset; offset += parameter_region_size; @@ -451,6 +458,8 @@ where memory_size, parameter_region_offset: calculate_shim_offset(parameter_region_start), parameter_region_size, + vtl2_reserved_region_offset: calculate_shim_offset(reserved_region_start), + vtl2_reserved_region_size: reserved_region_size, sidecar_offset: calculate_shim_offset(sidecar_base), sidecar_size, sidecar_entry_offset: calculate_shim_offset(sidecar_entrypoint), @@ -624,21 +633,24 @@ where importer.import_parameter(dt_parameter_area, 0, IgvmParameterType::DeviceTree)?; if isolation_type == IsolationType::Snp { - let secrets_page_base = config_region_page_base + PARAVISOR_CONFIG_SECRETS_PAGE_INDEX; + let reserved_region_page_base = reserved_region_start / HV_PAGE_SIZE; + let secrets_page_base: u64 = + reserved_region_page_base + PARAVISOR_RESERVED_VTL2_SNP_SECRETS_PAGE_INDEX; importer.import_pages( secrets_page_base, - PARAVISOR_CONFIG_SECRETS_SIZE_PAGES, - "underhill-secrets-page", + PARAVISOR_RESERVED_VTL2_SNP_SECRETS_SIZE_PAGES, + "underhill-snp-secrets-page", BootPageAcceptance::SecretsPage, &[], )?; let cpuid_page = create_snp_cpuid_page(); - let cpuid_page_base = config_region_page_base + PARAVISOR_CONFIG_CPUID_PAGE_INDEX; + let cpuid_page_base = + reserved_region_page_base + PARAVISOR_RESERVED_VTL2_SNP_CPUID_PAGE_INDEX; importer.import_pages( cpuid_page_base, 1, - "underhill-cpuid-page", + "underhill-snp-cpuid-page", BootPageAcceptance::CpuidPage, cpuid_page.as_bytes(), )?; @@ -646,12 +658,13 @@ where importer.import_pages( cpuid_page_base + 1, 1, - "underhill-cpuid-extended-state-page", + "underhill-snp-cpuid-extended-state-page", BootPageAcceptance::CpuidExtendedStatePage, &[], )?; - let vmsa_page_base = config_region_page_base + PARAVISOR_CONFIG_VMSA_PAGE_INDEX; + let vmsa_page_base = + reserved_region_page_base + PARAVISOR_RESERVED_VTL2_SNP_VMSA_PAGE_INDEX; importer.set_vp_context_page(vmsa_page_base)?; } @@ -1021,6 +1034,8 @@ where memory_size, parameter_region_offset: calculate_shim_offset(parameter_region_start), parameter_region_size, + vtl2_reserved_region_offset: 0, + vtl2_reserved_region_size: 0, sidecar_offset: 0, sidecar_size: 0, sidecar_entry_offset: 0, From 1ac9cd9179be5aaa42d9c2ef256ea08a7d90fecf Mon Sep 17 00:00:00 2001 From: Chris Oo Date: Tue, 12 Nov 2024 23:16:59 +0000 Subject: [PATCH 2/3] fix build --- .../src/loader/vtl2_config/mod.rs | 85 ++++++++----------- 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/openhcl/underhill_core/src/loader/vtl2_config/mod.rs b/openhcl/underhill_core/src/loader/vtl2_config/mod.rs index f5ae4c292..3530836c4 100644 --- a/openhcl/underhill_core/src/loader/vtl2_config/mod.rs +++ b/openhcl/underhill_core/src/loader/vtl2_config/mod.rs @@ -14,13 +14,13 @@ use bootloader_fdt_parser::ParsedBootDtInfo; use hvdef::HV_PAGE_SIZE; use inspect::Inspect; use loader_defs::paravisor::ParavisorMeasuredVtl2Config; -use loader_defs::paravisor::PARAVISOR_CONFIG_CPUID_PAGE_INDEX; -use loader_defs::paravisor::PARAVISOR_CONFIG_CPUID_SIZE_PAGES; use loader_defs::paravisor::PARAVISOR_CONFIG_PPTT_PAGE_INDEX; -use loader_defs::paravisor::PARAVISOR_CONFIG_SECRETS_PAGE_INDEX; -use loader_defs::paravisor::PARAVISOR_CONFIG_SECRETS_SIZE_PAGES; use loader_defs::paravisor::PARAVISOR_CONFIG_SLIT_PAGE_INDEX; use loader_defs::paravisor::PARAVISOR_MEASURED_VTL2_CONFIG_PAGE_INDEX; +use loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_CPUID_PAGE_INDEX; +use loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_CPUID_SIZE_PAGES; +use loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_SECRETS_PAGE_INDEX; +use loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_SECRETS_SIZE_PAGES; use memory_range::MemoryRange; use sparse_mmap::SparseMapping; use vm_topology::memory::MemoryRangeWithNode; @@ -88,16 +88,17 @@ impl MeasuredVtl2Info { } #[derive(Debug)] -/// Map of the portion of memory that contains the VTL2 parameters. +/// Map of the portion of memory that contains the VTL2 parameters to read. /// -/// On drop, this mapping zeroes out the specified config ranges. +/// If configured, on drop this mapping zeroes out the specified config ranges. struct Vtl2ParamsMap<'a> { mapping: SparseMapping, + zero_on_drop: bool, ranges: &'a [MemoryRange], } impl<'a> Vtl2ParamsMap<'a> { - fn new(config_ranges: &'a [MemoryRange]) -> anyhow::Result { + fn new(config_ranges: &'a [MemoryRange], zero_on_drop: bool) -> anyhow::Result { // No overlaps. // TODO: Move this check to host_fdt_parser? if let Some((l, r)) = config_ranges @@ -121,7 +122,7 @@ impl<'a> Vtl2ParamsMap<'a> { let dev_mem = fs_err::OpenOptions::new() .read(true) - .write(true) + .write(zero_on_drop) .open("/dev/mem")?; for range in config_ranges { mapping @@ -130,7 +131,7 @@ impl<'a> Vtl2ParamsMap<'a> { range.len() as usize, dev_mem.file(), range.start(), - true, + zero_on_drop, ) .context("failed to memory map igvm parameters")?; } @@ -138,6 +139,7 @@ impl<'a> Vtl2ParamsMap<'a> { Ok(Self { mapping, ranges: config_ranges, + zero_on_drop, }) } @@ -152,47 +154,27 @@ impl<'a> Vtl2ParamsMap<'a> { impl Drop for Vtl2ParamsMap<'_> { fn drop(&mut self) { - let base = self - .ranges - .first() - .expect("already checked that there is at least one range") - .start(); - - for range in self.ranges { - self.mapping - .fill_at((range.start() - base) as usize, 0, range.len() as usize) - .unwrap(); + if self.zero_on_drop { + let base = self + .ranges + .first() + .expect("already checked that there is at least one range") + .start(); + + for range in self.ranges { + self.mapping + .fill_at((range.start() - base) as usize, 0, range.len() as usize) + .unwrap(); + } } } } -/// Map that reads the VTL 2 reserved region, that should not be zeroed after -/// reading. -struct Vtl2ReservedMap { - mapping: SparseMapping, -} - -impl Vtl2ReservedMap { - fn new(reserved_range: MemoryRange) -> anyhow::Result { - let size = reserved_range.len() as usize; - - let mapping = SparseMapping::new(size).context("failed to create a sparse mapping")?; - - let dev_mem = fs_err::OpenOptions::new().read(true).open("/dev/mem")?; - - mapping - .map_file(0, size, dev_mem.file(), reserved_range.start(), false) - .context("failed to memory map reserved region")?; - - Ok(Self { mapping }) - } -} - -/// Reads the VTL 2 parameters from the vtl-boot-data region. +/// Reads the VTL 2 parameters from the config region and VTL2 reserved region. pub fn read_vtl2_params() -> anyhow::Result<(RuntimeParameters, MeasuredVtl2Info)> { let parsed_openhcl_boot = ParsedBootDtInfo::new().context("failed to parse openhcl_boot dt")?; - let mapping = Vtl2ParamsMap::new(&parsed_openhcl_boot.config_ranges) + let mapping = Vtl2ParamsMap::new(&parsed_openhcl_boot.config_ranges, true) .context("failed to map igvm parameters")?; // For the various ACPI tables, read the header to see how big the table @@ -238,21 +220,26 @@ pub fn read_vtl2_params() -> anyhow::Result<(RuntimeParameters, MeasuredVtl2Info } }; + // Read SNP specific information from the reserved region. let (cvm_cpuid_info, snp_secrets) = { if parsed_openhcl_boot.isolation == IsolationType::Snp { + let ranges = &[parsed_openhcl_boot.vtl2_reserved_range]; + let reserved_mapping = + Vtl2ParamsMap::new(ranges, false).context("failed to map vtl2 reserved region")?; + let mut cpuid_pages: Vec = - vec![0; (HV_PAGE_SIZE * PARAVISOR_CONFIG_CPUID_SIZE_PAGES) as usize]; - mapping + vec![0; (PARAVISOR_RESERVED_VTL2_SNP_CPUID_SIZE_PAGES * HV_PAGE_SIZE) as usize]; + reserved_mapping .read_at( - (PARAVISOR_CONFIG_CPUID_PAGE_INDEX * HV_PAGE_SIZE) as usize, + (PARAVISOR_RESERVED_VTL2_SNP_CPUID_PAGE_INDEX * HV_PAGE_SIZE) as usize, cpuid_pages.as_mut_slice(), ) .context("failed to read cpuid pages")?; let mut secrets = - vec![0; (HV_PAGE_SIZE * PARAVISOR_CONFIG_SECRETS_SIZE_PAGES) as usize]; - mapping + vec![0; (PARAVISOR_RESERVED_VTL2_SNP_SECRETS_SIZE_PAGES * HV_PAGE_SIZE) as usize]; + reserved_mapping .read_at( - (HV_PAGE_SIZE * PARAVISOR_CONFIG_SECRETS_PAGE_INDEX) as usize, + (PARAVISOR_RESERVED_VTL2_SNP_SECRETS_PAGE_INDEX * HV_PAGE_SIZE) as usize, secrets.as_mut_slice(), ) .context("failed to read secrets page")?; From 92a57e1e4390f163a0e95511bab45303cc312f0e Mon Sep 17 00:00:00 2001 From: Chris Oo Date: Wed, 13 Nov 2024 00:22:14 +0000 Subject: [PATCH 3/3] only add reserved region if set --- openhcl/openhcl_boot/src/main.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openhcl/openhcl_boot/src/main.rs b/openhcl/openhcl_boot/src/main.rs index c7a863c61..c7b4fe202 100644 --- a/openhcl/openhcl_boot/src/main.rs +++ b/openhcl/openhcl_boot/src/main.rs @@ -324,11 +324,13 @@ fn reserved_memory_regions( })); } - // Add the VTL2 reserved region. - reserved.push(( - partition_info.vtl2_reserved_region, - ReservedMemoryType::Vtl2Reserved, - )); + // Add the VTL2 reserved region, if it exists. + if !partition_info.vtl2_reserved_region.is_empty() { + reserved.push(( + partition_info.vtl2_reserved_region, + ReservedMemoryType::Vtl2Reserved, + )); + } reserved .as_mut()