UefiCpuPkg/MpInitLib: Allocate and initialize memory of MP Data buffer

v5:
  1. Add comment block for enum AP_INIT_STATE and structure CPU_AP_DATA.
  2. Add more comment for structure CPU_INFO_IN_HOB.
  3. Add more clarification in structure _CPU_MP_DATA for those fields
     pass from PEI to DXE.

Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Michael Kinney <michael.d.kinney@intel.com>
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index 32bbaee..f05db7c 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -93,15 +93,64 @@
   VOID

   )

 {

+  UINT32                   MaxLogicalProcessorNumber;

+  UINT32                   ApStackSize;

   MP_ASSEMBLY_ADDRESS_MAP  AddressMap;

+  UINTN                    BufferSize;

   UINT32                   MonitorFilterSize;

+  VOID                     *MpBuffer;

+  UINTN                    Buffer;

+  CPU_MP_DATA              *CpuMpData;

   UINT8                    ApLoopMode;

+  UINT8                    *MonitorBuffer;

   UINTN                    ApResetVectorSize;

+  UINTN                    BackupBufferAddr;

+  MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);

 

   AsmGetAddressMap (&AddressMap);

   ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);

+  ApStackSize = PcdGet32(PcdCpuApStackSize);

   ApLoopMode  = GetApLoopMode (&MonitorFilterSize);

 

+  BufferSize  = ApStackSize * MaxLogicalProcessorNumber;

+  BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;

+  BufferSize += sizeof (CPU_MP_DATA);

+  BufferSize += ApResetVectorSize;

+  BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;

+  MpBuffer    = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));

+  ASSERT (MpBuffer != NULL);

+  ZeroMem (MpBuffer, BufferSize);

+  Buffer = (UINTN) MpBuffer;

+

+  MonitorBuffer    = (UINT8 *) (Buffer + ApStackSize * MaxLogicalProcessorNumber);

+  BackupBufferAddr = (UINTN) MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber;

+  CpuMpData = (CPU_MP_DATA *) (BackupBufferAddr + ApResetVectorSize);

+  CpuMpData->Buffer           = Buffer;

+  CpuMpData->CpuApStackSize   = ApStackSize;

+  CpuMpData->BackupBuffer     = BackupBufferAddr;

+  CpuMpData->BackupBufferSize = ApResetVectorSize;

+  CpuMpData->EndOfPeiFlag     = FALSE;

+  CpuMpData->WakeupBuffer     = (UINTN) -1;

+  CpuMpData->CpuCount         = 1;

+  CpuMpData->BspNumber        = 0;

+  CpuMpData->WaitEvent        = NULL;

+  CpuMpData->CpuData          = (CPU_AP_DATA *) (CpuMpData + 1);

+  CpuMpData->CpuInfoInHob     = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);

+  InitializeSpinLock(&CpuMpData->MpLock);

+  //

+  // Save assembly code information

+  //

+  CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));

+  //

+  // Finally set AP loop mode

+  //

+  CpuMpData->ApLoopMode = ApLoopMode;

+  DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));

+  //

+  // Store BSP's MTRR setting

+  //

+  MtrrGetAllMtrrs (&CpuMpData->MtrrTable);

+

   return EFI_SUCCESS;

 }

 

diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 317facc..e605f8d 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -46,6 +46,47 @@
 } AP_LOOP_MODE;

 

 //

+// AP initialization state during APs wakeup

+//

+typedef enum {

+  ApInitConfig   = 1,

+  ApInitReconfig = 2,

+  ApInitDone     = 3

+} AP_INIT_STATE;

+

+//

+// AP related data

+//

+typedef struct {

+  SPIN_LOCK                      ApLock;

+  volatile UINT32                *StartupApSignal;

+  volatile UINTN                 ApFunction;

+  volatile UINTN                 ApFunctionArgument;

+  UINT32                         InitialApicId;

+  UINT32                         ApicId;

+  UINT32                         Health;

+  BOOLEAN                        CpuHealthy;

+  BOOLEAN                        Waiting;

+  BOOLEAN                        *Finished;

+  UINT64                         ExpectedTime;

+  UINT64                         CurrentTime;

+  UINT64                         TotalTime;

+  EFI_EVENT                      WaitEvent;

+} CPU_AP_DATA;

+

+//

+// Basic CPU information saved in Guided HOB.

+// Because the contents will be shard between PEI and DXE,

+// we need to make sure the each fields offset same in different

+// architecture.

+//

+typedef struct {

+  UINT32                         InitialApicId;

+  UINT32                         ApicId;

+  UINT32                         Health;

+} CPU_INFO_IN_HOB;

+

+//

 // AP reset code information including code address and size,

 // this structure will be shared be C code and assembly code.

 // It is natural aligned by design.

@@ -58,6 +99,8 @@
   UINTN             RelocateApLoopFuncSize;

 } MP_ASSEMBLY_ADDRESS_MAP;

 

+typedef struct _CPU_MP_DATA  CPU_MP_DATA;

+

 #pragma pack(1)

 

 //

@@ -79,9 +122,54 @@
   UINTN                 DataSegment;

   UINTN                 EnableExecuteDisable;

   UINTN                 Cr3;

+  CPU_MP_DATA           *CpuMpData;

 } MP_CPU_EXCHANGE_INFO;

 

 #pragma pack()

+

+//

+// CPU MP Data save in memory

+//

+struct _CPU_MP_DATA {

+  UINT64                         CpuInfoInHob;

+  UINT32                         CpuCount;

+  UINT32                         BspNumber;

+  //

+  // The above fields data will be passed from PEI to DXE

+  // Please make sure the fields offset same in the different

+  // architecture.

+  //

+  SPIN_LOCK                      MpLock;

+  UINTN                          Buffer;

+  UINTN                          CpuApStackSize;

+  MP_ASSEMBLY_ADDRESS_MAP        AddressMap;

+  UINTN                          WakeupBuffer;

+  UINTN                          BackupBuffer;

+  UINTN                          BackupBufferSize;

+  BOOLEAN                        EndOfPeiFlag;

+

+  volatile UINT32                StartCount;

+  volatile UINT32                FinishedCount;

+  volatile UINT32                RunningCount;

+  BOOLEAN                        SingleThread;

+  EFI_AP_PROCEDURE               Procedure;

+  VOID                           *ProcArguments;

+  BOOLEAN                        *Finished;

+  UINT64                         ExpectedTime;

+  UINT64                         CurrentTime;

+  UINT64                         TotalTime;

+  EFI_EVENT                      WaitEvent;

+  UINTN                          **FailedCpuList;

+

+  AP_INIT_STATE                  InitFlag;

+  BOOLEAN                        X2ApicEnable;

+  MTRR_SETTINGS                  MtrrTable;

+  UINT8                          ApLoopMode;

+  UINT8                          ApTargetCState;

+  UINT16                         PmCodeSegment;

+  CPU_AP_DATA                    *CpuData;

+  volatile MP_CPU_EXCHANGE_INFO  *MpCpuExchangeInfo;

+};

 /**

   Assembly code to place AP into safe loop mode.