diff options
author | lgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-03-17 10:00:52 +0000 |
---|---|---|
committer | lgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-03-17 10:00:52 +0000 |
commit | f799b36d2ce86878da352cda810bd695e9f7b39b (patch) | |
tree | a04166dd13f4c9b8b8d3dcdcf4663553634ef365 | |
parent | 429592f320ef15fe66a5cefd46224ec816c15162 (diff) | |
download | edk2-f799b36d2ce86878da352cda810bd695e9f7b39b.tar.gz |
1. Sync patch r10284 from main trunk.
Hold Memory Lock until DEBUG_CLEAR_MEMORY called in CoreFreePages().
2. Sync patch r10335 from main trunk.
Avoid DEBUG_CLEAR_MEMORY clearing MemoryMap internal structure.
3. Sync patch r10579 from main trunk.
1) Improve how memory usage is tracked in DXE Core
2) Update GetMemoryMap() to merge adjacent memory descriptors with identical types and attributes.
4. Sync patch r10589 from main trunk.
Add a missing parameter description in the function header for CoreFindFreePagesI().
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/UDK2008@11410 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r-- | MdeModulePkg/Core/Dxe/Mem/Page.c | 226 |
1 files changed, 174 insertions, 52 deletions
diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index 4f31b5f57f..d0ccec84e2 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -1,7 +1,7 @@ /** @file
UEFI Memory page management functions.
-Copyright (c) 2007 - 2008, Intel Corporation. <BR>
+Copyright (c) 2007 - 2011, Intel Corporation. <BR>
All rights reserved. This program and the accompanying materials
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
@@ -71,6 +71,7 @@ EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = { };
EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = MAX_ADDRESS;
+EFI_PHYSICAL_ADDRESS mDefaultBaseAddress = MAX_ADDRESS;
EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
{ EfiReservedMemoryType, 0 },
@@ -369,18 +370,20 @@ CoreFreeMemoryMapStack ( Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.
**/
-VOID
+BOOLEAN
PromoteMemoryResource (
VOID
)
{
- LIST_ENTRY *Link;
- EFI_GCD_MAP_ENTRY *Entry;
+ LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ BOOLEAN Promoted;
DEBUG ((DEBUG_PAGE, "Promote the memory resource\n"));
CoreAcquireGcdMemoryLock ();
+ Promoted = FALSE;
Link = mGcdMemorySpaceMap.ForwardLink;
while (Link != &mGcdMemorySpaceMap) {
@@ -410,6 +413,7 @@ PromoteMemoryResource ( );
CoreFreeMemoryMapStack ();
+ Promoted = TRUE;
}
Link = Link->ForwardLink;
@@ -417,7 +421,7 @@ PromoteMemoryResource ( CoreReleaseGcdMemoryLock ();
- return;
+ return Promoted;
}
@@ -456,7 +460,6 @@ CoreAddMemoryDescriptor ( if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) {
return;
}
-
CoreAcquireMemoryLock ();
End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
CoreAddRange (Type, Start, End, Attribute);
@@ -549,7 +552,6 @@ CoreAddMemoryDescriptor ( if (Type < 0 || Type > EfiMaxMemoryType) {
continue;
}
-
if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
CoreFreePages (
mMemoryTypeStatistics[Type].BaseAddress,
@@ -671,8 +673,8 @@ CoreConvertPages ( // Update counters for the number of pages allocated to each memory type
//
if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {
- if (Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress &&
- Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) {
+ if ((Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress && Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) ||
+ (Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress) ) {
if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {
mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;
} else {
@@ -682,10 +684,10 @@ CoreConvertPages ( }
if (NewType >= 0 && NewType < EfiMaxMemoryType) {
- if (Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) {
+ if ((Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) ||
+ (Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress) ) {
mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;
- if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages >
- gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {
+ if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {
gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;
}
}
@@ -756,6 +758,9 @@ CoreConvertPages ( // Add our new range in
//
CoreAddRange (NewType, Start, RangeEnd, Attribute);
+ if (NewType == EfiConventionalMemory) {
+ DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) Start, (UINTN) (RangeEnd - Start + 1));
+ }
//
// Move any map descriptor stack to general pool
@@ -782,6 +787,7 @@ CoreConvertPages ( the requested address.
@param MaxAddress The address that the range must be below
+ @param MinAddress The address that the range must be above
@param NumberOfPages Number of pages needed
@param NewType The type of memory the range is going to be
turned into
@@ -793,6 +799,7 @@ CoreConvertPages ( UINT64
CoreFindFreePagesI (
IN UINT64 MaxAddress,
+ IN UINT64 MinAddress,
IN UINT64 NumberOfPages,
IN EFI_MEMORY_TYPE NewType,
IN UINTN Alignment
@@ -849,9 +856,9 @@ CoreFindFreePagesI ( DescEnd = Entry->End;
//
- // If desc is past max allowed address, skip it
+ // If desc is past max allowed address or below min allowed address, skip it
//
- if (DescStart >= MaxAddress) {
+ if ((DescStart >= MaxAddress) || (DescEnd < MinAddress)) {
continue;
}
@@ -871,6 +878,12 @@ CoreFindFreePagesI ( DescNumberOfBytes = DescEnd - DescStart + 1;
if (DescNumberOfBytes >= NumberOfBytes) {
+ //
+ // If the start of the allocated range is below the min address allowed, skip it
+ //
+ if ((DescEnd - NumberOfBytes + 1) < MinAddress) {
+ continue;
+ }
//
// If this is the best match so far remember it
@@ -918,41 +931,62 @@ FindFreePages ( IN UINTN Alignment
)
{
- UINT64 NewMaxAddress;
- UINT64 Start;
+ UINT64 Start;
- NewMaxAddress = MaxAddress;
+ //
+ // Attempt to find free pages in the preferred bin based on the requested memory type
+ //
+ if (NewType >= 0 && NewType < EfiMaxMemoryType && MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {
+ Start = CoreFindFreePagesI (
+ mMemoryTypeStatistics[NewType].MaximumAddress,
+ mMemoryTypeStatistics[NewType].BaseAddress,
+ NoPages,
+ NewType,
+ Alignment
+ );
+ if (Start != 0) {
+ return Start;
+ }
+ }
- if (NewType >= 0 && NewType < EfiMaxMemoryType && NewMaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {
- NewMaxAddress = mMemoryTypeStatistics[NewType].MaximumAddress;
- } else {
- if (NewMaxAddress > mDefaultMaximumAddress) {
- NewMaxAddress = mDefaultMaximumAddress;
+ //
+ // Attempt to find free pages in the default allocation bin
+ //
+ if (MaxAddress >= mDefaultMaximumAddress) {
+ Start = CoreFindFreePagesI (mDefaultMaximumAddress, 0, NoPages, NewType, Alignment);
+ if (Start != 0) {
+ if (Start < mDefaultBaseAddress) {
+ mDefaultBaseAddress = Start;
+ }
+ return Start;
}
}
- Start = CoreFindFreePagesI (NewMaxAddress, NoPages, NewType, Alignment);
- if (Start == 0) {
- Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
- if (Start == 0) {
- //
- // Here means there may be no enough memory to use, so try to go through
- // all the memory descript to promote the untested memory directly
- //
- PromoteMemoryResource ();
+ //
+ // The allocation did not succeed in any of the prefered bins even after
+ // promoting resources. Attempt to find free pages anywhere is the requested
+ // address range. If this allocation fails, then there are not enough
+ // resources anywhere to satisfy the request.
+ //
+ Start = CoreFindFreePagesI (MaxAddress, 0, NoPages, NewType, Alignment);
+ if (Start != 0) {
+ return Start;
+ }
- //
- // Allocate memory again after the memory resource re-arranged
- //
- Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
- }
+ //
+ // If allocations from the preferred bins fail, then attempt to promote memory resources.
+ //
+ if (!PromoteMemoryResource ()) {
+ return 0;
}
- return Start;
+ //
+ // If any memory resources were promoted, then re-attempt the allocation
+ //
+ return FindFreePages (MaxAddress, NoPages, NewType, Alignment);
}
-
/**
Allocates pages from the memory map.
@@ -1095,8 +1129,8 @@ CoreFreePages ( }
}
if (Link == &gMemoryMap) {
- CoreReleaseMemoryLock ();
- return EFI_NOT_FOUND;
+ Status = EFI_NOT_FOUND;
+ goto Done;
}
Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
@@ -1112,8 +1146,8 @@ CoreFreePages ( }
if ((Memory & (Alignment - 1)) != 0) {
- CoreReleaseMemoryLock ();
- return EFI_INVALID_PARAMETER;
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
}
NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
@@ -1121,23 +1155,96 @@ CoreFreePages ( Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
- CoreReleaseMemoryLock ();
-
if (EFI_ERROR (Status)) {
- return Status;
+ goto Done;
}
+Done:
+ CoreReleaseMemoryLock ();
+ return Status;
+}
+
+/**
+ This function checks to see if the last memory map descriptor in a memory map
+ can be merged with any of the other memory map descriptors in a memorymap.
+ Memory descriptors may be merged if they are adjacent and have the same type
+ and attributes.
+
+ @param MemoryMap A pointer to the start of the memory map.
+ @param MemoryMapDescriptor A pointer to the last descriptor in MemoryMap.
+ @param DescriptorSize The size, in bytes, of an individual
+ EFI_MEMORY_DESCRIPTOR.
+
+ @return A pointer to the next available descriptor in MemoryMap
+
+**/
+EFI_MEMORY_DESCRIPTOR *
+MergeMemoryMapDescriptor (
+ IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN EFI_MEMORY_DESCRIPTOR *MemoryMapDescriptor,
+ IN UINTN DescriptorSize
+ )
+{
//
- // Destroy the contents
+ // Traverse the array of descriptors in MemoryMap
//
- if (Memory < MAX_ADDRESS) {
- DEBUG_CLEAR_MEMORY ((VOID *)(UINTN)Memory, NumberOfPages << EFI_PAGE_SHIFT);
+ for (; MemoryMap != MemoryMapDescriptor; MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize)) {
+ //
+ // Check to see if the Type fields are identical.
+ //
+ if (MemoryMap->Type != MemoryMapDescriptor->Type) {
+ continue;
+ }
+
+ //
+ // Check to see if the Attribute fields are identical.
+ //
+ if (MemoryMap->Attribute != MemoryMapDescriptor->Attribute) {
+ continue;
+ }
+
+ //
+ // Check to see if MemoryMapDescriptor is immediately above MemoryMap
+ //
+ if (MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) {
+ //
+ // Merge MemoryMapDescriptor into MemoryMap
+ //
+ MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;
+
+ //
+ // Return MemoryMapDescriptor as the next available slot int he MemoryMap array
+ //
+ return MemoryMapDescriptor;
+ }
+
+ //
+ // Check to see if MemoryMapDescriptor is immediately below MemoryMap
+ //
+ if (MemoryMap->PhysicalStart - EFI_PAGES_TO_SIZE ((UINTN)MemoryMapDescriptor->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) {
+ //
+ // Merge MemoryMapDescriptor into MemoryMap
+ //
+ MemoryMap->PhysicalStart = MemoryMapDescriptor->PhysicalStart;
+ MemoryMap->VirtualStart = MemoryMapDescriptor->VirtualStart;
+ MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;
+
+ //
+ // Return MemoryMapDescriptor as the next available slot int he MemoryMap array
+ //
+ return MemoryMapDescriptor;
+ }
}
- return Status;
+ //
+ // MemoryMapDescrtiptor could not be merged with any descriptors in MemoryMap.
+ //
+ // Return the slot immediately after MemoryMapDescriptor as the next available
+ // slot in the MemoryMap array
+ //
+ return NEXT_MEMORY_DESCRIPTOR (MemoryMapDescriptor, DescriptorSize);
}
-
/**
This function returns a copy of the current memory map. The map is an array of
memory descriptors, each of which describes a contiguous block of memory.
@@ -1186,6 +1293,7 @@ CoreGetMemoryMap ( MEMORY_MAP *Entry;
EFI_GCD_MAP_ENTRY *GcdMapEntry;
EFI_MEMORY_TYPE Type;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
//
// Make sure the parameters are valid
@@ -1251,6 +1359,7 @@ CoreGetMemoryMap ( // Build the map
//
ZeroMem (MemoryMap, BufferSize);
+ MemoryMapStart = MemoryMap;
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
ASSERT (Entry->VirtualStart == 0);
@@ -1284,7 +1393,11 @@ CoreGetMemoryMap ( MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
}
- MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
+ //
+ // Check to see if the new Memory Map Descriptor can be merged with an
+ // existing descriptor if they are adjacent and have the same attributes
+ //
+ MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
}
for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
@@ -1311,11 +1424,20 @@ CoreGetMemoryMap ( }
}
- MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
+ //
+ // Check to see if the new Memory Map Descriptor can be merged with an
+ // existing descriptor if they are adjacent and have the same attributes
+ //
+ MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
}
}
}
+ //
+ // Compute the size of the buffer actually used after all memory map descriptor merge operations
+ //
+ BufferSize = ((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart);
+
Status = EFI_SUCCESS;
Done:
|