return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);\r
}\r
\r
-\r
-STATIC\r
-UINT64\r
-GetSystemMemorySizeAbove4gb (\r
- )\r
-{\r
- UINT32 Size;\r
- UINTN CmosIndex;\r
-\r
- //\r
- // In PVH case, there is no CMOS, we have to calculate the memory size\r
- // from parsing the E820\r
- //\r
- if (XenPvhDetected ()) {\r
- UINT64 HighestAddress;\r
-\r
- HighestAddress = GetHighestSystemMemoryAddress (FALSE);\r
- ASSERT (HighestAddress == 0 || HighestAddress >= BASE_4GB);\r
-\r
- if (HighestAddress >= BASE_4GB) {\r
- HighestAddress -= BASE_4GB;\r
- }\r
-\r
- return HighestAddress;\r
- }\r
-\r
- //\r
- // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.\r
- // * CMOS(0x5d) is the most significant size byte\r
- // * CMOS(0x5c) is the middle size byte\r
- // * CMOS(0x5b) is the least significant size byte\r
- // * The size is specified in 64kb chunks\r
- //\r
-\r
- Size = 0;\r
- for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {\r
- Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);\r
- }\r
-\r
- return LShiftU64 (Size, 16);\r
-}\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
- RETURN_STATUS PcdStatus;\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
- if (Pci64Size == 0) {\r
- if (mBootMode != BOOT_ON_S3_RESUME) {\r
- DEBUG ((DEBUG_INFO, "%a: disabling 64-bit PCI host aperture\n",\r
- __FUNCTION__));\r
- PcdStatus = PcdSet64S (PcdPciMmio64Size, 0);\r
- ASSERT_RETURN_ERROR (PcdStatus);\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
- // 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
- PcdStatus = PcdSet64S (PcdPciMmio64Base, Pci64Base);\r
- ASSERT_RETURN_ERROR (PcdStatus);\r
- PcdStatus = PcdSet64S (PcdPciMmio64Size, Pci64Size);\r
- ASSERT_RETURN_ERROR (PcdStatus);\r
-\r
- DEBUG ((DEBUG_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
+ Initialize the mPhysMemAddressWidth variable, based on CPUID data.\r
**/\r
VOID\r
AddressWidthInitialization (\r
VOID\r
)\r
{\r
- UINT64 FirstNonAddress;\r
+ UINT32 RegEax;\r
\r
- //\r
- // As guest-physical memory size grows, the permanent PEI RAM requirements\r
- // are dominated by the identity-mapping page tables built by the DXE IPL.\r
- // 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 = GetFirstNonAddress ();\r
- mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);\r
-\r
- //\r
- // If FirstNonAddress is not an integral power of two, then we need an\r
- // additional bit.\r
- //\r
- if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {\r
- ++mPhysMemAddressWidth;\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000008) {\r
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+ mPhysMemAddressWidth = (UINT8) RegEax;\r
+ } else {\r
+ mPhysMemAddressWidth = 36;\r
}\r
\r
//\r
- // The minimum address width is 36 (covers up to and excluding 64 GB, which\r
- // is the maximum for Ia32 + PAE). The theoretical architecture maximum for\r
- // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We\r
- // can simply assert that here, since 48 bits are good enough for 256 TB.\r
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
//\r
- if (mPhysMemAddressWidth <= 36) {\r
- mPhysMemAddressWidth = 36;\r
+ ASSERT (mPhysMemAddressWidth <= 52);\r
+ if (mPhysMemAddressWidth > 48) {\r
+ mPhysMemAddressWidth = 48;\r
}\r
- ASSERT (mPhysMemAddressWidth <= 48);\r
}\r
\r
-\r
/**\r
Calculate the cap for the permanent PEI memory.\r
**/\r