From nobody Fri Dec 27 03:00:56 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1503072084469372.8814538348922; Fri, 18 Aug 2017 09:01:24 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 9786921CFA61A; Fri, 18 Aug 2017 08:58:40 -0700 (PDT) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 6F62421CFA5FB for ; Fri, 18 Aug 2017 08:58:37 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Aug 2017 09:00:54 -0700 Received: from shwdeopenpsi068.ccr.corp.intel.com ([10.239.9.22]) by orsmga003.jf.intel.com with ESMTP; 18 Aug 2017 09:00:53 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,393,1498546800"; d="scan'208";a="1005243145" From: Star Zeng To: edk2-devel@lists.01.org Date: Sat, 19 Aug 2017 00:00:38 +0800 Message-Id: <1503072038-134760-6-git-send-email-star.zeng@intel.com> X-Mailer: git-send-email 2.7.0.windows.1 In-Reply-To: <1503072038-134760-1-git-send-email-star.zeng@intel.com> References: <1503072038-134760-1-git-send-email-star.zeng@intel.com> Subject: [edk2] [PATCH 5/5] MdeModule PeiCore: Support pre memory page allocation X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ruiyu Ni , Liming Gao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Support pre memory page allocation. Support FreePages. Allocation made prior to permanent memory will be migrated to permanent memory and the HOB updated. Cc: Liming Gao Cc: Ruiyu Ni Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng --- MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 27 +- MdeModulePkg/Core/Pei/Memory/MemoryServices.c | 559 ++++++++++++++++++++++= ++-- MdeModulePkg/Core/Pei/PeiMain.h | 89 +++- MdeModulePkg/Core/Pei/PeiMain/PeiMain.c | 8 +- MdeModulePkg/Core/Pei/Ppi/Ppi.c | 16 +- 5 files changed, 646 insertions(+), 53 deletions(-) diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/C= ore/Pei/Dispatcher/Dispatcher.c index ff43a90ba53c..04ece9a627d5 100644 --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c @@ -682,13 +682,13 @@ PeiCheckAndSwitchStack ( && (*StackPointer =3D=3D INIT_CAR_VALUE); StackPointer ++); =20 - DEBUG ((EFI_D_INFO, "Temp Stack : BaseAddress=3D0x%p Length=3D0x%X\n= ", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize)); - DEBUG ((EFI_D_INFO, "Temp Heap : BaseAddress=3D0x%p Length=3D0x%X\n= ", Private->HobList.Raw, (UINT32)((UINTN) Private->HobList.HandoffInformati= onTable->EfiFreeMemoryTop - (UINTN) Private->HobList.Raw))); - DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT3= 2)SecCoreData->TemporaryRamSize)); - DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n= ", + DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=3D0x%p Length=3D0x%X\n= ", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize)); + DEBUG ((DEBUG_INFO, "Temp Heap : BaseAddress=3D0x%p Length=3D0x%X\n= ", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSi= ze)); + DEBUG ((DEBUG_INFO, "Total temporary memory: %d bytes.\n", (UINT3= 2)SecCoreData->TemporaryRamSize)); + DEBUG ((DEBUG_INFO, " temporary memory stack ever used: %d by= tes.\n", (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UI= NTN)SecCoreData->StackBase)) )); - DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n= ", + DEBUG ((DEBUG_INFO, " temporary memory heap used for HobList: %d by= tes.\n", (UINT32)((UINTN)Private->HobList.HandoffInformationTable->Efi= FreeMemoryBottom - (UINTN)Private->HobList.Raw) )); DEBUG_CODE_END (); @@ -801,15 +801,27 @@ PeiCheckAndSwitchStack ( ); =20 // + // Migrate memory pages allocated in pre-memory phase. + // It could not be called before calling TemporaryRamSupportPpi->Tem= poraryRamMigration() + // as the migrated memory pages may be overridden by TemporaryRamSup= portPpi->TemporaryRamMigration(). + // + MigrateMemoryPages (Private, TRUE); + + // // Entry PEI Phase 2 // PeiCore (SecCoreData, NULL, Private); } else { // + // Migrate memory pages allocated in pre-memory phase. + // + MigrateMemoryPages (Private, FALSE); + + // // Migrate the PEI Services Table pointer from temporary RAM to perm= anent RAM. // MigratePeiServicesTablePointer (); - =20 + // // Heap Offset // @@ -837,7 +849,7 @@ PeiCheckAndSwitchStack ( // HeapTemporaryRamSize =3D (UINTN) (Private->HobList.HandoffInformatio= nTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->Efi= MemoryBottom); ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <=3D Private->FreePhysi= calMemoryTop); - CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, (UINT8 *) PeiTemporaryRamB= ase, HeapTemporaryRamSize); + CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, PeiTemporaryRamBase, HeapT= emporaryRamSize); =20 // // Migrate Stack @@ -846,7 +858,6 @@ PeiCheckAndSwitchStack ( =20 // // Copy Hole Range Data - // Convert PPI from Hole.=20 // if (HoleMemSize !=3D 0) { // diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/C= ore/Pei/Memory/MemoryServices.c index 719372e06128..4eb0bcde67cb 100644 --- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c +++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c @@ -1,7 +1,7 @@ /** @file EFI PEI Core memory services =20 -Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials =20 are licensed and made available under the terms and conditions of the BSD = License =20 which accompanies this distribution. The full text of the license may be = found at =20 @@ -110,18 +110,387 @@ PeiInstallPeiMemory ( } =20 /** - The purpose of the service is to publish an interface that allows=20 + Migrate memory pages allocated in pre-memory phase. + Copy memory pages at temporary heap top to permanent heap top. + + @param[in] Private Pointer to the private data passed in = from caller. + @param[in] TemporaryRamMigrated Temporary memory has been migrated to = permanent memory. + +**/ +VOID +MigrateMemoryPages ( + IN PEI_CORE_INSTANCE *Private, + IN BOOLEAN TemporaryRamMigrated + ) +{ + EFI_PHYSICAL_ADDRESS NewMemPagesBase; + EFI_PHYSICAL_ADDRESS MemPagesBase; + + Private->MemoryPages.Size =3D (UINTN) (Private->HobList.HandoffInformati= onTable->EfiMemoryTop - + Private->HobList.HandoffInformation= Table->EfiFreeMemoryTop); + if (Private->MemoryPages.Size =3D=3D 0) { + // + // No any memory page allocated in pre-memory phase. + // + return; + } + Private->MemoryPages.Base =3D Private->HobList.HandoffInformationTable->= EfiFreeMemoryTop; + + ASSERT (Private->MemoryPages.Size <=3D Private->FreePhysicalMemoryTop); + NewMemPagesBase =3D Private->FreePhysicalMemoryTop - Private->MemoryPage= s.Size; + NewMemPagesBase &=3D ~(UINT64)EFI_PAGE_MASK; + ASSERT (NewMemPagesBase >=3D Private->PhysicalMemoryBegin); + // + // Copy memory pages at temporary heap top to permanent heap top. + // + if (TemporaryRamMigrated) { + // + // Memory pages at temporary heap top has been migrated to permanent h= eap, + // Here still needs to copy them from permanent heap to permanent heap= top. + // + MemPagesBase =3D Private->MemoryPages.Base; + if (Private->HeapOffsetPositive) { + MemPagesBase +=3D Private->HeapOffset; + } else { + MemPagesBase -=3D Private->HeapOffset; + } + CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)MemPagesBase, = Private->MemoryPages.Size); + } else { + CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)Private->Memor= yPages.Base, Private->MemoryPages.Size); + } + + if (NewMemPagesBase >=3D Private->MemoryPages.Base) { + Private->MemoryPages.OffsetPositive =3D TRUE; + Private->MemoryPages.Offset =3D (UINTN)(NewMemPagesBase - Private->Mem= oryPages.Base); + } else { + Private->MemoryPages.OffsetPositive =3D FALSE; + Private->MemoryPages.Offset =3D (UINTN)(Private->MemoryPages.Base - Ne= wMemPagesBase); + } + + DEBUG ((DEBUG_INFO, "Pages Offset =3D 0x%lX\n", (UINT64) Private->Memory= Pages.Offset)); + + Private->FreePhysicalMemoryTop =3D NewMemPagesBase; +} + +/** + Migrate MemoryBaseAddress in memory allocation HOBs + from the temporary memory to PEI installed memory. + + @param[in] PrivateData Pointer to PeiCore's private data structur= e. + +**/ +VOID +ConvertMemoryAllocationHobs ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + EFI_PHYSICAL_ADDRESS OldMemPagesBase; + UINTN OldMemPagesSize; + + if (PrivateData->MemoryPages.Size =3D=3D 0) { + // + // No any memory page allocated in pre-memory phase. + // + return; + } + + OldMemPagesBase =3D PrivateData->MemoryPages.Base; + OldMemPagesSize =3D PrivateData->MemoryPages.Size; + + MemoryAllocationHob =3D NULL; + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw !=3D NULL) { + MemoryAllocationHob =3D (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw; + if ((MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress >=3D OldMe= mPagesBase) && + (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress < (OldMemP= agesBase + OldMemPagesSize)) + ) { + if (PrivateData->MemoryPages.OffsetPositive) { + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress +=3D Privat= eData->MemoryPages.Offset; + } else { + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress -=3D Privat= eData->MemoryPages.Offset; + } + } + + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } +} + +/** + Internal function to build a HOB for the memory allocation. + It will search and reuse the unused(freed) memory allocation HOB, + or build memory allocation HOB normally if no unused(freed) memory alloc= ation HOB found. + + @param[in] BaseAddress The 64 bit physical address of the memory. + @param[in] Length The length of the memory allocation in byt= es. + @param[in] MemoryType The type of memory allocated by this HOB. + +**/ +VOID +InternalBuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + + // + // Search unused(freed) memory allocation HOB. + // + MemoryAllocationHob =3D NULL; + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_UNUSED); + while (Hob.Raw !=3D NULL) { + if (Hob.Header->HobLength =3D=3D sizeof (EFI_HOB_MEMORY_ALLOCATION)) { + MemoryAllocationHob =3D (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw; + break; + } + + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_UNUSED, Hob.Raw); + } + + if (MemoryAllocationHob !=3D NULL) { + // + // Reuse the unused(freed) memory allocation HOB. + // + MemoryAllocationHob->Header.HobType =3D EFI_HOB_TYPE_MEMORY_ALLOCATION; + ZeroMem (&(MemoryAllocationHob->AllocDescriptor.Name), sizeof (EFI_GUI= D)); + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress =3D BaseAddress; + MemoryAllocationHob->AllocDescriptor.MemoryLength =3D Length; + MemoryAllocationHob->AllocDescriptor.MemoryType =3D MemoryType; + // + // Zero the reserved space to match HOB spec + // + ZeroMem (MemoryAllocationHob->AllocDescriptor.Reserved, sizeof (Memory= AllocationHob->AllocDescriptor.Reserved)); + } else { + // + // No unused(freed) memory allocation HOB found. + // Build memory allocation HOB normally. + // + BuildMemoryAllocationHob ( + BaseAddress, + Length, + MemoryType + ); + } +} + +/** + Update or split memory allocation HOB for memory pages allocate and free. + + @param[in, out] MemoryAllocationHob Pointer to the memory allocation H= OB + that needs to be updated or split. + On output, it will be filled with + the input Memory, Bytes and Memory= Type. + @param[in] Memory Memory to allocate or free. + @param[in] Bytes Bytes to allocate or free. + @param[in] MemoryType EfiConventionalMemory for pages fr= ee, + others for pages allocate. + +**/ +VOID +UpdateOrSplitMemoryAllocationHob ( + IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINT64 Bytes, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + if ((Memory + Bytes) < + (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllo= cationHob->AllocDescriptor.MemoryLength)) { + // + // Last pages need to be split out. + // + InternalBuildMemoryAllocationHob ( + Memory + Bytes, + (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllo= cationHob->AllocDescriptor.MemoryLength) - (Memory + Bytes), + MemoryAllocationHob->AllocDescriptor.MemoryType + ); + } + + if (Memory > MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress) { + // + // First pages need to be split out. + // + InternalBuildMemoryAllocationHob ( + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress, + Memory - MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress, + MemoryAllocationHob->AllocDescriptor.MemoryType + ); + } + + // + // Update the memory allocation HOB. + // + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress =3D Memory; + MemoryAllocationHob->AllocDescriptor.MemoryLength =3D Bytes; + MemoryAllocationHob->AllocDescriptor.MemoryType =3D MemoryType; +} + +/** + Merge adjacent free memory ranges in memory allocation HOBs. + + @retval TRUE There are free memory ranges merged. + @retval FALSE No free memory ranges merged. + +**/ +BOOLEAN +MergeFreeMemoryInMemoryAllocationHob ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS Hob2; + EFI_HOB_MEMORY_ALLOCATION *MemoryHob; + EFI_HOB_MEMORY_ALLOCATION *MemoryHob2; + UINT64 Start; + UINT64 End; + BOOLEAN Merged; + + Merged =3D FALSE; + + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw !=3D NULL) { + if (Hob.MemoryAllocation->AllocDescriptor.MemoryType =3D=3D EfiConvent= ionalMemory) { + MemoryHob =3D (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw; + Start =3D MemoryHob->AllocDescriptor.MemoryBaseAddress; + End =3D MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->Al= locDescriptor.MemoryLength; + + Hob2.Raw =3D GET_NEXT_HOB (Hob); + Hob2.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + while (Hob2.Raw !=3D NULL) { + if (Hob2.MemoryAllocation->AllocDescriptor.MemoryType =3D=3D EfiCo= nventionalMemory) { + MemoryHob2 =3D (EFI_HOB_MEMORY_ALLOCATION *) Hob2.Raw; + if (Start =3D=3D (MemoryHob2->AllocDescriptor.MemoryBaseAddress = + MemoryHob2->AllocDescriptor.MemoryLength)) { + // + // Merge adjacent two free memory ranges. + // + MemoryHob2->AllocDescriptor.MemoryLength +=3D MemoryHob->Alloc= Descriptor.MemoryLength; + Merged =3D TRUE; + // + // Mark MemoryHob to be unused(freed). + // + MemoryHob->Header.HobType =3D EFI_HOB_TYPE_UNUSED; + break; + } else if (End =3D=3D MemoryHob2->AllocDescriptor.MemoryBaseAddr= ess) { + // + // Merge adjacent two free memory ranges. + // + MemoryHob2->AllocDescriptor.MemoryBaseAddress =3D MemoryHob->A= llocDescriptor.MemoryBaseAddress; + MemoryHob2->AllocDescriptor.MemoryLength +=3D MemoryHob->Alloc= Descriptor.MemoryLength; + Merged =3D TRUE; + // + // Mark MemoryHob to be unused(freed). + // + MemoryHob->Header.HobType =3D EFI_HOB_TYPE_UNUSED; + break; + } + } + Hob2.Raw =3D GET_NEXT_HOB (Hob2); + Hob2.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob2.Raw); + } + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + + return Merged; +} + +/** + Find free memory by searching memory allocation HOBs. + + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of contiguous 4 KB pages to all= ocate. + @param[in] Granularity Page allocation granularity. + @param[out] Memory Pointer to a physical address. On output, = the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocate= d. + @retval EFI_NOT_FOUND No memory allocation HOB with big enough f= ree memory found. + +**/ +EFI_STATUS +FindFreeMemoryFromMemoryAllocationHob ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Granularity, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + UINT64 Bytes; + EFI_PHYSICAL_ADDRESS BaseAddress; + + Bytes =3D LShiftU64 (Pages, EFI_PAGE_SHIFT); + + BaseAddress =3D 0; + MemoryAllocationHob =3D NULL; + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw !=3D NULL) { + if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType =3D=3D EfiConven= tionalMemory) && + (Hob.MemoryAllocation->AllocDescriptor.MemoryLength >=3D Bytes)) { + // + // Found one memory allocation HOB with big enough free memory. + // + MemoryAllocationHob =3D (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw; + BaseAddress =3D MemoryAllocationHob->AllocDescriptor.MemoryBaseAddre= ss + + MemoryAllocationHob->AllocDescriptor.MemoryLength - By= tes; + // + // Make sure the granularity could be satisfied. + // + BaseAddress &=3D ~(UINT64)(Granularity - 1); + if (BaseAddress >=3D MemoryAllocationHob->AllocDescriptor.MemoryBase= Address) { + break; + } + BaseAddress =3D 0; + MemoryAllocationHob =3D NULL; + } + // + // Continue to find. + // + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + + if (MemoryAllocationHob !=3D NULL) { + UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, BaseAddress, By= tes, MemoryType); + *Memory =3D BaseAddress; + return EFI_SUCCESS; + } else { + if (MergeFreeMemoryInMemoryAllocationHob ()) { + // + // Retry if there are free memory ranges merged. + // + return FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Gra= nularity, Memory); + } + return EFI_NOT_FOUND; + } +} + +/** + The purpose of the service is to publish an interface that allows PEIMs to allocate memory ranges that are managed by the PEI Foundation. =20 + Prior to InstallPeiMemory() being called, PEI will allocate pages from t= he heap. + After InstallPeiMemory() is called, PEI will allocate pages within the r= egion + of memory provided by InstallPeiMemory() service in a best-effort fashio= n. + Location-specific allocations are not managed by the PEI foundation code. + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES tab= le published by the PEI Foundation. @param MemoryType The type of memory to allocate. @param Pages The number of contiguous 4 KB pages to allocate. - @param Memory Pointer to a physical address. On output, the a= ddress is set to the base=20 + @param Memory Pointer to a physical address. On output, the a= ddress is set to the base of the page range that was allocated. =20 @retval EFI_SUCCESS The memory range was successfully allocate= d. @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. - @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoa= derData, EfiRuntimeServicesCode,=20 + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoa= derData, EfiRuntimeServicesCode, EfiRuntimeServicesData, EfiBootServicesCod= e, EfiBootServicesData, EfiACPIReclaimMemory, EfiReservedMemoryTyp= e, or EfiACPIMemoryNVS. =20 @@ -135,6 +504,7 @@ PeiAllocatePages ( OUT EFI_PHYSICAL_ADDRESS *Memory ) { + EFI_STATUS Status; PEI_CORE_INSTANCE *PrivateData; EFI_PEI_HOB_POINTERS Hob; EFI_PHYSICAL_ADDRESS *FreeMemoryTop; @@ -157,6 +527,16 @@ PeiAllocatePages ( =20 Granularity =3D DEFAULT_PAGE_ALLOCATION_GRANULARITY; =20 + PrivateData =3D PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + Hob.Raw =3D PrivateData->HobList.Raw; + + if (Hob.Raw =3D=3D NULL) { + // + // HOB is not initialized yet. + // + return EFI_NOT_AVAILABLE_YET; + } + if (RUNTIME_PAGE_ALLOCATION_GRANULARITY > DEFAULT_PAGE_ALLOCATION_GRANU= LARITY && (MemoryType =3D=3D EfiACPIReclaimMemory || MemoryType =3D=3D EfiACPIMemoryNVS || @@ -169,23 +549,13 @@ PeiAllocatePages ( Granularity / SIZE_1KB)); } =20 - PrivateData =3D PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); - Hob.Raw =3D PrivateData->HobList.Raw; - =20 - // - // Check if Hob already available - // - if (!PrivateData->PeiMemoryInstalled) { + if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) { // - // When PeiInstallMemory is called but temporary memory has *not* been= moved to temporary memory, + // When PeiInstallMemory is called but temporary memory has *not* been= moved to permanent memory, // the AllocatePage will depend on the field of PEI_CORE_INSTANCE stru= cture. // - if (!PrivateData->SwitchStackSignal) { - return EFI_NOT_AVAILABLE_YET; - } else { - FreeMemoryTop =3D &(PrivateData->FreePhysicalMemoryTop); - FreeMemoryBottom =3D &(PrivateData->PhysicalMemoryBegin); - } + FreeMemoryTop =3D &(PrivateData->FreePhysicalMemoryTop); + FreeMemoryBottom =3D &(PrivateData->PhysicalMemoryBegin); } else { FreeMemoryTop =3D &(Hob.HandoffInformationTable->EfiFreeMemoryTop); FreeMemoryBottom =3D &(Hob.HandoffInformationTable->EfiFreeMemoryBott= om); @@ -207,7 +577,7 @@ PeiAllocatePages ( // Create a memory allocation HOB to cover // the pages that we will lose to rounding // - BuildMemoryAllocationHob ( + InternalBuildMemoryAllocationHob ( *(FreeMemoryTop), Padding & ~(UINTN)EFI_PAGE_MASK, EfiConventionalMemory @@ -216,18 +586,20 @@ PeiAllocatePages ( =20 // // Verify that there is sufficient memory to satisfy the allocation. - // For page allocation, the overhead sizeof (EFI_HOB_MEMORY_ALLOCATION) = needs to be considered. // - if ((UINTN) (*FreeMemoryTop - *FreeMemoryBottom) < (UINTN) ALIGN_VALUE (= sizeof (EFI_HOB_MEMORY_ALLOCATION), 8)) { - DEBUG ((EFI_D_ERROR, "AllocatePages failed: No space to build memory a= llocation hob.\n")); - return EFI_OUT_OF_RESOURCES; - } - RemainingPages =3D (UINTN)(*FreeMemoryTop - *FreeMemoryBottom - ALIGN_VA= LUE (sizeof (EFI_HOB_MEMORY_ALLOCATION), 8)) >> EFI_PAGE_SHIFT; + RemainingPages =3D (UINTN)(*FreeMemoryTop - *FreeMemoryBottom) >> EFI_PA= GE_SHIFT; // // The number of remaining pages needs to be greater than or equal to th= at of the request pages. // Pages =3D ALIGN_VALUE (Pages, EFI_SIZE_TO_PAGES (Granularity)); if (RemainingPages < Pages) { + // + // Try to find free memory by searching memory allocation HOBs. + // + Status =3D FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, G= ranularity, Memory); + if (!EFI_ERROR (Status)) { + return Status; + } DEBUG ((EFI_D_ERROR, "AllocatePages failed: No 0x%lx Pages is availabl= e.\n", (UINT64) Pages)); DEBUG ((EFI_D_ERROR, "There is only left 0x%lx pages memory resource t= o be allocated.\n", (UINT64) RemainingPages)); return EFI_OUT_OF_RESOURCES; @@ -245,7 +617,7 @@ PeiAllocatePages ( // // Create a memory allocation HOB. // - BuildMemoryAllocationHob ( + InternalBuildMemoryAllocationHob ( *(FreeMemoryTop), Pages * EFI_PAGE_SIZE, MemoryType @@ -256,6 +628,141 @@ PeiAllocatePages ( } =20 /** + Mark the memory allocation HOB to be unused(freed) and update *FreeMemor= yTop + if MemoryBaseAddress =3D=3D *FreeMemoryTop. + + @param[in] PrivateData Pointer to PeiCore's priva= te data structure. + @param[in, out] MemoryAllocationHobToFree Pointer to memory allocati= on HOB to be freed. + +**/ +VOID +FreeMemoryAllocationHob ( + IN PEI_CORE_INSTANCE *PrivateData, + IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHobToFree + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS *FreeMemoryTop; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + + Hob.Raw =3D PrivateData->HobList.Raw; + + if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) { + // + // When PeiInstallMemory is called but temporary memory has *not* been= moved to permanent memory, + // use the FreePhysicalMemoryTop field of PEI_CORE_INSTANCE structure. + // + FreeMemoryTop =3D &(PrivateData->FreePhysicalMemoryTop); + } else { + FreeMemoryTop =3D &(Hob.HandoffInformationTable->EfiFreeMemoryTop); + } + + if (MemoryAllocationHobToFree->AllocDescriptor.MemoryBaseAddress =3D=3D = *FreeMemoryTop) { + // + // Update *FreeMemoryTop. + // + *FreeMemoryTop +=3D MemoryAllocationHobToFree->AllocDescriptor.MemoryL= ength; + // + // Mark the memory allocation HOB to be unused(freed). + // + MemoryAllocationHobToFree->Header.HobType =3D EFI_HOB_TYPE_UNUSED; + + MemoryAllocationHob =3D NULL; + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw !=3D NULL) { + if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType =3D=3D EfiConv= entionalMemory) && + (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress =3D=3D = *FreeMemoryTop)) { + // + // Found memory allocation HOB that has EfiConventionalMemory Memo= ryType and + // MemoryBaseAddress =3D=3D new *FreeMemoryTop. + // + MemoryAllocationHob =3D (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw; + break; + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + // + // Free memory allocation HOB iteratively. + // + if (MemoryAllocationHob !=3D NULL) { + FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob); + } + } +} + +/** + Frees memory pages. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICE= S table published by the PEI Foundation. + @param[in] Memory The base physical address of the pages to = be freed. + @param[in] Pages The number of contiguous 4 KB pages to fre= e. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pa= ges is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not alloca= ted with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +PeiFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINT64 Bytes; + UINT64 Start; + UINT64 End; + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + + Bytes =3D LShiftU64 (Pages, EFI_PAGE_SHIFT); + Start =3D Memory; + End =3D Start + Bytes - 1; + + if (Pages =3D=3D 0 || ((Start & EFI_PAGE_MASK) !=3D 0) || (Start >=3D En= d)) { + return EFI_INVALID_PARAMETER; + } + + PrivateData =3D PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + Hob.Raw =3D PrivateData->HobList.Raw; + + if (Hob.Raw =3D=3D NULL) { + // + // HOB is not initialized yet. + // + return EFI_NOT_AVAILABLE_YET; + } + + MemoryAllocationHob =3D NULL; + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw !=3D NULL) { + if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType !=3D EfiConventi= onalMemory) && + (Memory >=3D Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddre= ss) && + ((Memory + Bytes) <=3D (Hob.MemoryAllocation->AllocDescriptor.Memo= ryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength))) { + // + // Found the memory allocation HOB that includes the memory pages to= be freed. + // + MemoryAllocationHob =3D (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw; + break; + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + + if (MemoryAllocationHob !=3D NULL) { + UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, Memory, Bytes, = EfiConventionalMemory); + FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob); + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} + +/** =20 Pool allocation service. Before permanent memory is discoveried, the poo= l will be allocated the heap in the temporary memory. Genenrally, the size of h= eap in temporary=20 diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMai= n.h index 277f54a0c6ad..fef3753e4b3b 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.h +++ b/MdeModulePkg/Core/Pei/PeiMain.h @@ -233,6 +233,10 @@ struct _PEI_CORE_INSTANCE { BOOLEAN HeapOffsetPositive; UINTN StackOffset; BOOLEAN StackOffsetPositive; + // + // Information for migrating memory pages allocated in pre-memory phase. + // + HOLE_MEMORY_DATA MemoryPages; PEICORE_FUNCTION_POINTER ShadowedPeiCore; CACHE_SECTION_DATA CacheSection; // @@ -263,7 +267,7 @@ struct _PEI_CORE_INSTANCE { =20 // // Temp Memory Range is not covered by PeiTempMem and Stack. - // Those Memory Range will be migrated into phisical memory.=20 + // Those Memory Range will be migrated into physical memory. // HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER]; }; @@ -423,7 +427,7 @@ InitializePpiServices ( =20 /** =20 - Migrate the Hob list from the temporary memory stack to PEI installed me= mory. + Migrate the Hob list from the temporary memory to PEI installed memory. =20 @param SecCoreData Points to a data structure containing SEC to PEI = handoff data, such as the size=20 and location of temporary RAM, the stack location= and the BFV location. @@ -877,30 +881,81 @@ PeiInstallPeiMemory ( ); =20 /** + Migrate memory pages allocated in pre-memory phase. + Copy memory pages at temporary heap top to permanent heap top. =20 - Memory allocation service on permanent memory, - not usable prior to the memory installation. + @param[in] Private Pointer to the private data passed in = from caller. + @param[in] TemporaryRamMigrated Temporary memory has been migrated to = permanent memory. =20 +**/ +VOID +MigrateMemoryPages ( + IN PEI_CORE_INSTANCE *Private, + IN BOOLEAN TemporaryRamMigrated + ); =20 - @param PeiServices An indirect pointer to the EFI_PEI_SERV= ICES table published by the PEI Foundation. - @param MemoryType Type of memory to allocate. - @param Pages Number of pages to allocate. - @param Memory Pointer of memory allocated. +/** + Migrate MemoryBaseAddress in memory allocation HOBs + from the temporary memory to PEI installed memory. =20 - @retval EFI_SUCCESS The allocation was successful - @retval EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. - @retval EFI_NOT_AVAILABLE_YET Called with permanent memory not availa= ble - @retval EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy= the requirement - to allocate the number of pages. + @param[in] PrivateData Pointer to PeiCore's private data structur= e. + +**/ +VOID +ConvertMemoryAllocationHobs ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + Prior to InstallPeiMemory() being called, PEI will allocate pages from t= he heap. + After InstallPeiMemory() is called, PEI will allocate pages within the r= egion + of memory provided by InstallPeiMemory() service in a best-effort fashio= n. + Location-specific allocations are not managed by the PEI foundation code. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES tab= le published by the PEI Foundation. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory Pointer to a physical address. On output, the a= ddress is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocate= d. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoa= derData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCod= e, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryTyp= e, or EfiACPIMemoryNVS. =20 **/ EFI_STATUS EFIAPI PeiAllocatePages ( - IN CONST EFI_PEI_SERVICES **PeiServices, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT EFI_PHYSICAL_ADDRESS *Memory + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICE= S table published by the PEI Foundation. + @param[in] Memory The base physical address of the pages to = be freed. + @param[in] Pages The number of contiguous 4 KB pages to fre= e. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pa= ges is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not alloca= ted with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +PeiFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages ); =20 /** diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pe= i/PeiMain/PeiMain.c index d2897437d776..3cd61906c3df 100644 --- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c +++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c @@ -64,7 +64,8 @@ EFI_PEI_SERVICES gPs =3D { PeiRegisterForShadow, PeiFfsFindSectionData3, PeiFfsGetFileInfo2, - PeiResetSystem2 + PeiResetSystem2, + PeiFreePages, }; =20 /** @@ -232,6 +233,11 @@ PeiCore ( HandoffInformationTable->EfiFreeMemoryBottom =3D HandoffInformationT= able->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER); =20 // + // We need convert MemoryBaseAddress in memory allocation HOBs + // + ConvertMemoryAllocationHobs (OldCoreData); + + // // We need convert the PPI descriptor's pointer // ConvertPpiPointers (SecCoreData, OldCoreData); diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Pp= i.c index 36b8c235b235..082c37945802 100644 --- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c +++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c @@ -103,7 +103,7 @@ ConvertSinglePpiPointer ( =20 /** =20 - Migrate PPI Pointers from the temporary memory stack to PEI installed me= mory. + Migrate PPI Pointers from the temporary memory to PEI installed memory. =20 @param SecCoreData Points to a data structure containing SEC to PEI = handoff data, such as the size=20 and location of temporary RAM, the stack location= and the BFV location. @@ -121,6 +121,20 @@ ConvertPpiPointers ( =20 for (Index =3D 0; Index < PcdGet32 (PcdPeiCoreMaxPpiSupported); Index++)= { if (Index < PrivateData->PpiData.PpiListEnd || Index > PrivateData->Pp= iData.NotifyListEnd) { + if (PrivateData->MemoryPages.Size !=3D 0) { + // + // Convert PPI pointer in old memory pages + // It needs to be done before Convert PPI pointer in old Heap + // + ConvertSinglePpiPointer ( + &PrivateData->PpiData.PpiListPtrs[Index], + (UINTN)PrivateData->MemoryPages.Base, + (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.= Size, + PrivateData->MemoryPages.Offset, + PrivateData->MemoryPages.OffsetPositive + ); + } + // // Convert PPI pointer in old Heap // --=20 2.7.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel