mirror of https://github.com/acidanthera/audk.git
Only reserve the aligned memory instead of reserving the unaligned memory in PeiMemoryAllocationLib
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gao, Liming <liming.gao@intel.com> Reviewed-by: Michael Kinney <michael.d.kinney@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15878 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
fa7fadf78e
commit
6809c8723e
|
@ -2,7 +2,7 @@
|
||||||
Support routines for memory allocation routines
|
Support routines for memory allocation routines
|
||||||
based on PeiService for PEI phase drivers.
|
based on PeiService for PEI phase drivers.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -207,8 +207,15 @@ InternalAllocateAlignedPages (
|
||||||
IN UINTN Alignment
|
IN UINTN Alignment
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
VOID *Memory;
|
EFI_PHYSICAL_ADDRESS Memory;
|
||||||
UINTN AlignmentMask;
|
EFI_PHYSICAL_ADDRESS AlignedMemory;
|
||||||
|
EFI_PEI_HOB_POINTERS Hob;
|
||||||
|
BOOLEAN SkipBeforeMemHob = FALSE;
|
||||||
|
BOOLEAN SkipAfterMemHob = FALSE;
|
||||||
|
EFI_PHYSICAL_ADDRESS HobBaseAddress;
|
||||||
|
UINT64 HobLength;
|
||||||
|
EFI_MEMORY_TYPE HobMemoryType;
|
||||||
|
UINTN TotalPages;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Alignment must be a power of two or zero.
|
// Alignment must be a power of two or zero.
|
||||||
|
@ -221,17 +228,134 @@ InternalAllocateAlignedPages (
|
||||||
//
|
//
|
||||||
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
|
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
|
||||||
//
|
//
|
||||||
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
|
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
|
||||||
|
|
||||||
//
|
//
|
||||||
// We would rather waste some memory to save PEI code size.
|
// 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).
|
||||||
//
|
//
|
||||||
Memory = InternalAllocatePages (MemoryType, Pages + EFI_SIZE_TO_PAGES (Alignment));
|
TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment));
|
||||||
if (Alignment == 0) {
|
Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages);
|
||||||
AlignmentMask = Alignment;
|
if (Memory == 0) {
|
||||||
} else {
|
DEBUG((DEBUG_INFO, "Out of memory resource! \n"));
|
||||||
AlignmentMask = Alignment - 1;
|
return NULL;
|
||||||
}
|
}
|
||||||
return (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask);
|
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.
|
||||||
|
//
|
||||||
|
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.
|
||||||
|
//
|
||||||
|
SkipAfterMemHob = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
//
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue