]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Mem/Page.c
Correct typo in word in DxeCore.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / Page.c
index f3f74720b815cb79f697712670c75f5e994877d7..5c82d3178a9209cda18a87da22ef2e21011e0cd0 100644 (file)
@@ -28,7 +28,7 @@ typedef struct {
   UINTN                 InformationIndex;\r
   BOOLEAN               Special;\r
   BOOLEAN               Runtime;\r
-} EFI_MEMORY_TYPE_STAISTICS;\r
+} EFI_MEMORY_TYPE_STATISTICS;\r
 \r
 //\r
 // MemoryMap - The current memory map\r
@@ -52,7 +52,7 @@ UINTN         mFreeMapStack = 0;
 LIST_ENTRY   mFreeMemoryMapEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList);\r
 BOOLEAN      mMemoryTypeInformationInitialized = FALSE;\r
 \r
-EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {\r
+EFI_MEMORY_TYPE_STATISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {\r
   { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE,  FALSE },  // EfiReservedMemoryType\r
   { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE },  // EfiLoaderCode\r
   { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE },  // EfiLoaderData\r
@@ -71,6 +71,7 @@ EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {
 };\r
 \r
 EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = MAX_ADDRESS;\r
+EFI_PHYSICAL_ADDRESS mDefaultBaseAddress = MAX_ADDRESS;\r
 \r
 EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {\r
   { EfiReservedMemoryType,      0 },\r
@@ -374,18 +375,20 @@ CoreFreeMemoryMapStack (
   Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.\r
 \r
 **/\r
-VOID\r
+BOOLEAN\r
 PromoteMemoryResource (\r
   VOID\r
   )\r
 {\r
-  LIST_ENTRY                       *Link;\r
-  EFI_GCD_MAP_ENTRY                *Entry;\r
+  LIST_ENTRY         *Link;\r
+  EFI_GCD_MAP_ENTRY  *Entry;\r
+  BOOLEAN            Promoted;\r
 \r
   DEBUG ((DEBUG_PAGE, "Promote the memory resource\n"));\r
 \r
   CoreAcquireGcdMemoryLock ();\r
 \r
+  Promoted = FALSE;\r
   Link = mGcdMemorySpaceMap.ForwardLink;\r
   while (Link != &mGcdMemorySpaceMap) {\r
 \r
@@ -415,6 +418,7 @@ PromoteMemoryResource (
         );\r
       CoreFreeMemoryMapStack ();\r
 \r
+      Promoted = TRUE;\r
     }\r
 \r
     Link = Link->ForwardLink;\r
@@ -422,7 +426,7 @@ PromoteMemoryResource (
 \r
   CoreReleaseGcdMemoryLock ();\r
 \r
-  return;\r
+  return Promoted;\r
 }\r
 /**\r
   This function try to allocate Runtime code & Boot time code memory range. If LMFA enabled, 2 patchable PCD \r
@@ -744,8 +748,8 @@ CoreConvertPages (
     // Update counters for the number of pages allocated to each memory type\r
     //\r
     if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {\r
-      if (Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress &&\r
-          Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) {\r
+      if ((Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress && Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) ||\r
+          (Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress)                                                          ) {\r
         if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {\r
           mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;\r
         } else {\r
@@ -755,10 +759,10 @@ CoreConvertPages (
     }\r
 \r
     if (NewType >= 0 && NewType < EfiMaxMemoryType) {\r
-      if (Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) {\r
+      if ((Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) ||\r
+          (Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress)                                                  ) {\r
         mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;\r
-        if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages >\r
-            gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {\r
+        if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {\r
           gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;\r
         }\r
       }\r
@@ -858,6 +862,7 @@ CoreConvertPages (
   the requested address.\r
 \r
   @param  MaxAddress             The address that the range must be below\r
+  @param  MinAddress             The address that the range must be above\r
   @param  NumberOfPages          Number of pages needed\r
   @param  NewType                The type of memory the range is going to be\r
                                  turned into\r
@@ -869,6 +874,7 @@ CoreConvertPages (
 UINT64\r
 CoreFindFreePagesI (\r
   IN UINT64           MaxAddress,\r
+  IN UINT64           MinAddress,\r
   IN UINT64           NumberOfPages,\r
   IN EFI_MEMORY_TYPE  NewType,\r
   IN UINTN            Alignment\r
@@ -925,9 +931,9 @@ CoreFindFreePagesI (
     DescEnd = Entry->End;\r
 \r
     //\r
-    // If desc is past max allowed address, skip it\r
+    // If desc is past max allowed address or below min allowed address, skip it\r
     //\r
-    if (DescStart >= MaxAddress) {\r
+    if ((DescStart >= MaxAddress) || (DescEnd < MinAddress)) {\r
       continue;\r
     }\r
 \r
@@ -947,6 +953,12 @@ CoreFindFreePagesI (
     DescNumberOfBytes = DescEnd - DescStart + 1;\r
 \r
     if (DescNumberOfBytes >= NumberOfBytes) {\r
+      //\r
+      // If the start of the allocated range is below the min address allowed, skip it\r
+      //\r
+      if ((DescEnd - NumberOfBytes + 1) < MinAddress) {\r
+        continue;\r
+      }\r
 \r
       //\r
       // If this is the best match so far remember it\r
@@ -994,41 +1006,62 @@ FindFreePages (
     IN UINTN            Alignment\r
     )\r
 {\r
-  UINT64  NewMaxAddress;\r
-  UINT64  Start;\r
+  UINT64   Start;\r
 \r
-  NewMaxAddress = MaxAddress;\r
+  //\r
+  // Attempt to find free pages in the preferred bin based on the requested memory type\r
+  //\r
+  if (NewType >= 0 && NewType < EfiMaxMemoryType && MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {\r
+    Start = CoreFindFreePagesI (\r
+              mMemoryTypeStatistics[NewType].MaximumAddress, \r
+              mMemoryTypeStatistics[NewType].BaseAddress, \r
+              NoPages, \r
+              NewType, \r
+              Alignment\r
+              );\r
+    if (Start != 0) {\r
+      return Start;\r
+    }\r
+  }\r
 \r
-  if (NewType >= 0 && NewType < EfiMaxMemoryType && NewMaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {\r
-    NewMaxAddress  = mMemoryTypeStatistics[NewType].MaximumAddress;\r
-  } else {\r
-    if (NewMaxAddress > mDefaultMaximumAddress) {\r
-      NewMaxAddress  = mDefaultMaximumAddress;\r
+  //\r
+  // Attempt to find free pages in the default allocation bin\r
+  //\r
+  if (MaxAddress >= mDefaultMaximumAddress) {\r
+    Start = CoreFindFreePagesI (mDefaultMaximumAddress, 0, NoPages, NewType, Alignment);\r
+    if (Start != 0) {\r
+      if (Start < mDefaultBaseAddress) {\r
+        mDefaultBaseAddress = Start;\r
+      }\r
+      return Start;\r
     }\r
   }\r
 \r
-  Start = CoreFindFreePagesI (NewMaxAddress, NoPages, NewType, Alignment);\r
-  if (Start == 0) {\r
-    Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);\r
-    if (Start == 0) {\r
-      //\r
-      // Here means there may be no enough memory to use, so try to go through\r
-      // all the memory descript to promote the untested memory directly\r
-      //\r
-      PromoteMemoryResource ();\r
+  //\r
+  // The allocation did not succeed in any of the prefered bins even after \r
+  // promoting resources. Attempt to find free pages anywhere is the requested \r
+  // address range.  If this allocation fails, then there are not enough \r
+  // resources anywhere to satisfy the request.\r
+  //\r
+  Start = CoreFindFreePagesI (MaxAddress, 0, NoPages, NewType, Alignment);\r
+  if (Start != 0) {\r
+    return Start;\r
+  }\r
 \r
-      //\r
-      // Allocate memory again after the memory resource re-arranged\r
-      //\r
-      Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);\r
-    }\r
+  //\r
+  // If allocations from the preferred bins fail, then attempt to promote memory resources.\r
+  //\r
+  if (!PromoteMemoryResource ()) {\r
+    return 0;\r
   }\r
 \r
-  return Start;\r
+  //\r
+  // If any memory resources were promoted, then re-attempt the allocation\r
+  //\r
+  return FindFreePages (MaxAddress, NoPages, NewType, Alignment);\r
 }\r
 \r
 \r
-\r
 /**\r
   Allocates pages from the memory map.\r
 \r
@@ -1206,6 +1239,86 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  This function checks to see if the last memory map descriptor in a memory map\r
+  can be merged with any of the other memory map descriptors in a memorymap.\r
+  Memory descriptors may be merged if they are adjacent and have the same type\r
+  and attributes.\r
+\r
+  @param  MemoryMap              A pointer to the start of the memory map.\r
+  @param  MemoryMapDescriptor    A pointer to the last descriptor in MemoryMap.\r
+  @param  DescriptorSize         The size, in bytes, of an individual\r
+                                 EFI_MEMORY_DESCRIPTOR.\r
+\r
+  @return  A pointer to the next available descriptor in MemoryMap\r
+\r
+**/\r
+EFI_MEMORY_DESCRIPTOR *\r
+MergeMemoryMapDescriptor (\r
+  IN EFI_MEMORY_DESCRIPTOR  *MemoryMap,\r
+  IN EFI_MEMORY_DESCRIPTOR  *MemoryMapDescriptor,\r
+  IN UINTN                  DescriptorSize\r
+  )\r
+{\r
+  //\r
+  // Traverse the array of descriptors in MemoryMap\r
+  //\r
+  for (; MemoryMap != MemoryMapDescriptor; MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize)) {\r
+    //\r
+    // Check to see if the Type fields are identical.\r
+    //\r
+    if (MemoryMap->Type != MemoryMapDescriptor->Type) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check to see if the Attribute fields are identical.\r
+    //\r
+    if (MemoryMap->Attribute != MemoryMapDescriptor->Attribute) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check to see if MemoryMapDescriptor is immediately above MemoryMap\r
+    //\r
+    if (MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) { \r
+      //\r
+      // Merge MemoryMapDescriptor into MemoryMap\r
+      //\r
+      MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;\r
+\r
+      //\r
+      // Return MemoryMapDescriptor as the next available slot int he MemoryMap array\r
+      //\r
+      return MemoryMapDescriptor;\r
+    }\r
+\r
+    //\r
+    // Check to see if MemoryMapDescriptor is immediately below MemoryMap\r
+    //\r
+    if (MemoryMap->PhysicalStart - EFI_PAGES_TO_SIZE ((UINTN)MemoryMapDescriptor->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) {\r
+      //\r
+      // Merge MemoryMapDescriptor into MemoryMap\r
+      //\r
+      MemoryMap->PhysicalStart  = MemoryMapDescriptor->PhysicalStart;\r
+      MemoryMap->VirtualStart   = MemoryMapDescriptor->VirtualStart;\r
+      MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;\r
+\r
+      //\r
+      // Return MemoryMapDescriptor as the next available slot int he MemoryMap array\r
+      //\r
+      return MemoryMapDescriptor;\r
+    }\r
+  }\r
+\r
+  //\r
+  // MemoryMapDescrtiptor could not be merged with any descriptors in MemoryMap.\r
+  //\r
+  // Return the slot immediately after MemoryMapDescriptor as the next available \r
+  // slot in the MemoryMap array\r
+  //\r
+  return NEXT_MEMORY_DESCRIPTOR (MemoryMapDescriptor, DescriptorSize);\r
+}\r
 \r
 /**\r
   This function returns a copy of the current memory map. The map is an array of\r
@@ -1255,6 +1368,7 @@ CoreGetMemoryMap (
   MEMORY_MAP                        *Entry;\r
   EFI_GCD_MAP_ENTRY                 *GcdMapEntry;\r
   EFI_MEMORY_TYPE                   Type;\r
+  EFI_MEMORY_DESCRIPTOR             *MemoryMapStart;\r
 \r
   //\r
   // Make sure the parameters are valid\r
@@ -1320,6 +1434,7 @@ CoreGetMemoryMap (
   // Build the map\r
   //\r
   ZeroMem (MemoryMap, BufferSize);\r
+  MemoryMapStart = MemoryMap;\r
   for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {\r
     Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);\r
     ASSERT (Entry->VirtualStart == 0);\r
@@ -1353,7 +1468,11 @@ CoreGetMemoryMap (
       MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;\r
     }\r
 \r
-    MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);\r
+    //\r
+    // Check to see if the new Memory Map Descriptor can be merged with an \r
+    // existing descriptor if they are adjacent and have the same attributes\r
+    //\r
+    MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);\r
   }\r
 \r
   for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {\r
@@ -1380,11 +1499,20 @@ CoreGetMemoryMap (
           }\r
         }\r
 \r
-        MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);\r
+        //\r
+        // Check to see if the new Memory Map Descriptor can be merged with an \r
+        // existing descriptor if they are adjacent and have the same attributes\r
+        //\r
+        MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);\r
       }\r
     }\r
   }\r
 \r
+  //\r
+  // Compute the size of the buffer actually used after all memory map descriptor merge operations\r
+  //\r
+  BufferSize = ((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart);\r
+\r
   Status = EFI_SUCCESS;\r
 \r
 Done:\r