Home | History | Annotate | Download | only in PlatformPei
      1 /**@file
      2   Memory Detection for Virtual Machines.
      3 
      4   Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 Module Name:
     14 
     15   MemDetect.c
     16 
     17 **/
     18 
     19 //
     20 // The package level header files this module uses
     21 //
     22 #include <PiPei.h>
     23 
     24 //
     25 // The Library classes this module consumes
     26 //
     27 #include <Library/BaseMemoryLib.h>
     28 #include <Library/DebugLib.h>
     29 #include <Library/HobLib.h>
     30 #include <Library/IoLib.h>
     31 #include <Library/PcdLib.h>
     32 #include <Library/PeimEntryPoint.h>
     33 #include <Library/ResourcePublicationLib.h>
     34 #include <Library/MtrrLib.h>
     35 #include <Library/QemuFwCfgLib.h>
     36 
     37 #include "Platform.h"
     38 #include "Cmos.h"
     39 
     40 UINT8 mPhysMemAddressWidth;
     41 
     42 STATIC UINT32 mS3AcpiReservedMemoryBase;
     43 STATIC UINT32 mS3AcpiReservedMemorySize;
     44 
     45 UINT32
     46 GetSystemMemorySizeBelow4gb (
     47   VOID
     48   )
     49 {
     50   UINT8 Cmos0x34;
     51   UINT8 Cmos0x35;
     52 
     53   //
     54   // CMOS 0x34/0x35 specifies the system memory above 16 MB.
     55   // * CMOS(0x35) is the high byte
     56   // * CMOS(0x34) is the low byte
     57   // * The size is specified in 64kb chunks
     58   // * Since this is memory above 16MB, the 16MB must be added
     59   //   into the calculation to get the total memory size.
     60   //
     61 
     62   Cmos0x34 = (UINT8) CmosRead8 (0x34);
     63   Cmos0x35 = (UINT8) CmosRead8 (0x35);
     64 
     65   return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
     66 }
     67 
     68 
     69 STATIC
     70 UINT64
     71 GetSystemMemorySizeAbove4gb (
     72   )
     73 {
     74   UINT32 Size;
     75   UINTN  CmosIndex;
     76 
     77   //
     78   // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
     79   // * CMOS(0x5d) is the most significant size byte
     80   // * CMOS(0x5c) is the middle size byte
     81   // * CMOS(0x5b) is the least significant size byte
     82   // * The size is specified in 64kb chunks
     83   //
     84 
     85   Size = 0;
     86   for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
     87     Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);
     88   }
     89 
     90   return LShiftU64 (Size, 16);
     91 }
     92 
     93 
     94 /**
     95   Return the highest address that DXE could possibly use, plus one.
     96 **/
     97 STATIC
     98 UINT64
     99 GetFirstNonAddress (
    100   VOID
    101   )
    102 {
    103   UINT64               FirstNonAddress;
    104   UINT64               Pci64Base, Pci64Size;
    105   CHAR8                MbString[7 + 1];
    106   EFI_STATUS           Status;
    107   FIRMWARE_CONFIG_ITEM FwCfgItem;
    108   UINTN                FwCfgSize;
    109   UINT64               HotPlugMemoryEnd;
    110   RETURN_STATUS        PcdStatus;
    111 
    112   FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();
    113 
    114   //
    115   // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
    116   // resources to 32-bit anyway. See DegradeResource() in
    117   // "PciResourceSupport.c".
    118   //
    119 #ifdef MDE_CPU_IA32
    120   if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
    121     return FirstNonAddress;
    122   }
    123 #endif
    124 
    125   //
    126   // Otherwise, in order to calculate the highest address plus one, we must
    127   // consider the 64-bit PCI host aperture too. Fetch the default size.
    128   //
    129   Pci64Size = PcdGet64 (PcdPciMmio64Size);
    130 
    131   //
    132   // See if the user specified the number of megabytes for the 64-bit PCI host
    133   // aperture. The number of non-NUL characters in MbString allows for
    134   // 9,999,999 MB, which is approximately 10 TB.
    135   //
    136   // As signaled by the "X-" prefix, this knob is experimental, and might go
    137   // away at any time.
    138   //
    139   Status = QemuFwCfgFindFile ("opt/ovmf/X-PciMmio64Mb", &FwCfgItem,
    140              &FwCfgSize);
    141   if (!EFI_ERROR (Status)) {
    142     if (FwCfgSize >= sizeof MbString) {
    143       DEBUG ((EFI_D_WARN,
    144         "%a: ignoring malformed 64-bit PCI host aperture size from fw_cfg\n",
    145         __FUNCTION__));
    146     } else {
    147       QemuFwCfgSelectItem (FwCfgItem);
    148       QemuFwCfgReadBytes (FwCfgSize, MbString);
    149       MbString[FwCfgSize] = '\0';
    150       Pci64Size = LShiftU64 (AsciiStrDecimalToUint64 (MbString), 20);
    151     }
    152   }
    153 
    154   if (Pci64Size == 0) {
    155     if (mBootMode != BOOT_ON_S3_RESUME) {
    156       DEBUG ((EFI_D_INFO, "%a: disabling 64-bit PCI host aperture\n",
    157         __FUNCTION__));
    158       PcdStatus = PcdSet64S (PcdPciMmio64Size, 0);
    159       ASSERT_RETURN_ERROR (PcdStatus);
    160     }
    161 
    162     //
    163     // There's nothing more to do; the amount of memory above 4GB fully
    164     // determines the highest address plus one. The memory hotplug area (see
    165     // below) plays no role for the firmware in this case.
    166     //
    167     return FirstNonAddress;
    168   }
    169 
    170   //
    171   // The "etc/reserved-memory-end" fw_cfg file, when present, contains an
    172   // absolute, exclusive end address for the memory hotplug area. This area
    173   // starts right at the end of the memory above 4GB. The 64-bit PCI host
    174   // aperture must be placed above it.
    175   //
    176   Status = QemuFwCfgFindFile ("etc/reserved-memory-end", &FwCfgItem,
    177              &FwCfgSize);
    178   if (!EFI_ERROR (Status) && FwCfgSize == sizeof HotPlugMemoryEnd) {
    179     QemuFwCfgSelectItem (FwCfgItem);
    180     QemuFwCfgReadBytes (FwCfgSize, &HotPlugMemoryEnd);
    181 
    182     ASSERT (HotPlugMemoryEnd >= FirstNonAddress);
    183     FirstNonAddress = HotPlugMemoryEnd;
    184   }
    185 
    186   //
    187   // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
    188   // that the host can map it with 1GB hugepages. Follow suit.
    189   //
    190   Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
    191   Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);
    192 
    193   //
    194   // The 64-bit PCI host aperture should also be "naturally" aligned. The
    195   // alignment is determined by rounding the size of the aperture down to the
    196   // next smaller or equal power of two. That is, align the aperture by the
    197   // largest BAR size that can fit into it.
    198   //
    199   Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));
    200 
    201   if (mBootMode != BOOT_ON_S3_RESUME) {
    202     //
    203     // The core PciHostBridgeDxe driver will automatically add this range to
    204     // the GCD memory space map through our PciHostBridgeLib instance; here we
    205     // only need to set the PCDs.
    206     //
    207     PcdStatus = PcdSet64S (PcdPciMmio64Base, Pci64Base);
    208     ASSERT_RETURN_ERROR (PcdStatus);
    209     PcdStatus = PcdSet64S (PcdPciMmio64Size, Pci64Size);
    210     ASSERT_RETURN_ERROR (PcdStatus);
    211 
    212     DEBUG ((EFI_D_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",
    213       __FUNCTION__, Pci64Base, Pci64Size));
    214   }
    215 
    216   //
    217   // The useful address space ends with the 64-bit PCI host aperture.
    218   //
    219   FirstNonAddress = Pci64Base + Pci64Size;
    220   return FirstNonAddress;
    221 }
    222 
    223 
    224 /**
    225   Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
    226 **/
    227 VOID
    228 AddressWidthInitialization (
    229   VOID
    230   )
    231 {
    232   UINT64 FirstNonAddress;
    233 
    234   //
    235   // As guest-physical memory size grows, the permanent PEI RAM requirements
    236   // are dominated by the identity-mapping page tables built by the DXE IPL.
    237   // The DXL IPL keys off of the physical address bits advertized in the CPU
    238   // HOB. To conserve memory, we calculate the minimum address width here.
    239   //
    240   FirstNonAddress      = GetFirstNonAddress ();
    241   mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
    242 
    243   //
    244   // If FirstNonAddress is not an integral power of two, then we need an
    245   // additional bit.
    246   //
    247   if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
    248     ++mPhysMemAddressWidth;
    249   }
    250 
    251   //
    252   // The minimum address width is 36 (covers up to and excluding 64 GB, which
    253   // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
    254   // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
    255   // can simply assert that here, since 48 bits are good enough for 256 TB.
    256   //
    257   if (mPhysMemAddressWidth <= 36) {
    258     mPhysMemAddressWidth = 36;
    259   }
    260   ASSERT (mPhysMemAddressWidth <= 48);
    261 }
    262 
    263 
    264 /**
    265   Calculate the cap for the permanent PEI memory.
    266 **/
    267 STATIC
    268 UINT32
    269 GetPeiMemoryCap (
    270   VOID
    271   )
    272 {
    273   BOOLEAN Page1GSupport;
    274   UINT32  RegEax;
    275   UINT32  RegEdx;
    276   UINT32  Pml4Entries;
    277   UINT32  PdpEntries;
    278   UINTN   TotalPages;
    279 
    280   //
    281   // If DXE is 32-bit, then just return the traditional 64 MB cap.
    282   //
    283 #ifdef MDE_CPU_IA32
    284   if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
    285     return SIZE_64MB;
    286   }
    287 #endif
    288 
    289   //
    290   // Dependent on physical address width, PEI memory allocations can be
    291   // dominated by the page tables built for 64-bit DXE. So we key the cap off
    292   // of those. The code below is based on CreateIdentityMappingPageTables() in
    293   // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".
    294   //
    295   Page1GSupport = FALSE;
    296   if (PcdGetBool (PcdUse1GPageTable)) {
    297     AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
    298     if (RegEax >= 0x80000001) {
    299       AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
    300       if ((RegEdx & BIT26) != 0) {
    301         Page1GSupport = TRUE;
    302       }
    303     }
    304   }
    305 
    306   if (mPhysMemAddressWidth <= 39) {
    307     Pml4Entries = 1;
    308     PdpEntries = 1 << (mPhysMemAddressWidth - 30);
    309     ASSERT (PdpEntries <= 0x200);
    310   } else {
    311     Pml4Entries = 1 << (mPhysMemAddressWidth - 39);
    312     ASSERT (Pml4Entries <= 0x200);
    313     PdpEntries = 512;
    314   }
    315 
    316   TotalPages = Page1GSupport ? Pml4Entries + 1 :
    317                                (PdpEntries + 1) * Pml4Entries + 1;
    318   ASSERT (TotalPages <= 0x40201);
    319 
    320   //
    321   // Add 64 MB for miscellaneous allocations. Note that for
    322   // mPhysMemAddressWidth values close to 36, the cap will actually be
    323   // dominated by this increment.
    324   //
    325   return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);
    326 }
    327 
    328 
    329 /**
    330   Publish PEI core memory
    331 
    332   @return EFI_SUCCESS     The PEIM initialized successfully.
    333 
    334 **/
    335 EFI_STATUS
    336 PublishPeiMemory (
    337   VOID
    338   )
    339 {
    340   EFI_STATUS                  Status;
    341   EFI_PHYSICAL_ADDRESS        MemoryBase;
    342   UINT64                      MemorySize;
    343   UINT32                      LowerMemorySize;
    344   UINT32                      PeiMemoryCap;
    345 
    346   LowerMemorySize = GetSystemMemorySizeBelow4gb ();
    347   if (FeaturePcdGet (PcdSmmSmramRequire)) {
    348     //
    349     // TSEG is chipped from the end of low RAM
    350     //
    351     LowerMemorySize -= FixedPcdGet8 (PcdQ35TsegMbytes) * SIZE_1MB;
    352   }
    353 
    354   //
    355   // If S3 is supported, then the S3 permanent PEI memory is placed next,
    356   // downwards. Its size is primarily dictated by CpuMpPei. The formula below
    357   // is an approximation.
    358   //
    359   if (mS3Supported) {
    360     mS3AcpiReservedMemorySize = SIZE_512KB +
    361       mMaxCpuCount *
    362       PcdGet32 (PcdCpuApStackSize);
    363     mS3AcpiReservedMemoryBase = LowerMemorySize - mS3AcpiReservedMemorySize;
    364     LowerMemorySize = mS3AcpiReservedMemoryBase;
    365   }
    366 
    367   if (mBootMode == BOOT_ON_S3_RESUME) {
    368     MemoryBase = mS3AcpiReservedMemoryBase;
    369     MemorySize = mS3AcpiReservedMemorySize;
    370   } else {
    371     PeiMemoryCap = GetPeiMemoryCap ();
    372     DEBUG ((EFI_D_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u KB\n",
    373       __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));
    374 
    375     //
    376     // Determine the range of memory to use during PEI
    377     //
    378     // Technically we could lay the permanent PEI RAM over SEC's temporary
    379     // decompression and scratch buffer even if "secure S3" is needed, since
    380     // their lifetimes don't overlap. However, PeiFvInitialization() will cover
    381     // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS memory
    382     // allocation HOB, and other allocations served from the permanent PEI RAM
    383     // shouldn't overlap with that HOB.
    384     //
    385     MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?
    386       PcdGet32 (PcdOvmfDecompressionScratchEnd) :
    387       PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);
    388     MemorySize = LowerMemorySize - MemoryBase;
    389     if (MemorySize > PeiMemoryCap) {
    390       MemoryBase = LowerMemorySize - PeiMemoryCap;
    391       MemorySize = PeiMemoryCap;
    392     }
    393   }
    394 
    395   //
    396   // Publish this memory to the PEI Core
    397   //
    398   Status = PublishSystemMemory(MemoryBase, MemorySize);
    399   ASSERT_EFI_ERROR (Status);
    400 
    401   return Status;
    402 }
    403 
    404 
    405 /**
    406   Peform Memory Detection for QEMU / KVM
    407 
    408 **/
    409 STATIC
    410 VOID
    411 QemuInitializeRam (
    412   VOID
    413   )
    414 {
    415   UINT64                      LowerMemorySize;
    416   UINT64                      UpperMemorySize;
    417   MTRR_SETTINGS               MtrrSettings;
    418   EFI_STATUS                  Status;
    419 
    420   DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));
    421 
    422   //
    423   // Determine total memory size available
    424   //
    425   LowerMemorySize = GetSystemMemorySizeBelow4gb ();
    426   UpperMemorySize = GetSystemMemorySizeAbove4gb ();
    427 
    428   if (mBootMode == BOOT_ON_S3_RESUME) {
    429     //
    430     // Create the following memory HOB as an exception on the S3 boot path.
    431     //
    432     // Normally we'd create memory HOBs only on the normal boot path. However,
    433     // CpuMpPei specifically needs such a low-memory HOB on the S3 path as
    434     // well, for "borrowing" a subset of it temporarily, for the AP startup
    435     // vector.
    436     //
    437     // CpuMpPei saves the original contents of the borrowed area in permanent
    438     // PEI RAM, in a backup buffer allocated with the normal PEI services.
    439     // CpuMpPei restores the original contents ("returns" the borrowed area) at
    440     // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before
    441     // transferring control to the OS's wakeup vector in the FACS.
    442     //
    443     // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to
    444     // restore the original contents. Furthermore, we expect all such PEIMs
    445     // (CpuMpPei included) to claim the borrowed areas by producing memory
    446     // allocation HOBs, and to honor preexistent memory allocation HOBs when
    447     // looking for an area to borrow.
    448     //
    449     AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
    450   } else {
    451     //
    452     // Create memory HOBs
    453     //
    454     AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
    455 
    456     if (FeaturePcdGet (PcdSmmSmramRequire)) {
    457       UINT32 TsegSize;
    458 
    459       TsegSize = FixedPcdGet8 (PcdQ35TsegMbytes) * SIZE_1MB;
    460       AddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);
    461       AddReservedMemoryBaseSizeHob (LowerMemorySize - TsegSize, TsegSize,
    462         TRUE);
    463     } else {
    464       AddMemoryRangeHob (BASE_1MB, LowerMemorySize);
    465     }
    466 
    467     if (UpperMemorySize != 0) {
    468       AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
    469     }
    470   }
    471 
    472   //
    473   // We'd like to keep the following ranges uncached:
    474   // - [640 KB, 1 MB)
    475   // - [LowerMemorySize, 4 GB)
    476   //
    477   // Everything else should be WB. Unfortunately, programming the inverse (ie.
    478   // keeping the default UC, and configuring the complement set of the above as
    479   // WB) is not reliable in general, because the end of the upper RAM can have
    480   // practically any alignment, and we may not have enough variable MTRRs to
    481   // cover it exactly.
    482   //
    483   if (IsMtrrSupported ()) {
    484     MtrrGetAllMtrrs (&MtrrSettings);
    485 
    486     //
    487     // MTRRs disabled, fixed MTRRs disabled, default type is uncached
    488     //
    489     ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
    490     ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
    491     ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
    492 
    493     //
    494     // flip default type to writeback
    495     //
    496     SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
    497     ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
    498     MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
    499     MtrrSetAllMtrrs (&MtrrSettings);
    500 
    501     //
    502     // Set memory range from 640KB to 1MB to uncacheable
    503     //
    504     Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,
    505                BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);
    506     ASSERT_EFI_ERROR (Status);
    507 
    508     //
    509     // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as
    510     // uncacheable
    511     //
    512     Status = MtrrSetMemoryAttribute (LowerMemorySize,
    513                SIZE_4GB - LowerMemorySize, CacheUncacheable);
    514     ASSERT_EFI_ERROR (Status);
    515   }
    516 }
    517 
    518 /**
    519   Publish system RAM and reserve memory regions
    520 
    521 **/
    522 VOID
    523 InitializeRamRegions (
    524   VOID
    525   )
    526 {
    527   if (!mXen) {
    528     QemuInitializeRam ();
    529   } else {
    530     XenPublishRamRegions ();
    531   }
    532 
    533   if (mS3Supported && mBootMode != BOOT_ON_S3_RESUME) {
    534     //
    535     // This is the memory range that will be used for PEI on S3 resume
    536     //
    537     BuildMemoryAllocationHob (
    538       mS3AcpiReservedMemoryBase,
    539       mS3AcpiReservedMemorySize,
    540       EfiACPIMemoryNVS
    541       );
    542 
    543     //
    544     // Cover the initial RAM area used as stack and temporary PEI heap.
    545     //
    546     // This is reserved as ACPI NVS so it can be used on S3 resume.
    547     //
    548     BuildMemoryAllocationHob (
    549       PcdGet32 (PcdOvmfSecPeiTempRamBase),
    550       PcdGet32 (PcdOvmfSecPeiTempRamSize),
    551       EfiACPIMemoryNVS
    552       );
    553 
    554     //
    555     // SEC stores its table of GUIDed section handlers here.
    556     //
    557     BuildMemoryAllocationHob (
    558       PcdGet64 (PcdGuidedExtractHandlerTableAddress),
    559       PcdGet32 (PcdGuidedExtractHandlerTableSize),
    560       EfiACPIMemoryNVS
    561       );
    562 
    563 #ifdef MDE_CPU_X64
    564     //
    565     // Reserve the initial page tables built by the reset vector code.
    566     //
    567     // Since this memory range will be used by the Reset Vector on S3
    568     // resume, it must be reserved as ACPI NVS.
    569     //
    570     BuildMemoryAllocationHob (
    571       (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecPageTablesBase),
    572       (UINT64)(UINTN) PcdGet32 (PcdOvmfSecPageTablesSize),
    573       EfiACPIMemoryNVS
    574       );
    575 #endif
    576   }
    577 
    578   if (mBootMode != BOOT_ON_S3_RESUME) {
    579     if (!FeaturePcdGet (PcdSmmSmramRequire)) {
    580       //
    581       // Reserve the lock box storage area
    582       //
    583       // Since this memory range will be used on S3 resume, it must be
    584       // reserved as ACPI NVS.
    585       //
    586       // If S3 is unsupported, then various drivers might still write to the
    587       // LockBox area. We ought to prevent DXE from serving allocation requests
    588       // such that they would overlap the LockBox storage.
    589       //
    590       ZeroMem (
    591         (VOID*)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),
    592         (UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize)
    593         );
    594       BuildMemoryAllocationHob (
    595         (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),
    596         (UINT64)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize),
    597         mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
    598         );
    599     }
    600 
    601     if (FeaturePcdGet (PcdSmmSmramRequire)) {
    602       UINT32 TsegSize;
    603 
    604       //
    605       // Make sure the TSEG area that we reported as a reserved memory resource
    606       // cannot be used for reserved memory allocations.
    607       //
    608       TsegSize = FixedPcdGet8 (PcdQ35TsegMbytes) * SIZE_1MB;
    609       BuildMemoryAllocationHob (
    610         GetSystemMemorySizeBelow4gb() - TsegSize,
    611         TsegSize,
    612         EfiReservedMemoryType
    613         );
    614     }
    615   }
    616 }
    617