Skip to content

Commit

Permalink
openhcl: use host-provided srat/madt along with other host acpi tables
Browse files Browse the repository at this point in the history
When the host provides ACPI table specializations, assume we also need
the host provided SRAT and MADT tables instead of generating fresh ones.
  • Loading branch information
jstarks authored and mebersol committed Jan 10, 2025
1 parent 1bd3678 commit 6b85718
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 39 deletions.
34 changes: 29 additions & 5 deletions openhcl/underhill_core/src/loader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
64 changes: 31 additions & 33 deletions openhcl/underhill_core/src/loader/vtl2_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,6 +33,8 @@ use zerocopy::AsBytes;
#[derive(Debug, Inspect)]
pub struct RuntimeParameters {
parsed_openhcl_boot: ParsedBootDtInfo,
madt: Option<Vec<u8>>,
srat: Option<Vec<u8>>,
slit: Option<Vec<u8>>,
pptt: Option<Vec<u8>>,
cvm_cpuid_info: Option<Vec<u8>>,
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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<u8> = vec![0; table_header.length.get() as usize];
let mut table: Vec<u8> = 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<u8> = 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) = {
Expand Down Expand Up @@ -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,
};
Expand Down
14 changes: 13 additions & 1 deletion vm/loader/loader_defs/src/paravisor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@ 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;

/// 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_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.
Expand All @@ -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;
Expand Down
36 changes: 36 additions & 0 deletions vm/loader/src/paravisor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 6b85718

Please sign in to comment.