From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@lists.01.org>
Cc: Anthony Perard <anthony.perard@citrix.com>,
Ard Biesheuvel <ard.biesheuvel@linaro.org>,
Jordan Justen <jordan.l.justen@intel.com>,
Julien Grall <julien.grall@linaro.org>
Subject: [PATCH v2 7/8] OvmfPkg/PlatformPei: remedy UEFI memory map fragmentation
Date: Thu, 30 Nov 2017 17:30:28 +0100 [thread overview]
Message-ID: <20171130163029.19743-8-lersek@redhat.com> (raw)
In-Reply-To: <20171130163029.19743-1-lersek@redhat.com>
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 <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
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 <Guid/MemoryTypeInformation.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Uefi/UefiMultiPhase.h>
+
+#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 <Library/QemuFwCfgLib.h>
#include <Library/QemuFwCfgS3Lib.h>
#include <Library/ResourcePublicationLib.h>
-#include <Guid/MemoryTypeInformation.h>
#include <Ppi/MasterBootMode.h>
#include <IndustryStandard/Pci22.h>
#include <OvmfPlatforms.h>
@@ -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
next prev parent reply other threads:[~2017-11-30 16:26 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-30 16:30 [PATCH v2 0/8] OvmfPkg: add the Variable PEIM, defragment the UEFI memmap Laszlo Ersek
2017-11-30 16:30 ` [PATCH v2 1/8] OvmfPkg: introduce PcdMemVarstoreEmuEnable feature flag Laszlo Ersek
2017-12-01 8:44 ` Ard Biesheuvel
2017-11-30 16:30 ` [PATCH v2 2/8] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: check PcdMemVarstoreEmuEnable Laszlo Ersek
2017-12-01 8:44 ` Ard Biesheuvel
2017-11-30 16:30 ` [PATCH v2 3/8] OvmfPkg: conditionally disable reserved memory varstore emulation at build Laszlo Ersek
2017-12-01 8:51 ` Ard Biesheuvel
2017-12-01 10:52 ` Laszlo Ersek
2017-12-01 10:53 ` Ard Biesheuvel
2017-12-01 11:41 ` Laszlo Ersek
2017-12-02 8:53 ` Ard Biesheuvel
2017-11-30 16:30 ` [PATCH v2 4/8] OvmfPkg: introduce FlashNvStorageAddressLib Laszlo Ersek
2017-12-01 8:55 ` Ard Biesheuvel
2017-12-01 11:03 ` Laszlo Ersek
2017-12-01 11:28 ` Laszlo Ersek
2017-11-30 16:30 ` [PATCH v2 5/8] OvmfPkg: include FaultTolerantWritePei and VariablePei Laszlo Ersek
2017-11-30 16:30 ` [PATCH v2 6/8] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: don't set flash PCDs if SMM or no-emu Laszlo Ersek
2017-11-30 16:30 ` Laszlo Ersek [this message]
2017-11-30 16:30 ` [PATCH v2 8/8] OvmfPkg/README: document MEM_VARSTORE_EMU_ENABLE and memmap defrag Laszlo Ersek
2017-11-30 19:00 ` [PATCH v2 0/8] OvmfPkg: add the Variable PEIM, defragment the UEFI memmap Jordan Justen
2017-12-01 8:42 ` Ard Biesheuvel
2017-12-01 10:48 ` Laszlo Ersek
2017-12-01 10:44 ` Laszlo Ersek
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=20171130163029.19743-8-lersek@redhat.com \
--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