summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.c49
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.h88
2 files changed, 137 insertions, 0 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index 32bbaee5cc..f05db7c2a5 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -93,15 +93,64 @@ MpInitLibInitialize (
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 317facc80c..e605f8de41 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -46,6 +46,47 @@ typedef enum {
} 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 @@ typedef struct {
UINTN RelocateApLoopFuncSize;
} MP_ASSEMBLY_ADDRESS_MAP;
+typedef struct _CPU_MP_DATA CPU_MP_DATA;
+
#pragma pack(1)
//
@@ -79,9 +122,54 @@ typedef struct {
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.