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

Reply via email to