MdeModulePkg/Core/Dxe: Set MemoryTypeInfo bin range from HOB

Provide an optional method for PEI to declare a specific address
range to use for the Memory Type Information bins. The current
algorithm uses heuristics that tends to place the Memory Type
Information bins in the same location, but memory configuration
changes across boots or algorithm changes across a firmware
updates could potentially change the Memory Type Information bin
location. If the bin locations move across an S4 save/resume
cycle, then the S4 resume may fail. Enabling this feature
increases the number of scenarios that an S4 resume operation
may succeed.

If the HOB List contains a Resource Descriptor HOB that
describes tested system memory and has an Owner GUID of
gEfiMemoryTypeInformationGuid, then use the address range
described by the Resource Descriptor HOB as the preferred
location of the Memory Type Information bins. If this HOB is
not detected, then the current behavior is preserved.

The HOB with an Owner GUID of gEfiMemoryTypeInformationGuid
is ignored for the following conditions:
* The HOB with an Owner GUID of gEfiMemoryTypeInformationGuid
  is smaller than the Memory Type Information bins.
* The HOB list contains more than one Resource Descriptor HOB
  with an owner GUID of gEfiMemoryTypeInformationGuid.
* The Resource Descriptor HOB with an Owner GUID of
  gEfiMemoryTypeInformationGuid is the same Resource Descriptor
  HOB that that describes the PHIT memory range.

Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Aaron Li <aaron.li@intel.com>
Cc: Liu Yun <yun.y.liu@intel.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Michael D Kinney
2024-01-28 13:33:32 -08:00
committed by mergify[bot]
parent c5e702e45a
commit af6e0e728f
4 changed files with 186 additions and 8 deletions

View File

@@ -2238,6 +2238,8 @@ CoreInitializeMemoryServices (
EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
EFI_HOB_RESOURCE_DESCRIPTOR *MemoryTypeInformationResourceHob;
UINTN Count;
EFI_PHYSICAL_ADDRESS BaseAddress;
UINT64 Length;
UINT64 Attributes;
@@ -2289,12 +2291,47 @@ CoreInitializeMemoryServices (
//
// See if a Memory Type Information HOB is available
//
GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
MemoryTypeInformationResourceHob = NULL;
GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
if (GuidHob != NULL) {
EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
if ((EfiMemoryTypeInformation != NULL) && (DataSize > 0) && (DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION))) {
CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
//
// Look for Resource Descriptor HOB with a ResourceType of System Memory
// and an Owner GUID of gEfiMemoryTypeInformationGuid. If more than 1 is
// found, then set MemoryTypeInformationResourceHob to NULL.
//
Count = 0;
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
continue;
}
ResourceHob = Hob.ResourceDescriptor;
if (!CompareGuid (&ResourceHob->Owner, &gEfiMemoryTypeInformationGuid)) {
continue;
}
Count++;
if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
continue;
}
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
continue;
}
if (ResourceHob->ResourceLength >= CalculateTotalMemoryBinSizeNeeded ()) {
MemoryTypeInformationResourceHob = ResourceHob;
}
}
if (Count > 1) {
MemoryTypeInformationResourceHob = NULL;
}
}
}
@@ -2344,6 +2381,15 @@ CoreInitializeMemoryServices (
PhitResourceHob = ResourceHob;
Found = TRUE;
//
// If a Memory Type Information Resource HOB was found and is the same
// Resource HOB that describes the PHIT HOB, then ignore the Memory Type
// Information Resource HOB.
//
if (MemoryTypeInformationResourceHob == PhitResourceHob) {
MemoryTypeInformationResourceHob = NULL;
}
//
// Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
//
@@ -2387,8 +2433,9 @@ CoreInitializeMemoryServices (
if (Length < MinimalMemorySizeNeeded) {
//
// Search all the resource descriptor HOBs from the highest possible addresses down for a memory
// region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
// The max address must be within the physically addressible range for the processor.
// region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB
// and the Memory Type Information Resource HOB. The max address must be within the physically
// addressable range for the processor.
//
HighAddress = MAX_ALLOC_ADDRESS;
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
@@ -2399,6 +2446,13 @@ CoreInitializeMemoryServices (
continue;
}
//
// Skip the Resource Descriptor HOB that contains Memory Type Information bins
//
if (Hob.ResourceDescriptor == MemoryTypeInformationResourceHob) {
continue;
}
//
// Skip all HOBs except Resource Descriptor HOBs
//
@@ -2466,6 +2520,18 @@ CoreInitializeMemoryServices (
Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
}
if (MemoryTypeInformationResourceHob != NULL) {
//
// If a Memory Type Information Resource HOB was found, then use the address
// range of the Memory Type Information Resource HOB as the preferred
// address range for the Memory Type Information bins.
//
CoreSetMemoryTypeInformationRange (
MemoryTypeInformationResourceHob->PhysicalStart,
MemoryTypeInformationResourceHob->ResourceLength
);
}
//
// Declare the very first memory region, so the EFI Memory Services are available.
//