It has been deemed inappropriate, for general use, for UefiCpuPkg/CpuDxe to keep reflecting the most recent MTRR settings to an AcpiNVS buffer, for CpuS3DataDxe to pass through to PiSmmCpuDxeSmm. Instead, Michael Kinney suggested to fetch and save the MTRR settings in CpuS3DataDxe, in a similarly delayed manner: at EndOfDxe.
That idea matches OVMF's BDS very well. The events are sequenced like this: - PiSmmCpuDxeSmm installs EFI_SMM_CONFIGURATION_PROTOCOL. - SmmConfigurationEventNotify() is invoked in CpuS3DataDxe, which in turn calls SaveCpuS3Data(). - SaveCpuS3Data() allocates AcpiNVS memory for ACPI_CPU_DATA, and (with this patch) MTRR_SETTINGS too, linking the latter into the former. - SaveCpuS3Data() registers a handler for EndOfDxe. - Later, OVMF's BDS signals EndOfDxe, thus CpuS3DataDxe populates the MTRR_SETTINGS block, with the then-current MTRR settings. - Right after, BDS writes the last opcode (an INFO opcode) to the S3 boot script, and installs gEfiDxeSmmReadyToLockProtocolGuid in the DXE protocol database. - In turn, the SMM core installs gEfiSmmReadyToLockProtocolGuid in the SMM protocol database. - In turn, SmmReadyToLockEventNotify() is called in PiSmmCpuDxeSmm, which copies the MTRR settings from AcpiNVS to SMRAM. On the S3 resume path, PiSmmCpuDxeSmm will apply the MTRR settings to all APs directly from SMRAM. This patch significantly diverges from the original Quark_EDKII_v1.1.0/IA32FamilyCpuBasePkg/CpuMpDxe/ driver. Suggested-by: Michael Kinney <michael.d.kin...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- Notes: v2: - This approach is new in v2. In v1, QuarkPort/CpuS3DataDxe simply relayed the PcdCpuMtrrTableAddress value from UefiCpuPkg/CpuDxe to PiSmmCpuDxeSmm. OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf | 2 + OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c | 41 ++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf b/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf index 249408b..2610a63 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/CpuS3DataDxe.inf @@ -78,8 +78,10 @@ [LibraryClasses] UefiLib DebugLib BaseLib + MtrrLib [Guids] + gEfiEndOfDxeEventGroupGuid [Protocols] gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED diff --git a/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c b/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c index a69c58c..25ac8b1 100644 --- a/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c +++ b/OvmfPkg/QuarkPort/CpuS3DataDxe/ProcessorConfig.c @@ -34,6 +34,8 @@ **/ +#include <Library/MtrrLib.h> + #include "MpService.h" #include "Cpu.h" #include "MpApic.h" @@ -220,6 +222,27 @@ WakeupAPAndCollectBist ( } /** + Callback function executed when the EndOfDxe event group is signaled. + + We delay saving the MTRR settings until BDS signals EndOfDxe. + + @param[in] Event Event whose notification function is being invoked. + @param[out] Context Pointer to the MTRR_SETTINGS buffer to fill in. +**/ +STATIC +VOID +EFIAPI +SaveMtrrsOnEndOfDxe ( + IN EFI_EVENT Event, + OUT VOID *Context + ) +{ + DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__)); + MtrrGetAllMtrrs (Context); + gBS->CloseEvent (Event); +} + +/** Prepare ACPI NVS memory below 4G memory for use of S3 resume. This function allocates ACPI NVS memory below 4G memory for use of S3 resume, @@ -234,6 +257,9 @@ SaveCpuS3Data ( ) { MP_CPU_SAVED_DATA *MpCpuSavedData; + MTRR_SETTINGS *MtrrSettings; + EFI_STATUS Status; + EFI_EVENT EndOfDxeEvent; // // Allocate ACPI NVS memory below 4G memory for use of S3 resume. @@ -241,6 +267,20 @@ SaveCpuS3Data ( MpCpuSavedData = AllocateAcpiNvsMemoryBelow4G (sizeof (MP_CPU_SAVED_DATA)); // + // Allocate buffer for MTRR settings. + // + MtrrSettings = AllocateAcpiNvsMemoryBelow4G (sizeof *MtrrSettings); + + // + // Install notification callback for EndOfDxe that will fill in the MTRR + // settings. + // + Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + SaveMtrrsOnEndOfDxe, MtrrSettings, + &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent); + ASSERT_EFI_ERROR (Status); + + // // Set the value for CPU data // mAcpiCpuData = &(MpCpuSavedData->AcpiCpuData); @@ -252,6 +292,7 @@ SaveCpuS3Data ( mAcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) mExchangeInfo->StackStart; mAcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize); + mAcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)MtrrSettings; mAcpiCpuData->ApMachineCheckHandlerBase = mApMachineCheckHandlerBase; mAcpiCpuData->ApMachineCheckHandlerSize = mApMachineCheckHandlerSize; -- 1.8.3.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel