summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorJeremy Compostella <jeremy.compostella@intel.com>2024-10-08 16:55:51 -0700
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-10-17 13:32:42 +0000
commit996e740cc83aa499d91b3ab3ae857dab7578e05c (patch)
tree85d685e012b1c6f903b9b3aa4b5ef22578d6219d /MdeModulePkg
parent1b70dcd375765d293f57fe546710b98525e6a46d (diff)
downloadedk2-996e740cc83aa499d91b3ab3ae857dab7578e05c.tar.gz
edk2-996e740cc83aa499d91b3ab3ae857dab7578e05c.tar.bz2
edk2-996e740cc83aa499d91b3ab3ae857dab7578e05c.zip
MdeModulePkg: Fix PeiAllocatePages() corner case
I recently ran into an AllocatePages() hang. It turns out that AllocatePages() does not account for the Memory Allocation HOB when it makes the decision of allocating out of free memory. Here is the scenario: FreeMemoryTop - 0x71C03000 FreeMemoryBottom - 0x71BDBFD8 => We have 159,784 bytes left => ~39.0098 pages left. We attempt to allocate 39 pages. There are enough pages left but allocating those pages requires to allocate a Memory Allocation HOB which needs an extra 48 bytes. But once the pages are allocated, there are only 40 bytes left. In addition to taking into account the Memory Allocation HOB size, this commit reverses the condition to keep it simple. Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Core/Pei/Memory/MemoryServices.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
index 59613e5131..65e3405e9c 100644
--- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
+++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
@@ -555,6 +555,7 @@ PeiAllocatePages (
EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
EFI_PHYSICAL_ADDRESS *FreeMemoryBottom;
UINTN RemainingPages;
+ UINTN RemainingMemory;
UINTN Granularity;
UINTN Padding;
@@ -636,24 +637,18 @@ PeiAllocatePages (
//
// Verify that there is sufficient memory to satisfy the allocation.
//
- RemainingPages = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom) >> EFI_PAGE_SHIFT;
+ RemainingMemory = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom);
+ RemainingPages = RemainingMemory >> EFI_PAGE_SHIFT;
//
- // The number of remaining pages needs to be greater than or equal to that of the request pages.
+ // The number of remaining pages needs to be greater than or equal to that of
+ // the request pages. In addition, there should be enough space left to hold a
+ // Memory Allocation HOB.
//
Pages = ALIGN_VALUE (Pages, EFI_SIZE_TO_PAGES (Granularity));
- if (RemainingPages < Pages) {
- //
- // Try to find free memory by searching memory allocation HOBs.
- //
- Status = FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
- if (!EFI_ERROR (Status)) {
- return Status;
- }
-
- DEBUG ((DEBUG_ERROR, "AllocatePages failed: No 0x%lx Pages is available.\n", (UINT64)Pages));
- DEBUG ((DEBUG_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64)RemainingPages));
- return EFI_OUT_OF_RESOURCES;
- } else {
+ if ((RemainingPages > Pages) ||
+ ((RemainingPages == Pages) &&
+ ((RemainingMemory & EFI_PAGE_MASK) >= sizeof (EFI_HOB_MEMORY_ALLOCATION))))
+ {
//
// Update the PHIT to reflect the memory usage
//
@@ -674,6 +669,18 @@ PeiAllocatePages (
);
return EFI_SUCCESS;
+ } else {
+ //
+ // Try to find free memory by searching memory allocation HOBs.
+ //
+ Status = FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((DEBUG_ERROR, "AllocatePages failed: No 0x%lx Pages is available.\n", (UINT64)Pages));
+ DEBUG ((DEBUG_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64)RemainingPages));
+ return EFI_OUT_OF_RESOURCES;
}
}