From c8dccc45eba1e85140c8f14c56542ae4e7c71ba0 Mon Sep 17 00:00:00 2001 From: John Starks Date: Thu, 18 Jun 2026 18:03:46 -0700 Subject: [PATCH] MsvmPkg/AARCH64: Make Hyper-V optional via SEC platform type PPI Add PcdHvEnabled so the AARCH64 firmware can boot on platforms without Hyper-V. The loader passes an MSVM_SEC_PLATFORM_TYPE value in x2 at SEC entry (HyperV=0, Generic=1). SEC validates the value and installs a PPI. PlatformPei reads the PPI and sets PcdHvEnabled, which gates: - SetGuestOsId hypercall in SEC - EfiHvDxe initialization (exits early when disabled) - CrashLib VP register writes (PSCI reset and BiosDevice diagnostics still function) - Hypervisor vendor identity in FACP Config.c validates that VMBus is not enabled when Hv is disabled. Also restructure EventLogDxe to locate the IVM protocol before installing its own protocols, and delete SecEntry.masm (MSVC ARM64 toolchain is no longer supported). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 1 + MsvmPkg/AcpiPlatformDxe/Facp.c | 7 +- MsvmPkg/EfiHvDxe/EfiHv.c | 6 + MsvmPkg/EfiHvDxe/EfiHvDxe.inf | 3 + MsvmPkg/EventLogDxe/EventLogDxe.c | 28 +++-- MsvmPkg/EventLogDxe/EventLogDxe.inf | 3 +- MsvmPkg/Include/Ppi/SecPlatformType.h | 32 +++++ MsvmPkg/Library/CrashLib/AArch64/Crash.c | 125 ++++++++++--------- MsvmPkg/Library/CrashLib/CrashLib.inf | 3 + MsvmPkg/MsvmPkg.dec | 4 +- MsvmPkg/MsvmPkgAARCH64.dsc | 1 + MsvmPkg/MsvmPkgX64.dsc | 1 + MsvmPkg/PlatformPei/Config.c | 11 ++ MsvmPkg/PlatformPei/Platform.c | 39 ++++++ MsvmPkg/PlatformPei/PlatformPei.inf | 4 + MsvmPkg/Sec/AArch64/SecEntry.S | 3 +- MsvmPkg/Sec/AArch64/SecEntry.masm | 128 -------------------- MsvmPkg/Sec/AArch64/SecMain.c | 42 ++++++- MsvmPkg/Sec/SecMain.inf | 4 +- 19 files changed, 231 insertions(+), 214 deletions(-) create mode 100644 MsvmPkg/Include/Ppi/SecPlatformType.h delete mode 100644 MsvmPkg/Sec/AArch64/SecEntry.masm diff --git a/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf index 7015c2bcda..0ab2e3d813 100644 --- a/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +++ b/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -69,6 +69,7 @@ gMsvmPkgTokenSpaceGuid.PcdHighMmioGapBasePageNumber ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdHighMmioGapSizeInPages ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated ## CONSUMES + gMsvmPkgTokenSpaceGuid.PcdHvEnabled ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdLoadOempTable ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdLowMmioGapBasePageNumber ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdLowMmioGapSizeInPages ## CONSUMES diff --git a/MsvmPkg/AcpiPlatformDxe/Facp.c b/MsvmPkg/AcpiPlatformDxe/Facp.c index 94f8707cab..89f9cb1fef 100644 --- a/MsvmPkg/AcpiPlatformDxe/Facp.c +++ b/MsvmPkg/AcpiPlatformDxe/Facp.c @@ -48,9 +48,12 @@ Return Value: } // - // Set the hypervisor vendor identity to MsHyperV + // Set the hypervisor vendor identity to MsHyperV when Hv is enabled. // - CopyMem(&facp->HypervisorVendorIdentity, "MsHyperV", 8); + if (PcdGetBool(PcdHvEnabled)) + { + CopyMem(&facp->HypervisorVendorIdentity, "MsHyperV", 8); + } if (PcdGetBool(PcdLowPowerS0IdleEnabled)) { diff --git a/MsvmPkg/EfiHvDxe/EfiHv.c b/MsvmPkg/EfiHvDxe/EfiHv.c index 984ae648ed..6824b1645d 100644 --- a/MsvmPkg/EfiHvDxe/EfiHv.c +++ b/MsvmPkg/EfiHvDxe/EfiHv.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -2320,6 +2321,11 @@ EfiHvInitialize ( { EFI_STATUS status; + if (!PcdGetBool(PcdHvEnabled)) + { + return EFI_UNSUPPORTED; + } + InitializeListHead(&mHostVisiblePageList); #if defined (MDE_CPU_X64) diff --git a/MsvmPkg/EfiHvDxe/EfiHvDxe.inf b/MsvmPkg/EfiHvDxe/EfiHvDxe.inf index b47ab34e9f..b10ae4225e 100644 --- a/MsvmPkg/EfiHvDxe/EfiHvDxe.inf +++ b/MsvmPkg/EfiHvDxe/EfiHvDxe.inf @@ -59,6 +59,9 @@ [Protocols.AARCH64] gHardwareInterruptProtocolGuid ## CONSUMES +[Pcd] + gMsvmPkgTokenSpaceGuid.PcdHvEnabled ## CONSUMES + [Pcd.X64] gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaBoundary ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaCanonicalizationBitmask ## CONSUMES diff --git a/MsvmPkg/EventLogDxe/EventLogDxe.c b/MsvmPkg/EventLogDxe/EventLogDxe.c index ad3be2a8af..19159a0fc6 100644 --- a/MsvmPkg/EventLogDxe/EventLogDxe.c +++ b/MsvmPkg/EventLogDxe/EventLogDxe.c @@ -6,11 +6,11 @@ **/ #include "EventLogDxe.h" +#include #include #include "StatusCode.h" #include "EventLogger.h" -EFI_HV_PROTOCOL *mHv; EFI_HV_IVM_PROTOCOL *mHvIvm; EFI_STATUS @@ -43,24 +43,26 @@ Return Value: EFI_STATUS status; DEBUG((DEBUG_INIT, "EventLog Driver Starting\n")); + // - // Initialize the event channel management and then the status code protocol + // The IVM protocol is required for hardware-isolated VMs. Check this + // before EventLoggerInitialize, which installs protocols — returning + // error after that would leave dangling protocol entries. // - status = EventLoggerInitialize(); - - if (EFI_ERROR(status)) + if (IsHardwareIsolatedNoParavisor()) { - goto Exit; - } - - status = gBS->LocateProtocol(&gEfiHvProtocolGuid, NULL, (VOID **)&mHv); + status = gBS->LocateProtocol(&gEfiHvIvmProtocolGuid, NULL, (VOID **)&mHvIvm); - if (EFI_ERROR(status)) - { - goto Exit; + if (EFI_ERROR(status)) + { + goto Exit; + } } - status = gBS->LocateProtocol(&gEfiHvIvmProtocolGuid, NULL, (VOID **)&mHvIvm); + // + // Initialize the event channel management and then the status code protocol + // + status = EventLoggerInitialize(); if (EFI_ERROR(status)) { diff --git a/MsvmPkg/EventLogDxe/EventLogDxe.inf b/MsvmPkg/EventLogDxe/EventLogDxe.inf index 0ebd231fec..447be1a794 100644 --- a/MsvmPkg/EventLogDxe/EventLogDxe.inf +++ b/MsvmPkg/EventLogDxe/EventLogDxe.inf @@ -61,8 +61,7 @@ [Protocols] gEfiEventLogProtocolGuid ## PRODUCES gEfiFirmwareVolume2ProtocolGuid ## CONSUMES - gEfiHvIvmProtocolGuid ## CONSUMES - gEfiHvProtocolGuid ## CONSUMES + gEfiHvIvmProtocolGuid ## SOMETIMES_CONSUMES gEfiRscHandlerProtocolGuid ## CONSUMES gEfiStatusCodeRuntimeProtocolGuid ## PRODUCES diff --git a/MsvmPkg/Include/Ppi/SecPlatformType.h b/MsvmPkg/Include/Ppi/SecPlatformType.h new file mode 100644 index 0000000000..000d751967 --- /dev/null +++ b/MsvmPkg/Include/Ppi/SecPlatformType.h @@ -0,0 +1,32 @@ +/** @file + SEC Platform Type PPI definition. + + This PPI is installed by the SEC phase to communicate the platform type + to PEI modules. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SEC_PLATFORM_TYPE_H_ +#define SEC_PLATFORM_TYPE_H_ + +/// +/// Platform type values passed by the loader. +/// +typedef enum { + MsvmSecPlatformHyperV = 0, // Hyper-V with MS extensions + MsvmSecPlatformGeneric = 1, // Generic virtualization (no MS extensions) +} MSVM_SEC_PLATFORM_TYPE; + +/// +/// PPI carrying the platform type from SEC to PEI. +/// +typedef struct { + MSVM_SEC_PLATFORM_TYPE PlatformType; +} MSVM_SEC_PLATFORM_TYPE_PPI; + +extern EFI_GUID gMsvmSecPlatformTypePpiGuid; + +#endif // SEC_PLATFORM_TYPE_H_ diff --git a/MsvmPkg/Library/CrashLib/AArch64/Crash.c b/MsvmPkg/Library/CrashLib/AArch64/Crash.c index 865e2b008f..1bdabcf463 100644 --- a/MsvmPkg/Library/CrashLib/AArch64/Crash.c +++ b/MsvmPkg/Library/CrashLib/AArch64/Crash.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -51,72 +52,76 @@ ReportCrash( IN UINTN MessageLength ) { - // - // Set the guest ID before writing crash registers, if necessary. - // - HV_REGISTER_VALUE registerValue; - HV_STATUS status = AsmGetVpRegister(HvRegisterGuestOsId, ®isterValue); - ASSERT(status == HV_STATUS_SUCCESS); - - if (registerValue.Reg64 == 0) + if (PcdGetBool(PcdHvEnabled)) { - DEBUG((EFI_D_INFO, "GuestOsId is not set in ReportCrash(); setting now.\n")); - - HV_GUEST_OS_ID_CONTENTS guestOsId; - guestOsId.AsUINT64 = 0; - guestOsId.OsId = HvGuestOsMicrosoftUndefined; - guestOsId.VendorId = HvGuestOsVendorMicrosoft; - - status = AsmSetVpRegister64(HvRegisterGuestOsId, guestOsId.AsUINT64); + // + // Set the guest ID before writing crash registers, if necessary. + // + HV_REGISTER_VALUE registerValue; + HV_STATUS status = AsmGetVpRegister(HvRegisterGuestOsId, ®isterValue); ASSERT(status == HV_STATUS_SUCCESS); - } - else - { - DEBUG((EFI_D_VERBOSE, "GuestOsId is 0x%llx.\n", (UINTN)registerValue.Reg64)); - } - - // - // Determine if crash MSRs are supported - // - status = AsmGetVpRegister(HvRegisterPrivilegesAndFeaturesInfo, ®isterValue); - ASSERT(status == HV_STATUS_SUCCESS); - - DEBUG((EFI_D_VERBOSE, "HvRegisterFeaturesInfo (low) is 0x%llx.\n", (UINTN)registerValue.Reg128.Low64)); - DEBUG((EFI_D_VERBOSE, "HvRegisterFeaturesInfo (high) is 0x%llx.\n", (UINTN)registerValue.Reg128.High64)); - HV_HYPERVISOR_FEATURES hvFeatures; - *((PHV_UINT128)&hvFeatures) = registerValue.Reg128; + if (registerValue.Reg64 == 0) + { + DEBUG((EFI_D_INFO, "GuestOsId is not set in ReportCrash(); setting now.\n")); + + HV_GUEST_OS_ID_CONTENTS guestOsId; + guestOsId.AsUINT64 = 0; + guestOsId.OsId = HvGuestOsMicrosoftUndefined; + guestOsId.VendorId = HvGuestOsVendorMicrosoft; + + status = AsmSetVpRegister64(HvRegisterGuestOsId, guestOsId.AsUINT64); + ASSERT(status == HV_STATUS_SUCCESS); + } + else + { + DEBUG((EFI_D_VERBOSE, "GuestOsId is 0x%llx.\n", (UINTN)registerValue.Reg64)); + } + + // + // Determine if crash MSRs are supported + // + status = AsmGetVpRegister(HvRegisterPrivilegesAndFeaturesInfo, ®isterValue); + ASSERT(status == HV_STATUS_SUCCESS); - if (!hvFeatures.GuestCrashRegsAvailable) - { - DEBUG((EFI_D_INFO, "GuestCrashRegister enlightenment is not available.\n")); - return; + DEBUG((EFI_D_VERBOSE, "HvRegisterFeaturesInfo (low) is 0x%llx.\n", (UINTN)registerValue.Reg128.Low64)); + DEBUG((EFI_D_VERBOSE, "HvRegisterFeaturesInfo (high) is 0x%llx.\n", (UINTN)registerValue.Reg128.High64)); + + HV_HYPERVISOR_FEATURES hvFeatures; + *((PHV_UINT128)&hvFeatures) = registerValue.Reg128; + + if (hvFeatures.GuestCrashRegsAvailable) + { + // + // N.B. For ARM64, the crash control registers cannot currently be read for capabilities. + // + + AsmSetVpRegister64(HvRegisterGuestCrashP0, Param0); + AsmSetVpRegister64(HvRegisterGuestCrashP1, Param1); + AsmSetVpRegister64(HvRegisterGuestCrashP2, Param2); + AsmSetVpRegister64(HvRegisterGuestCrashP3, MessageBuffer); + AsmSetVpRegister64(HvRegisterGuestCrashP4, MessageLength); + + // + // Write the control register. + // + HV_CRASH_CTL_REG_CONTENTS writeCrashCtlReg; + writeCrashCtlReg.AsUINT64 = 0; + writeCrashCtlReg.CrashNotify = 1; + + writeCrashCtlReg.CrashMessage = 1; + writeCrashCtlReg.NoCrashDump = 1; + writeCrashCtlReg.PreOSId = MSVM_PKG_CRASH_ID; + + AsmSetVpRegister64(HvRegisterGuestCrashCtl, writeCrashCtlReg.AsUINT64); + DEBUG((EFI_D_INFO, "ReportCrash successful.\n")); + } + else + { + DEBUG((EFI_D_INFO, "GuestCrashRegister enlightenment is not available.\n")); + } } - // - // N.B. For ARM64, the crash control registers cannot currently be read for capabilities. - // - - AsmSetVpRegister64(HvRegisterGuestCrashP0, Param0); - AsmSetVpRegister64(HvRegisterGuestCrashP1, Param1); - AsmSetVpRegister64(HvRegisterGuestCrashP2, Param2); - AsmSetVpRegister64(HvRegisterGuestCrashP3, MessageBuffer); - AsmSetVpRegister64(HvRegisterGuestCrashP4, MessageLength); - - // - // Write the control register. - // - HV_CRASH_CTL_REG_CONTENTS writeCrashCtlReg; - writeCrashCtlReg.AsUINT64 = 0; - writeCrashCtlReg.CrashNotify = 1; - - writeCrashCtlReg.CrashMessage = 1; - writeCrashCtlReg.NoCrashDump = 1; - writeCrashCtlReg.PreOSId = MSVM_PKG_CRASH_ID; - - AsmSetVpRegister64(HvRegisterGuestCrashCtl, writeCrashCtlReg.AsUINT64); - DEBUG((EFI_D_INFO, "ReportCrash successful.\n")); - // // Tell the host to collect EFI diagnostics. // diff --git a/MsvmPkg/Library/CrashLib/CrashLib.inf b/MsvmPkg/Library/CrashLib/CrashLib.inf index 6a7d8736e6..c56af5bbe0 100644 --- a/MsvmPkg/Library/CrashLib/CrashLib.inf +++ b/MsvmPkg/Library/CrashLib/CrashLib.inf @@ -42,3 +42,6 @@ [LibraryClasses.AARCH64] ArmSmcLib HvHypercallLib + +[Pcd.AARCH64] + gMsvmPkgTokenSpaceGuid.PcdHvEnabled ## CONSUMES diff --git a/MsvmPkg/MsvmPkg.dec b/MsvmPkg/MsvmPkg.dec index b46b7ce80b..b5eb427a21 100644 --- a/MsvmPkg/MsvmPkg.dec +++ b/MsvmPkg/MsvmPkg.dec @@ -52,9 +52,10 @@ gMsvmUnableToBootEventGuid = {0x3c8d08a8, 0x42c5, 0x4c33, {0xa6, 0xd8, 0x13, 0xf4, 0xda, 0x4a, 0xa6, 0x85}} [Ppis] + gMsvmSecPlatformTypePpiGuid = {0x7a3b9e2c, 0x4d15, 0x4f8a, {0xb1, 0x0e, 0x3c, 0x5d, 0x8f, 0x2a, 0x6b, 0x47}} [Protocols] - gMsvmAziHsmProtocolGuid = {0x38976D4E, 0x7454, 0x40CF, {0x9E, 0x12, 0x95, 0xCE, 0x61, 0xA4, 0xCD, 0x6C}} + gMsvmAziHsmProtocolGuid = {0x38976D4E, 0x7454, 0x40CF, {0x9E, 0x12, 0x95, 0xCE, 0x61, 0xA4, 0xCD, 0x6C}} # Hyper-V Protocol gEfiHvProtocolGuid = {0xa261a0f1, 0xaa53, 0x4c83, {0x94, 0xda, 0x12, 0x0c, 0xdf, 0x6d, 0x8c, 0x8d}} gEfiHvIvmProtocolGuid = {0xc40a31b5, 0x3899, 0x4f76, {0xbf, 0x7e, 0x32, 0x95, 0x83, 0x3f, 0xee, 0xe7}} @@ -304,6 +305,7 @@ gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE|BOOLEAN|0x6065 gMsvmPkgTokenSpaceGuid.PcdMtrrsInitializedAtLoad|FALSE|BOOLEAN|0x6067 gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled|TRUE|BOOLEAN|0x6068 + gMsvmPkgTokenSpaceGuid.PcdHvEnabled|TRUE|BOOLEAN|0x6069 gMsvmPkgTokenSpaceGuid.PcdForceDmaBounceEnabled|FALSE|BOOLEAN|0x6076 # UEFI_CONFIG_PROCESSOR_INFORMATION diff --git a/MsvmPkg/MsvmPkgAARCH64.dsc b/MsvmPkg/MsvmPkgAARCH64.dsc index 2c0d7dcb79..4d05d31e76 100644 --- a/MsvmPkg/MsvmPkgAARCH64.dsc +++ b/MsvmPkg/MsvmPkgAARCH64.dsc @@ -699,6 +699,7 @@ gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled|TRUE + gMsvmPkgTokenSpaceGuid.PcdHvEnabled|TRUE gMsvmPkgTokenSpaceGuid.PcdForceDmaBounceEnabled|FALSE # UEFI_CONFIG_PROCESSOR_INFORMATION diff --git a/MsvmPkg/MsvmPkgX64.dsc b/MsvmPkg/MsvmPkgX64.dsc index 010983e2fb..b58cd404dd 100644 --- a/MsvmPkg/MsvmPkgX64.dsc +++ b/MsvmPkg/MsvmPkgX64.dsc @@ -717,6 +717,7 @@ gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled|TRUE + gMsvmPkgTokenSpaceGuid.PcdHvEnabled|TRUE gMsvmPkgTokenSpaceGuid.PcdForceDmaBounceEnabled|FALSE # UEFI_CONFIG_PROCESSOR_INFORMATION diff --git a/MsvmPkg/PlatformPei/Config.c b/MsvmPkg/PlatformPei/Config.c index 70ea627b32..6deb211dab 100644 --- a/MsvmPkg/PlatformPei/Config.c +++ b/MsvmPkg/PlatformPei/Config.c @@ -946,6 +946,17 @@ ConfigSetUefiConfigFlags( PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdTpmLocalityRegsEnabled, (UINT8) ConfigFlags->Flags.TpmLocalityRegsEnabled)); PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdMtrrsInitializedAtLoad, (UINT8) ConfigFlags->Flags.MtrrsInitializedAtLoad)); PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdVmbusEnabled, !ConfigFlags->Flags.VmbusDisabled)); + + // + // VMBus requires Hv. PcdHvEnabled was already set from the SEC platform + // type PPI in InitializePlatform(). Validate consistency here. + // + if (!PcdGetBool(PcdHvEnabled) && !ConfigFlags->Flags.VmbusDisabled) + { + DEBUG((DEBUG_ERROR, "Invalid config: VMBus enabled but Hv disabled.\n")); + FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + } + PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdPciDisableBusEnumeration, (UINT8) ConfigFlags->Flags.PciResourcesPreAssigned)); PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdForceDmaBounceEnabled, (UINT8) ConfigFlags->Flags.ForceDmaBounceEnabled)); diff --git a/MsvmPkg/PlatformPei/Platform.c b/MsvmPkg/PlatformPei/Platform.c index 655eac842e..ec5c8227fb 100644 --- a/MsvmPkg/PlatformPei/Platform.c +++ b/MsvmPkg/PlatformPei/Platform.c @@ -27,6 +27,7 @@ #if defined(MDE_CPU_AARCH64) #include +#include #endif #if defined (MDE_CPU_X64) #include @@ -1040,6 +1041,44 @@ Return Value: ZeroMem(&context, sizeof(context)); +#if defined(MDE_CPU_AARCH64) + // + // On AARCH64, determine HV presence from the platform type passed by the + // loader via the SEC platform type PPI. This is the single source of truth. + // + { + MSVM_SEC_PLATFORM_TYPE_PPI *SecPlatformTypePpi; + BOOLEAN HvEnabled; + + status = PeiServicesLocatePpi( + &gMsvmSecPlatformTypePpiGuid, + 0, + NULL, + (VOID **)&SecPlatformTypePpi + ); + if (EFI_ERROR(status)) + { + DEBUG((DEBUG_ERROR, "Failed to locate SEC Platform Type PPI: %r\n", status)); + FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + } + + switch (SecPlatformTypePpi->PlatformType) + { + case MsvmSecPlatformHyperV: + HvEnabled = TRUE; + break; + case MsvmSecPlatformGeneric: + HvEnabled = FALSE; + break; + default: + DEBUG((DEBUG_ERROR, "Unrecognized platform type: %d\n", SecPlatformTypePpi->PlatformType)); + FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + } + + PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdHvEnabled, HvEnabled)); + } +#endif + // // Determine whether this system is running isolated in order to determine // the correct mechanism for loading the configuration. diff --git a/MsvmPkg/PlatformPei/PlatformPei.inf b/MsvmPkg/PlatformPei/PlatformPei.inf index c6a785e213..40ac4cc2dd 100644 --- a/MsvmPkg/PlatformPei/PlatformPei.inf +++ b/MsvmPkg/PlatformPei/PlatformPei.inf @@ -183,6 +183,7 @@ gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled gMsvmPkgTokenSpaceGuid.PcdMtrrsInitializedAtLoad gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled + gMsvmPkgTokenSpaceGuid.PcdHvEnabled gMsvmPkgTokenSpaceGuid.PcdForceDmaBounceEnabled gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesPtr gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesSize @@ -203,6 +204,9 @@ [Ppis] gEfiPeiMasterBootModePpiGuid +[Ppis.AARCH64] + gMsvmSecPlatformTypePpiGuid ## CONSUMES + [Depex] TRUE diff --git a/MsvmPkg/Sec/AArch64/SecEntry.S b/MsvmPkg/Sec/AArch64/SecEntry.S index 9057c6aae2..116fd2e519 100644 --- a/MsvmPkg/Sec/AArch64/SecEntry.S +++ b/MsvmPkg/Sec/AArch64/SecEntry.S @@ -11,13 +11,12 @@ ASM_FUNC(_ModuleEntryPoint) // Loader sets register state that become inputs to this function // x0 - Firmware Volume Base Address // x1 - Stack Base Address + // x2 - Platform Type (MSVM_SEC_PLATFORM_TYPE; 0 = HyperV, 1 = Generic) // bl SerialWriteBanner // print banner to COM2 mov sp, x1 // Establish stack - leave x1 as second arg to C code - ldr x2, [x0, #8] // Get PEI Core entry from second entry in FV reset vector - bl SecStartupWithStack // jump to C code with 3 args (x0,x1,x2) ASM_FUNC(HvInvokeDebugger) diff --git a/MsvmPkg/Sec/AArch64/SecEntry.masm b/MsvmPkg/Sec/AArch64/SecEntry.masm deleted file mode 100644 index 4fd0a96c2a..0000000000 --- a/MsvmPkg/Sec/AArch64/SecEntry.masm +++ /dev/null @@ -1,128 +0,0 @@ -/** @file - SecEntry - - Copyright (c) Microsoft Corporation. - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - - AREA |.text|,ALIGN=3,CODE,READONLY - - EXPORT _ModuleEntryPoint - EXPORT SetGuestOsId - IMPORT SecStartupWithStack - -_ModuleEntryPoint PROC - // Loader sets register state that become inputs to this function - // x0 - Firmware Volume Base Address - // x1 - Stack Base Address - - // bl SerialWriteBanner // print banner to COM2 - mov sp, x1 // Establish stack - leave x1 as second arg to C code - b SecStartupWithStack // jump to C code with 2 args (x0,x1) - -_ModuleEntryPoint ENDP - -HvInvokeDebugger PROC - - // *untested* - - mov x2, x0 // supplemental Code: from caller in x0 - mov x1, 0x1 // reason: HV_DEBUG_INVOKE_REASON_CLOCK_WATCHDOG - ldr x0, =0x000000000001000A // hypercall input - IsFast = 1, CallCode = 0A - hvc #1 - and x0, x0, #0xFFFF // isolate result code - ret - -HvInvokeDebugger ENDP - -SetGuestOsId PROC - - ldr x0, =0x0000000100010051 // hypercall input (rep 1 argument, fast, HvCallSetVpRegisters) - ldr x1, =0xFFFFFFFFFFFFFFFF // partition id (self) - ldr x2, =0x00000000FFFFFFFE // pad + vp index (-2 == self) - ldr x3, =0x0000000000090002 // pad + RegisterName == HvRegisterGuestOsId - mov x4, #0 // pad - mov x5, #0x0001000000000000 // RegisterValue.Low == HvGuestOsVendorMicrosoft | HvGuestOsMicrosoftUndefined - mov x6, #0 // RegisterValue.High - hvc #1 - and x0, x0, #0xFFFF // isolate result - ret - -SetGuestOsId ENDP - -// -// SerialWriteBanner -// -// Writes "SECMAIN @ ELn" where n is the current EL. -// -SerialWriteBanner PROC - - // writes a - - ldr x9, =0x00000000EFFEB000 - mov w10, #0x1B // ESC - strb w10, [x9] - mov w10, #0x63 // 'c' - strb w10, [x9] - mov w10, #0x1B // ESC - strb w10, [x9] - mov w10, #0x5B // '[' - strb w10, [x9] - mov w10, #0x33 // '3' - strb w10, [x9] - mov w10, #0x4A // 'J' - strb w10, [x9] - mov w10, #0x53 // 'S' - strb w10, [x9] - mov w10, #0x45 // 'E' - strb w10, [x9] - mov w10, #0x43 // 'C' - strb w10, [x9] - mov w10, #0x4D // 'M' - strb w10, [x9] - mov w10, #0x41 // 'A' - strb w10, [x9] - mov w10, #0x49 // 'I' - strb w10, [x9] - mov w10, #0x4E // 'N' - strb w10, [x9] - mov w10, #0x20 // ' ' - strb w10, [x9] - mov w10, #0x40 // '@' - strb w10, [x9] - mov w10, #0x20 // ' ' - strb w10, [x9] - mov w10, #0x45 // 'E' - strb w10, [x9] - mov w10, #0x4C // 'L' - strb w10, [x9] - - // TODO: What's the constant for ARM64_CurrentEL format? - // mrs x8, #ARM64_CurrentEL - cmp x8, #0x8 - bgt %f3 - beq %f2 - cbnz x8, %f1 -5 - bne %b5 // shouldn't get here -1 - mov w10, #0x31 // '1' - b %f4 -2 - mov w10, #0x32 // '2' - b %f4 -3 - mov w10, #0x33 // '3' - b %f4 -4 - strb w10, [x9] - mov w10, #0x0D // '\r' - strb w10, [x9] - mov w10, #0x0A // '\n' - strb w10, [x9] - ret - -SerialWriteBanner ENDP - - END diff --git a/MsvmPkg/Sec/AArch64/SecMain.c b/MsvmPkg/Sec/AArch64/SecMain.c index a8741478de..f46b680c65 100644 --- a/MsvmPkg/Sec/AArch64/SecMain.c +++ b/MsvmPkg/Sec/AArch64/SecMain.c @@ -14,6 +14,7 @@ #include #include #include +#include VOID SetGuestOsId(); @@ -37,14 +38,23 @@ EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = TemporaryRamMigration }; +MSVM_SEC_PLATFORM_TYPE_PPI mSecPlatformTypePpi = +{ + MsvmSecPlatformHyperV +}; 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), + &gMsvmSecPlatformTypePpiGuid, + &mSecPlatformTypePpi + }, }; @@ -110,7 +120,8 @@ VOID EFIAPI SecStartupWithStack ( IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, - IN VOID *TopOfCurrentStack + IN VOID *TopOfCurrentStack, + IN UINT64 PlatformType ) /*++ @@ -125,6 +136,9 @@ Routine Description: TopOfCurrentStack - the top of the current stack + PlatformType - Platform type from the loader (MSVM_SEC_PLATFORM_TYPE). + 0 = HyperV (default), 1 = Generic. + Return Value: None. @@ -138,12 +152,26 @@ Return Value: DEBUG((DEBUG_VERBOSE, sequence)); DEBUG((DEBUG_VERBOSE, - ">>> SecStartupWithStack @ %p (%p, %p)\n", + ">>> SecStartupWithStack @ %p (%p, %p, 0x%llx)\n", SecStartupWithStack, BootFv, - TopOfCurrentStack + TopOfCurrentStack, + PlatformType )); + // + // Store the platform type for the PPI so PEI modules can access it. + // Fail immediately if the loader passed an unrecognized platform type. + // + if (PlatformType != MsvmSecPlatformHyperV && + PlatformType != MsvmSecPlatformGeneric) + { + DEBUG((DEBUG_ERROR, "Unrecognized platform type: 0x%llx\n", PlatformType)); + ASSERT(FALSE); + CpuDeadLoop(); + } + mSecPlatformTypePpi.PlatformType = (MSVM_SEC_PLATFORM_TYPE)PlatformType; + // // Initialize floating point operating environment // to be compliant with UEFI spec. @@ -181,8 +209,12 @@ Return Value: // // Set the guest OS ID so that hypercalls are possible. + // Only do this when running under Hyper-V. // - SetGuestOsId(); + if (PlatformType == MsvmSecPlatformHyperV) + { + SetGuestOsId(); + } // // Initialize Debug Agent to support source level debug in SEC/PEI phases diff --git a/MsvmPkg/Sec/SecMain.inf b/MsvmPkg/Sec/SecMain.inf index b5f039e977..09bf2c9d65 100644 --- a/MsvmPkg/Sec/SecMain.inf +++ b/MsvmPkg/Sec/SecMain.inf @@ -28,7 +28,6 @@ X64/SecMain.c [Sources.AARCH64] - AArch64/SecEntry.masm AArch64/SecEntry.S AArch64/SecMain.c @@ -63,6 +62,9 @@ [Ppis] gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED +[Ppis.AARCH64] + gMsvmSecPlatformTypePpiGuid # PPI ALWAYS_PRODUCED + [FixedPcd] gMsvmPkgTokenSpaceGuid.PcdBiosBaseAddress gMsvmPkgTokenSpaceGuid.PcdCom1RegisterBase