mirror of https://github.com/acidanthera/audk.git
1) Improve how memory usage is tracked in DXE Core
2) Update GetMemoryMap() to merge adjacent memory descriptors with identical types and attributes. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10579 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
2a2e33b20f
commit
2345e7d4a4
|
@ -71,6 +71,7 @@ EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = MAX_ADDRESS;
|
EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = MAX_ADDRESS;
|
||||||
|
EFI_PHYSICAL_ADDRESS mDefaultBaseAddress = MAX_ADDRESS;
|
||||||
|
|
||||||
EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
|
EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
|
||||||
{ EfiReservedMemoryType, 0 },
|
{ EfiReservedMemoryType, 0 },
|
||||||
|
@ -374,18 +375,20 @@ CoreFreeMemoryMapStack (
|
||||||
Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.
|
Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
VOID
|
BOOLEAN
|
||||||
PromoteMemoryResource (
|
PromoteMemoryResource (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LIST_ENTRY *Link;
|
LIST_ENTRY *Link;
|
||||||
EFI_GCD_MAP_ENTRY *Entry;
|
EFI_GCD_MAP_ENTRY *Entry;
|
||||||
|
BOOLEAN Promoted;
|
||||||
|
|
||||||
DEBUG ((DEBUG_PAGE, "Promote the memory resource\n"));
|
DEBUG ((DEBUG_PAGE, "Promote the memory resource\n"));
|
||||||
|
|
||||||
CoreAcquireGcdMemoryLock ();
|
CoreAcquireGcdMemoryLock ();
|
||||||
|
|
||||||
|
Promoted = FALSE;
|
||||||
Link = mGcdMemorySpaceMap.ForwardLink;
|
Link = mGcdMemorySpaceMap.ForwardLink;
|
||||||
while (Link != &mGcdMemorySpaceMap) {
|
while (Link != &mGcdMemorySpaceMap) {
|
||||||
|
|
||||||
|
@ -415,6 +418,7 @@ PromoteMemoryResource (
|
||||||
);
|
);
|
||||||
CoreFreeMemoryMapStack ();
|
CoreFreeMemoryMapStack ();
|
||||||
|
|
||||||
|
Promoted = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Link = Link->ForwardLink;
|
Link = Link->ForwardLink;
|
||||||
|
@ -422,7 +426,7 @@ PromoteMemoryResource (
|
||||||
|
|
||||||
CoreReleaseGcdMemoryLock ();
|
CoreReleaseGcdMemoryLock ();
|
||||||
|
|
||||||
return;
|
return Promoted;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
This function try to allocate Runtime code & Boot time code memory range. If LMFA enabled, 2 patchable PCD
|
This function try to allocate Runtime code & Boot time code memory range. If LMFA enabled, 2 patchable PCD
|
||||||
|
@ -744,8 +748,8 @@ CoreConvertPages (
|
||||||
// Update counters for the number of pages allocated to each memory type
|
// Update counters for the number of pages allocated to each memory type
|
||||||
//
|
//
|
||||||
if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {
|
if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {
|
||||||
if (Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress &&
|
if ((Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress && Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) ||
|
||||||
Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) {
|
(Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress) ) {
|
||||||
if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {
|
if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {
|
||||||
mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;
|
mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -755,10 +759,10 @@ CoreConvertPages (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewType >= 0 && NewType < EfiMaxMemoryType) {
|
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;
|
mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;
|
||||||
if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages >
|
if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {
|
||||||
gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {
|
|
||||||
gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;
|
gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -869,6 +873,7 @@ CoreConvertPages (
|
||||||
UINT64
|
UINT64
|
||||||
CoreFindFreePagesI (
|
CoreFindFreePagesI (
|
||||||
IN UINT64 MaxAddress,
|
IN UINT64 MaxAddress,
|
||||||
|
IN UINT64 MinAddress,
|
||||||
IN UINT64 NumberOfPages,
|
IN UINT64 NumberOfPages,
|
||||||
IN EFI_MEMORY_TYPE NewType,
|
IN EFI_MEMORY_TYPE NewType,
|
||||||
IN UINTN Alignment
|
IN UINTN Alignment
|
||||||
|
@ -925,9 +930,9 @@ CoreFindFreePagesI (
|
||||||
DescEnd = Entry->End;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,6 +952,12 @@ CoreFindFreePagesI (
|
||||||
DescNumberOfBytes = DescEnd - DescStart + 1;
|
DescNumberOfBytes = DescEnd - DescStart + 1;
|
||||||
|
|
||||||
if (DescNumberOfBytes >= NumberOfBytes) {
|
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
|
// If this is the best match so far remember it
|
||||||
|
@ -994,41 +1005,62 @@ FindFreePages (
|
||||||
IN UINTN Alignment
|
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 && NewMaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {
|
//
|
||||||
NewMaxAddress = mMemoryTypeStatistics[NewType].MaximumAddress;
|
if (NewType >= 0 && NewType < EfiMaxMemoryType && MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {
|
||||||
} else {
|
Start = CoreFindFreePagesI (
|
||||||
if (NewMaxAddress > mDefaultMaximumAddress) {
|
mMemoryTypeStatistics[NewType].MaximumAddress,
|
||||||
NewMaxAddress = mDefaultMaximumAddress;
|
mMemoryTypeStatistics[NewType].BaseAddress,
|
||||||
|
NoPages,
|
||||||
|
NewType,
|
||||||
|
Alignment
|
||||||
|
);
|
||||||
|
if (Start != 0) {
|
||||||
|
return Start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Start = CoreFindFreePagesI (NewMaxAddress, NoPages, NewType, Alignment);
|
//
|
||||||
if (Start == 0) {
|
// Attempt to find free pages in the default allocation bin
|
||||||
Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
|
//
|
||||||
if (Start == 0) {
|
if (MaxAddress >= mDefaultMaximumAddress) {
|
||||||
//
|
Start = CoreFindFreePagesI (mDefaultMaximumAddress, 0, NoPages, NewType, Alignment);
|
||||||
// Here means there may be no enough memory to use, so try to go through
|
if (Start != 0) {
|
||||||
// all the memory descript to promote the untested memory directly
|
if (Start < mDefaultBaseAddress) {
|
||||||
//
|
mDefaultBaseAddress = Start;
|
||||||
PromoteMemoryResource ();
|
}
|
||||||
|
return Start;
|
||||||
//
|
|
||||||
// Allocate memory again after the memory resource re-arranged
|
|
||||||
//
|
|
||||||
Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Start;
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If allocations from the preferred bins fail, then attempt to promote memory resources.
|
||||||
|
//
|
||||||
|
if (!PromoteMemoryResource ()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If any memory resources were promoted, then re-attempt the allocation
|
||||||
|
//
|
||||||
|
return FindFreePages (MaxAddress, NoPages, NewType, Alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Allocates pages from the memory map.
|
Allocates pages from the memory map.
|
||||||
|
|
||||||
|
@ -1206,6 +1238,86 @@ Done:
|
||||||
return Status;
|
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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Traverse the array of descriptors in MemoryMap
|
||||||
|
//
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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
|
This function returns a copy of the current memory map. The map is an array of
|
||||||
|
@ -1255,6 +1367,7 @@ CoreGetMemoryMap (
|
||||||
MEMORY_MAP *Entry;
|
MEMORY_MAP *Entry;
|
||||||
EFI_GCD_MAP_ENTRY *GcdMapEntry;
|
EFI_GCD_MAP_ENTRY *GcdMapEntry;
|
||||||
EFI_MEMORY_TYPE Type;
|
EFI_MEMORY_TYPE Type;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure the parameters are valid
|
// Make sure the parameters are valid
|
||||||
|
@ -1320,6 +1433,7 @@ CoreGetMemoryMap (
|
||||||
// Build the map
|
// Build the map
|
||||||
//
|
//
|
||||||
ZeroMem (MemoryMap, BufferSize);
|
ZeroMem (MemoryMap, BufferSize);
|
||||||
|
MemoryMapStart = MemoryMap;
|
||||||
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
|
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
|
||||||
Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
|
Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
|
||||||
ASSERT (Entry->VirtualStart == 0);
|
ASSERT (Entry->VirtualStart == 0);
|
||||||
|
@ -1353,7 +1467,11 @@ CoreGetMemoryMap (
|
||||||
MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
|
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) {
|
for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
|
||||||
|
@ -1380,11 +1498,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;
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
|
|
Loading…
Reference in New Issue