From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=209.132.183.28; helo=mx1.redhat.com; envelope-from=lersek@redhat.com; receiver=edk2-devel@lists.01.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 1B428220C1C3A for ; Thu, 30 Nov 2017 08:26:23 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3A7E24900C; Thu, 30 Nov 2017 16:30:48 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-19.rdu2.redhat.com [10.10.120.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id BC3BF5D9C7; Thu, 30 Nov 2017 16:30:46 +0000 (UTC) From: Laszlo Ersek To: edk2-devel-01 Cc: Anthony Perard , Ard Biesheuvel , Jordan Justen , Julien Grall Date: Thu, 30 Nov 2017 17:30:28 +0100 Message-Id: <20171130163029.19743-8-lersek@redhat.com> In-Reply-To: <20171130163029.19743-1-lersek@redhat.com> References: <20171130163029.19743-1-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 30 Nov 2017 16:30:48 +0000 (UTC) Subject: [PATCH v2 7/8] OvmfPkg/PlatformPei: remedy UEFI memory map fragmentation X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Nov 2017 16:26:23 -0000 The Memory Type Information HOB is used for sizing the allocation bins for the various memory types. If the PEI phase does not produce the HOB, and it includes the VariablePei driver, then the DXE IPL PEIM will itself build the HOB, from the "MemoryTypeInformation" non-volatile variable. (The HOB is consumed in the DxeLoadCore() function, and it is ignored if the boot mode is BOOT_ON_S3_RESUME. Accordingly, we already don't build the HOB in InitializePlatform() during S3 resume; MemMapInitialization() isn't called.) In the BDS phase, BmSetMemoryTypeInformationVariable() reads the variable (if it exists) under all boot modes different from BOOT_WITH_DEFAULT_SETTINGS, and (re-)sets the variable if it doesn't exist, or the counts of the pages allocated during boot have changed, relative to what the variable predicted. In effect this creates a feedback loop between BDS and the next boot's PEI, making sure the memory allocation bins are sized large enough in advance. Ultimately, for BOOT_WITH_FULL_CONFIGURATION, as a special case of the above, this measures the maximum boot memory requirement per UEFI memory type, and over time decreases fragmentation in the UEFI memory map. We continue creating our (constant) Memory Type Information HOB in OvmfPkg/PlatformPei -- which prevents the above feedback loop -- except in one case: when OVMF is built with SMM_REQUIRE=TRUE or MEM_VARSTORE_EMU_ENABLE=FALSE (that is, when a flash-based varstore is guaranteed), and the "MemoryTypeInformation" variable exists (that is, when the virtual machine has been booted at least once). This lets the OS installer see a somewhat fragmented memory map at first boot, but further boots should witness defragmented maps. In practice the difference seems to be 20-24 entries in the UEFI memory map. In the longer term this should also serve as basis for S4 enablement. For now, we keep the PcdResetOnMemoryTypeInformationChange|FALSE setting in the OVMF DSC files, dating back to commit 7709cf48e432 ("DuetPkg, OvmfPkg, UnixPkg: Remove unnecessary reset during boot", 2010-12-06). Cc: Anthony Perard Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Julien Grall Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- OvmfPkg/PlatformPei/PlatformPei.inf | 2 + OvmfPkg/PlatformPei/Platform.h | 5 + OvmfPkg/PlatformPei/MemTypeInfo.c | 151 ++++++++++++++++++++ OvmfPkg/PlatformPei/Platform.c | 23 +-- 4 files changed, 159 insertions(+), 22 deletions(-) diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 4b8626cb2a27..062cc083c698 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -34,6 +34,7 @@ [Sources] FeatureControl.c Fv.c MemDetect.c + MemTypeInfo.c Platform.c Xen.c @@ -113,6 +114,7 @@ [FeaturePcd] [Ppis] gEfiPeiMasterBootModePpiGuid gEfiPeiMpServicesPpiGuid + gEfiPeiReadOnlyVariable2PpiGuid [Depex] TRUE diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index f942e61bb4f9..5847b46a308d 100644 --- a/OvmfPkg/PlatformPei/Platform.h +++ b/OvmfPkg/PlatformPei/Platform.h @@ -78,6 +78,11 @@ PeiFvInitialization ( VOID ); +VOID +MemTypeInfoInitialization ( + VOID + ); + VOID InstallFeatureControlCallback ( VOID diff --git a/OvmfPkg/PlatformPei/MemTypeInfo.c b/OvmfPkg/PlatformPei/MemTypeInfo.c new file mode 100644 index 000000000000..46ed9aaf8f31 --- /dev/null +++ b/OvmfPkg/PlatformPei/MemTypeInfo.c @@ -0,0 +1,151 @@ +/**@file + Produce a default memory type information HOB unless we can determine, from + the existence of the "MemoryTypeInformation" variable, that the DXE IPL PEIM + will produce the HOB. + + Copyright (C) 2017, Red Hat, Inc. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include "Platform.h" + +STATIC EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { + { EfiACPIMemoryNVS, 0x004 }, + { EfiACPIReclaimMemory, 0x008 }, + { EfiReservedMemoryType, 0x004 }, + { EfiRuntimeServicesData, 0x024 }, + { EfiRuntimeServicesCode, 0x030 }, + { EfiBootServicesCode, 0x180 }, + { EfiBootServicesData, 0xF00 }, + { EfiMaxMemoryType, 0x000 } +}; + +STATIC +VOID +BuildMemTypeInfoHob ( + VOID + ) +{ + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof mDefaultMemoryTypeInformation + ); + DEBUG (( + DEBUG_INFO, + "%a: default memory type information HOB built\n", + __FUNCTION__ + )); +} + +/** + Notification function called when EFI_PEI_READ_ONLY_VARIABLE2_PPI becomes + available. + + @param[in] PeiServices Indirect reference to the PEI Services Table. + @param[in] NotifyDescriptor Address of the notification descriptor data + structure. + @param[in] Ppi Address of the PPI that was installed. + + @return Status of the notification. The status code returned from this + function is ignored. +**/ +STATIC +EFI_STATUS +EFIAPI +OnReadOnlyVariable2Available ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2; + UINTN DataSize; + EFI_STATUS Status; + + DEBUG ((DEBUG_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__)); + + // + // Check if the "MemoryTypeInformation" variable exists, in the + // gEfiMemoryTypeInformationGuid namespace. + // + ReadOnlyVariable2 = Ppi; + DataSize = 0; + Status = ReadOnlyVariable2->GetVariable ( + ReadOnlyVariable2, + EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, + &gEfiMemoryTypeInformationGuid, + NULL, + &DataSize, + NULL + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // The variable exists; the DXE IPL PEIM will build the HOB from it. + // + return EFI_SUCCESS; + } + // + // Install the default memory type information HOB. + // + BuildMemTypeInfoHob (); + return EFI_SUCCESS; +} + +// +// Notification object for registering the callback, for when +// EFI_PEI_READ_ONLY_VARIABLE2_PPI becomes available. +// +STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mReadOnlyVariable2Notify = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), // Flags + &gEfiPeiReadOnlyVariable2PpiGuid, // Guid + OnReadOnlyVariable2Available // Notify +}; + +VOID +MemTypeInfoInitialization ( + VOID + ) +{ + EFI_STATUS Status; + + if (!FeaturePcdGet (PcdSmmSmramRequire) && + FeaturePcdGet (PcdMemVarstoreEmuEnable)) { + // + // EFI_PEI_READ_ONLY_VARIABLE2_PPI will never be available; install + // the default memory type information HOB right away. + // + BuildMemTypeInfoHob (); + return; + } + + Status = PeiServicesNotifyPpi (&mReadOnlyVariable2Notify); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: failed to set up R/O Variable 2 callback: %r\n", + __FUNCTION__, + Status + )); + // + // Install the default HOB as a last resort. + // + BuildMemTypeInfoHob (); + } +} diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index 34e7e903fc70..1a45531359a6 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -42,18 +41,6 @@ #include "Platform.h" #include "Cmos.h" -EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { - { EfiACPIMemoryNVS, 0x004 }, - { EfiACPIReclaimMemory, 0x008 }, - { EfiReservedMemoryType, 0x004 }, - { EfiRuntimeServicesData, 0x024 }, - { EfiRuntimeServicesCode, 0x030 }, - { EfiBootServicesCode, 0x180 }, - { EfiBootServicesData, 0xF00 }, - { EfiMaxMemoryType, 0x000 } -}; - - EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = { { EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, @@ -165,15 +152,6 @@ MemMapInitialization ( PciIoBase = 0xC000; PciIoSize = 0x4000; - // - // Create Memory Type Information HOB - // - BuildGuidDataHob ( - &gEfiMemoryTypeInformationGuid, - mDefaultMemoryTypeInformation, - sizeof(mDefaultMemoryTypeInformation) - ); - // // Video memory + Legacy BIOS region // @@ -669,6 +647,7 @@ InitializePlatform ( ReserveEmuVariableNvStore (); } PeiFvInitialization (); + MemTypeInfoInitialization (); MemMapInitialization (); NoexecDxeInitialization (); } -- 2.14.1.3.gb7cf6e02401b