From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 17D5F780091 for ; Tue, 23 Jan 2024 01:54:00 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=Pe8b8Jqp9aLvXXqtIS/ze41tWjiUzzYIIltRCcdjnDI=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20140610; t=1705974839; v=1; b=L0xLAhqftgMR5jKcya1wTk4i2IPJHig2OCEjiHnnuAFysMvHgLzoqD2jULlQbBpYTMkXQxVQ c3PRa6tyBlwje8wJiRMC0kcS/KD4KOzX6TU58H5smUOUrzn58ifYR2yKh66fBwuJQYCZg/LPdEw H7rKHpeoPY/KH6YNW7s1twMo= X-Received: by 127.0.0.2 with SMTP id nnCsYY7687511xtvwLor94rT; Mon, 22 Jan 2024 17:53:59 -0800 X-Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.10]) by mx.groups.io with SMTP id smtpd.web11.1648.1705974838789002813 for ; Mon, 22 Jan 2024 17:53:59 -0800 X-IronPort-AV: E=McAfee;i="6600,9927,10961"; a="14733998" X-IronPort-AV: E=Sophos;i="6.05,212,1701158400"; d="scan'208";a="14733998" X-Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 17:53:58 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.05,212,1701158400"; d="scan'208";a="1483939" X-Received: from mdkinney-mobl.amr.corp.intel.com ([10.212.171.71]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 17:53:58 -0800 From: "Michael D Kinney" To: devel@edk2.groups.io Cc: Liming Gao , Aaron Li , Liu Yun , Andrew Fish Subject: [edk2-devel] [Patch 1/1] MdeModulePkg/Core/Dxe: Set MemoryTypeInfo bin range from HOB Date: Mon, 22 Jan 2024 17:53:53 -0800 Message-Id: <20240123015353.216-1-michael.d.kinney@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,michael.d.kinney@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: ktfuWlKUFi7VaubfWYMtbYA3x7686176AA= Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=L0xLAhqf; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=intel.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io 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 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. Update the DxeMain initialization order to initialize GCD services before any runtime allocations are performed. This is required to prevent runtime data fragmentation when the UEFI System Table and UEFI Runtime Service Table is allocated. Cc: Liming Gao Cc: Aaron Li Cc: Liu Yun Cc: Andrew Fish Signed-off-by: Michael D Kinney --- MdeModulePkg/Core/Dxe/DxeMain.h | 6 ++ MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c | 23 +++--- MdeModulePkg/Core/Dxe/Gcd/Gcd.c | 65 +++++++++++++++- MdeModulePkg/Core/Dxe/Mem/Page.c | 99 +++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 11 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 86a7be2f5188..53e26703f8c7 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -277,6 +277,12 @@ CoreInitializePool ( VOID ); +VOID +CoreSetMemoryTypeInformationRange ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + /** Called to initialize the memory map and add descriptors to the current descriptor list. diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index 0e0f9769b99d..17d510a287e5 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -276,6 +276,18 @@ DxeMain ( MemoryProfileInit (HobStart); + // + // Start the Image Services. + // + Status = CoreInitializeImageServices (HobStart); + ASSERT_EFI_ERROR (Status); + + // + // Initialize the Global Coherency Domain Services + // + Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength); + ASSERT_EFI_ERROR (Status); + // // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table @@ -289,16 +301,9 @@ DxeMain ( gDxeCoreST->RuntimeServices = gDxeCoreRT; // - // Start the Image Services. + // Update DXE Core Loaded Image Protocol with allocated UEFI System Table // - Status = CoreInitializeImageServices (HobStart); - ASSERT_EFI_ERROR (Status); - - // - // Initialize the Global Coherency Domain Services - // - Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength); - ASSERT_EFI_ERROR (Status); + gDxeCoreLoadedImage->SystemTable = gDxeCoreST; // // Call constructor for all libraries diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c index 792cd2e0af23..189a87470251 100644 --- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c +++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c @@ -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,42 @@ CoreInitializeMemoryServices ( // // See if a Memory Type Information HOB is available // + 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 +2376,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 +2428,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 +2441,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 +2515,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. // diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index 6497af573353..d22bf27b539e 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -532,6 +532,105 @@ CoreLoadingFixedAddressHook ( return; } +/** + Sets the preferred memory range to use for the Memory Type Information bins. + This service must be called before fist call to CoreAddMemoryDescriptor(). + + If the location of the Memory Type Information bins has already been + established or the size of the range provides is smaller than all the + Memory Type Information bins, then the range provides is not used. + + @param Start The start address of the Memory Type Information range. + @param Length The size, in bytes, of the Memory Type Information range. +**/ +VOID +CoreSetMemoryTypeInformationRange ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +{ + EFI_PHYSICAL_ADDRESS Top; + EFI_MEMORY_TYPE Type; + UINTN Index; + UINTN Size; + + // + // Return if Memory Type Information bin locations have already been set + // + if (mMemoryTypeInformationInitialized) { + return; + } + + // + // Return if size of the Memory Type Information bins is greater than Length + // + Size = 0; + for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { + // + // Make sure the memory type in the gMemoryTypeInformation[] array is valid + // + Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type); + if ((UINT32)Type > EfiMaxMemoryType) { + continue; + } + Size += EFI_PAGES_TO_SIZE (gMemoryTypeInformation[Index].NumberOfPages); + } + if (Size > Length) { + return; + } + + // + // Loop through each memory type in the order specified by the + // gMemoryTypeInformation[] array + // + Top = Start + Length; + for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { + // + // Make sure the memory type in the gMemoryTypeInformation[] array is valid + // + Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type); + if ((UINT32)Type > EfiMaxMemoryType) { + continue; + } + + if (gMemoryTypeInformation[Index].NumberOfPages != 0) { + mMemoryTypeStatistics[Type].MaximumAddress = Top - 1; + Top -= EFI_PAGES_TO_SIZE (gMemoryTypeInformation[Index].NumberOfPages); + mMemoryTypeStatistics[Type].BaseAddress = Top; + + // + // If the current base address is the lowest address so far, then update + // the default maximum address + // + if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) { + mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1; + } + + mMemoryTypeStatistics[Type].NumberOfPages = gMemoryTypeInformation[Index].NumberOfPages; + gMemoryTypeInformation[Index].NumberOfPages = 0; + } + } + + // + // If the number of pages reserved for a memory type is 0, then all + // allocations for that type should be in the default range. + // + for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) { + for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { + if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) { + mMemoryTypeStatistics[Type].InformationIndex = Index; + } + } + + mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0; + if (mMemoryTypeStatistics[Type].MaximumAddress == MAX_ALLOC_ADDRESS) { + mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress; + } + } + + mMemoryTypeInformationInitialized = TRUE; +} + /** Called to initialize the memory map and add descriptors to the current descriptor list. -- 2.40.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114163): https://edk2.groups.io/g/devel/message/114163 Mute This Topic: https://groups.io/mt/103901750/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-