Skip to content

Commit

Permalink
igvmbld: Change memory layout to allow SVSM to invalidate boot mem re…
Browse files Browse the repository at this point in the history
…gions

The current layout of memory places some pages inside the low memory
range but outside of the first 640K. The SVSM invalidates all low
memory up to 0xA0000 but by placing pages outside this range means we
would need to add extra logic to SVSM to detect and invalidate these
pages.

This patch moves the secrets page below 640K and moves the QEMU VMSA
region to the base of the kernel space making Hyper-V and QEMU
consistent with each other.

The memory map comment has been updated to reflect these changes.

Signed-off-by: Roy Hopkins <roy.hopkins@suse.com>
  • Loading branch information
roy-hopkins committed Jan 10, 2024
1 parent d6b606c commit 571db22
Showing 1 changed file with 25 additions and 26 deletions.
51 changes: 25 additions & 26 deletions igvmbld/igvmbld.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,12 +936,17 @@ int main(int argc, const char *argv[])
platform = setup_igvm_platform_header();

// Construct a set of ranges for the memory map:
// 00000-0EFFF: zero-filled (must be pre-validated)
// 0F000-0FFFF: initial stage 2 stack page
// 10000-nnnnn: stage 2 image
// nnnnn-9EFFF: zero-filled (must be pre-validated)
// 9F000-9FFFF: CPUID page
// A0000-nnnnn: kernel and filesystem
// 0x000000-0x00EFFF: zero-filled (must be pre-validated)
// 0x00F000-0x00FFFF: initial stage 2 stack page
// 0x010000-0x0nnnnn: stage 2 image
// 0x0nnnnn-0x09DFFF: zero-filled (must be pre-validated)
// 0x09E000-0x09EFFF: Secrets page
// 0x09F000-0x09FFFF: CPUID page
// 0x100000-0x1nnnnn: kernel
// 0x1nnnnn-0x1nnnnn: filesystem
// 0x1nnnnn-0x1nnnnn: IGVM parameter block
// 0x1nnnnn-0x1nnnnn: general and memory map parameter pages
// 0xFFnn0000-0xFFFFFFFF: OVMF firmware (QEMU only, if specified)
construct_empty_data_object(0x00000, 0xF000, "Low memory");

// Construct a page containing an initial stack. This is the page
Expand All @@ -958,17 +963,22 @@ int main(int argc, const char *argv[])

stage2_top = (stage2_data->address + stage2_data->size + PAGE_SIZE - 1) &
~(PAGE_SIZE - 1);
if (stage2_top > 0x9F000)
if (stage2_top > 0x9E000)
{
fprintf(stderr, "stage 2 image is too large\n");
return 1;
}
else if (stage2_top < 0x9F000)
else if (stage2_top < 0x9E000)
{
construct_empty_data_object(stage2_top, 0x9F000 - stage2_top, "Stage 2 free space");
construct_empty_data_object(stage2_top, 0x9E000 - stage2_top, "Stage 2 free space");
}

cpuid_page = construct_mem_data_object(0x9F000, 0x1000, "CPUID page");
// Allocate a page to hold the secrets page. This is not considered part
// of the IGVM data.
secrets_page = construct_empty_data_object(0x9E000, PAGE_SIZE, "Secrets page");
secrets_page->page_type = IgvmPageType_Secrets;

cpuid_page = construct_mem_data_object(0x9F000, PAGE_SIZE, "CPUID page");
cpuid_page->page_type = IgvmPageType_Cpuid;
fill_cpuid_page((SNP_CPUID_PAGE *)cpuid_page->data);

Expand Down Expand Up @@ -1043,12 +1053,6 @@ int main(int argc, const char *argv[])
stage2_stack->filesystem_end = address;
}

// Allocate a page to hold the secrets page. This is not considered part
// of the IGVM data.
secrets_page = construct_empty_data_object(address, PAGE_SIZE, "Secrets page");
secrets_page->page_type = IgvmPageType_Secrets;
address += PAGE_SIZE;

// Construct a data object for the IGVM parameter block.
stage2_stack->igvm_param_block = address;
igvm_parameter_object = construct_mem_data_object(address, sizeof(IgvmParamBlock), "IGVM Parameter Block");
Expand Down Expand Up @@ -1086,11 +1090,6 @@ int main(int argc, const char *argv[])
igvm_parameter_block->kernel_base = 0x04000000;
igvm_parameter_block->kernel_size = 0x01000000;

// Place the VMSA at the base of the kernel region and mark that page
// as reserved.
vmsa_address = igvm_parameter_block->kernel_base;
igvm_parameter_block->kernel_reserved_size = 0x1000;

// Add additional information if firmware is being launched.
if (fw_info.fw_info.size != 0)
{
Expand All @@ -1117,13 +1116,13 @@ int main(int argc, const char *argv[])
// Place the kernel area at 512 GB with a size of 16 MB.
igvm_parameter_block->kernel_base = 0x0000008000000000;
igvm_parameter_block->kernel_size = 0x01000000;

// Place the VMSA at the next available address, since the address
// won't actually be consumed by QEMU anyway.
vmsa_address = address;
address += PAGE_SIZE;
}

// Place the VMSA at the base of the kernel region and mark that page
// as reserved.
vmsa_address = igvm_parameter_block->kernel_base;
igvm_parameter_block->kernel_reserved_size = 0x1000;

// If a firmware file has been specified then add it and set the relevant
// parameter block entries.
if (fw_filename && is_qemu)
Expand Down

0 comments on commit 571db22

Please sign in to comment.