summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorYuanhao Xie <yuanhao.xie@intel.com>2022-08-19 14:17:28 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2022-08-31 04:23:55 +0000
commit9ab2b34dd4f7e5cc6170ff812b0a07d58e5510b6 (patch)
treeb82620b1e55715fa040e1efc265dc3990c44fa8b /UefiCpuPkg
parent76cf3d35e6cc20140e50b299aa7162ced4acef59 (diff)
downloadedk2-9ab2b34dd4f7e5cc6170ff812b0a07d58e5510b6.tar.gz
edk2-9ab2b34dd4f7e5cc6170ff812b0a07d58e5510b6.tar.bz2
edk2-9ab2b34dd4f7e5cc6170ff812b0a07d58e5510b6.zip
UefiCpuPkg: Use Top of each AP's stack to save CpuMpData
To remove the dependency of CPU register, 4/8 byte at the top of the stack is occupied for CpuMpData. BIST information is also taken care here. This modification is only for PEI phase, since in DXE phase CpuMpData is accessed via global variable. Signed-off-by: Yuanhao Xie <yuanhao.xie@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com>
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