Skip to content

Commit

Permalink
svsm: Allow the firmware metadata location to be specified via config
Browse files Browse the repository at this point in the history
When using fw_cfg, the OVMF metadata is located at a hardcoded location
of 1 page below 4GB. When using IGVM for configuration it is possible
for the IGVM file to specify a different location for the firmware
itself so it makes sense to also specify a parameter to describe the
metdata page location. This commit adds a new IGVM parameter field and
uses this to determine the OVMF metadata location.

Signed-off-by: Roy Hopkins <roy.hopkins@suse.com>
  • Loading branch information
roy-hopkins committed Dec 14, 2023
1 parent 6617b5e commit c9d9a9d
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
8 changes: 8 additions & 0 deletions igvm_params/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub struct IgvmParamBlock {
pub debug_serial_port: u16,

_reserved: u16,

/// The guest physical address of the start of the guest firmware. The
/// permissions on the pages in the firmware range are adjusted to the guest
/// VMPL. If this field is zero then no firmware is launched after
Expand All @@ -66,6 +67,13 @@ pub struct IgvmParamBlock {
/// no firmware is launched after initialization is complete.
pub fw_size: u32,

/// The guest physical address of the page that contains metadata that
/// corresponds to the firmware. The SVSM expects the page to contain
/// metadata in the format defined by OVMF.
pub fw_metadata: u32,

_reserved2: u32,

/// The amount of space that must be reserved at the base of the kernel
/// memory region (e.g. for VMSA contents).
pub kernel_reserved_size: u32,
Expand Down
11 changes: 11 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::address::PhysAddr;
use crate::error::SvsmError;
use crate::fw_cfg::FwCfg;
use crate::igvm_params::IgvmParams;
use crate::mm::{PAGE_SIZE, SIZE_1G};
use crate::serial::SERIAL_PORT;
use crate::utils::MemoryRegion;
use alloc::vec::Vec;
Expand Down Expand Up @@ -72,6 +73,16 @@ impl<'a> SvsmConfig<'a> {
}
}

pub fn get_fw_metadata(&self) -> Result<PhysAddr, SvsmError> {
match self {
SvsmConfig::FirmwareConfig(_) => {
// The metadata location always starts at 32 bytes below 4GB
Ok(PhysAddr::from((4 * SIZE_1G) - PAGE_SIZE))
}
SvsmConfig::IgvmConfig(igvm_params) => igvm_params.get_fw_metadata(),
}
}

pub fn get_fw_regions(&self) -> Result<Vec<MemoryRegion<PhysAddr>>, SvsmError> {
match self {
SvsmConfig::FirmwareConfig(fw_cfg) => {
Expand Down
8 changes: 8 additions & 0 deletions src/igvm_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ impl IgvmParams<'_> {
self.igvm_param_block.debug_serial_port
}

pub fn get_fw_metadata(&self) -> Result<PhysAddr, SvsmError> {
if !self.should_launch_fw() || self.igvm_param_block.fw_metadata == 0 {
Err(Firmware)
} else {
Ok(PhysAddr::from(self.igvm_param_block.fw_metadata as u64))
}
}

pub fn get_fw_regions(&self) -> Result<Vec<MemoryRegion<PhysAddr>>, SvsmError> {
if !self.should_launch_fw() {
Err(Firmware)
Expand Down
11 changes: 5 additions & 6 deletions src/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use svsm::mm::alloc::{memory_info, print_memory_info, root_mem_init};
use svsm::mm::memory::init_memory_map;
use svsm::mm::pagetable::paging_init;
use svsm::mm::virtualrange::virt_log_usage;
use svsm::mm::{init_kernel_mapping_info, PerCPUPageMappingGuard, SIZE_1G};
use svsm::mm::{init_kernel_mapping_info, PerCPUPageMappingGuard};
use svsm::requests::{request_loop, update_mappings};
use svsm::serial::SerialPort;
use svsm::sev::secrets_page::{copy_secrets_page, disable_vmpck0, SecretsPage};
Expand Down Expand Up @@ -304,10 +304,9 @@ fn mapping_info_init(launch_info: &KernelLaunchInfo) {
);
}

fn map_and_parse_fw_meta() -> Result<SevFWMetaData, SvsmError> {
// Map meta-data location, it starts at 32 bytes below 4GiB
let pstart = PhysAddr::from((4 * SIZE_1G) - PAGE_SIZE);
let guard = PerCPUPageMappingGuard::create_4k(pstart)?;
fn map_and_parse_fw_meta(config: &SvsmConfig) -> Result<SevFWMetaData, SvsmError> {
// Map the metadata location which is defined by the firmware config
let guard = PerCPUPageMappingGuard::create_4k(config.get_fw_metadata()?)?;
let vstart = guard.virt_addr().as_ptr::<u8>();
// Safety: we just mapped a page, so the size must hold. The type
// of the slice elements is `u8` so there are no alignment requirements.
Expand Down Expand Up @@ -460,7 +459,7 @@ pub extern "C" fn svsm_main() {

let fw_metadata = if config.should_launch_fw() {
Some(
map_and_parse_fw_meta()
map_and_parse_fw_meta(&config)
.unwrap_or_else(|e| panic!("Failed to parse FW SEV meta-data: {:#?}", e)),
)
} else {
Expand Down

0 comments on commit c9d9a9d

Please sign in to comment.