From 0e21b41afe8a04d71a9193f2aa14d5ceddff984f Mon Sep 17 00:00:00 2001 From: Jiong Wang Date: Fri, 17 Jul 2026 15:26:28 -0700 Subject: [PATCH] MsvmPkg: unify UEFI parameter configuration handoff Firmware should consume the loader-provided parameter-area schema without parsing or otherwise depending on the IGVM container format. Publish the optional parameter-area address received by SEC through a new parameter-config PPI. X64 receives the address through R12, while AArch64 defines x3 as the corresponding optional SEC input for a future loader producer. Platform PEI evaluates the hardware-isolated-without-a-paravisor condition once and resolves the effective parameter header before parsing. Isolated launches start with the historical fixed address for compatibility with TDX and older images, and a non-NULL pointer supplied by SEC overrides that value. Non-isolated launches require an explicit pointer to select parameter parsing; otherwise they retain the legacy configuration path. Pass the resolved non-NULL header and evaluated isolation state to GetIgvmConfigInfo. The parser validates its required pointer, does not repeat the isolation query, and applies the appropriate firmware defaults. Non-isolated parameter launches retain the former OpenVMM defaults for serial COM1, hibernation, memory protection, MTRRs, and preassigned PCI resources, while isolated guests retain their existing defaults. This lets OpenVMM use the parameter area already described by a UEFI IGVM instead of constructing a second legacy UEFI configuration blob. Direct UEFI launches and isolated images without an explicit pointer remain compatible. Tested with RELEASE CLANGPDB firmware builds for X64 and AARCH64. The focused X64 OpenVMM boot_uefi_custom_igvm execution test passed (1 passed, 313 skipped; nextest run 29ddd7ec-c4ab-41aa-b2c1-0c56f79cb385). --- MsvmPkg/Include/Ppi/ParameterConfig.h | 25 +++++++++++++++ MsvmPkg/MsvmPkg.dec | 1 + MsvmPkg/PlatformPei/Config.c | 46 +++++++++++++++++++++------ MsvmPkg/PlatformPei/Config.h | 3 +- MsvmPkg/PlatformPei/IgvmConfig.c | 43 +++++++++++++++++++------ MsvmPkg/PlatformPei/PlatformPei.inf | 1 + MsvmPkg/Sec/AArch64/SecEntry.S | 3 +- MsvmPkg/Sec/AArch64/SecMain.c | 22 ++++++++++--- MsvmPkg/Sec/SecMain.inf | 1 + MsvmPkg/Sec/X64/SecMain.c | 15 ++++++++- 10 files changed, 134 insertions(+), 26 deletions(-) create mode 100644 MsvmPkg/Include/Ppi/ParameterConfig.h diff --git a/MsvmPkg/Include/Ppi/ParameterConfig.h b/MsvmPkg/Include/Ppi/ParameterConfig.h new file mode 100644 index 0000000000..ccb90d534e --- /dev/null +++ b/MsvmPkg/Include/Ppi/ParameterConfig.h @@ -0,0 +1,25 @@ +/** @file + SEC parameter configuration PPI definition. + + This PPI carries the optional parameter configuration header supplied in + the initial VP context from SEC to PEI. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PARAMETER_CONFIG_H_ +#define PARAMETER_CONFIG_H_ + +/// +/// PPI carrying an optional parameter configuration header from SEC to PEI. +/// A NULL header means that the legacy UEFI configuration blob is in use. +/// +typedef struct { + VOID *ParameterConfigHeader; +} MSVM_PARAMETER_CONFIG_PPI; + +extern EFI_GUID gMsvmParameterConfigPpiGuid; + +#endif // PARAMETER_CONFIG_H_ diff --git a/MsvmPkg/MsvmPkg.dec b/MsvmPkg/MsvmPkg.dec index 6132c50f98..b676d836cd 100644 --- a/MsvmPkg/MsvmPkg.dec +++ b/MsvmPkg/MsvmPkg.dec @@ -53,6 +53,7 @@ [Ppis] gMsvmSecPlatformTypePpiGuid = {0x7a3b9e2c, 0x4d15, 0x4f8a, {0xb1, 0x0e, 0x3c, 0x5d, 0x8f, 0x2a, 0x6b, 0x47}} + gMsvmParameterConfigPpiGuid = {0x81b465f3, 0xa0f3, 0x46d2, {0x9e, 0xeb, 0x3b, 0x5b, 0x94, 0x6b, 0x95, 0x52}} [Protocols] gMsvmAziHsmProtocolGuid = {0x38976D4E, 0x7454, 0x40CF, {0x9E, 0x12, 0x95, 0xCE, 0x61, 0xA4, 0xCD, 0x6C}} diff --git a/MsvmPkg/PlatformPei/Config.c b/MsvmPkg/PlatformPei/Config.c index 6deb211dab..cd29dbf7a4 100644 --- a/MsvmPkg/PlatformPei/Config.c +++ b/MsvmPkg/PlatformPei/Config.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "Hv.h" #include "Config.h" @@ -1706,17 +1707,42 @@ Return Value: n/a --*/ -{ - EFI_STATUS status; - - // - // If this is a hardware-isolated VM running without a paravisor, then no - // config blob is present. Instead, the parameters were inserted in IGVM - // format and must be parsed as such. +{ + BOOLEAN hardwareIsolatedNoParavisor; + VOID *parameterConfigHeader; + MSVM_PARAMETER_CONFIG_PPI *parameterConfigPpi; + EFI_STATUS status; + + hardwareIsolatedNoParavisor = IsHardwareIsolatedNoParavisor(); + + // + // Older isolated images use the parameter format at the historical fixed + // address without providing an explicit pointer in their initial context. + // + parameterConfigHeader = hardwareIsolatedNoParavisor + ? GetStartOfConfigBlob() + : NULL; + + // + // SEC receives the parameter configuration address in the architecture's + // initial VP context and publishes it through this PPI. // - if (IsHardwareIsolatedNoParavisor()) - { - status = GetIgvmConfigInfo(); + status = PeiServicesLocatePpi( + &gMsvmParameterConfigPpiGuid, + 0, + NULL, + (VOID **)¶meterConfigPpi); + if (!EFI_ERROR(status) && + (parameterConfigPpi->ParameterConfigHeader != NULL)) + { + parameterConfigHeader = parameterConfigPpi->ParameterConfigHeader; + } + + if (parameterConfigHeader != NULL) + { + status = GetIgvmConfigInfo( + parameterConfigHeader, + hardwareIsolatedNoParavisor); } else { diff --git a/MsvmPkg/PlatformPei/Config.h b/MsvmPkg/PlatformPei/Config.h index 5f826af9c4..897577e080 100644 --- a/MsvmPkg/PlatformPei/Config.h +++ b/MsvmPkg/PlatformPei/Config.h @@ -24,7 +24,8 @@ GetConfiguration( EFI_STATUS GetIgvmConfigInfo( - VOID + IN VOID *ParameterConfigHeader, + IN BOOLEAN HardwareIsolatedNoParavisor ); VOID diff --git a/MsvmPkg/PlatformPei/IgvmConfig.c b/MsvmPkg/PlatformPei/IgvmConfig.c index 2737be1e24..ea1ab17992 100644 --- a/MsvmPkg/PlatformPei/IgvmConfig.c +++ b/MsvmPkg/PlatformPei/IgvmConfig.c @@ -365,9 +365,10 @@ Return Value: } -EFI_STATUS -GetIgvmConfigInfo( - VOID +EFI_STATUS +GetIgvmConfigInfo( + IN VOID *ParameterConfigHeader, + IN BOOLEAN HardwareIsolatedNoParavisor ) /*++ @@ -377,7 +378,10 @@ Routine Description: Arguments: - None. + ParameterConfigHeader - Supplies the parameter area base. + + HardwareIsolatedNoParavisor - Supplies whether the VM is hardware + isolated without a paravisor. Return Value: @@ -398,7 +402,12 @@ Return Value: // area. // - parameterInfo = (UEFI_IGVM_PARAMETER_INFO *)GetStartOfConfigBlob(); + if (ParameterConfigHeader == NULL) + { + return EFI_INVALID_PARAMETER; + } + + parameterInfo = (UEFI_IGVM_PARAMETER_INFO *)ParameterConfigHeader; // // Capture the total size of config information. @@ -515,10 +524,26 @@ Return Value: // ZeroMem(&configFlags, sizeof(configFlags)); - configFlags.Flags.MeasureAdditionalPcrs = 1; - configFlags.Flags.DefaultBootAlwaysAttempt = 1; - configFlags.Flags.VpciBootEnabled = 1; - configFlags.Flags.MemoryProtectionMode = ConfigLibMemoryProtectionModeDefault; + if (HardwareIsolatedNoParavisor) + { + configFlags.Flags.MeasureAdditionalPcrs = 1; + configFlags.Flags.DefaultBootAlwaysAttempt = 1; + configFlags.Flags.VpciBootEnabled = 1; + configFlags.Flags.MemoryProtectionMode = ConfigLibMemoryProtectionModeDefault; + } + else + { + // + // Match the legacy OpenVMM defaults for a directly launched UEFI VM. + // Isolated guests retain the existing IGVM defaults above. + // + configFlags.Flags.SerialControllersEnabled = 1; + configFlags.Flags.HibernateEnabled = 1; + configFlags.Flags.ConsoleMode = ConfigLibConsoleModeCOM1; + configFlags.Flags.MemoryProtectionMode = ConfigLibMemoryProtectionModeDisabled; + configFlags.Flags.MtrrsInitializedAtLoad = 1; + configFlags.Flags.PciResourcesPreAssigned = 1; + } ConfigSetUefiConfigFlags(&configFlags); diff --git a/MsvmPkg/PlatformPei/PlatformPei.inf b/MsvmPkg/PlatformPei/PlatformPei.inf index 8ff5b775f4..f4059af342 100644 --- a/MsvmPkg/PlatformPei/PlatformPei.inf +++ b/MsvmPkg/PlatformPei/PlatformPei.inf @@ -204,6 +204,7 @@ [Ppis] gEfiPeiMasterBootModePpiGuid + gMsvmParameterConfigPpiGuid ## CONSUMES [Ppis.AARCH64] gMsvmSecPlatformTypePpiGuid ## CONSUMES diff --git a/MsvmPkg/Sec/AArch64/SecEntry.S b/MsvmPkg/Sec/AArch64/SecEntry.S index 116fd2e519..216eeedb4a 100644 --- a/MsvmPkg/Sec/AArch64/SecEntry.S +++ b/MsvmPkg/Sec/AArch64/SecEntry.S @@ -12,12 +12,13 @@ ASM_FUNC(_ModuleEntryPoint) // x0 - Firmware Volume Base Address // x1 - Stack Base Address // x2 - Platform Type (MSVM_SEC_PLATFORM_TYPE; 0 = HyperV, 1 = Generic) + // x3 - Optional parameter configuration header // bl SerialWriteBanner // print banner to COM2 mov sp, x1 // Establish stack - leave x1 as second arg to C code - bl SecStartupWithStack // jump to C code with 3 args (x0,x1,x2) + bl SecStartupWithStack // jump to C code with 4 args (x0,x1,x2,x3) ASM_FUNC(HvInvokeDebugger) diff --git a/MsvmPkg/Sec/AArch64/SecMain.c b/MsvmPkg/Sec/AArch64/SecMain.c index f46b680c65..06e03f6aca 100644 --- a/MsvmPkg/Sec/AArch64/SecMain.c +++ b/MsvmPkg/Sec/AArch64/SecMain.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,8 @@ MSVM_SEC_PLATFORM_TYPE_PPI mSecPlatformTypePpi = MsvmSecPlatformHyperV }; +MSVM_PARAMETER_CONFIG_PPI mParameterConfigPpi; + EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = { { @@ -51,10 +54,15 @@ EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = &mTemporaryRamSupportPpi }, { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + EFI_PEI_PPI_DESCRIPTOR_PPI, &gMsvmSecPlatformTypePpiGuid, &mSecPlatformTypePpi }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gMsvmParameterConfigPpiGuid, + &mParameterConfigPpi + }, }; @@ -121,7 +129,8 @@ EFIAPI SecStartupWithStack ( IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, IN VOID *TopOfCurrentStack, - IN UINT64 PlatformType + IN UINT64 PlatformType, + IN OPTIONAL VOID *ParameterConfigHeader ) /*++ @@ -139,6 +148,9 @@ Routine Description: PlatformType - Platform type from the loader (MSVM_SEC_PLATFORM_TYPE). 0 = HyperV (default), 1 = Generic. + ParameterConfigHeader - Supplies the optional parameter configuration + header provided by the loader. + Return Value: None. @@ -152,11 +164,12 @@ Return Value: DEBUG((DEBUG_VERBOSE, sequence)); DEBUG((DEBUG_VERBOSE, - ">>> SecStartupWithStack @ %p (%p, %p, 0x%llx)\n", + ">>> SecStartupWithStack @ %p (%p, %p, 0x%llx, %p)\n", SecStartupWithStack, BootFv, TopOfCurrentStack, - PlatformType + PlatformType, + ParameterConfigHeader )); // @@ -171,6 +184,7 @@ Return Value: CpuDeadLoop(); } mSecPlatformTypePpi.PlatformType = (MSVM_SEC_PLATFORM_TYPE)PlatformType; + mParameterConfigPpi.ParameterConfigHeader = ParameterConfigHeader; // // Initialize floating point operating environment diff --git a/MsvmPkg/Sec/SecMain.inf b/MsvmPkg/Sec/SecMain.inf index 09bf2c9d65..63698476cd 100644 --- a/MsvmPkg/Sec/SecMain.inf +++ b/MsvmPkg/Sec/SecMain.inf @@ -61,6 +61,7 @@ [Ppis] gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED + gMsvmParameterConfigPpiGuid # PPI ALWAYS_PRODUCED [Ppis.AARCH64] gMsvmSecPlatformTypePpiGuid # PPI ALWAYS_PRODUCED diff --git a/MsvmPkg/Sec/X64/SecMain.c b/MsvmPkg/Sec/X64/SecMain.c index 14a6c8f433..2d66a6911f 100644 --- a/MsvmPkg/Sec/X64/SecMain.c +++ b/MsvmPkg/Sec/X64/SecMain.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include "SecP.h" @@ -48,13 +49,21 @@ EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = }; +MSVM_PARAMETER_CONFIG_PPI mParameterConfigPpi; + + EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = { { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + EFI_PEI_PPI_DESCRIPTOR_PPI, &gEfiTemporaryRamSupportPpiGuid, &mTemporaryRamSupportPpi }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gMsvmParameterConfigPpiGuid, + &mParameterConfigPpi + }, }; HV_HYPERVISOR_ISOLATION_CONFIGURATION mIsolationConfiguration; @@ -1079,6 +1088,9 @@ Routine Description: IsolationConfiguration - Supplies the isolation configuration of the current partition. + UefiIgvmConfigHeader - Supplies the optional IGVM parameter configuration + header provided by the loader. + Return Value: None. @@ -1124,6 +1136,7 @@ Return Value: // mIsolationConfiguration = *IsolationConfiguration; + mParameterConfigPpi.ParameterConfigHeader = UefiIgvmConfigHeader; Handler = 0; Vector = 0;