MdeModulePkg/FPDT: Lock boot performance table address variable at EndOfDxe

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2957

1. Allocate performance data table at EndOfDxe and then lock the varible
   which store the table address at EndOfDxe.

2. Enlarge PCD gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize
   from 0x20000 to 0x30000 in order to hold the Delta performance data
   between EndOfDxe and ReadyToBoot.

3. SMM performance data is collected by DXE modules through SMM communication
   at ReadyToBoot before.
   Now to do SMM communication twice, one for allocating the performance
   size at EndOfDxe, another is at ReadyToBoot to get SMM performance data.

4. Make SmmCorePerformanceLib rather than FirmwarePerformanceSmm to communicate
   with DxeCorePerformanceLib for SMM performance data and size.

Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
This commit is contained in:
Dandan Bi
2021-06-28 19:50:22 +08:00
committed by mergify[bot]
parent 4c495e5e3d
commit 466ebdd2e0
13 changed files with 306 additions and 293 deletions

View File

@ -5,7 +5,7 @@
for Firmware Basic Boot Performance Record and other boot performance records,
and install FPDT to ACPI table.
Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -16,6 +16,7 @@
#include <Protocol/AcpiTable.h>
#include <Protocol/LockBox.h>
#include <Protocol/Variable.h>
#include <Protocol/VariablePolicy.h>
#include <Guid/Acpi.h>
#include <Guid/FirmwarePerformance.h>
@ -32,6 +33,8 @@
#include <Library/HobLib.h>
#include <Library/LockBoxLib.h>
#include <Library/UefiLib.h>
#include <Library/VariablePolicyHelperLib.h>
#include <Library/PerformanceLib.h>
#define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))
@ -278,11 +281,12 @@ InstallFirmwarePerformanceDataTable (
VOID
)
{
EFI_STATUS Status;
EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
UINTN BootPerformanceDataSize;
FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
UINTN Size;
EFI_STATUS Status;
EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
UINTN BootPerformanceDataSize;
FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
UINTN Size;
EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicyProtocol;
//
// Get AcpiTable Protocol.
@ -292,6 +296,14 @@ InstallFirmwarePerformanceDataTable (
return Status;
}
//
// Get VariablePolicy Protocol.
//
Status = gBS->LocateProtocol(&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicyProtocol);
if (EFI_ERROR (Status)) {
return Status;
}
if (mReceivedAcpiBootPerformanceTable != NULL) {
mAcpiBootPerformanceTable = mReceivedAcpiBootPerformanceTable;
mAcpiBootPerformanceTable->BasicBoot.ResetEnd = mBootPerformanceTableTemplate.BasicBoot.ResetEnd;
@ -369,6 +381,24 @@ InstallFirmwarePerformanceDataTable (
&PerformanceVariable
);
//
// Lock the variable which stores the Performance Table pointers.
//
Status = RegisterBasicVariablePolicy (
VariablePolicyProtocol,
&gEfiFirmwarePerformanceGuid,
EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
VARIABLE_POLICY_NO_MIN_SIZE,
VARIABLE_POLICY_NO_MAX_SIZE,
VARIABLE_POLICY_NO_MUST_ATTR,
VARIABLE_POLICY_NO_CANT_ATTR,
VARIABLE_POLICY_TYPE_LOCK_NOW
);
if (EFI_ERROR(Status)) {
DEBUG((DEBUG_ERROR, "[FirmwarePerformanceDxe] Error when lock variable %s, Status = %r\n", EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, Status));
ASSERT_EFI_ERROR(Status);
}
//
// Publish Firmware Performance Data Table.
//
@ -501,18 +531,12 @@ FpdtStatusCodeListenerDxe (
DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));
DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n"));
DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesExit = 0\n"));
} else if (Value == (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)) {
if (mAcpiBootPerformanceTable == NULL) {
//
// ACPI Firmware Performance Data Table not installed yet, install it now.
//
InstallFirmwarePerformanceDataTable ();
}
} else if (Data != NULL && CompareGuid (&Data->Type, &gEdkiiFpdtExtendedFirmwarePerformanceGuid)) {
//
// Get the Boot performance table and then install it to ACPI table.
//
CopyMem (&mReceivedAcpiBootPerformanceTable, Data + 1, Data->Size);
InstallFirmwarePerformanceDataTable ();
} else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
DEBUG ((DEBUG_ERROR, "FpdtStatusCodeListenerDxe: Performance data reported through gEfiFirmwarePerformanceGuid will not be collected by FirmwarePerformanceDataTableDxe\n"));
Status = EFI_UNSUPPORTED;
@ -526,6 +550,32 @@ FpdtStatusCodeListenerDxe (
return Status;
}
/**
Notify function for event EndOfDxe.
This is used to install ACPI Firmware Performance Data Table for basic boot records.
@param[in] Event The Event that is being processed.
@param[in] Context The Event Context.
**/
VOID
EFIAPI
FpdtEndOfDxeEventNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//
// When performance is enabled, the FPDT will be installed when DxeCorePerformanceLib report the data to FimwarePerformanceDxe.
// This is used to install the FPDT for the basic boot recods when performance infrastructure is not enabled.
//
if ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0) {
return;
}
ASSERT (mReceivedAcpiBootPerformanceTable == NULL);
InstallFirmwarePerformanceDataTable ();
}
/**
Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
@ -596,6 +646,7 @@ FirmwarePerformanceDxeEntryPoint (
FIRMWARE_SEC_PERFORMANCE *Performance;
VOID *Registration;
UINT64 OemTableId;
EFI_EVENT EndOfDxeEvent;
CopyMem (
mFirmwarePerformanceTableTemplate.Header.OemId,
@ -620,6 +671,19 @@ FirmwarePerformanceDxeEntryPoint (
Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerDxe, TPL_HIGH_LEVEL);
ASSERT_EFI_ERROR (Status);
//
// Register the notify function to install FPDT at EndOfDxe.
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
FpdtEndOfDxeEventNotify,
NULL,
&gEfiEndOfDxeEventGroupGuid,
&EndOfDxeEvent
);
ASSERT_EFI_ERROR (Status);
//
// Register the notify function to update FPDT on ExitBootServices Event.
//