From 6b857189f901e687d09f592575a7ccad0316e285 Mon Sep 17 00:00:00 2001 From: John Starks Date: Fri, 10 Jan 2025 05:58:26 +0000 Subject: [PATCH] openhcl: use host-provided srat/madt along with other host acpi tables When the host provides ACPI table specializations, assume we also need the host provided SRAT and MADT tables instead of generating fresh ones. --- openhcl/underhill_core/src/loader/mod.rs | 34 ++++++++-- .../src/loader/vtl2_config/mod.rs | 64 +++++++++---------- vm/loader/loader_defs/src/paravisor.rs | 14 +++- vm/loader/src/paravisor.rs | 36 +++++++++++ 4 files changed, 109 insertions(+), 39 deletions(-) diff --git a/openhcl/underhill_core/src/loader/mod.rs b/openhcl/underhill_core/src/loader/mod.rs index a439c595ef..2507dd39c2 100644 --- a/openhcl/underhill_core/src/loader/mod.rs +++ b/openhcl/underhill_core/src/loader/mod.rs @@ -428,14 +428,38 @@ pub fn write_uefi_config( acpi_irq: crate::worker::SYSTEM_IRQ_ACPI, }; - // Build the ACPI tables as specified. - let madt = acpi_builder.build_madt(); - let srat = acpi_builder.build_srat(); + let (mut madt, mut srat); + if !isolated { + // The host has ACPI table specializations. Use the host-provided SRAT + // and MADT as well. + // + // FUTURE: merge these with any guest topology modifications, or at + // least validate that no such modifications are present. + tracing::info!("using host-provided srat and madt"); + madt = igvm_parameters.madt(); + srat = igvm_parameters.srat(); + } else { + tracing::info!("using generated srat and madt"); + madt = None; + srat = None; + } + + // Build the ACPI tables as necessary. + let mut madt_buf = Vec::new(); + let madt = *madt.get_or_insert_with(|| { + madt_buf = acpi_builder.build_madt(); + &madt_buf + }); + let mut srat_buf = Vec::new(); + let srat = *srat.get_or_insert_with(|| { + srat_buf = acpi_builder.build_srat(); + &srat_buf + }); // - Data that comes from the IGVM parameters { - cfg.add_raw(config::BlobStructureType::Madt, &madt) - .add_raw(config::BlobStructureType::Srat, &srat) + cfg.add_raw(config::BlobStructureType::Madt, madt) + .add_raw(config::BlobStructureType::Srat, srat) .add_raw( config::BlobStructureType::MemoryMap, vtl0_memory_map diff --git a/openhcl/underhill_core/src/loader/vtl2_config/mod.rs b/openhcl/underhill_core/src/loader/vtl2_config/mod.rs index 38d94c5423..fb2ba7cade 100644 --- a/openhcl/underhill_core/src/loader/vtl2_config/mod.rs +++ b/openhcl/underhill_core/src/loader/vtl2_config/mod.rs @@ -14,8 +14,10 @@ use bootloader_fdt_parser::ParsedBootDtInfo; use hvdef::HV_PAGE_SIZE; use inspect::Inspect; use loader_defs::paravisor::ParavisorMeasuredVtl2Config; +use loader_defs::paravisor::PARAVISOR_CONFIG_MADT_PAGE_INDEX; use loader_defs::paravisor::PARAVISOR_CONFIG_PPTT_PAGE_INDEX; use loader_defs::paravisor::PARAVISOR_CONFIG_SLIT_PAGE_INDEX; +use loader_defs::paravisor::PARAVISOR_CONFIG_SRAT_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; @@ -31,6 +33,8 @@ use zerocopy::AsBytes; #[derive(Debug, Inspect)] pub struct RuntimeParameters { parsed_openhcl_boot: ParsedBootDtInfo, + madt: Option>, + srat: Option>, slit: Option>, pptt: Option>, cvm_cpuid_info: Option>, @@ -64,6 +68,16 @@ impl RuntimeParameters { self.pptt.as_deref() } + /// The VM's ACPI SRAT table provided by the host. + pub fn srat(&self) -> Option<&[u8]> { + self.srat.as_deref() + } + + /// The VM's ACPI MADT table provided by the host. + pub fn madt(&self) -> Option<&[u8]> { + self.madt.as_deref() + } + /// The hardware supplied cpuid information for a CVM. pub fn cvm_cpuid_info(&self) -> Option<&[u8]> { self.cvm_cpuid_info.as_deref() @@ -184,46 +198,28 @@ pub fn read_vtl2_params() -> anyhow::Result<(RuntimeParameters, MeasuredVtl2Info // For the various ACPI tables, read the header to see how big the table // is, then read the exact table. - - let slit = { + let table = |index| { let table_header: acpi_spec::Header = mapping - .read_plain((PARAVISOR_CONFIG_SLIT_PAGE_INDEX * HV_PAGE_SIZE) as usize) - .context("failed to read slit header")?; - tracing::trace!(?table_header, "Read SLIT ACPI header"); + .read_plain((index * HV_PAGE_SIZE) as usize) + .context("failed to read table header")?; + tracing::trace!(?table_header, "Read ACPI header"); - if table_header.length.get() == 0 { + let table = if table_header.length.get() == 0 { None } else { - let mut slit: Vec = vec![0; table_header.length.get() as usize]; + let mut table: Vec = vec![0; table_header.length.get() as usize]; mapping - .read_at( - (PARAVISOR_CONFIG_SLIT_PAGE_INDEX * HV_PAGE_SIZE) as usize, - slit.as_mut_slice(), - ) - .context("failed to read slit")?; - Some(slit) - } + .read_at((index * HV_PAGE_SIZE) as usize, table.as_mut_slice()) + .context("failed to read table")?; + Some(table) + }; + anyhow::Ok(table) }; - let pptt = { - let table_header: acpi_spec::Header = mapping - .read_plain((PARAVISOR_CONFIG_PPTT_PAGE_INDEX * HV_PAGE_SIZE) as usize) - .context("failed to read pptt header")?; - tracing::trace!(?table_header, "Read PPTT ACPI header"); - - if table_header.length.get() == 0 { - None - } else { - let mut pptt: Vec = vec![0; table_header.length.get() as usize]; - mapping - .read_at( - (PARAVISOR_CONFIG_PPTT_PAGE_INDEX * HV_PAGE_SIZE) as usize, - pptt.as_mut_slice(), - ) - .context("failed to read pptt")?; - Some(pptt) - } - }; + let slit = table(PARAVISOR_CONFIG_SLIT_PAGE_INDEX)?; + let pptt = table(PARAVISOR_CONFIG_PPTT_PAGE_INDEX)?; + let madt = table(PARAVISOR_CONFIG_MADT_PAGE_INDEX)?; + let srat = table(PARAVISOR_CONFIG_SRAT_PAGE_INDEX)?; // Read SNP specific information from the reserved region. let (cvm_cpuid_info, snp_secrets) = { @@ -281,6 +277,8 @@ pub fn read_vtl2_params() -> anyhow::Result<(RuntimeParameters, MeasuredVtl2Info parsed_openhcl_boot, slit, pptt, + madt, + srat, cvm_cpuid_info, snp_secrets, }; diff --git a/vm/loader/loader_defs/src/paravisor.rs b/vm/loader/loader_defs/src/paravisor.rs index b00ce6ca4e..d3391c1dfe 100644 --- a/vm/loader/loader_defs/src/paravisor.rs +++ b/vm/loader/loader_defs/src/paravisor.rs @@ -20,6 +20,10 @@ use zerocopy::FromZeroes; pub const PARAVISOR_CONFIG_SLIT_SIZE_PAGES: u64 = 20; /// Size in pages for the PPTT. pub const PARAVISOR_CONFIG_PPTT_SIZE_PAGES: u64 = 20; +/// Size in pages for the MADT. +pub const PARAVISOR_CONFIG_MADT_SIZE_PAGES: u64 = 20; +/// Size in pages for the SRAT. +pub const PARAVISOR_CONFIG_SRAT_SIZE_PAGES: u64 = 20; /// Size in pages for the device tree. pub const PARAVISOR_CONFIG_DEVICE_TREE_SIZE_PAGES: u64 = 64; @@ -27,6 +31,8 @@ pub const PARAVISOR_CONFIG_DEVICE_TREE_SIZE_PAGES: u64 = 64; pub const PARAVISOR_UNMEASURED_VTL2_CONFIG_REGION_PAGE_COUNT_MAX: u64 = PARAVISOR_CONFIG_SLIT_SIZE_PAGES + PARAVISOR_CONFIG_PPTT_SIZE_PAGES + + PARAVISOR_CONFIG_MADT_SIZE_PAGES + + PARAVISOR_CONFIG_SRAT_SIZE_PAGES + PARAVISOR_CONFIG_DEVICE_TREE_SIZE_PAGES; // Page indices for different parameters within the unmeasured vtl 2 config region. @@ -35,9 +41,15 @@ pub const PARAVISOR_CONFIG_SLIT_PAGE_INDEX: u64 = 0; /// The page index to the PPTT. pub const PARAVISOR_CONFIG_PPTT_PAGE_INDEX: u64 = PARAVISOR_CONFIG_SLIT_PAGE_INDEX + PARAVISOR_CONFIG_SLIT_SIZE_PAGES; +/// The page index to the MADT. +pub const PARAVISOR_CONFIG_MADT_PAGE_INDEX: u64 = + PARAVISOR_CONFIG_PPTT_PAGE_INDEX + PARAVISOR_CONFIG_PPTT_SIZE_PAGES; +/// The page index to the SRAT. +pub const PARAVISOR_CONFIG_SRAT_PAGE_INDEX: u64 = + PARAVISOR_CONFIG_MADT_PAGE_INDEX + PARAVISOR_CONFIG_MADT_SIZE_PAGES; /// 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; + PARAVISOR_CONFIG_SRAT_PAGE_INDEX + PARAVISOR_CONFIG_SRAT_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; diff --git a/vm/loader/src/paravisor.rs b/vm/loader/src/paravisor.rs index 5b4a334a4f..fd50f1f420 100644 --- a/vm/loader/src/paravisor.rs +++ b/vm/loader/src/paravisor.rs @@ -623,6 +623,24 @@ where )?; importer.import_parameter(pptt_parameter_area, 0, IgvmParameterType::Pptt)?; + // Madt + let madt_page_base = config_region_page_base + PARAVISOR_CONFIG_MADT_PAGE_INDEX; + let madt_parameter_area = importer.create_parameter_area( + madt_page_base, + PARAVISOR_CONFIG_MADT_SIZE_PAGES as u32, + "underhill-madt", + )?; + importer.import_parameter(madt_parameter_area, 0, IgvmParameterType::Madt)?; + + // Srat + let srat_page_base = config_region_page_base + PARAVISOR_CONFIG_SRAT_PAGE_INDEX; + let srat_parameter_area = importer.create_parameter_area( + srat_page_base, + PARAVISOR_CONFIG_SRAT_SIZE_PAGES as u32, + "underhill-srat", + )?; + importer.import_parameter(srat_parameter_area, 0, IgvmParameterType::Srat)?; + // device tree let dt_page_base = config_region_page_base + PARAVISOR_CONFIG_DEVICE_TREE_PAGE_INDEX; let dt_parameter_area = importer.create_parameter_area( @@ -1273,6 +1291,24 @@ where )?; importer.import_parameter(pptt_parameter_area, 0, IgvmParameterType::Pptt)?; + // Madt + let madt_page_base = config_region_page_base + PARAVISOR_CONFIG_MADT_PAGE_INDEX; + let madt_parameter_area = importer.create_parameter_area( + madt_page_base, + PARAVISOR_CONFIG_MADT_SIZE_PAGES as u32, + "underhill-madt", + )?; + importer.import_parameter(madt_parameter_area, 0, IgvmParameterType::Madt)?; + + // Srat + let srat_page_base = config_region_page_base + PARAVISOR_CONFIG_SRAT_PAGE_INDEX; + let srat_parameter_area = importer.create_parameter_area( + srat_page_base, + PARAVISOR_CONFIG_SRAT_SIZE_PAGES as u32, + "underhill-srat", + )?; + importer.import_parameter(srat_parameter_area, 0, IgvmParameterType::Srat)?; + // device tree let dt_page_base = config_region_page_base + PARAVISOR_CONFIG_DEVICE_TREE_PAGE_INDEX; let dt_parameter_area = importer.create_parameter_area(