]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/PlatformPei/MemDetect.c
OvmfPkg: add a Name GUID to each Firmware Volume
[mirror_edk2.git] / OvmfPkg / PlatformPei / MemDetect.c
index 455fcbb49d13a590b7a118e3a7fbcf3efed00f9a..7991ba29d7aa89534f89cb65a4c6f37c3a2a99be 100644 (file)
@@ -1,7 +1,7 @@
 /**@file\r
   Memory Detection for Virtual Machines.\r
 \r
-  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2016, 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
@@ -32,6 +32,7 @@ Module Name:
 #include <Library/PeimEntryPoint.h>\r
 #include <Library/ResourcePublicationLib.h>\r
 #include <Library/MtrrLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
 \r
 #include "Platform.h"\r
 #include "Cmos.h"\r
@@ -87,6 +88,131 @@ GetSystemMemorySizeAbove4gb (
 }\r
 \r
 \r
+/**\r
+  Return the highest address that DXE could possibly use, plus one.\r
+**/\r
+STATIC\r
+UINT64\r
+GetFirstNonAddress (\r
+  VOID\r
+  )\r
+{\r
+  UINT64               FirstNonAddress;\r
+  UINT64               Pci64Base, Pci64Size;\r
+  CHAR8                MbString[7 + 1];\r
+  EFI_STATUS           Status;\r
+  FIRMWARE_CONFIG_ITEM FwCfgItem;\r
+  UINTN                FwCfgSize;\r
+  UINT64               HotPlugMemoryEnd;\r
+\r
+  FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();\r
+\r
+  //\r
+  // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO\r
+  // resources to 32-bit anyway. See DegradeResource() in\r
+  // "PciResourceSupport.c".\r
+  //\r
+#ifdef MDE_CPU_IA32\r
+  if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+    return FirstNonAddress;\r
+  }\r
+#endif\r
+\r
+  //\r
+  // Otherwise, in order to calculate the highest address plus one, we must\r
+  // consider the 64-bit PCI host aperture too. Fetch the default size.\r
+  //\r
+  Pci64Size = PcdGet64 (PcdPciMmio64Size);\r
+\r
+  //\r
+  // See if the user specified the number of megabytes for the 64-bit PCI host\r
+  // aperture. The number of non-NUL characters in MbString allows for\r
+  // 9,999,999 MB, which is approximately 10 TB.\r
+  //\r
+  // As signaled by the "X-" prefix, this knob is experimental, and might go\r
+  // away at any time.\r
+  //\r
+  Status = QemuFwCfgFindFile ("opt/ovmf/X-PciMmio64Mb", &FwCfgItem,\r
+             &FwCfgSize);\r
+  if (!EFI_ERROR (Status)) {\r
+    if (FwCfgSize >= sizeof MbString) {\r
+      DEBUG ((EFI_D_WARN,\r
+        "%a: ignoring malformed 64-bit PCI host aperture size from fw_cfg\n",\r
+        __FUNCTION__));\r
+    } else {\r
+      QemuFwCfgSelectItem (FwCfgItem);\r
+      QemuFwCfgReadBytes (FwCfgSize, MbString);\r
+      MbString[FwCfgSize] = '\0';\r
+      Pci64Size = LShiftU64 (AsciiStrDecimalToUint64 (MbString), 20);\r
+    }\r
+  }\r
+\r
+  if (Pci64Size == 0) {\r
+    if (mBootMode != BOOT_ON_S3_RESUME) {\r
+      DEBUG ((EFI_D_INFO, "%a: disabling 64-bit PCI host aperture\n",\r
+        __FUNCTION__));\r
+      PcdSet64 (PcdPciMmio64Size, 0);\r
+    }\r
+\r
+    //\r
+    // There's nothing more to do; the amount of memory above 4GB fully\r
+    // determines the highest address plus one. The memory hotplug area (see\r
+    // below) plays no role for the firmware in this case.\r
+    //\r
+    return FirstNonAddress;\r
+  }\r
+\r
+  //\r
+  // The "etc/reserved-memory-end" fw_cfg file, when present, contains an\r
+  // absolute, exclusive end address for the memory hotplug area. This area\r
+  // starts right at the end of the memory above 4GB. The 64-bit PCI host\r
+  // aperture must be placed above it.\r
+  //\r
+  Status = QemuFwCfgFindFile ("etc/reserved-memory-end", &FwCfgItem,\r
+             &FwCfgSize);\r
+  if (!EFI_ERROR (Status) && FwCfgSize == sizeof HotPlugMemoryEnd) {\r
+    QemuFwCfgSelectItem (FwCfgItem);\r
+    QemuFwCfgReadBytes (FwCfgSize, &HotPlugMemoryEnd);\r
+\r
+    ASSERT (HotPlugMemoryEnd >= FirstNonAddress);\r
+    FirstNonAddress = HotPlugMemoryEnd;\r
+  }\r
+\r
+  //\r
+  // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so\r
+  // that the host can map it with 1GB hugepages. Follow suit.\r
+  //\r
+  Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);\r
+  Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);\r
+\r
+  //\r
+  // The 64-bit PCI host aperture should also be "naturally" aligned. The\r
+  // alignment is determined by rounding the size of the aperture down to the\r
+  // next smaller or equal power of two. That is, align the aperture by the\r
+  // largest BAR size that can fit into it.\r
+  //\r
+  Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));\r
+\r
+  if (mBootMode != BOOT_ON_S3_RESUME) {\r
+    //\r
+    // The core PciHostBridgeDxe driver will automatically add this range to\r
+    // the GCD memory space map through our PciHostBridgeLib instance; here we\r
+    // only need to set the PCDs.\r
+    //\r
+    PcdSet64 (PcdPciMmio64Base, Pci64Base);\r
+    PcdSet64 (PcdPciMmio64Size, Pci64Size);\r
+    DEBUG ((EFI_D_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",\r
+      __FUNCTION__, Pci64Base, Pci64Size));\r
+  }\r
+\r
+  //\r
+  // The useful address space ends with the 64-bit PCI host aperture.\r
+  //\r
+  FirstNonAddress = Pci64Base + Pci64Size;\r
+  return FirstNonAddress;\r
+}\r
+\r
+\r
 /**\r
   Initialize the mPhysMemAddressWidth variable, based on guest RAM size.\r
 **/\r
@@ -103,7 +229,7 @@ AddressWidthInitialization (
   // The DXL IPL keys off of the physical address bits advertized in the CPU\r
   // HOB. To conserve memory, we calculate the minimum address width here.\r
   //\r
-  FirstNonAddress      = BASE_4GB + GetSystemMemorySizeAbove4gb ();\r
+  FirstNonAddress      = GetFirstNonAddress ();\r
   mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);\r
 \r
   //\r
@@ -296,7 +422,7 @@ QemuInitializeRam (
     }\r
 \r
     if (UpperMemorySize != 0) {\r
-      AddUntestedMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);\r
+      AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);\r
     }\r
   }\r
 \r