]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg: Use Top of each AP's stack to save CpuMpData
authorYuanhao Xie <yuanhao.xie@intel.com>
Fri, 19 Aug 2022 06:17:28 +0000 (14:17 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 31 Aug 2022 04:23:55 +0000 (04:23 +0000)
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>
UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/Library/MpInitLib/MpLib.h
UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm

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