]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Mem/Page.c
MdeModulePkg DxeCore/PiSmmCore: Add UEFI memory and SMRAM profile support.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / Page.c
index 131b4eb4ce600e972a535e70ce846c3215e34562..18780070c5eaf8df44a27756933ba236c8c3800a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   UEFI Memory page management functions.\r
 \r
-Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -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
@@ -177,7 +177,20 @@ CoreAddRange (
   ASSERT_LOCKED (&gMemoryLock);\r
 \r
   DEBUG ((DEBUG_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type));\r
-\r
+  \r
+  //\r
+  // If memory of type EfiConventionalMemory is being added that includes the page \r
+  // starting at address 0, then zero the page starting at address 0.  This has \r
+  // two benifits.  It helps find NULL pointer bugs and it also maximizes \r
+  // compatibility with operating systems that may evaluate memory in this page \r
+  // for legacy data structures.  If memory of any other type is added starting \r
+  // at address 0, then do not zero the page at address 0 because the page is being \r
+  // used for other purposes.\r
+  //  \r
+  if (Type == EfiConventionalMemory && Start == 0 && (End >= EFI_PAGE_SIZE - 1)) {\r
+    SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);\r
+  }\r
+  \r
   //\r
   // Memory map being altered so updated key\r
   //\r
@@ -557,7 +570,7 @@ CoreAddMemoryDescriptor (
     // Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
     //\r
     Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[Index].Type);\r
-    if (Type < 0 || Type > EfiMaxMemoryType) {\r
+    if ((UINT32)Type > EfiMaxMemoryType) {\r
       continue;\r
     }\r
     if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
@@ -581,7 +594,7 @@ CoreAddMemoryDescriptor (
           // Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
           //\r
           Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[FreeIndex].Type);\r
-          if (Type < 0 || Type > EfiMaxMemoryType) {\r
+          if ((UINT32)Type > EfiMaxMemoryType) {\r
             continue;\r
           }\r
 \r
@@ -624,7 +637,7 @@ CoreAddMemoryDescriptor (
     // Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
     //\r
     Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[Index].Type);\r
-    if (Type < 0 || Type > EfiMaxMemoryType) {\r
+    if ((UINT32)Type > EfiMaxMemoryType) {\r
       continue;\r
     }\r
     if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
@@ -747,7 +760,7 @@ CoreConvertPages (
     //\r
     // Update counters for the number of pages allocated to each memory type\r
     //\r
-    if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {\r
+    if ((UINT32)Entry->Type < EfiMaxMemoryType) {\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
@@ -758,7 +771,7 @@ CoreConvertPages (
       }\r
     }\r
 \r
-    if (NewType >= 0 && NewType < EfiMaxMemoryType) {\r
+    if ((UINT32)NewType < EfiMaxMemoryType) {\r
       if ((Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) ||\r
           (Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress)                                                  ) {\r
         mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;\r
@@ -834,7 +847,18 @@ CoreConvertPages (
     //\r
     CoreAddRange (NewType, Start, RangeEnd, Attribute);\r
     if (NewType == EfiConventionalMemory) {\r
-      DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) Start, (UINTN) (RangeEnd - Start + 1));\r
+      //\r
+      // Avoid calling DEBUG_CLEAR_MEMORY() for an address of 0 because this\r
+      // macro will ASSERT() if address is 0.  Instead, CoreAddRange() guarantees\r
+      // that the page starting at address 0 is always filled with zeros.\r
+      //\r
+      if (Start == 0) {\r
+        if (RangeEnd > EFI_PAGE_SIZE) {\r
+          DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) EFI_PAGE_SIZE, (UINTN) (RangeEnd - EFI_PAGE_SIZE + 1));\r
+        }\r
+      } else {\r
+        DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) Start, (UINTN) (RangeEnd - Start + 1));\r
+      }\r
     }\r
 \r
     //\r
@@ -906,7 +930,7 @@ CoreFindFreePagesI (
     //\r
     // Set MaxAddress to a page boundary\r
     //\r
-    MaxAddress &= ~EFI_PAGE_MASK;\r
+    MaxAddress &= ~(UINT64)EFI_PAGE_MASK;\r
 \r
     //\r
     // Set MaxAddress to end of the page\r
@@ -1011,7 +1035,7 @@ FindFreePages (
   //\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
+  if ((UINT32)NewType < EfiMaxMemoryType && MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {\r
     Start = CoreFindFreePagesI (\r
               mMemoryTypeStatistics[NewType].MaximumAddress, \r
               mMemoryTypeStatistics[NewType].BaseAddress, \r
@@ -1082,7 +1106,7 @@ FindFreePages (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreAllocatePages (\r
+CoreInternalAllocatePages (\r
   IN EFI_ALLOCATE_TYPE      Type,\r
   IN EFI_MEMORY_TYPE        MemoryType,\r
   IN UINTN                  NumberOfPages,\r
@@ -1094,7 +1118,7 @@ CoreAllocatePages (
   UINT64          MaxAddress;\r
   UINTN           Alignment;\r
 \r
-  if (Type < AllocateAnyPages || Type >= (UINTN) MaxAllocateType) {\r
+  if ((UINT32)Type >= MaxAllocateType) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -1103,6 +1127,10 @@ CoreAllocatePages (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if (Memory == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;\r
 \r
   if  (MemoryType == EfiACPIReclaimMemory   ||\r
@@ -1164,6 +1192,41 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Allocates pages from the memory map.\r
+\r
+  @param  Type                   The type of allocation to perform\r
+  @param  MemoryType             The type of memory to turn the allocated pages\r
+                                 into\r
+  @param  NumberOfPages          The number of pages to allocate\r
+  @param  Memory                 A pointer to receive the base allocated memory\r
+                                 address\r
+\r
+  @return Status. On success, Memory is filled in with the base address allocated\r
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in\r
+                                 spec.\r
+  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.\r
+  @retval EFI_SUCCESS            Pages successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreAllocatePages (\r
+  IN  EFI_ALLOCATE_TYPE     Type,\r
+  IN  EFI_MEMORY_TYPE       MemoryType,\r
+  IN  UINTN                 NumberOfPages,\r
+  OUT EFI_PHYSICAL_ADDRESS  *Memory\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory);\r
+  }\r
+  return Status;\r
+}\r
 \r
 /**\r
   Frees previous allocated pages.\r
@@ -1178,7 +1241,7 @@ Done:
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreFreePages (\r
+CoreInternalFreePages (\r
   IN EFI_PHYSICAL_ADDRESS   Memory,\r
   IN UINTN                  NumberOfPages\r
   )\r
@@ -1239,6 +1302,33 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Frees previous allocated pages.\r
+\r
+  @param  Memory                 Base address of memory being freed\r
+  @param  NumberOfPages          The number of pages to free\r
+\r
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range\r
+  @retval EFI_INVALID_PARAMETER  Address not aligned\r
+  @return EFI_SUCCESS         -Pages successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreFreePages (\r
+  IN EFI_PHYSICAL_ADDRESS  Memory,\r
+  IN UINTN                 NumberOfPages\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = CoreInternalFreePages (Memory, NumberOfPages);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory);\r
+  }\r
+  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
@@ -1464,8 +1554,10 @@ CoreGetMemoryMap (
       }\r
     }\r
     MemoryMap->Attribute = Entry->Attribute;\r
-    if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {\r
-      MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;\r
+    if (MemoryMap->Type < EfiMaxMemoryType) {\r
+      if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {\r
+        MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;\r
+      }\r
     }\r
 \r
     //\r
@@ -1516,11 +1608,6 @@ CoreGetMemoryMap (
   Status = EFI_SUCCESS;\r
 \r
 Done:\r
-\r
-  CoreReleaseMemoryLock ();\r
-\r
-  CoreReleaseGcdMemoryLock ();\r
-\r
   //\r
   // Update the map key finally\r
   //\r
@@ -1528,6 +1615,10 @@ Done:
     *MapKey = mMemoryMapKey;\r
   }\r
 \r
+  CoreReleaseMemoryLock ();\r
+\r
+  CoreReleaseGcdMemoryLock ();\r
+\r
   *MemoryMapSize = BufferSize;\r
 \r
   return Status;\r