MdePkg PeiMemoryAllocationLib: Update InternalAllocateAlignedPages

Update InternalAllocateAlignedPages to use PeiServicesFreePages.

Let the InternalAllocateAlignedPages in PeiMemoryAllocationLib use
same algorithm with InternalAllocateAlignedPages in
UefiMemoryAllocationLib.

Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Star Zeng 2017-03-03 18:15:13 +08:00
parent 2132ef05c4
commit c2ab95806b
1 changed files with 40 additions and 132 deletions

View File

@ -181,15 +181,12 @@ InternalAllocateAlignedPages (
IN UINTN Alignment
)
{
EFI_PHYSICAL_ADDRESS Memory;
EFI_PHYSICAL_ADDRESS AlignedMemory;
EFI_PEI_HOB_POINTERS Hob;
BOOLEAN SkipBeforeMemHob;
BOOLEAN SkipAfterMemHob;
EFI_PHYSICAL_ADDRESS HobBaseAddress;
UINT64 HobLength;
EFI_MEMORY_TYPE HobMemoryType;
UINTN TotalPages;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS Memory;
UINTN AlignedMemory;
UINTN AlignmentMask;
UINTN UnalignedPages;
UINTN RealPages;
//
// Alignment must be a power of two or zero.
@ -199,139 +196,50 @@ InternalAllocateAlignedPages (
if (Pages == 0) {
return NULL;
}
//
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
//
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
//
// We would rather waste some memory to save PEI code size.
// meaning in addition to the requested size for the aligned mem,
// we simply reserve an overhead memory equal to Alignmemt(page-aligned), no matter what.
// The overhead mem size could be reduced later with more involved malloc mechanisms
// (e.g., somthing that can detect the alignment boundary before allocating memory or
// can request that memory be allocated at a certain address that is aleady aligned).
//
TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment));
Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages);
if (Memory == 0) {
DEBUG((DEBUG_INFO, "Out of memory resource! \n"));
return NULL;
}
DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType));
//
// Alignment calculation
//
AlignedMemory = Memory;
if (Alignment > EFI_PAGE_SIZE) {
AlignedMemory = ALIGN_VALUE (Memory, Alignment);
}
DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages));
//
// In general three HOBs cover the total allocated space.
// The aligned portion is covered by the aligned mem HOB and
// the unaligned(to be freed) portions before and after the aligned portion are covered by newly created HOBs.
//
// Before mem HOB covers the region between "Memory" and "AlignedMemory"
// Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)"
// After mem HOB covers the region between "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" and "Memory + EFI_PAGES_TO_SIZE(TotalPages)"
//
// The before or after mem HOBs need to be skipped under special cases where the aligned portion
// touches either the top or bottom of the original allocated space.
//
SkipBeforeMemHob = FALSE;
SkipAfterMemHob = FALSE;
if (Memory == AlignedMemory) {
SkipBeforeMemHob = TRUE;
}
if ((Memory + EFI_PAGES_TO_SIZE(TotalPages)) == (AlignedMemory + EFI_PAGES_TO_SIZE(Pages))) {
//
// This condition is never met in the current implementation.
// There is always some after-mem since the overhead mem(used in TotalPages)
// is no less than Alignment.
// Calculate the total number of pages since alignment is larger than page size.
//
SkipAfterMemHob = TRUE;
}
AlignmentMask = Alignment - 1;
RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
//
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
//
ASSERT (RealPages > Pages);
//
// Search for the mem HOB referring to the original(unaligned) allocation
// and update the size and type if needed.
//
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
while (Hob.Raw != NULL) {
if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == Memory) {
break;
Status = PeiServicesAllocatePages (MemoryType, RealPages, &Memory);
if (EFI_ERROR (Status)) {
return NULL;
}
AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
if (UnalignedPages > 0) {
//
// Free first unaligned page(s).
//
Status = PeiServicesFreePages (Memory, UnalignedPages);
ASSERT_EFI_ERROR (Status);
}
Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
UnalignedPages = RealPages - Pages - UnalignedPages;
if (UnalignedPages > 0) {
//
// Free last unaligned page(s).
//
Status = PeiServicesFreePages (Memory, UnalignedPages);
ASSERT_EFI_ERROR (Status);
}
Hob.Raw = GET_NEXT_HOB (Hob);
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
}
ASSERT (Hob.Raw != NULL);
if (SkipBeforeMemHob) {
//
// Use this HOB as aligned mem HOB as there is no portion before it.
//
HobLength = EFI_PAGES_TO_SIZE(Pages);
Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;
} else {
//
// Use this HOB as before mem HOB and create a new HOB for the aligned portion
// Do not over-allocate pages in this case.
//
HobLength = (AlignedMemory - Memory);
Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;
Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory;
}
HobBaseAddress = Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress;
HobMemoryType = Hob.MemoryAllocation->AllocDescriptor.MemoryType;
//
// Build the aligned mem HOB if needed
//
if (!SkipBeforeMemHob) {
DEBUG((DEBUG_INFO, "Updated before-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
HobBaseAddress = AlignedMemory;
HobLength = EFI_PAGES_TO_SIZE(Pages);
HobMemoryType = MemoryType;
BuildMemoryAllocationHob (
HobBaseAddress,
HobLength,
HobMemoryType
);
DEBUG((DEBUG_INFO, "Created aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
} else {
if (HobBaseAddress != 0) {
DEBUG((DEBUG_INFO, "Updated aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
Status = PeiServicesAllocatePages (MemoryType, Pages, &Memory);
if (EFI_ERROR (Status)) {
return NULL;
}
AlignedMemory = (UINTN) Memory;
}
//
// Build the after mem HOB if needed
//
if (!SkipAfterMemHob) {
HobBaseAddress = AlignedMemory + EFI_PAGES_TO_SIZE(Pages);
HobLength = (Memory + EFI_PAGES_TO_SIZE(TotalPages)) - (AlignedMemory + EFI_PAGES_TO_SIZE(Pages));
HobMemoryType = EfiConventionalMemory;
BuildMemoryAllocationHob (
HobBaseAddress,
HobLength,
HobMemoryType
);
DEBUG((DEBUG_INFO, "Created after-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
}
return (VOID *) (UINTN) AlignedMemory;
return (VOID *) AlignedMemory;
}
/**