diff options
author | Jeremy Compostella <jeremy.compostella@intel.com> | 2024-10-08 16:55:51 -0700 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-10-17 13:32:42 +0000 |
commit | 996e740cc83aa499d91b3ab3ae857dab7578e05c (patch) | |
tree | 85d685e012b1c6f903b9b3aa4b5ef22578d6219d /MdeModulePkg | |
parent | 1b70dcd375765d293f57fe546710b98525e6a46d (diff) | |
download | edk2-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.c | 37 |
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;
}
}
|