public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Gerd Hoffmann" <kraxel@redhat.com>
To: Min Xu <min.m.xu@intel.com>
Cc: devel@edk2.groups.io, Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Brijesh Singh <brijesh.singh@amd.com>,
	Erdem Aktas <erdemaktas@google.com>,
	James Bottomley <jejb@linux.ibm.com>,
	Jiewen Yao <jiewen.yao@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Sebastien Boeuf <sebastien.boeuf@intel.com>
Subject: Re: [PATCH V8 28/47] OvmfPkg/PlatformInitLib: Create MemDetect.c
Date: Tue, 15 Mar 2022 09:14:57 +0100	[thread overview]
Message-ID: <20220315081457.6ykewdihqwrn7jt4@sirius.home.kraxel.org> (raw)
In-Reply-To: <a96ba6b2276aac339822791ed538640951479805.1647047482.git.min.m.xu@intel.com>

On Sat, Mar 12, 2022 at 09:53:53AM +0800, Min Xu wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3863
> 
> Move functions in PlatformPei\MemDetect.c to PlatformInitLib\MemDetect.c.
> 
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Brijesh Singh <brijesh.singh@amd.com>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Cc: Sebastien Boeuf <sebastien.boeuf@intel.com>
> Signed-off-by: Min Xu <min.m.xu@intel.com>

Acked-by: Gerd Hoffmann <kraxel@redhat.com>

> ---
>  OvmfPkg/Include/Library/PlatformInitLib.h     |  37 +
>  OvmfPkg/Library/PlatformInitLib/MemDetect.c   | 842 ++++++++++++++++++
>  .../PlatformInitLib/PlatformInitLib.inf       |  49 +
>  OvmfPkg/PlatformPei/MemDetect.c               | 804 +----------------
>  OvmfPkg/PlatformPei/Platform.h                |  12 -
>  5 files changed, 929 insertions(+), 815 deletions(-)
>  create mode 100644 OvmfPkg/Library/PlatformInitLib/MemDetect.c
> 
> diff --git a/OvmfPkg/Include/Library/PlatformInitLib.h b/OvmfPkg/Include/Library/PlatformInitLib.h
> index 9b99d4c1f514..2e4bb8140368 100644
> --- a/OvmfPkg/Include/Library/PlatformInitLib.h
> +++ b/OvmfPkg/Include/Library/PlatformInitLib.h
> @@ -132,4 +132,41 @@ PlatformAddReservedMemoryBaseSizeHob (
>    IN BOOLEAN               Cacheable
>    );
>  
> +VOID
> +EFIAPI
> +PlatformQemuUc32BaseInitialization (
> +  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  );
> +
> +UINT32
> +EFIAPI
> +PlatformGetSystemMemorySizeBelow4gb (
> +  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  );
> +
> +/**
> +  Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
> +**/
> +VOID
> +EFIAPI
> +PlatformAddressWidthInitialization (
> +  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  );
> +
> +/**
> +  Peform Memory Detection for QEMU / KVM
> +
> +**/
> +VOID
> +EFIAPI
> +PlatformQemuInitializeRam (
> +  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  );
> +
> +VOID
> +EFIAPI
> +PlatformQemuInitializeRamForS3 (
> +  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  );
> +
>  #endif // PLATFORM_INIT_LIB_H_
> diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
> new file mode 100644
> index 000000000000..fbd3073bd3d1
> --- /dev/null
> +++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
> @@ -0,0 +1,842 @@
> +/**@file
> +  Memory Detection for Virtual Machines.
> +
> +  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +Module Name:
> +
> +  MemDetect.c
> +
> +**/
> +
> +//
> +// The package level header files this module uses
> +//
> +#include <IndustryStandard/E820.h>
> +#include <IndustryStandard/I440FxPiix4.h>
> +#include <IndustryStandard/Q35MchIch9.h>
> +#include <IndustryStandard/CloudHv.h>
> +#include <IndustryStandard/Xen/arch-x86/hvm/start_info.h>
> +#include <PiPei.h>
> +#include <Register/Intel/SmramSaveStateMap.h>
> +
> +//
> +// The Library classes this module consumes
> +//
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemEncryptSevLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/PeimEntryPoint.h>
> +#include <Library/ResourcePublicationLib.h>
> +#include <Library/MtrrLib.h>
> +#include <Library/QemuFwCfgLib.h>
> +#include <Library/QemuFwCfgSimpleParserLib.h>
> +#include <Library/PlatformInitLib.h>
> +
> +VOID
> +EFIAPI
> +PlatformQemuUc32BaseInitialization (
> +  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  )
> +{
> +  UINT32  LowerMemorySize;
> +
> +  if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {
> +    return;
> +  }
> +
> +  if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
> +    //
> +    // On q35, the 32-bit area that we'll mark as UC, through variable MTRRs,
> +    // starts at PcdPciExpressBaseAddress. The platform DSC is responsible for
> +    // setting PcdPciExpressBaseAddress such that describing the
> +    // [PcdPciExpressBaseAddress, 4GB) range require a very small number of
> +    // variable MTRRs (preferably 1 or 2).
> +    //
> +    ASSERT (FixedPcdGet64 (PcdPciExpressBaseAddress) <= MAX_UINT32);
> +    PlatformInfoHob->Uc32Base = (UINT32)FixedPcdGet64 (PcdPciExpressBaseAddress);
> +    return;
> +  }
> +
> +  if (PlatformInfoHob->HostBridgeDevId == CLOUDHV_DEVICE_ID) {
> +    PlatformInfoHob->Uc32Size = CLOUDHV_MMIO_HOLE_SIZE;
> +    PlatformInfoHob->Uc32Base = CLOUDHV_MMIO_HOLE_ADDRESS;
> +    return;
> +  }
> +
> +  ASSERT (PlatformInfoHob->HostBridgeDevId == INTEL_82441_DEVICE_ID);
> +  //
> +  // On i440fx, start with the [LowerMemorySize, 4GB) range. Make sure one
> +  // variable MTRR suffices by truncating the size to a whole power of two,
> +  // while keeping the end affixed to 4GB. This will round the base up.
> +  //
> +  LowerMemorySize           = PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob);
> +  PlatformInfoHob->Uc32Size = GetPowerOfTwo32 ((UINT32)(SIZE_4GB - LowerMemorySize));
> +  PlatformInfoHob->Uc32Base = (UINT32)(SIZE_4GB - PlatformInfoHob->Uc32Size);
> +  //
> +  // Assuming that LowerMemorySize is at least 1 byte, Uc32Size is at most 2GB.
> +  // Therefore mQemuUc32Base is at least 2GB.
> +  //
> +  ASSERT (PlatformInfoHob->Uc32Base >= BASE_2GB);
> +
> +  if (PlatformInfoHob->Uc32Base != LowerMemorySize) {
> +    DEBUG ((
> +      DEBUG_VERBOSE,
> +      "%a: rounded UC32 base from 0x%x up to 0x%x, for "
> +      "an UC32 size of 0x%x\n",
> +      __FUNCTION__,
> +      LowerMemorySize,
> +      PlatformInfoHob->Uc32Base,
> +      PlatformInfoHob->Uc32Size
> +      ));
> +  }
> +}
> +
> +/**
> +  Iterate over the RAM entries in QEMU's fw_cfg E820 RAM map that start outside
> +  of the 32-bit address range.
> +
> +  Find the highest exclusive >=4GB RAM address, or produce memory resource
> +  descriptor HOBs for RAM entries that start at or above 4GB.
> +
> +  @param[out] MaxAddress  If MaxAddress is NULL, then PlatformScanOrAdd64BitE820Ram()
> +                          produces memory resource descriptor HOBs for RAM
> +                          entries that start at or above 4GB.
> +
> +                          Otherwise, MaxAddress holds the highest exclusive
> +                          >=4GB RAM address on output. If QEMU's fw_cfg E820
> +                          RAM map contains no RAM entry that starts outside of
> +                          the 32-bit address range, then MaxAddress is exactly
> +                          4GB on output.
> +
> +  @retval EFI_SUCCESS         The fw_cfg E820 RAM map was found and processed.
> +
> +  @retval EFI_PROTOCOL_ERROR  The RAM map was found, but its size wasn't a
> +                              whole multiple of sizeof(EFI_E820_ENTRY64). No
> +                              RAM entry was processed.
> +
> +  @return                     Error codes from QemuFwCfgFindFile(). No RAM
> +                              entry was processed.
> +**/
> +STATIC
> +EFI_STATUS
> +PlatformScanOrAdd64BitE820Ram (
> +  IN BOOLEAN  AddHighHob,
> +  OUT UINT64  *LowMemory OPTIONAL,
> +  OUT UINT64  *MaxAddress OPTIONAL
> +  )
> +{
> +  EFI_STATUS            Status;
> +  FIRMWARE_CONFIG_ITEM  FwCfgItem;
> +  UINTN                 FwCfgSize;
> +  EFI_E820_ENTRY64      E820Entry;
> +  UINTN                 Processed;
> +
> +  Status = QemuFwCfgFindFile ("etc/e820", &FwCfgItem, &FwCfgSize);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (FwCfgSize % sizeof E820Entry != 0) {
> +    return EFI_PROTOCOL_ERROR;
> +  }
> +
> +  if (LowMemory != NULL) {
> +    *LowMemory = 0;
> +  }
> +
> +  if (MaxAddress != NULL) {
> +    *MaxAddress = BASE_4GB;
> +  }
> +
> +  QemuFwCfgSelectItem (FwCfgItem);
> +  for (Processed = 0; Processed < FwCfgSize; Processed += sizeof E820Entry) {
> +    QemuFwCfgReadBytes (sizeof E820Entry, &E820Entry);
> +    DEBUG ((
> +      DEBUG_VERBOSE,
> +      "%a: Base=0x%Lx Length=0x%Lx Type=%u\n",
> +      __FUNCTION__,
> +      E820Entry.BaseAddr,
> +      E820Entry.Length,
> +      E820Entry.Type
> +      ));
> +    if (E820Entry.Type == EfiAcpiAddressRangeMemory) {
> +      if (AddHighHob && (E820Entry.BaseAddr >= BASE_4GB)) {
> +        UINT64  Base;
> +        UINT64  End;
> +
> +        //
> +        // Round up the start address, and round down the end address.
> +        //
> +        Base = ALIGN_VALUE (E820Entry.BaseAddr, (UINT64)EFI_PAGE_SIZE);
> +        End  = (E820Entry.BaseAddr + E820Entry.Length) &
> +               ~(UINT64)EFI_PAGE_MASK;
> +        if (Base < End) {
> +          PlatformAddMemoryRangeHob (Base, End);
> +          DEBUG ((
> +            DEBUG_VERBOSE,
> +            "%a: PlatformAddMemoryRangeHob [0x%Lx, 0x%Lx)\n",
> +            __FUNCTION__,
> +            Base,
> +            End
> +            ));
> +        }
> +      }
> +
> +      if (MaxAddress || LowMemory) {
> +        UINT64  Candidate;
> +
> +        Candidate = E820Entry.BaseAddr + E820Entry.Length;
> +        if (MaxAddress && (Candidate > *MaxAddress)) {
> +          *MaxAddress = Candidate;
> +          DEBUG ((
> +            DEBUG_VERBOSE,
> +            "%a: MaxAddress=0x%Lx\n",
> +            __FUNCTION__,
> +            *MaxAddress
> +            ));
> +        }
> +
> +        if (LowMemory && (Candidate > *LowMemory) && (Candidate < BASE_4GB)) {
> +          *LowMemory = Candidate;
> +          DEBUG ((
> +            DEBUG_VERBOSE,
> +            "%a: LowMemory=0x%Lx\n",
> +            __FUNCTION__,
> +            *LowMemory
> +            ));
> +        }
> +      }
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Returns PVH memmap
> +
> +  @param Entries      Pointer to PVH memmap
> +  @param Count        Number of entries
> +
> +  @return EFI_STATUS
> +**/
> +EFI_STATUS
> +GetPvhMemmapEntries (
> +  struct hvm_memmap_table_entry  **Entries,
> +  UINT32                         *Count
> +  )
> +{
> +  UINT32                 *PVHResetVectorData;
> +  struct hvm_start_info  *pvh_start_info;
> +
> +  PVHResetVectorData = (VOID *)(UINTN)PcdGet32 (PcdXenPvhStartOfDayStructPtr);
> +  if (PVHResetVectorData == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  pvh_start_info = (struct hvm_start_info *)(UINTN)PVHResetVectorData[0];
> +
> +  *Entries = (struct hvm_memmap_table_entry *)(UINTN)pvh_start_info->memmap_paddr;
> +  *Count   = pvh_start_info->memmap_entries;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +UINT64
> +GetHighestSystemMemoryAddressFromPvhMemmap (
> +  BOOLEAN  Below4gb
> +  )
> +{
> +  struct hvm_memmap_table_entry  *Memmap;
> +  UINT32                         MemmapEntriesCount;
> +  struct hvm_memmap_table_entry  *Entry;
> +  EFI_STATUS                     Status;
> +  UINT32                         Loop;
> +  UINT64                         HighestAddress;
> +  UINT64                         EntryEnd;
> +
> +  HighestAddress = 0;
> +
> +  Status = GetPvhMemmapEntries (&Memmap, &MemmapEntriesCount);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  for (Loop = 0; Loop < MemmapEntriesCount; Loop++) {
> +    Entry    = Memmap + Loop;
> +    EntryEnd = Entry->addr + Entry->size;
> +
> +    if ((Entry->type == XEN_HVM_MEMMAP_TYPE_RAM) &&
> +        (EntryEnd > HighestAddress))
> +    {
> +      if (Below4gb && (EntryEnd <= BASE_4GB)) {
> +        HighestAddress = EntryEnd;
> +      } else if (!Below4gb && (EntryEnd >= BASE_4GB)) {
> +        HighestAddress = EntryEnd;
> +      }
> +    }
> +  }
> +
> +  return HighestAddress;
> +}
> +
> +UINT32
> +EFIAPI
> +PlatformGetSystemMemorySizeBelow4gb (
> +  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT64      LowerMemorySize = 0;
> +  UINT8       Cmos0x34;
> +  UINT8       Cmos0x35;
> +
> +  if (PlatformInfoHob->HostBridgeDevId == CLOUDHV_DEVICE_ID) {
> +    // Get the information from PVH memmap
> +    return (UINT32)GetHighestSystemMemoryAddressFromPvhMemmap (TRUE);
> +  }
> +
> +  Status = PlatformScanOrAdd64BitE820Ram (FALSE, &LowerMemorySize, NULL);
> +  if ((Status == EFI_SUCCESS) && (LowerMemorySize > 0)) {
> +    return (UINT32)LowerMemorySize;
> +  }
> +
> +  //
> +  // CMOS 0x34/0x35 specifies the system memory above 16 MB.
> +  // * CMOS(0x35) is the high byte
> +  // * CMOS(0x34) is the low byte
> +  // * The size is specified in 64kb chunks
> +  // * Since this is memory above 16MB, the 16MB must be added
> +  //   into the calculation to get the total memory size.
> +  //
> +
> +  Cmos0x34 = (UINT8)PlatformCmosRead8 (0x34);
> +  Cmos0x35 = (UINT8)PlatformCmosRead8 (0x35);
> +
> +  return (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
> +}
> +
> +STATIC
> +UINT64
> +PlatformGetSystemMemorySizeAbove4gb (
> +  )
> +{
> +  UINT32  Size;
> +  UINTN   CmosIndex;
> +
> +  //
> +  // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
> +  // * CMOS(0x5d) is the most significant size byte
> +  // * CMOS(0x5c) is the middle size byte
> +  // * CMOS(0x5b) is the least significant size byte
> +  // * The size is specified in 64kb chunks
> +  //
> +
> +  Size = 0;
> +  for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
> +    Size = (UINT32)(Size << 8) + (UINT32)PlatformCmosRead8 (CmosIndex);
> +  }
> +
> +  return LShiftU64 (Size, 16);
> +}
> +
> +/**
> +  Return the highest address that DXE could possibly use, plus one.
> +**/
> +STATIC
> +UINT64
> +PlatformGetFirstNonAddress (
> +  IN OUT  EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  )
> +{
> +  UINT64                FirstNonAddress;
> +  UINT32                FwCfgPciMmio64Mb;
> +  EFI_STATUS            Status;
> +  FIRMWARE_CONFIG_ITEM  FwCfgItem;
> +  UINTN                 FwCfgSize;
> +  UINT64                HotPlugMemoryEnd;
> +
> +  //
> +  // set FirstNonAddress to suppress incorrect compiler/analyzer warnings
> +  //
> +  FirstNonAddress = 0;
> +
> +  //
> +  // If QEMU presents an E820 map, then get the highest exclusive >=4GB RAM
> +  // address from it. This can express an address >= 4GB+1TB.
> +  //
> +  // Otherwise, get the flat size of the memory above 4GB from the CMOS (which
> +  // can only express a size smaller than 1TB), and add it to 4GB.
> +  //
> +  Status = PlatformScanOrAdd64BitE820Ram (FALSE, NULL, &FirstNonAddress);
> +  if (EFI_ERROR (Status)) {
> +    FirstNonAddress = BASE_4GB + PlatformGetSystemMemorySizeAbove4gb ();
> +  }
> +
> +  //
> +  // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
> +  // resources to 32-bit anyway. See DegradeResource() in
> +  // "PciResourceSupport.c".
> +  //
> + #ifdef MDE_CPU_IA32
> +  if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
> +    return FirstNonAddress;
> +  }
> +
> + #endif
> +
> +  //
> +  // See if the user specified the number of megabytes for the 64-bit PCI host
> +  // aperture. Accept an aperture size up to 16TB.
> +  //
> +  // As signaled by the "X-" prefix, this knob is experimental, and might go
> +  // away at any time.
> +  //
> +  Status = QemuFwCfgParseUint32 (
> +             "opt/ovmf/X-PciMmio64Mb",
> +             FALSE,
> +             &FwCfgPciMmio64Mb
> +             );
> +  switch (Status) {
> +    case EFI_UNSUPPORTED:
> +    case EFI_NOT_FOUND:
> +      break;
> +    case EFI_SUCCESS:
> +      if (FwCfgPciMmio64Mb <= 0x1000000) {
> +        PlatformInfoHob->PcdPciMmio64Size = LShiftU64 (FwCfgPciMmio64Mb, 20);
> +        break;
> +      }
> +
> +    //
> +    // fall through
> +    //
> +    default:
> +      DEBUG ((
> +        DEBUG_WARN,
> +        "%a: ignoring malformed 64-bit PCI host aperture size from fw_cfg\n",
> +        __FUNCTION__
> +        ));
> +      break;
> +  }
> +
> +  if (PlatformInfoHob->PcdPciMmio64Size == 0) {
> +    if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "%a: disabling 64-bit PCI host aperture\n",
> +        __FUNCTION__
> +        ));
> +    }
> +
> +    //
> +    // There's nothing more to do; the amount of memory above 4GB fully
> +    // determines the highest address plus one. The memory hotplug area (see
> +    // below) plays no role for the firmware in this case.
> +    //
> +    return FirstNonAddress;
> +  }
> +
> +  //
> +  // The "etc/reserved-memory-end" fw_cfg file, when present, contains an
> +  // absolute, exclusive end address for the memory hotplug area. This area
> +  // starts right at the end of the memory above 4GB. The 64-bit PCI host
> +  // aperture must be placed above it.
> +  //
> +  Status = QemuFwCfgFindFile (
> +             "etc/reserved-memory-end",
> +             &FwCfgItem,
> +             &FwCfgSize
> +             );
> +  if (!EFI_ERROR (Status) && (FwCfgSize == sizeof HotPlugMemoryEnd)) {
> +    QemuFwCfgSelectItem (FwCfgItem);
> +    QemuFwCfgReadBytes (FwCfgSize, &HotPlugMemoryEnd);
> +    DEBUG ((
> +      DEBUG_VERBOSE,
> +      "%a: HotPlugMemoryEnd=0x%Lx\n",
> +      __FUNCTION__,
> +      HotPlugMemoryEnd
> +      ));
> +
> +    ASSERT (HotPlugMemoryEnd >= FirstNonAddress);
> +    FirstNonAddress = HotPlugMemoryEnd;
> +  }
> +
> +  //
> +  // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
> +  // that the host can map it with 1GB hugepages. Follow suit.
> +  //
> +  PlatformInfoHob->PcdPciMmio64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
> +  PlatformInfoHob->PcdPciMmio64Size = ALIGN_VALUE (PlatformInfoHob->PcdPciMmio64Size, (UINT64)SIZE_1GB);
> +
> +  //
> +  // The 64-bit PCI host aperture should also be "naturally" aligned. The
> +  // alignment is determined by rounding the size of the aperture down to the
> +  // next smaller or equal power of two. That is, align the aperture by the
> +  // largest BAR size that can fit into it.
> +  //
> +  PlatformInfoHob->PcdPciMmio64Base = ALIGN_VALUE (PlatformInfoHob->PcdPciMmio64Base, GetPowerOfTwo64 (PlatformInfoHob->PcdPciMmio64Size));
> +
> +  //
> +  // The useful address space ends with the 64-bit PCI host aperture.
> +  //
> +  FirstNonAddress = PlatformInfoHob->PcdPciMmio64Base + PlatformInfoHob->PcdPciMmio64Size;
> +  return FirstNonAddress;
> +}
> +
> +/**
> +  Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
> +**/
> +VOID
> +EFIAPI
> +PlatformAddressWidthInitialization (
> +  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  )
> +{
> +  UINT64  FirstNonAddress;
> +  UINT8   PhysMemAddressWidth;
> +
> +  //
> +  // As guest-physical memory size grows, the permanent PEI RAM requirements
> +  // are dominated by the identity-mapping page tables built by the DXE IPL.
> +  // The DXL IPL keys off of the physical address bits advertized in the CPU
> +  // HOB. To conserve memory, we calculate the minimum address width here.
> +  //
> +  FirstNonAddress     = PlatformGetFirstNonAddress (PlatformInfoHob);
> +  PhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
> +
> +  //
> +  // If FirstNonAddress is not an integral power of two, then we need an
> +  // additional bit.
> +  //
> +  if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
> +    ++PhysMemAddressWidth;
> +  }
> +
> +  //
> +  // The minimum address width is 36 (covers up to and excluding 64 GB, which
> +  // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
> +  // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
> +  // can simply assert that here, since 48 bits are good enough for 256 TB.
> +  //
> +  if (PhysMemAddressWidth <= 36) {
> +    PhysMemAddressWidth = 36;
> +  }
> +
> +  ASSERT (PhysMemAddressWidth <= 48);
> +
> +  PlatformInfoHob->FirstNonAddress     = FirstNonAddress;
> +  PlatformInfoHob->PhysMemAddressWidth = PhysMemAddressWidth;
> +}
> +
> +STATIC
> +VOID
> +QemuInitializeRamBelow1gb (
> +  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  )
> +{
> +  if (PlatformInfoHob->SmmSmramRequire && PlatformInfoHob->Q35SmramAtDefaultSmbase) {
> +    PlatformAddMemoryRangeHob (0, SMM_DEFAULT_SMBASE);
> +    PlatformAddReservedMemoryBaseSizeHob (
> +      SMM_DEFAULT_SMBASE,
> +      MCH_DEFAULT_SMBASE_SIZE,
> +      TRUE /* Cacheable */
> +      );
> +    STATIC_ASSERT (
> +      SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE < BASE_512KB + BASE_128KB,
> +      "end of SMRAM at default SMBASE ends at, or exceeds, 640KB"
> +      );
> +    PlatformAddMemoryRangeHob (
> +      SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE,
> +      BASE_512KB + BASE_128KB
> +      );
> +  } else {
> +    PlatformAddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
> +  }
> +}
> +
> +/**
> +  Peform Memory Detection for QEMU / KVM
> +
> +**/
> +VOID
> +EFIAPI
> +PlatformQemuInitializeRam (
> +  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  )
> +{
> +  UINT64         LowerMemorySize;
> +  UINT64         UpperMemorySize;
> +  MTRR_SETTINGS  MtrrSettings;
> +  EFI_STATUS     Status;
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  //
> +  // Determine total memory size available
> +  //
> +  LowerMemorySize = PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob);
> +
> +  if (PlatformInfoHob->BootMode == BOOT_ON_S3_RESUME) {
> +    //
> +    // Create the following memory HOB as an exception on the S3 boot path.
> +    //
> +    // Normally we'd create memory HOBs only on the normal boot path. However,
> +    // CpuMpPei specifically needs such a low-memory HOB on the S3 path as
> +    // well, for "borrowing" a subset of it temporarily, for the AP startup
> +    // vector.
> +    //
> +    // CpuMpPei saves the original contents of the borrowed area in permanent
> +    // PEI RAM, in a backup buffer allocated with the normal PEI services.
> +    // CpuMpPei restores the original contents ("returns" the borrowed area) at
> +    // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before
> +    // transferring control to the OS's wakeup vector in the FACS.
> +    //
> +    // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to
> +    // restore the original contents. Furthermore, we expect all such PEIMs
> +    // (CpuMpPei included) to claim the borrowed areas by producing memory
> +    // allocation HOBs, and to honor preexistent memory allocation HOBs when
> +    // looking for an area to borrow.
> +    //
> +    QemuInitializeRamBelow1gb (PlatformInfoHob);
> +  } else {
> +    //
> +    // Create memory HOBs
> +    //
> +    QemuInitializeRamBelow1gb (PlatformInfoHob);
> +
> +    if (PlatformInfoHob->SmmSmramRequire) {
> +      UINT32  TsegSize;
> +
> +      TsegSize = PlatformInfoHob->Q35TsegMbytes * SIZE_1MB;
> +      PlatformAddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);
> +      PlatformAddReservedMemoryBaseSizeHob (
> +        LowerMemorySize - TsegSize,
> +        TsegSize,
> +        TRUE
> +        );
> +    } else {
> +      PlatformAddMemoryRangeHob (BASE_1MB, LowerMemorySize);
> +    }
> +
> +    //
> +    // If QEMU presents an E820 map, then create memory HOBs for the >=4GB RAM
> +    // entries. Otherwise, create a single memory HOB with the flat >=4GB
> +    // memory size read from the CMOS.
> +    //
> +    Status = PlatformScanOrAdd64BitE820Ram (TRUE, NULL, NULL);
> +    if (EFI_ERROR (Status)) {
> +      UpperMemorySize = PlatformGetSystemMemorySizeAbove4gb ();
> +      if (UpperMemorySize != 0) {
> +        PlatformAddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
> +      }
> +    }
> +  }
> +
> +  //
> +  // We'd like to keep the following ranges uncached:
> +  // - [640 KB, 1 MB)
> +  // - [LowerMemorySize, 4 GB)
> +  //
> +  // Everything else should be WB. Unfortunately, programming the inverse (ie.
> +  // keeping the default UC, and configuring the complement set of the above as
> +  // WB) is not reliable in general, because the end of the upper RAM can have
> +  // practically any alignment, and we may not have enough variable MTRRs to
> +  // cover it exactly.
> +  //
> +  if (IsMtrrSupported () && (PlatformInfoHob->HostBridgeDevId != CLOUDHV_DEVICE_ID)) {
> +    MtrrGetAllMtrrs (&MtrrSettings);
> +
> +    //
> +    // MTRRs disabled, fixed MTRRs disabled, default type is uncached
> +    //
> +    ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
> +    ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
> +    ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
> +
> +    //
> +    // flip default type to writeback
> +    //
> +    SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
> +    ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
> +    MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
> +    MtrrSetAllMtrrs (&MtrrSettings);
> +
> +    //
> +    // Set memory range from 640KB to 1MB to uncacheable
> +    //
> +    Status = MtrrSetMemoryAttribute (
> +               BASE_512KB + BASE_128KB,
> +               BASE_1MB - (BASE_512KB + BASE_128KB),
> +               CacheUncacheable
> +               );
> +    ASSERT_EFI_ERROR (Status);
> +
> +    //
> +    // Set the memory range from the start of the 32-bit MMIO area (32-bit PCI
> +    // MMIO aperture on i440fx, PCIEXBAR on q35) to 4GB as uncacheable.
> +    //
> +    Status = MtrrSetMemoryAttribute (
> +               PlatformInfoHob->Uc32Base,
> +               SIZE_4GB - PlatformInfoHob->Uc32Base,
> +               CacheUncacheable
> +               );
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +}
> +
> +VOID
> +EFIAPI
> +PlatformQemuInitializeRamForS3 (
> +  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> +  )
> +{
> +  if (PlatformInfoHob->S3Supported && (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME)) {
> +    //
> +    // This is the memory range that will be used for PEI on S3 resume
> +    //
> +    BuildMemoryAllocationHob (
> +      PlatformInfoHob->S3AcpiReservedMemoryBase,
> +      PlatformInfoHob->S3AcpiReservedMemorySize,
> +      EfiACPIMemoryNVS
> +      );
> +
> +    //
> +    // Cover the initial RAM area used as stack and temporary PEI heap.
> +    //
> +    // This is reserved as ACPI NVS so it can be used on S3 resume.
> +    //
> +    BuildMemoryAllocationHob (
> +      PcdGet32 (PcdOvmfSecPeiTempRamBase),
> +      PcdGet32 (PcdOvmfSecPeiTempRamSize),
> +      EfiACPIMemoryNVS
> +      );
> +
> +    //
> +    // SEC stores its table of GUIDed section handlers here.
> +    //
> +    BuildMemoryAllocationHob (
> +      PcdGet64 (PcdGuidedExtractHandlerTableAddress),
> +      PcdGet32 (PcdGuidedExtractHandlerTableSize),
> +      EfiACPIMemoryNVS
> +      );
> +
> + #ifdef MDE_CPU_X64
> +    //
> +    // Reserve the initial page tables built by the reset vector code.
> +    //
> +    // Since this memory range will be used by the Reset Vector on S3
> +    // resume, it must be reserved as ACPI NVS.
> +    //
> +    BuildMemoryAllocationHob (
> +      (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecPageTablesBase),
> +      (UINT64)(UINTN)PcdGet32 (PcdOvmfSecPageTablesSize),
> +      EfiACPIMemoryNVS
> +      );
> +
> +    if (PlatformInfoHob->SevEsIsEnabled) {
> +      //
> +      // If SEV-ES is enabled, reserve the GHCB-related memory area. This
> +      // includes the extra page table used to break down the 2MB page
> +      // mapping into 4KB page entries where the GHCB resides and the
> +      // GHCB area itself.
> +      //
> +      // Since this memory range will be used by the Reset Vector on S3
> +      // resume, it must be reserved as ACPI NVS.
> +      //
> +      BuildMemoryAllocationHob (
> +        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecGhcbPageTableBase),
> +        (UINT64)(UINTN)PcdGet32 (PcdOvmfSecGhcbPageTableSize),
> +        EfiACPIMemoryNVS
> +        );
> +      BuildMemoryAllocationHob (
> +        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecGhcbBase),
> +        (UINT64)(UINTN)PcdGet32 (PcdOvmfSecGhcbSize),
> +        EfiACPIMemoryNVS
> +        );
> +      BuildMemoryAllocationHob (
> +        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecGhcbBackupBase),
> +        (UINT64)(UINTN)PcdGet32 (PcdOvmfSecGhcbBackupSize),
> +        EfiACPIMemoryNVS
> +        );
> +    }
> +
> + #endif
> +  }
> +
> +  if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
> +    if (!PlatformInfoHob->SmmSmramRequire) {
> +      //
> +      // Reserve the lock box storage area
> +      //
> +      // Since this memory range will be used on S3 resume, it must be
> +      // reserved as ACPI NVS.
> +      //
> +      // If S3 is unsupported, then various drivers might still write to the
> +      // LockBox area. We ought to prevent DXE from serving allocation requests
> +      // such that they would overlap the LockBox storage.
> +      //
> +      ZeroMem (
> +        (VOID *)(UINTN)PcdGet32 (PcdOvmfLockBoxStorageBase),
> +        (UINTN)PcdGet32 (PcdOvmfLockBoxStorageSize)
> +        );
> +      BuildMemoryAllocationHob (
> +        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfLockBoxStorageBase),
> +        (UINT64)(UINTN)PcdGet32 (PcdOvmfLockBoxStorageSize),
> +        PlatformInfoHob->S3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
> +        );
> +    }
> +
> +    if (PlatformInfoHob->SmmSmramRequire) {
> +      UINT32  TsegSize;
> +
> +      //
> +      // Make sure the TSEG area that we reported as a reserved memory resource
> +      // cannot be used for reserved memory allocations.
> +      //
> +      TsegSize = PlatformInfoHob->Q35TsegMbytes * SIZE_1MB;
> +      BuildMemoryAllocationHob (
> +        PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob) - TsegSize,
> +        TsegSize,
> +        EfiReservedMemoryType
> +        );
> +      //
> +      // Similarly, allocate away the (already reserved) SMRAM at the default
> +      // SMBASE, if it exists.
> +      //
> +      if (PlatformInfoHob->Q35SmramAtDefaultSmbase) {
> +        BuildMemoryAllocationHob (
> +          SMM_DEFAULT_SMBASE,
> +          MCH_DEFAULT_SMBASE_SIZE,
> +          EfiReservedMemoryType
> +          );
> +      }
> +    }
> +
> + #ifdef MDE_CPU_X64
> +    if (FixedPcdGet32 (PcdOvmfWorkAreaSize) != 0) {
> +      //
> +      // Reserve the work area.
> +      //
> +      // Since this memory range will be used by the Reset Vector on S3
> +      // resume, it must be reserved as ACPI NVS.
> +      //
> +      // If S3 is unsupported, then various drivers might still write to the
> +      // work area. We ought to prevent DXE from serving allocation requests
> +      // such that they would overlap the work area.
> +      //
> +      BuildMemoryAllocationHob (
> +        (EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaBase),
> +        (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaSize),
> +        PlatformInfoHob->S3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
> +        );
> +    }
> +
> + #endif
> +  }
> +}
> diff --git a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
> index 21813458cb59..19a88d363819 100644
> --- a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
> +++ b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
> @@ -24,15 +24,64 @@
>  
>  [Sources]
>    Cmos.c
> +  MemDetect.c
>    Platform.c
>  
>  [Packages]
> +  EmbeddedPkg/EmbeddedPkg.dec
>    MdeModulePkg/MdeModulePkg.dec
>    MdePkg/MdePkg.dec
>    OvmfPkg/OvmfPkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
>  
>  [LibraryClasses]
>    BaseLib
>    DebugLib
>    IoLib
>    HobLib
> +  QemuFwCfgLib
> +  QemuFwCfgSimpleParserLib
> +  MtrrLib
> +  PcdLib
> +  PciLib
> +
> +[FixedPcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
> +
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
> +  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
> +
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
> +
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
> +
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize
> +
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase
> +  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
> +  gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtr
> +  gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtrSize
> +  gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
> +  gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
> +
> +[FeaturePcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
> diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
> index 5709766f86f3..3907de1545de 100644
> --- a/OvmfPkg/PlatformPei/MemDetect.c
> +++ b/OvmfPkg/PlatformPei/MemDetect.c
> @@ -34,7 +34,7 @@ Module Name:
>  #include <Library/PciLib.h>
>  #include <Library/PeimEntryPoint.h>
>  #include <Library/ResourcePublicationLib.h>
> -#include <Library/MtrrLib.h>
> +
>  #include <Library/QemuFwCfgLib.h>
>  #include <Library/QemuFwCfgSimpleParserLib.h>
>  
> @@ -126,501 +126,6 @@ Q35SmramAtDefaultSmbaseInitialization (
>    ASSERT_RETURN_ERROR (PcdStatus);
>  }
>  
> -VOID
> -EFIAPI
> -PlatformQemuUc32BaseInitialization (
> -  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  )
> -{
> -  UINT32  LowerMemorySize;
> -
> -  if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {
> -    return;
> -  }
> -
> -  if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
> -    //
> -    // On q35, the 32-bit area that we'll mark as UC, through variable MTRRs,
> -    // starts at PcdPciExpressBaseAddress. The platform DSC is responsible for
> -    // setting PcdPciExpressBaseAddress such that describing the
> -    // [PcdPciExpressBaseAddress, 4GB) range require a very small number of
> -    // variable MTRRs (preferably 1 or 2).
> -    //
> -    ASSERT (FixedPcdGet64 (PcdPciExpressBaseAddress) <= MAX_UINT32);
> -    PlatformInfoHob->Uc32Base = (UINT32)FixedPcdGet64 (PcdPciExpressBaseAddress);
> -    return;
> -  }
> -
> -  if (PlatformInfoHob->HostBridgeDevId == CLOUDHV_DEVICE_ID) {
> -    PlatformInfoHob->Uc32Size = CLOUDHV_MMIO_HOLE_SIZE;
> -    PlatformInfoHob->Uc32Base = CLOUDHV_MMIO_HOLE_ADDRESS;
> -    return;
> -  }
> -
> -  ASSERT (PlatformInfoHob->HostBridgeDevId == INTEL_82441_DEVICE_ID);
> -  //
> -  // On i440fx, start with the [LowerMemorySize, 4GB) range. Make sure one
> -  // variable MTRR suffices by truncating the size to a whole power of two,
> -  // while keeping the end affixed to 4GB. This will round the base up.
> -  //
> -  LowerMemorySize           = PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob);
> -  PlatformInfoHob->Uc32Size = GetPowerOfTwo32 ((UINT32)(SIZE_4GB - LowerMemorySize));
> -  PlatformInfoHob->Uc32Base = (UINT32)(SIZE_4GB - PlatformInfoHob->Uc32Size);
> -  //
> -  // Assuming that LowerMemorySize is at least 1 byte, Uc32Size is at most 2GB.
> -  // Therefore mQemuUc32Base is at least 2GB.
> -  //
> -  ASSERT (PlatformInfoHob->Uc32Base >= BASE_2GB);
> -
> -  if (PlatformInfoHob->Uc32Base != LowerMemorySize) {
> -    DEBUG ((
> -      DEBUG_VERBOSE,
> -      "%a: rounded UC32 base from 0x%x up to 0x%x, for "
> -      "an UC32 size of 0x%x\n",
> -      __FUNCTION__,
> -      LowerMemorySize,
> -      PlatformInfoHob->Uc32Base,
> -      PlatformInfoHob->Uc32Size
> -      ));
> -  }
> -}
> -
> -/**
> -  Iterate over the RAM entries in QEMU's fw_cfg E820 RAM map that start outside
> -  of the 32-bit address range.
> -
> -  Find the highest exclusive >=4GB RAM address, or produce memory resource
> -  descriptor HOBs for RAM entries that start at or above 4GB.
> -
> -  @param[out] MaxAddress  If MaxAddress is NULL, then PlatformScanOrAdd64BitE820Ram()
> -                          produces memory resource descriptor HOBs for RAM
> -                          entries that start at or above 4GB.
> -
> -                          Otherwise, MaxAddress holds the highest exclusive
> -                          >=4GB RAM address on output. If QEMU's fw_cfg E820
> -                          RAM map contains no RAM entry that starts outside of
> -                          the 32-bit address range, then MaxAddress is exactly
> -                          4GB on output.
> -
> -  @retval EFI_SUCCESS         The fw_cfg E820 RAM map was found and processed.
> -
> -  @retval EFI_PROTOCOL_ERROR  The RAM map was found, but its size wasn't a
> -                              whole multiple of sizeof(EFI_E820_ENTRY64). No
> -                              RAM entry was processed.
> -
> -  @return                     Error codes from QemuFwCfgFindFile(). No RAM
> -                              entry was processed.
> -**/
> -STATIC
> -EFI_STATUS
> -PlatformScanOrAdd64BitE820Ram (
> -  IN BOOLEAN  AddHighHob,
> -  OUT UINT64  *LowMemory OPTIONAL,
> -  OUT UINT64  *MaxAddress OPTIONAL
> -  )
> -{
> -  EFI_STATUS            Status;
> -  FIRMWARE_CONFIG_ITEM  FwCfgItem;
> -  UINTN                 FwCfgSize;
> -  EFI_E820_ENTRY64      E820Entry;
> -  UINTN                 Processed;
> -
> -  Status = QemuFwCfgFindFile ("etc/e820", &FwCfgItem, &FwCfgSize);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> -  }
> -
> -  if (FwCfgSize % sizeof E820Entry != 0) {
> -    return EFI_PROTOCOL_ERROR;
> -  }
> -
> -  if (LowMemory != NULL) {
> -    *LowMemory = 0;
> -  }
> -
> -  if (MaxAddress != NULL) {
> -    *MaxAddress = BASE_4GB;
> -  }
> -
> -  QemuFwCfgSelectItem (FwCfgItem);
> -  for (Processed = 0; Processed < FwCfgSize; Processed += sizeof E820Entry) {
> -    QemuFwCfgReadBytes (sizeof E820Entry, &E820Entry);
> -    DEBUG ((
> -      DEBUG_VERBOSE,
> -      "%a: Base=0x%Lx Length=0x%Lx Type=%u\n",
> -      __FUNCTION__,
> -      E820Entry.BaseAddr,
> -      E820Entry.Length,
> -      E820Entry.Type
> -      ));
> -    if (E820Entry.Type == EfiAcpiAddressRangeMemory) {
> -      if (AddHighHob && (E820Entry.BaseAddr >= BASE_4GB)) {
> -        UINT64  Base;
> -        UINT64  End;
> -
> -        //
> -        // Round up the start address, and round down the end address.
> -        //
> -        Base = ALIGN_VALUE (E820Entry.BaseAddr, (UINT64)EFI_PAGE_SIZE);
> -        End  = (E820Entry.BaseAddr + E820Entry.Length) &
> -               ~(UINT64)EFI_PAGE_MASK;
> -        if (Base < End) {
> -          PlatformAddMemoryRangeHob (Base, End);
> -          DEBUG ((
> -            DEBUG_VERBOSE,
> -            "%a: PlatformAddMemoryRangeHob [0x%Lx, 0x%Lx)\n",
> -            __FUNCTION__,
> -            Base,
> -            End
> -            ));
> -        }
> -      }
> -
> -      if (MaxAddress || LowMemory) {
> -        UINT64  Candidate;
> -
> -        Candidate = E820Entry.BaseAddr + E820Entry.Length;
> -        if (MaxAddress && (Candidate > *MaxAddress)) {
> -          *MaxAddress = Candidate;
> -          DEBUG ((
> -            DEBUG_VERBOSE,
> -            "%a: MaxAddress=0x%Lx\n",
> -            __FUNCTION__,
> -            *MaxAddress
> -            ));
> -        }
> -
> -        if (LowMemory && (Candidate > *LowMemory) && (Candidate < BASE_4GB)) {
> -          *LowMemory = Candidate;
> -          DEBUG ((
> -            DEBUG_VERBOSE,
> -            "%a: LowMemory=0x%Lx\n",
> -            __FUNCTION__,
> -            *LowMemory
> -            ));
> -        }
> -      }
> -    }
> -  }
> -
> -  return EFI_SUCCESS;
> -}
> -
> -/**
> -  Returns PVH memmap
> -
> -  @param Entries      Pointer to PVH memmap
> -  @param Count        Number of entries
> -
> -  @return EFI_STATUS
> -**/
> -EFI_STATUS
> -GetPvhMemmapEntries (
> -  struct hvm_memmap_table_entry  **Entries,
> -  UINT32                         *Count
> -  )
> -{
> -  UINT32                 *PVHResetVectorData;
> -  struct hvm_start_info  *pvh_start_info;
> -
> -  PVHResetVectorData = (VOID *)(UINTN)PcdGet32 (PcdXenPvhStartOfDayStructPtr);
> -  if (PVHResetVectorData == 0) {
> -    return EFI_NOT_FOUND;
> -  }
> -
> -  pvh_start_info = (struct hvm_start_info *)(UINTN)PVHResetVectorData[0];
> -
> -  *Entries = (struct hvm_memmap_table_entry *)(UINTN)pvh_start_info->memmap_paddr;
> -  *Count   = pvh_start_info->memmap_entries;
> -
> -  return EFI_SUCCESS;
> -}
> -
> -STATIC
> -UINT64
> -GetHighestSystemMemoryAddressFromPvhMemmap (
> -  BOOLEAN  Below4gb
> -  )
> -{
> -  struct hvm_memmap_table_entry  *Memmap;
> -  UINT32                         MemmapEntriesCount;
> -  struct hvm_memmap_table_entry  *Entry;
> -  EFI_STATUS                     Status;
> -  UINT32                         Loop;
> -  UINT64                         HighestAddress;
> -  UINT64                         EntryEnd;
> -
> -  HighestAddress = 0;
> -
> -  Status = GetPvhMemmapEntries (&Memmap, &MemmapEntriesCount);
> -  ASSERT_EFI_ERROR (Status);
> -
> -  for (Loop = 0; Loop < MemmapEntriesCount; Loop++) {
> -    Entry    = Memmap + Loop;
> -    EntryEnd = Entry->addr + Entry->size;
> -
> -    if ((Entry->type == XEN_HVM_MEMMAP_TYPE_RAM) &&
> -        (EntryEnd > HighestAddress))
> -    {
> -      if (Below4gb && (EntryEnd <= BASE_4GB)) {
> -        HighestAddress = EntryEnd;
> -      } else if (!Below4gb && (EntryEnd >= BASE_4GB)) {
> -        HighestAddress = EntryEnd;
> -      }
> -    }
> -  }
> -
> -  return HighestAddress;
> -}
> -
> -UINT32
> -EFIAPI
> -PlatformGetSystemMemorySizeBelow4gb (
> -  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  )
> -{
> -  EFI_STATUS  Status;
> -  UINT64      LowerMemorySize = 0;
> -  UINT8       Cmos0x34;
> -  UINT8       Cmos0x35;
> -
> -  if (PlatformInfoHob->HostBridgeDevId == CLOUDHV_DEVICE_ID) {
> -    // Get the information from PVH memmap
> -    return (UINT32)GetHighestSystemMemoryAddressFromPvhMemmap (TRUE);
> -  }
> -
> -  Status = PlatformScanOrAdd64BitE820Ram (FALSE, &LowerMemorySize, NULL);
> -  if ((Status == EFI_SUCCESS) && (LowerMemorySize > 0)) {
> -    return (UINT32)LowerMemorySize;
> -  }
> -
> -  //
> -  // CMOS 0x34/0x35 specifies the system memory above 16 MB.
> -  // * CMOS(0x35) is the high byte
> -  // * CMOS(0x34) is the low byte
> -  // * The size is specified in 64kb chunks
> -  // * Since this is memory above 16MB, the 16MB must be added
> -  //   into the calculation to get the total memory size.
> -  //
> -
> -  Cmos0x34 = (UINT8)PlatformCmosRead8 (0x34);
> -  Cmos0x35 = (UINT8)PlatformCmosRead8 (0x35);
> -
> -  return (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
> -}
> -
> -STATIC
> -UINT64
> -PlatformGetSystemMemorySizeAbove4gb (
> -  )
> -{
> -  UINT32  Size;
> -  UINTN   CmosIndex;
> -
> -  //
> -  // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
> -  // * CMOS(0x5d) is the most significant size byte
> -  // * CMOS(0x5c) is the middle size byte
> -  // * CMOS(0x5b) is the least significant size byte
> -  // * The size is specified in 64kb chunks
> -  //
> -
> -  Size = 0;
> -  for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
> -    Size = (UINT32)(Size << 8) + (UINT32)PlatformCmosRead8 (CmosIndex);
> -  }
> -
> -  return LShiftU64 (Size, 16);
> -}
> -
> -/**
> -  Return the highest address that DXE could possibly use, plus one.
> -**/
> -STATIC
> -UINT64
> -PlatformGetFirstNonAddress (
> -  IN OUT  EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  )
> -{
> -  UINT64                FirstNonAddress;
> -  UINT32                FwCfgPciMmio64Mb;
> -  EFI_STATUS            Status;
> -  FIRMWARE_CONFIG_ITEM  FwCfgItem;
> -  UINTN                 FwCfgSize;
> -  UINT64                HotPlugMemoryEnd;
> -
> -  //
> -  // set FirstNonAddress to suppress incorrect compiler/analyzer warnings
> -  //
> -  FirstNonAddress = 0;
> -
> -  //
> -  // If QEMU presents an E820 map, then get the highest exclusive >=4GB RAM
> -  // address from it. This can express an address >= 4GB+1TB.
> -  //
> -  // Otherwise, get the flat size of the memory above 4GB from the CMOS (which
> -  // can only express a size smaller than 1TB), and add it to 4GB.
> -  //
> -  Status = PlatformScanOrAdd64BitE820Ram (FALSE, NULL, &FirstNonAddress);
> -  if (EFI_ERROR (Status)) {
> -    FirstNonAddress = BASE_4GB + PlatformGetSystemMemorySizeAbove4gb ();
> -  }
> -
> -  //
> -  // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
> -  // resources to 32-bit anyway. See DegradeResource() in
> -  // "PciResourceSupport.c".
> -  //
> - #ifdef MDE_CPU_IA32
> -  if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
> -    return FirstNonAddress;
> -  }
> -
> - #endif
> -
> -  //
> -  // See if the user specified the number of megabytes for the 64-bit PCI host
> -  // aperture. Accept an aperture size up to 16TB.
> -  //
> -  // As signaled by the "X-" prefix, this knob is experimental, and might go
> -  // away at any time.
> -  //
> -  Status = QemuFwCfgParseUint32 (
> -             "opt/ovmf/X-PciMmio64Mb",
> -             FALSE,
> -             &FwCfgPciMmio64Mb
> -             );
> -  switch (Status) {
> -    case EFI_UNSUPPORTED:
> -    case EFI_NOT_FOUND:
> -      break;
> -    case EFI_SUCCESS:
> -      if (FwCfgPciMmio64Mb <= 0x1000000) {
> -        PlatformInfoHob->PcdPciMmio64Size = LShiftU64 (FwCfgPciMmio64Mb, 20);
> -        break;
> -      }
> -
> -    //
> -    // fall through
> -    //
> -    default:
> -      DEBUG ((
> -        DEBUG_WARN,
> -        "%a: ignoring malformed 64-bit PCI host aperture size from fw_cfg\n",
> -        __FUNCTION__
> -        ));
> -      break;
> -  }
> -
> -  if (PlatformInfoHob->PcdPciMmio64Size == 0) {
> -    if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
> -      DEBUG ((
> -        DEBUG_INFO,
> -        "%a: disabling 64-bit PCI host aperture\n",
> -        __FUNCTION__
> -        ));
> -    }
> -
> -    //
> -    // There's nothing more to do; the amount of memory above 4GB fully
> -    // determines the highest address plus one. The memory hotplug area (see
> -    // below) plays no role for the firmware in this case.
> -    //
> -    return FirstNonAddress;
> -  }
> -
> -  //
> -  // The "etc/reserved-memory-end" fw_cfg file, when present, contains an
> -  // absolute, exclusive end address for the memory hotplug area. This area
> -  // starts right at the end of the memory above 4GB. The 64-bit PCI host
> -  // aperture must be placed above it.
> -  //
> -  Status = QemuFwCfgFindFile (
> -             "etc/reserved-memory-end",
> -             &FwCfgItem,
> -             &FwCfgSize
> -             );
> -  if (!EFI_ERROR (Status) && (FwCfgSize == sizeof HotPlugMemoryEnd)) {
> -    QemuFwCfgSelectItem (FwCfgItem);
> -    QemuFwCfgReadBytes (FwCfgSize, &HotPlugMemoryEnd);
> -    DEBUG ((
> -      DEBUG_VERBOSE,
> -      "%a: HotPlugMemoryEnd=0x%Lx\n",
> -      __FUNCTION__,
> -      HotPlugMemoryEnd
> -      ));
> -
> -    ASSERT (HotPlugMemoryEnd >= FirstNonAddress);
> -    FirstNonAddress = HotPlugMemoryEnd;
> -  }
> -
> -  //
> -  // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
> -  // that the host can map it with 1GB hugepages. Follow suit.
> -  //
> -  PlatformInfoHob->PcdPciMmio64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
> -  PlatformInfoHob->PcdPciMmio64Size = ALIGN_VALUE (PlatformInfoHob->PcdPciMmio64Size, (UINT64)SIZE_1GB);
> -
> -  //
> -  // The 64-bit PCI host aperture should also be "naturally" aligned. The
> -  // alignment is determined by rounding the size of the aperture down to the
> -  // next smaller or equal power of two. That is, align the aperture by the
> -  // largest BAR size that can fit into it.
> -  //
> -  PlatformInfoHob->PcdPciMmio64Base = ALIGN_VALUE (PlatformInfoHob->PcdPciMmio64Base, GetPowerOfTwo64 (PlatformInfoHob->PcdPciMmio64Size));
> -
> -  //
> -  // The useful address space ends with the 64-bit PCI host aperture.
> -  //
> -  FirstNonAddress = PlatformInfoHob->PcdPciMmio64Base + PlatformInfoHob->PcdPciMmio64Size;
> -  return FirstNonAddress;
> -}
> -
> -/**
> -  Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
> -**/
> -VOID
> -EFIAPI
> -PlatformAddressWidthInitialization (
> -  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  )
> -{
> -  UINT64  FirstNonAddress;
> -  UINT8   PhysMemAddressWidth;
> -
> -  //
> -  // As guest-physical memory size grows, the permanent PEI RAM requirements
> -  // are dominated by the identity-mapping page tables built by the DXE IPL.
> -  // The DXL IPL keys off of the physical address bits advertized in the CPU
> -  // HOB. To conserve memory, we calculate the minimum address width here.
> -  //
> -  FirstNonAddress     = PlatformGetFirstNonAddress (PlatformInfoHob);
> -  PhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
> -
> -  //
> -  // If FirstNonAddress is not an integral power of two, then we need an
> -  // additional bit.
> -  //
> -  if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
> -    ++PhysMemAddressWidth;
> -  }
> -
> -  //
> -  // The minimum address width is 36 (covers up to and excluding 64 GB, which
> -  // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
> -  // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
> -  // can simply assert that here, since 48 bits are good enough for 256 TB.
> -  //
> -  if (PhysMemAddressWidth <= 36) {
> -    PhysMemAddressWidth = 36;
> -  }
> -
> -  ASSERT (PhysMemAddressWidth <= 48);
> -
> -  PlatformInfoHob->FirstNonAddress     = FirstNonAddress;
> -  PlatformInfoHob->PhysMemAddressWidth = PhysMemAddressWidth;
> -}
> -
>  /**
>    Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
>  **/
> @@ -842,313 +347,6 @@ PublishPeiMemory (
>    return Status;
>  }
>  
> -STATIC
> -VOID
> -QemuInitializeRamBelow1gb (
> -  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  )
> -{
> -  if (PlatformInfoHob->SmmSmramRequire && PlatformInfoHob->Q35SmramAtDefaultSmbase) {
> -    PlatformAddMemoryRangeHob (0, SMM_DEFAULT_SMBASE);
> -    PlatformAddReservedMemoryBaseSizeHob (
> -      SMM_DEFAULT_SMBASE,
> -      MCH_DEFAULT_SMBASE_SIZE,
> -      TRUE /* Cacheable */
> -      );
> -    STATIC_ASSERT (
> -      SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE < BASE_512KB + BASE_128KB,
> -      "end of SMRAM at default SMBASE ends at, or exceeds, 640KB"
> -      );
> -    PlatformAddMemoryRangeHob (
> -      SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE,
> -      BASE_512KB + BASE_128KB
> -      );
> -  } else {
> -    PlatformAddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
> -  }
> -}
> -
> -/**
> -  Peform Memory Detection for QEMU / KVM
> -
> -**/
> -STATIC
> -VOID
> -PlatformQemuInitializeRam (
> -  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  )
> -{
> -  UINT64         LowerMemorySize;
> -  UINT64         UpperMemorySize;
> -  MTRR_SETTINGS  MtrrSettings;
> -  EFI_STATUS     Status;
> -
> -  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> -
> -  //
> -  // Determine total memory size available
> -  //
> -  LowerMemorySize = PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob);
> -
> -  if (PlatformInfoHob->BootMode == BOOT_ON_S3_RESUME) {
> -    //
> -    // Create the following memory HOB as an exception on the S3 boot path.
> -    //
> -    // Normally we'd create memory HOBs only on the normal boot path. However,
> -    // CpuMpPei specifically needs such a low-memory HOB on the S3 path as
> -    // well, for "borrowing" a subset of it temporarily, for the AP startup
> -    // vector.
> -    //
> -    // CpuMpPei saves the original contents of the borrowed area in permanent
> -    // PEI RAM, in a backup buffer allocated with the normal PEI services.
> -    // CpuMpPei restores the original contents ("returns" the borrowed area) at
> -    // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before
> -    // transferring control to the OS's wakeup vector in the FACS.
> -    //
> -    // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to
> -    // restore the original contents. Furthermore, we expect all such PEIMs
> -    // (CpuMpPei included) to claim the borrowed areas by producing memory
> -    // allocation HOBs, and to honor preexistent memory allocation HOBs when
> -    // looking for an area to borrow.
> -    //
> -    QemuInitializeRamBelow1gb (PlatformInfoHob);
> -  } else {
> -    //
> -    // Create memory HOBs
> -    //
> -    QemuInitializeRamBelow1gb (PlatformInfoHob);
> -
> -    if (PlatformInfoHob->SmmSmramRequire) {
> -      UINT32  TsegSize;
> -
> -      TsegSize = PlatformInfoHob->Q35TsegMbytes * SIZE_1MB;
> -      PlatformAddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);
> -      PlatformAddReservedMemoryBaseSizeHob (
> -        LowerMemorySize - TsegSize,
> -        TsegSize,
> -        TRUE
> -        );
> -    } else {
> -      PlatformAddMemoryRangeHob (BASE_1MB, LowerMemorySize);
> -    }
> -
> -    //
> -    // If QEMU presents an E820 map, then create memory HOBs for the >=4GB RAM
> -    // entries. Otherwise, create a single memory HOB with the flat >=4GB
> -    // memory size read from the CMOS.
> -    //
> -    Status = PlatformScanOrAdd64BitE820Ram (TRUE, NULL, NULL);
> -    if (EFI_ERROR (Status)) {
> -      UpperMemorySize = PlatformGetSystemMemorySizeAbove4gb ();
> -      if (UpperMemorySize != 0) {
> -        PlatformAddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
> -      }
> -    }
> -  }
> -
> -  //
> -  // We'd like to keep the following ranges uncached:
> -  // - [640 KB, 1 MB)
> -  // - [LowerMemorySize, 4 GB)
> -  //
> -  // Everything else should be WB. Unfortunately, programming the inverse (ie.
> -  // keeping the default UC, and configuring the complement set of the above as
> -  // WB) is not reliable in general, because the end of the upper RAM can have
> -  // practically any alignment, and we may not have enough variable MTRRs to
> -  // cover it exactly.
> -  //
> -  if (IsMtrrSupported () && (PlatformInfoHob->HostBridgeDevId != CLOUDHV_DEVICE_ID)) {
> -    MtrrGetAllMtrrs (&MtrrSettings);
> -
> -    //
> -    // MTRRs disabled, fixed MTRRs disabled, default type is uncached
> -    //
> -    ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
> -    ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
> -    ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
> -
> -    //
> -    // flip default type to writeback
> -    //
> -    SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
> -    ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
> -    MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
> -    MtrrSetAllMtrrs (&MtrrSettings);
> -
> -    //
> -    // Set memory range from 640KB to 1MB to uncacheable
> -    //
> -    Status = MtrrSetMemoryAttribute (
> -               BASE_512KB + BASE_128KB,
> -               BASE_1MB - (BASE_512KB + BASE_128KB),
> -               CacheUncacheable
> -               );
> -    ASSERT_EFI_ERROR (Status);
> -
> -    //
> -    // Set the memory range from the start of the 32-bit MMIO area (32-bit PCI
> -    // MMIO aperture on i440fx, PCIEXBAR on q35) to 4GB as uncacheable.
> -    //
> -    Status = MtrrSetMemoryAttribute (
> -               PlatformInfoHob->Uc32Base,
> -               SIZE_4GB - PlatformInfoHob->Uc32Base,
> -               CacheUncacheable
> -               );
> -    ASSERT_EFI_ERROR (Status);
> -  }
> -}
> -
> -STATIC
> -VOID
> -PlatformQemuInitializeRamForS3 (
> -  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  )
> -{
> -  if (PlatformInfoHob->S3Supported && (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME)) {
> -    //
> -    // This is the memory range that will be used for PEI on S3 resume
> -    //
> -    BuildMemoryAllocationHob (
> -      PlatformInfoHob->S3AcpiReservedMemoryBase,
> -      PlatformInfoHob->S3AcpiReservedMemorySize,
> -      EfiACPIMemoryNVS
> -      );
> -
> -    //
> -    // Cover the initial RAM area used as stack and temporary PEI heap.
> -    //
> -    // This is reserved as ACPI NVS so it can be used on S3 resume.
> -    //
> -    BuildMemoryAllocationHob (
> -      PcdGet32 (PcdOvmfSecPeiTempRamBase),
> -      PcdGet32 (PcdOvmfSecPeiTempRamSize),
> -      EfiACPIMemoryNVS
> -      );
> -
> -    //
> -    // SEC stores its table of GUIDed section handlers here.
> -    //
> -    BuildMemoryAllocationHob (
> -      PcdGet64 (PcdGuidedExtractHandlerTableAddress),
> -      PcdGet32 (PcdGuidedExtractHandlerTableSize),
> -      EfiACPIMemoryNVS
> -      );
> -
> - #ifdef MDE_CPU_X64
> -    //
> -    // Reserve the initial page tables built by the reset vector code.
> -    //
> -    // Since this memory range will be used by the Reset Vector on S3
> -    // resume, it must be reserved as ACPI NVS.
> -    //
> -    BuildMemoryAllocationHob (
> -      (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecPageTablesBase),
> -      (UINT64)(UINTN)PcdGet32 (PcdOvmfSecPageTablesSize),
> -      EfiACPIMemoryNVS
> -      );
> -
> -    if (PlatformInfoHob->SevEsIsEnabled) {
> -      //
> -      // If SEV-ES is enabled, reserve the GHCB-related memory area. This
> -      // includes the extra page table used to break down the 2MB page
> -      // mapping into 4KB page entries where the GHCB resides and the
> -      // GHCB area itself.
> -      //
> -      // Since this memory range will be used by the Reset Vector on S3
> -      // resume, it must be reserved as ACPI NVS.
> -      //
> -      BuildMemoryAllocationHob (
> -        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecGhcbPageTableBase),
> -        (UINT64)(UINTN)PcdGet32 (PcdOvmfSecGhcbPageTableSize),
> -        EfiACPIMemoryNVS
> -        );
> -      BuildMemoryAllocationHob (
> -        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecGhcbBase),
> -        (UINT64)(UINTN)PcdGet32 (PcdOvmfSecGhcbSize),
> -        EfiACPIMemoryNVS
> -        );
> -      BuildMemoryAllocationHob (
> -        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSecGhcbBackupBase),
> -        (UINT64)(UINTN)PcdGet32 (PcdOvmfSecGhcbBackupSize),
> -        EfiACPIMemoryNVS
> -        );
> -    }
> -
> - #endif
> -  }
> -
> -  if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
> -    if (!PlatformInfoHob->SmmSmramRequire) {
> -      //
> -      // Reserve the lock box storage area
> -      //
> -      // Since this memory range will be used on S3 resume, it must be
> -      // reserved as ACPI NVS.
> -      //
> -      // If S3 is unsupported, then various drivers might still write to the
> -      // LockBox area. We ought to prevent DXE from serving allocation requests
> -      // such that they would overlap the LockBox storage.
> -      //
> -      ZeroMem (
> -        (VOID *)(UINTN)PcdGet32 (PcdOvmfLockBoxStorageBase),
> -        (UINTN)PcdGet32 (PcdOvmfLockBoxStorageSize)
> -        );
> -      BuildMemoryAllocationHob (
> -        (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfLockBoxStorageBase),
> -        (UINT64)(UINTN)PcdGet32 (PcdOvmfLockBoxStorageSize),
> -        PlatformInfoHob->S3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
> -        );
> -    }
> -
> -    if (PlatformInfoHob->SmmSmramRequire) {
> -      UINT32  TsegSize;
> -
> -      //
> -      // Make sure the TSEG area that we reported as a reserved memory resource
> -      // cannot be used for reserved memory allocations.
> -      //
> -      TsegSize = PlatformInfoHob->Q35TsegMbytes * SIZE_1MB;
> -      BuildMemoryAllocationHob (
> -        PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob) - TsegSize,
> -        TsegSize,
> -        EfiReservedMemoryType
> -        );
> -      //
> -      // Similarly, allocate away the (already reserved) SMRAM at the default
> -      // SMBASE, if it exists.
> -      //
> -      if (PlatformInfoHob->Q35SmramAtDefaultSmbase) {
> -        BuildMemoryAllocationHob (
> -          SMM_DEFAULT_SMBASE,
> -          MCH_DEFAULT_SMBASE_SIZE,
> -          EfiReservedMemoryType
> -          );
> -      }
> -    }
> -
> - #ifdef MDE_CPU_X64
> -    if (FixedPcdGet32 (PcdOvmfWorkAreaSize) != 0) {
> -      //
> -      // Reserve the work area.
> -      //
> -      // Since this memory range will be used by the Reset Vector on S3
> -      // resume, it must be reserved as ACPI NVS.
> -      //
> -      // If S3 is unsupported, then various drivers might still write to the
> -      // work area. We ought to prevent DXE from serving allocation requests
> -      // such that they would overlap the work area.
> -      //
> -      BuildMemoryAllocationHob (
> -        (EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaBase),
> -        (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaSize),
> -        PlatformInfoHob->S3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
> -        );
> -    }
> -
> - #endif
> -  }
> -}
> -
>  /**
>    Publish system RAM and reserve memory regions
>  
> diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
> index 494836c3efe4..31670747d8b0 100644
> --- a/OvmfPkg/PlatformPei/Platform.h
> +++ b/OvmfPkg/PlatformPei/Platform.h
> @@ -32,18 +32,6 @@ PublishPeiMemory (
>    VOID
>    );
>  
> -UINT32
> -EFIAPI
> -PlatformGetSystemMemorySizeBelow4gb (
> -  IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  );
> -
> -VOID
> -EFIAPI
> -PlatformQemuUc32BaseInitialization (
> -  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -  );
> -
>  VOID
>  InitializeRamRegions (
>    IN EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
> -- 
> 2.29.2.windows.2
> 

-- 


  reply	other threads:[~2022-03-15  8:15 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-12  1:53 [PATCH V8 00/47] Enable Intel TDX in OvmfPkg (Config-A) Min Xu
2022-03-12  1:53 ` [PATCH V8 01/47] MdePkg: Add Tdx.h Min Xu
2022-03-12  1:53 ` [PATCH V8 02/47] MdePkg: Introduce basic Tdx functions in BaseLib Min Xu
2022-03-15  7:41   ` [edk2-devel] " Ni, Ray
2022-03-16  1:18     ` Min Xu
2022-03-16  1:26       ` Ni, Ray
2022-03-15  7:44   ` Ni, Ray
2022-03-16  2:15     ` Min Xu
2022-03-12  1:53 ` [PATCH V8 03/47] MdePkg: Add TdxLib to wrap Tdx operations Min Xu
2022-03-12  1:53 ` [PATCH V8 04/47] UefiCpuPkg: Extend VmgExitLibNull to handle #VE exception Min Xu
2022-03-12  1:53 ` [PATCH V8 05/47] OvmfPkg: Extend VmgExitLib " Min Xu
2022-03-12  1:53 ` [PATCH V8 06/47] UefiCpuPkg/CpuExceptionHandler: Add base support for the " Min Xu
2022-03-12  1:53 ` [PATCH V8 07/47] MdePkg: Add helper functions for Tdx guest in BaseIoLibIntrinsic Min Xu
2022-03-12  1:53 ` [PATCH V8 08/47] MdePkg: Support mmio " Min Xu
2022-03-12  1:53 ` [PATCH V8 09/47] MdePkg: Support IoFifo " Min Xu
2022-03-12  1:53 ` [PATCH V8 10/47] MdePkg: Support IoRead/IoWrite " Min Xu
2022-03-12  1:53 ` [PATCH V8 11/47] UefiCpuPkg: Support TDX in BaseXApicX2ApicLib Min Xu
2022-03-12  1:53 ` [PATCH V8 12/47] MdePkg: Add macro to check SEV / TDX guest Min Xu
2022-03-12  1:53 ` [PATCH V8 13/47] UefiCpuPkg: Enable Tdx support in MpInitLib Min Xu
2022-03-15  7:57   ` Ni, Ray
2022-03-16  8:32     ` Min Xu
2022-03-16  8:36       ` Ni, Ray
2022-03-16 11:53         ` Min Xu
2022-03-12  1:53 ` [PATCH V8 14/47] OvmfPkg: Add IntelTdx.h in OvmfPkg/Include/IndustryStandard Min Xu
2022-03-12  1:53 ` [PATCH V8 15/47] OvmfPkg: Add TdxMailboxLib Min Xu
2022-03-12  1:53 ` [PATCH V8 16/47] OvmfPkg: Create initial version of PlatformInitLib Min Xu
2022-03-15  7:41   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 17/47] OvmfPkg/PlatformInitLib: Add hob functions Min Xu
2022-03-15  7:42   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 18/47] OvmfPkg/PlatformPei: Move global variables to PlatformInfoHob Min Xu
2022-03-15  7:57   ` Gerd Hoffmann
2022-03-16  5:26     ` [edk2-devel] " Min Xu
2022-03-12  1:53 ` [PATCH V8 19/47] OvmfPkg/PlatformPei: Refactor MiscInitialization Min Xu
2022-03-15  7:59   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 20/47] OvmfPkg/PlatformPei: Refactor MiscInitialization for CloudHV Min Xu
2022-03-15  7:59   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 21/47] OvmfPkg/PlatformPei: Refactor AddressWidthInitialization Min Xu
2022-03-15  8:04   ` Gerd Hoffmann
2022-03-16  5:56     ` [edk2-devel] " Min Xu
2022-03-12  1:53 ` [PATCH V8 22/47] OvmfPkg/PlatformPei: Refactor MaxCpuCountInitialization Min Xu
2022-03-15  8:04   ` Gerd Hoffmann
2022-03-16  6:25     ` Min Xu
2022-03-12  1:53 ` [PATCH V8 23/47] OvmfPkg/PlatformPei: Refactor QemuUc32BaseInitialization Min Xu
2022-03-15  8:05   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 25/47] OvmfPkg/PlatformPei: Refactor MemMapInitialization Min Xu
2022-03-15  8:06   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 26/47] OvmfPkg/PlatformPei: Refactor NoexecDxeInitialization Min Xu
2022-03-15  8:13   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 27/47] OvmfPkg/PlatformPei: Refactor MiscInitialization Min Xu
2022-03-15  8:14   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 28/47] OvmfPkg/PlatformInitLib: Create MemDetect.c Min Xu
2022-03-15  8:14   ` Gerd Hoffmann [this message]
2022-03-12  1:53 ` [PATCH V8 29/47] OvmfPkg/PlatformInitLib: Move functions to Platform.c Min Xu
2022-03-15  8:15   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 30/47] MdePkg: Add EFI_RESOURCE_MEMORY_UNACCEPTED defition Min Xu
2022-03-15  8:15   ` Gerd Hoffmann
2022-03-12  1:53 ` [PATCH V8 31/47] OvmfPkg: Update PlatformInitLib to process Tdx hoblist Min Xu
2022-03-12  1:53 ` [PATCH V8 32/47] OvmfPkg/Sec: Declare local variable as volatile in SecCoreStartupWithStack Min Xu
2022-03-12  1:53 ` [PATCH V8 33/47] OvmfPkg: Update Sec to support Tdx Min Xu
2022-03-12  1:53 ` [PATCH V8 34/47] OvmfPkg: Check Tdx in QemuFwCfgPei to avoid DMA operation Min Xu
2022-03-12  1:54 ` [PATCH V8 35/47] MdeModulePkg: Skip setting IA32_ERER.NXE if it has already been set Min Xu
2022-03-15  5:16   ` Wang, Jian J
2022-03-12  1:54 ` [PATCH V8 36/47] MdeModulePkg: Add PcdTdxSharedBitMask Min Xu
2022-03-15  5:16   ` Wang, Jian J
2022-03-12  1:54 ` [PATCH V8 37/47] UefiCpuPkg: Update AddressEncMask in CpuPageTable Min Xu
2022-03-12  1:54 ` [PATCH V8 38/47] OvmfPkg: Update PlatformInitLib for Tdx guest Min Xu
2022-03-12  1:54 ` [PATCH V8 39/47] OvmfPkg: Update PlatformPei to support " Min Xu
2022-03-12  1:54 ` [PATCH V8 40/47] OvmfPkg: Update AcpiPlatformDxe to alter MADT table Min Xu
2022-03-15  3:55 ` 回复: [edk2-devel] [PATCH V8 00/47] Enable Intel TDX in OvmfPkg (Config-A) gaoliming
2022-03-15  7:11   ` Min Xu
2022-03-17  1:00     ` 回复: " gaoliming
2022-03-17  1:16       ` Min Xu
     [not found] ` <5cf66f701073359f385e7ff28b5173555ab483c3.1647047482.git.min.m.xu@intel.com>
2022-03-15  8:05   ` [PATCH V8 24/47] OvmfPkg/PlatformPei: Refactor InitializeRamRegions Gerd Hoffmann
     [not found] ` <16DB7F586DEAD807.23528@groups.io>
2022-03-17  5:31   ` [edk2-devel] [PATCH V8 12/47] MdePkg: Add macro to check SEV / TDX guest Min Xu
2022-03-18  1:13     ` 回复: " gaoliming

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220315081457.6ykewdihqwrn7jt4@sirius.home.kraxel.org \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox