summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UefiCpuPkg/Library/MpInitLib/AmdSev.c17
-rw-r--r--UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf1
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpHandOff.h47
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.c83
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.h19
-rw-r--r--UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf2
-rw-r--r--UefiCpuPkg/Library/MpInitLib/PeiMpLib.c32
7 files changed, 186 insertions, 15 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
index ca9bfed7f3..bda4960f6f 100644
--- a/UefiCpuPkg/Library/MpInitLib/AmdSev.c
+++ b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
@@ -260,3 +260,20 @@ FillExchangeInfoDataSevEs (
ExchangeInfo->ExtTopoAvail = !!ExtTopoEbx.Bits.LogicalProcessors;
}
}
+
+/**
+ Get pointer to CPU MP Data structure from GUIDed HOB.
+
+ @param[in] CpuMpData The pointer to CPU MP Data structure.
+**/
+VOID
+AmdSevUpdateCpuMpData (
+ IN CPU_MP_DATA *CpuMpData
+ )
+{
+ CPU_MP_DATA *OldCpuMpData;
+
+ OldCpuMpData = GetCpuMpDataFromGuidedHob ();
+
+ OldCpuMpData->NewCpuMpData = CpuMpData;
+}
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
index 67ebf7254c..7d45d3ad4d 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
@@ -38,6 +38,7 @@
MpLib.c
MpLib.h
Microcode.c
+ MpHandOff.h
[Packages]
MdePkg/MdePkg.dec
diff --git a/UefiCpuPkg/Library/MpInitLib/MpHandOff.h b/UefiCpuPkg/Library/MpInitLib/MpHandOff.h
new file mode 100644
index 0000000000..83e4055ec9
--- /dev/null
+++ b/UefiCpuPkg/Library/MpInitLib/MpHandOff.h
@@ -0,0 +1,47 @@
+/** @file
+ Defines the HOB GUID used to describe the MSEG memory region allocated in PEI.
+ Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MP_HANDOFF_H_
+#define MP_HANDOFF_H_
+
+#define MP_HANDOFF_GUID \
+ { \
+ 0x11e2bd88, 0xed38, 0x4abd, {0xa3, 0x99, 0x21, 0xf2, 0x5f, 0xd0, 0x7a, 0x60 } \
+ }
+
+extern EFI_GUID mMpHandOffGuid;
+
+//
+// The information required to transfer from the PEI phase to the
+// DXE phase is contained within the MP_HAND_OFF and PROCESSOR_HAND_OFF.
+// If the SizeOfPointer (WaitLoopExecutionMode) of both phases are equal,
+// and the APs is not in halt mode,
+// then the APs can be awakened by triggering the start-up
+// signal, rather than using INIT-SIPI-SIPI.
+// To trigger the start-up signal, BSP writes the specified
+// StartupSignalValue to the StartupSignalAddress of each processor.
+// This address is monitored by the APs.
+//
+typedef struct {
+ UINT32 ApicId;
+ UINT32 Health;
+ UINT64 StartupSignalAddress;
+ UINT64 StartupProcedureAddress;
+} PROCESSOR_HAND_OFF;
+
+typedef struct {
+ //
+ // The ProcessorIndex indicates the range of processors. If it is set to 0, it signifies
+ // processors from 0 to CpuCount - 1. Multiple instances in the HOB list describe
+ // processors from ProcessorIndex to ProcessorIndex + CpuCount - 1.
+ //
+ UINT32 ProcessorIndex;
+ UINT32 CpuCount;
+ UINT32 WaitLoopExecutionMode;
+ UINT32 StartupSignalValue;
+ PROCESSOR_HAND_OFF Info[];
+} MP_HAND_OFF;
+#endif
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index e8dd640f9b..ccc01859f0 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -14,6 +14,7 @@
#include <Register/Amd/Ghcb.h>
EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
+EFI_GUID mMpHandOffGuid = MP_HANDOFF_GUID;
/**
Save the volatile registers required to be restored following INIT IPI.
@@ -1815,6 +1816,59 @@ CheckAllAPs (
}
/**
+ This function Get BspNumber.
+
+ @param[in] MpHandOff Pointer to MpHandOff
+ @return BspNumber
+**/
+UINT32
+GetBspNumber (
+ IN CONST MP_HAND_OFF *MpHandOff
+ )
+{
+ UINT32 ApicId;
+ UINT32 BspNumber;
+ UINT32 Index;
+
+ //
+ // Get the processor number for the BSP
+ //
+ BspNumber = MAX_UINT32;
+ ApicId = GetInitialApicId ();
+ for (Index = 0; Index < MpHandOff->CpuCount; Index++) {
+ if (MpHandOff->Info[Index].ApicId == ApicId) {
+ BspNumber = Index;
+ }
+ }
+
+ ASSERT (BspNumber != MAX_UINT32);
+
+ return BspNumber;
+}
+
+/**
+ Get pointer to MP_HAND_OFF GUIDed HOB.
+
+ @return The pointer to MP_HAND_OFF structure.
+**/
+MP_HAND_OFF *
+GetMpHandOffHob (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ MP_HAND_OFF *MpHandOff;
+
+ MpHandOff = NULL;
+ GuidHob = GetFirstGuidHob (&mMpHandOffGuid);
+ if (GuidHob != NULL) {
+ MpHandOff = (MP_HAND_OFF *)GET_GUID_HOB_DATA (GuidHob);
+ }
+
+ return MpHandOff;
+}
+
+/**
MP Initialize Library initialization.
This service will allocate AP reset vector and wakeup all APs to do APs
@@ -1833,7 +1887,7 @@ MpInitLibInitialize (
VOID
)
{
- CPU_MP_DATA *OldCpuMpData;
+ MP_HAND_OFF *MpHandOff;
CPU_INFO_IN_HOB *CpuInfoInHob;
UINT32 MaxLogicalProcessorNumber;
UINT32 ApStackSize;
@@ -1852,11 +1906,11 @@ MpInitLibInitialize (
UINTN BackupBufferAddr;
UINTN ApIdtBase;
- OldCpuMpData = GetCpuMpDataFromGuidedHob ();
- if (OldCpuMpData == NULL) {
+ MpHandOff = GetMpHandOffHob ();
+ if (MpHandOff == NULL) {
MaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
} else {
- MaxLogicalProcessorNumber = OldCpuMpData->CpuCount;
+ MaxLogicalProcessorNumber = MpHandOff->CpuCount;
}
ASSERT (MaxLogicalProcessorNumber != 0);
@@ -2000,7 +2054,7 @@ MpInitLibInitialize (
//
ProgramVirtualWireMode ();
- if (OldCpuMpData == NULL) {
+ if (MpHandOff == NULL) {
if (MaxLogicalProcessorNumber > 1) {
//
// Wakeup all APs and calculate the processor count in system
@@ -2012,15 +2066,18 @@ MpInitLibInitialize (
// APs have been wakeup before, just get the CPU Information
// from HOB
//
- OldCpuMpData->NewCpuMpData = CpuMpData;
- CpuMpData->CpuCount = OldCpuMpData->CpuCount;
- CpuMpData->BspNumber = OldCpuMpData->BspNumber;
- CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob;
- CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
+ AmdSevUpdateCpuMpData (CpuMpData);
+ CpuMpData->CpuCount = MpHandOff->CpuCount;
+ CpuMpData->BspNumber = GetBspNumber (MpHandOff);
+ CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
InitializeSpinLock (&CpuMpData->CpuData[Index].ApLock);
- CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0) ? TRUE : FALSE;
+ CpuMpData->CpuData[Index].CpuHealthy = (MpHandOff->Info[Index].Health == 0) ? TRUE : FALSE;
CpuMpData->CpuData[Index].ApFunction = 0;
+ CpuInfoInHob[Index].InitialApicId = MpHandOff->Info[Index].ApicId;
+ CpuInfoInHob[Index].ApTopOfStack = CpuMpData->Buffer + (Index + 1) * CpuMpData->CpuApStackSize;
+ CpuInfoInHob[Index].ApicId = MpHandOff->Info[Index].ApicId;
+ CpuInfoInHob[Index].Health = MpHandOff->Info[Index].Health;
}
}
@@ -2049,7 +2106,7 @@ MpInitLibInitialize (
// Wakeup APs to do some AP initialize sync (Microcode & MTRR)
//
if (CpuMpData->CpuCount > 1) {
- if (OldCpuMpData != NULL) {
+ if (MpHandOff != NULL) {
//
// Only needs to use this flag for DXE phase to update the wake up
// buffer. Wakeup buffer allocated in PEI phase is no longer valid
@@ -2066,7 +2123,7 @@ MpInitLibInitialize (
CpuPause ();
}
- if (OldCpuMpData != NULL) {
+ if (MpHandOff != NULL) {
CpuMpData->InitFlag = ApInitDone;
}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index b694c7b40f..a7f36d323b 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -39,8 +39,17 @@
#include <Register/Amd/Ghcb.h>
#include <Guid/MicrocodePatchHob.h>
+#include "MpHandOff.h"
#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
+//
+// To trigger the start-up signal, BSP writes the specified
+// StartupSignalValue to the StartupSignalAddress of each processor.
+// This address is monitored by the APs, and as soon as they receive
+// the value that matches the MP_HAND_OFF_SIGNAL, they will wake up
+// and switch the context from PEI to DXE phase.
+//
+#define MP_HAND_OFF_SIGNAL SIGNATURE_32 ('M', 'P', 'H', 'O')
#define CPU_INIT_MP_LIB_HOB_GUID \
{ \
@@ -891,4 +900,14 @@ SevSnpCreateAP (
IN INTN ProcessorNumber
);
+/**
+ Get pointer to CPU MP Data structure from GUIDed HOB.
+
+ @param[in] CpuMpData The pointer to CPU MP Data structure.
+**/
+VOID
+AmdSevUpdateCpuMpData (
+ IN CPU_MP_DATA *CpuMpData
+ );
+
#endif
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
index 78eded96bf..83e9028d0f 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
@@ -36,7 +36,7 @@
MpLib.c
MpLib.h
Microcode.c
-
+ MpHandOff.h
[Packages]
MdePkg/MdePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
index 013f89b197..f80e00edcf 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
@@ -126,7 +126,37 @@ SaveCpuMpData (
IN CPU_MP_DATA *CpuMpData
)
{
- UINT64 Data64;
+ UINT64 Data64;
+ UINTN Index;
+ CPU_INFO_IN_HOB *CpuInfoInHob;
+ MP_HAND_OFF *MpHandOff;
+ UINTN MpHandOffSize;
+
+ //
+ // When APs are in a state that can be waken up by a store operation to a memory address,
+ // report the MP_HAND_OFF data for DXE to use.
+ //
+ CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
+ MpHandOffSize = sizeof (MP_HAND_OFF) + sizeof (PROCESSOR_HAND_OFF) * CpuMpData->CpuCount;
+ MpHandOff = (MP_HAND_OFF *)BuildGuidHob (&mMpHandOffGuid, MpHandOffSize);
+ ASSERT (MpHandOff != NULL);
+ ZeroMem (MpHandOff, MpHandOffSize);
+ MpHandOff->ProcessorIndex = 0;
+
+ MpHandOff->CpuCount = CpuMpData->CpuCount;
+ if (CpuMpData->ApLoopMode != ApInHltLoop) {
+ MpHandOff->StartupSignalValue = MP_HAND_OFF_SIGNAL;
+ MpHandOff->WaitLoopExecutionMode = sizeof (VOID *);
+ }
+
+ for (Index = 0; Index < MpHandOff->CpuCount; Index++) {
+ MpHandOff->Info[Index].ApicId = CpuInfoInHob[Index].ApicId;
+ MpHandOff->Info[Index].Health = CpuInfoInHob[Index].Health;
+ if (CpuMpData->ApLoopMode != ApInHltLoop) {
+ MpHandOff->Info[Index].StartupSignalAddress = (UINT64)(UINTN)CpuMpData->CpuData[Index].StartupApSignal;
+ MpHandOff->Info[Index].StartupProcedureAddress = (UINT64)(UINTN)&CpuMpData->CpuData[Index].ApFunction;
+ }
+ }
//
// Build location of CPU MP DATA buffer in HOB