summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm8
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.c37
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.h8
-rw-r--r--UefiCpuPkg/Library/MpInitLib/PeiMpLib.c10
-rw-r--r--UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm9
5 files changed, 59 insertions, 13 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
index 1d67f510e9..bfcdbd31c1 100644
--- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
@@ -179,6 +179,14 @@ ProgramStack:
mov esp, dword [edi + CPU_INFO_IN_HOB.ApTopOfStack]
CProcedureInvoke:
+ ;
+ ; Reserve 4 bytes for CpuMpData.
+ ; When the AP wakes up again via INIT-SIPI-SIPI, push 0 will cause the existing CpuMpData to be overwritten with 0.
+ ; CpuMpData is filled in via InitializeApData() during the first time INIT-SIPI-SIPI,
+ ; while overwirrten may occurs when under ApInHltLoop but InitFlag is not set to ApInitConfig.
+ ; Therefore reservation is implemented by sub esp instead of push 0.
+ ;
+ sub esp, 4
push ebp ; push BIST data at top of AP stack
xor ebp, ebp ; clear ebp for call stack trace
push ebp
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index 041a32e659..1c053f87a4 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -599,6 +599,7 @@ InitializeApData (
{
CPU_INFO_IN_HOB *CpuInfoInHob;
MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;
+ AP_STACK_DATA *ApStackData;
CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();
@@ -606,6 +607,12 @@ InitializeApData (
CpuInfoInHob[ProcessorNumber].Health = BistData;
CpuInfoInHob[ProcessorNumber].ApTopOfStack = ApTopOfStack;
+ //
+ // AP_STACK_DATA is stored at the top of AP Stack
+ //
+ ApStackData = (AP_STACK_DATA *)((UINTN)ApTopOfStack - sizeof (AP_STACK_DATA));
+ ApStackData->MpData = CpuMpData;
+
CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;
@@ -651,6 +658,7 @@ ApWakeupFunction (
CPU_INFO_IN_HOB *CpuInfoInHob;
UINT64 ApTopOfStack;
UINTN CurrentApicMode;
+ AP_STACK_DATA *ApStackData;
//
// AP finished assembly code and begin to execute C code
@@ -676,7 +684,9 @@ ApWakeupFunction (
// This is first time AP wakeup, get BIST information from AP stack
//
ApTopOfStack = CpuMpData->Buffer + (ProcessorNumber + 1) * CpuMpData->CpuApStackSize;
- BistData = *(UINT32 *)((UINTN)ApTopOfStack - sizeof (UINTN));
+ ApStackData = (AP_STACK_DATA *)((UINTN)ApTopOfStack - sizeof (AP_STACK_DATA));
+ BistData = (UINT32)ApStackData->Bist;
+
//
// CpuMpData->CpuData[0].VolatileRegisters is initialized based on BSP environment,
// to initialize AP in InitConfig path.
@@ -1824,14 +1834,22 @@ MpInitLibInitialize (
AsmGetAddressMap (&AddressMap);
GetApResetVectorSize (&AddressMap, &ApResetVectorSizeBelow1Mb, &ApResetVectorSizeAbove1Mb);
ApStackSize = PcdGet32 (PcdCpuApStackSize);
- ApLoopMode = GetApLoopMode (&MonitorFilterSize);
+ //
+ // ApStackSize must be power of 2
+ //
+ ASSERT ((ApStackSize & (ApStackSize - 1)) == 0);
+ ApLoopMode = GetApLoopMode (&MonitorFilterSize);
//
// Save BSP's Control registers for APs.
//
SaveVolatileRegisters (&VolatileRegisters);
- BufferSize = ApStackSize * MaxLogicalProcessorNumber;
+ BufferSize = ApStackSize * MaxLogicalProcessorNumber;
+ //
+ // Allocate extra ApStackSize to let AP stack align on ApStackSize bounday
+ //
+ BufferSize += ApStackSize;
BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;
BufferSize += ApResetVectorSizeBelow1Mb;
BufferSize = ALIGN_VALUE (BufferSize, 8);
@@ -1841,13 +1859,13 @@ MpInitLibInitialize (
MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
ASSERT (MpBuffer != NULL);
ZeroMem (MpBuffer, BufferSize);
- Buffer = (UINTN)MpBuffer;
+ Buffer = ALIGN_VALUE ((UINTN)MpBuffer, ApStackSize);
//
- // The layout of the Buffer is as below:
+ // The layout of the Buffer is as below (lower address on top):
//
- // +--------------------+ <-- Buffer
- // AP Stacks (N)
+ // +--------------------+ <-- Buffer (Pointer of CpuMpData is stored in the top of each AP's stack.)
+ // AP Stacks (N) (StackTop = (RSP + ApStackSize) & ~ApStackSize))
// +--------------------+ <-- MonitorBuffer
// AP Monitor Filters (N)
// +--------------------+ <-- BackupBufferAddr (CpuMpData->BackupBuffer)
@@ -1855,7 +1873,7 @@ MpInitLibInitialize (
// +--------------------+
// Padding
// +--------------------+ <-- ApIdtBase (8-byte boundary)
- // AP IDT All APs share one separate IDT. So AP can get address of CPU_MP_DATA from IDT Base.
+ // AP IDT All APs share one separate IDT.
// +--------------------+ <-- CpuMpData
// CPU_MP_DATA
// +--------------------+ <-- CpuMpData->CpuData
@@ -1892,10 +1910,11 @@ MpInitLibInitialize (
//
// Make sure no memory usage outside of the allocated buffer.
+ // (ApStackSize - (Buffer - (UINTN)MpBuffer)) is the redundant caused by alignment
//
ASSERT (
(CpuMpData->CpuInfoInHob + sizeof (CPU_INFO_IN_HOB) * MaxLogicalProcessorNumber) ==
- Buffer + BufferSize
+ (UINTN)MpBuffer + BufferSize - (ApStackSize - Buffer + (UINTN)MpBuffer)
);
//
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 47b722cb2f..f5086e497e 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -301,6 +301,14 @@ struct _CPU_MP_DATA {
UINT64 GhcbBase;
};
+//
+// AP_STACK_DATA is stored at the top of each AP stack.
+//
+typedef struct {
+ UINTN Bist;
+ CPU_MP_DATA *MpData;
+} AP_STACK_DATA;
+
#define AP_SAFE_STACK_SIZE 128
#define AP_RESET_STACK_SIZE AP_SAFE_STACK_SIZE
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
index 65400b95a2..e732371ddd 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
@@ -89,7 +89,7 @@ EnableDebugAgent (
/**
Get pointer to CPU MP Data structure.
For BSP, the pointer is retrieved from HOB.
- For AP, the structure is just after IDT.
+ For AP, the structure is stored in the top of each AP's stack.
@return The pointer to CPU MP Data structure.
**/
@@ -100,15 +100,17 @@ GetCpuMpData (
{
CPU_MP_DATA *CpuMpData;
MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
- IA32_DESCRIPTOR Idtr;
+ UINTN ApTopOfStack;
+ AP_STACK_DATA *ApStackData;
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
if (ApicBaseMsr.Bits.BSP == 1) {
CpuMpData = GetCpuMpDataFromGuidedHob ();
ASSERT (CpuMpData != NULL);
} else {
- AsmReadIdtr (&Idtr);
- CpuMpData = (CPU_MP_DATA *)(Idtr.Base + Idtr.Limit + 1);
+ ApTopOfStack = ALIGN_VALUE ((UINTN)&ApTopOfStack, (UINTN)PcdGet32 (PcdCpuApStackSize));
+ ApStackData = (AP_STACK_DATA *)((UINTN)ApTopOfStack- sizeof (AP_STACK_DATA));
+ CpuMpData = (CPU_MP_DATA *)ApStackData->MpData;
}
return CpuMpData;
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index b7f8d48504..5d71995bf8 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -239,11 +239,20 @@ ProgramStack:
mov rsp, qword [rdi + CPU_INFO_IN_HOB.ApTopOfStack]
CProcedureInvoke:
+ ;
+ ; Reserve 8 bytes for CpuMpData.
+ ; When the AP wakes up again via INIT-SIPI-SIPI, push 0 will cause the existing CpuMpData to be overwritten with 0.
+ ; CpuMpData is filled in via InitializeApData() during the first time INIT-SIPI-SIPI,
+ ; while overwirrten may occurs when under ApInHltLoop but InitFlag is not set to ApInitConfig.
+ ; Therefore reservation is implemented by sub rsp instead of push 0.
+ ;
+ sub rsp, 8
push rbp ; Push BIST data at top of AP stack
xor rbp, rbp ; Clear ebp for call stack trace
push rbp
mov rbp, rsp
+ push qword 0 ; Push 8 bytes for alignment
mov rax, qword [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitializeFloatingPointUnits)]
sub rsp, 20h
call rax ; Call assembly function to initialize FPU per UEFI spec