OVMF's PlatformPei module discovers and installs permanent memory: InitializePlatform [OvmfPkg/PlatformPei/Platform.c] PublishPeiMemory() for Xen | MemDetect() otherwise PublishSystemMemory() [MdePkg/.../PeiResourcePublicationLib.c] PeiServicesInstallPeiMemory() [MdePkg/.../PeiServicesLib.c] PeiInstallPeiMemory() [MdeModulePkg/Core/Pei/.../MemoryServices.c]
This enables PeiDispatcher() [MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c] via the private "SwitchStackSignal" flag to migrate the PEI phase's temporary stack and heap to the permanent memory just discovered. (OVMF implements said migration in TemporaryRamMigration() [OvmfPkg/Sec/SecMain.c], exposed through the (optional) EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI interface.) The ever-current stack is exposed to the rest of the system through a memory allocation HOB that is named with a special GUID. The PEI dispatcher installs this HOB right before migrating the stack / heap from temporary RAM to permanent RAM: PeiDispatcher() [MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c] BuildStackHob() [MdePkg/Library/PeiHobLib/HobLib.c] TemporaryRamMigration() [OvmfPkg/Sec/SecMain.c] Per default, BuildStackHob() describes the PEI stack/heap as EfiBootServicesData. It makes sense because the PEI stack and heap are usually not needed to survive into (or even after) runtime. However, in OVMF we rewrite the area during S3 Resume (when we repeat the same temporary RAM migration), hence we must prevent the OS from repurposing it. Let's look up the HOB and flip the described memory type to ACPI NVS in TemporaryRamMigration(). (Note that refreshing the preinstalled stack allocation HOB is permitted, the DXE IPL does it too when not on the S3 resume path): HandOffToDxeCore() UpdateStackHob() Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- OvmfPkg/Sec/SecMain.inf | 4 ++++ OvmfPkg/Sec/SecMain.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index 91d0a44..d0f9455 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -59,6 +59,7 @@ PeCoffGetEntryPointLib PeCoffExtraActionLib ExtractGuidedSectionLib + HobLib [Ppis] gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED @@ -66,3 +67,6 @@ [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfMemFvBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfMemFvSize + +[Guids] + gEfiHobMemoryAllocStackGuid diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index 3882dad..77aeffa 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -28,9 +28,12 @@ #include <Library/PeCoffGetEntryPointLib.h> #include <Library/PeCoffExtraActionLib.h> #include <Library/ExtractGuidedSectionLib.h> +#include <Library/HobLib.h> #include <Ppi/TemporaryRamSupport.h> +#include <Guid/MemoryAllocationHob.h> + #define SEC_IDT_ENTRY_COUNT 34 typedef struct _SEC_IDT_TABLE { @@ -695,6 +698,31 @@ SecStartupPhase2( CpuDeadLoop (); } +/** + Expand the lifetime of the migrated PEI stack / heap area by changing its + allocation type to ACPI NVS. +**/ +VOID +EFIAPI +ReservePermanentFromOs ( + VOID + ) +{ + EFI_HOB_MEMORY_ALLOCATION *MemHob; + + for (MemHob = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); MemHob != NULL; + MemHob = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, + GET_NEXT_HOB (MemHob))) { + if (CompareGuid (&gEfiHobMemoryAllocStackGuid, + &MemHob->AllocDescriptor.Name)) { + break; + } + } + ASSERT (MemHob != NULL); + ASSERT (MemHob->AllocDescriptor.MemoryType == EfiBootServicesData); + MemHob->AllocDescriptor.MemoryType = EfiACPIMemoryNVS; +} + EFI_STATUS EFIAPI TemporaryRamMigration ( @@ -715,6 +743,13 @@ TemporaryRamMigration ( DEBUG ((EFI_D_ERROR, "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n", (UINTN)TemporaryMemoryBase, (UINTN)PermanentMemoryBase, CopySize)); + // + // This pokes into a HOB that's currently in temporary memory itself. Update + // it before it is migrated to permanent memory, with the rest of temporary + // memory. + // + ReservePermanentFromOs (); + OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1)); -- 1.8.3.1 ------------------------------------------------------------------------------ Sponsored by Intel(R) XDK Develop, test and display web and hybrid apps with a single code base. Download it for free now! http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel