]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuMpPei/CpuMpPei.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / CpuMpPei.c
index eaf99c73cd261edd2424d00e4d839f1bb38ef061..e7f1fe9f426c363f84ed69aa5bfbea7b6b357b55 100644 (file)
@@ -1,23 +1,19 @@
 /** @file\r
   CPU PEI Module installs CPU Multiple Processor PPI.\r
 \r
-  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "CpuMpPei.h"\r
 \r
+extern EDKII_PEI_MP_SERVICES2_PPI  mMpServices2Ppi;\r
+\r
 //\r
 // CPU MP PPI to be installed\r
 //\r
-EFI_PEI_MP_SERVICES_PPI                mMpServicesPpi = {\r
+EFI_PEI_MP_SERVICES_PPI  mMpServicesPpi = {\r
   PeiGetNumberOfProcessors,\r
   PeiGetProcessorInfo,\r
   PeiStartupAllAPs,\r
@@ -27,10 +23,17 @@ EFI_PEI_MP_SERVICES_PPI                mMpServicesPpi = {
   PeiWhoAmI,\r
 };\r
 \r
-EFI_PEI_PPI_DESCRIPTOR           mPeiCpuMpPpiDesc = {\r
-  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-  &gEfiPeiMpServicesPpiGuid,\r
-  &mMpServicesPpi\r
+EFI_PEI_PPI_DESCRIPTOR  mPeiCpuMpPpiList[] = {\r
+  {\r
+    EFI_PEI_PPI_DESCRIPTOR_PPI,\r
+    &gEdkiiPeiMpServices2PpiGuid,\r
+    &mMpServices2Ppi\r
+  },\r
+  {\r
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+    &gEfiPeiMpServicesPpiGuid,\r
+    &mMpServicesPpi\r
+  }\r
 };\r
 \r
 /**\r
@@ -70,10 +73,10 @@ EFI_PEI_PPI_DESCRIPTOR           mPeiCpuMpPpiDesc = {
 EFI_STATUS\r
 EFIAPI\r
 PeiGetNumberOfProcessors (\r
-  IN  CONST EFI_PEI_SERVICES    **PeiServices,\r
-  IN  EFI_PEI_MP_SERVICES_PPI   *This,\r
-  OUT UINTN                     *NumberOfProcessors,\r
-  OUT UINTN                     *NumberOfEnabledProcessors\r
+  IN  CONST EFI_PEI_SERVICES   **PeiServices,\r
+  IN  EFI_PEI_MP_SERVICES_PPI  *This,\r
+  OUT UINTN                    *NumberOfProcessors,\r
+  OUT UINTN                    *NumberOfEnabledProcessors\r
   )\r
 {\r
   if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {\r
@@ -190,12 +193,12 @@ PeiGetProcessorInfo (
 EFI_STATUS\r
 EFIAPI\r
 PeiStartupAllAPs (\r
-  IN  CONST EFI_PEI_SERVICES    **PeiServices,\r
-  IN  EFI_PEI_MP_SERVICES_PPI   *This,\r
-  IN  EFI_AP_PROCEDURE          Procedure,\r
-  IN  BOOLEAN                   SingleThread,\r
-  IN  UINTN                     TimeoutInMicroSeconds,\r
-  IN  VOID                      *ProcedureArgument      OPTIONAL\r
+  IN  CONST EFI_PEI_SERVICES   **PeiServices,\r
+  IN  EFI_PEI_MP_SERVICES_PPI  *This,\r
+  IN  EFI_AP_PROCEDURE         Procedure,\r
+  IN  BOOLEAN                  SingleThread,\r
+  IN  UINTN                    TimeoutInMicroSeconds,\r
+  IN  VOID                     *ProcedureArgument      OPTIONAL\r
   )\r
 {\r
   return MpInitLibStartupAllAPs (\r
@@ -257,12 +260,12 @@ PeiStartupAllAPs (
 EFI_STATUS\r
 EFIAPI\r
 PeiStartupThisAP (\r
-  IN  CONST EFI_PEI_SERVICES    **PeiServices,\r
-  IN  EFI_PEI_MP_SERVICES_PPI   *This,\r
-  IN  EFI_AP_PROCEDURE          Procedure,\r
-  IN  UINTN                     ProcessorNumber,\r
-  IN  UINTN                     TimeoutInMicroseconds,\r
-  IN  VOID                      *ProcedureArgument      OPTIONAL\r
+  IN  CONST EFI_PEI_SERVICES   **PeiServices,\r
+  IN  EFI_PEI_MP_SERVICES_PPI  *This,\r
+  IN  EFI_AP_PROCEDURE         Procedure,\r
+  IN  UINTN                    ProcessorNumber,\r
+  IN  UINTN                    TimeoutInMicroseconds,\r
+  IN  VOID                     *ProcedureArgument      OPTIONAL\r
   )\r
 {\r
   return MpInitLibStartupThisAP (\r
@@ -302,7 +305,7 @@ PeiStartupThisAP (
   @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to this\r
                                   service returning.\r
   @retval EFI_UNSUPPORTED         Switching the BSP is not supported.\r
-  @retval EFI_SUCCESS             The calling processor is an AP.\r
+  @retval EFI_DEVICE_ERROR        The calling processor is an AP.\r
   @retval EFI_NOT_FOUND           The processor with the handle specified by\r
                                   ProcessorNumber does not exist.\r
   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or a disabled\r
@@ -363,11 +366,11 @@ PeiSwitchBSP (
 EFI_STATUS\r
 EFIAPI\r
 PeiEnableDisableAP (\r
-  IN  CONST EFI_PEI_SERVICES    **PeiServices,\r
-  IN  EFI_PEI_MP_SERVICES_PPI   *This,\r
-  IN  UINTN                     ProcessorNumber,\r
-  IN  BOOLEAN                   EnableAP,\r
-  IN  UINT32                    *HealthFlag OPTIONAL\r
+  IN  CONST EFI_PEI_SERVICES   **PeiServices,\r
+  IN  EFI_PEI_MP_SERVICES_PPI  *This,\r
+  IN  UINTN                    ProcessorNumber,\r
+  IN  BOOLEAN                  EnableAP,\r
+  IN  UINT32                   *HealthFlag OPTIONAL\r
   )\r
 {\r
   return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);\r
@@ -408,50 +411,179 @@ PeiWhoAmI (
   return MpInitLibWhoAmI (ProcessorNumber);\r
 }\r
 \r
+//\r
+// Structure for InitializeSeparateExceptionStacks\r
+//\r
+typedef struct {\r
+  VOID          *Buffer;\r
+  UINTN         BufferSize;\r
+  EFI_STATUS    Status;\r
+} EXCEPTION_STACK_SWITCH_CONTEXT;\r
+\r
 /**\r
-  The Entry point of the MP CPU PEIM.\r
+  Initializes CPU exceptions handlers for the sake of stack switch requirement.\r
 \r
-  This function will wakeup APs and collect CPU AP count and install the\r
-  Mp Service Ppi.\r
+  This function is a wrapper of InitializeSeparateExceptionStacks. It's mainly\r
+  for the sake of AP's init because of EFI_AP_PROCEDURE API requirement.\r
 \r
-  @param  FileHandle    Handle of the file being invoked.\r
-  @param  PeiServices   Describes the list of possible PEI Services.\r
+  @param[in,out] Buffer  The pointer to private data buffer.\r
 \r
-  @retval EFI_SUCCESS   MpServicePpi is installed successfully.\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeExceptionStackSwitchHandlers (\r
+  IN OUT VOID  *Buffer\r
+  )\r
+{\r
+  EXCEPTION_STACK_SWITCH_CONTEXT  *SwitchStackData;\r
+  UINTN                           Index;\r
+\r
+  MpInitLibWhoAmI (&Index);\r
+  SwitchStackData = (EXCEPTION_STACK_SWITCH_CONTEXT *)Buffer;\r
+\r
+  //\r
+  // This function may be called twice for each Cpu. Only run InitializeSeparateExceptionStacks\r
+  // if this is the first call or the first call failed because of size too small.\r
+  //\r
+  if ((SwitchStackData[Index].Status == EFI_NOT_STARTED) || (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL)) {\r
+    SwitchStackData[Index].Status = InitializeSeparateExceptionStacks (SwitchStackData[Index].Buffer, &SwitchStackData[Index].BufferSize);\r
+  }\r
+}\r
+\r
+/**\r
+  Initializes MP exceptions handlers for the sake of stack switch requirement.\r
+\r
+  This function will allocate required resources required to setup stack switch\r
+  and pass them through SwitchStackData to each logic processor.\r
+\r
+**/\r
+VOID\r
+InitializeMpExceptionStackSwitchHandlers (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                           Index;\r
+  UINTN                           NumberOfProcessors;\r
+  EXCEPTION_STACK_SWITCH_CONTEXT  *SwitchStackData;\r
+  UINTN                           BufferSize;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           *Buffer;\r
+\r
+  if (!PcdGetBool (PcdCpuStackGuard)) {\r
+    return;\r
+  }\r
+\r
+  MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL);\r
+  SwitchStackData = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT)));\r
+  ASSERT (SwitchStackData != NULL);\r
+  ZeroMem (SwitchStackData, NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT));\r
+  for (Index = 0; Index < NumberOfProcessors; ++Index) {\r
+    //\r
+    // Because the procedure may runs multiple times, use the status EFI_NOT_STARTED\r
+    // to indicate the procedure haven't been run yet.\r
+    //\r
+    SwitchStackData[Index].Status = EFI_NOT_STARTED;\r
+  }\r
+\r
+  Status = MpInitLibStartupAllCPUs (\r
+             InitializeExceptionStackSwitchHandlers,\r
+             0,\r
+             SwitchStackData\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  BufferSize = 0;\r
+  for (Index = 0; Index < NumberOfProcessors; ++Index) {\r
+    if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {\r
+      ASSERT (SwitchStackData[Index].BufferSize != 0);\r
+      BufferSize += SwitchStackData[Index].BufferSize;\r
+    } else {\r
+      ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);\r
+      ASSERT (SwitchStackData[Index].BufferSize == 0);\r
+    }\r
+  }\r
+\r
+  if (BufferSize != 0) {\r
+    Buffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));\r
+    ASSERT (Buffer != NULL);\r
+    BufferSize = 0;\r
+    for (Index = 0; Index < NumberOfProcessors; ++Index) {\r
+      if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {\r
+        SwitchStackData[Index].Buffer = (VOID *)(&Buffer[BufferSize]);\r
+        BufferSize                   += SwitchStackData[Index].BufferSize;\r
+        DEBUG ((\r
+          DEBUG_INFO,\r
+          "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlers: 0x%lX with size 0x%lX\n",\r
+          (UINT64)(UINTN)Index,\r
+          (UINT64)(UINTN)SwitchStackData[Index].Buffer,\r
+          (UINT64)(UINTN)SwitchStackData[Index].BufferSize\r
+          ));\r
+      }\r
+    }\r
+\r
+    Status = MpInitLibStartupAllCPUs (\r
+               InitializeExceptionStackSwitchHandlers,\r
+               0,\r
+               SwitchStackData\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+    for (Index = 0; Index < NumberOfProcessors; ++Index) {\r
+      ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);\r
+    }\r
+  }\r
+\r
+  FreePages (SwitchStackData, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT)));\r
+}\r
+\r
+/**\r
+  Initializes MP and exceptions handlers.\r
+\r
+  @param  PeiServices                The pointer to the PEI Services Table.\r
+\r
+  @retval EFI_SUCCESS     MP was successfully initialized.\r
+  @retval others          Error occurred in MP initialization.\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-CpuMpPeimInit (\r
-  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
-  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+InitializeCpuMpWorker (\r
+  IN CONST EFI_PEI_SERVICES  **PeiServices\r
   )\r
 {\r
-  EFI_STATUS           Status;\r
-  EFI_VECTOR_HANDOFF_INFO         *VectorInfo;\r
-  EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;\r
+  EFI_STATUS                       Status;\r
+  EFI_VECTOR_HANDOFF_INFO          *VectorInfo;\r
+  EFI_PEI_VECTOR_HANDOFF_INFO_PPI  *VectorHandoffInfoPpi;\r
 \r
   //\r
   // Get Vector Hand-off Info PPI\r
   //\r
   VectorInfo = NULL;\r
-  Status = PeiServicesLocatePpi (\r
-             &gEfiVectorHandoffInfoPpiGuid,\r
-             0,\r
-             NULL,\r
-             (VOID **)&VectorHandoffInfoPpi\r
-             );\r
+  Status     = PeiServicesLocatePpi (\r
+                 &gEfiVectorHandoffInfoPpiGuid,\r
+                 0,\r
+                 NULL,\r
+                 (VOID **)&VectorHandoffInfoPpi\r
+                 );\r
   if (Status == EFI_SUCCESS) {\r
     VectorInfo = VectorHandoffInfoPpi->Info;\r
   }\r
-  Status = InitializeCpuExceptionHandlers (VectorInfo);\r
-  ASSERT_EFI_ERROR (Status);\r
-  \r
+\r
   //\r
-  // Wakeup APs to do initialization\r
+  // Initialize default handlers\r
   //\r
+  Status = InitializeCpuExceptionHandlers (VectorInfo);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Status = MpInitLibInitialize ();\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Special initialization for the sake of Stack Guard\r
+  //\r
+  InitializeMpExceptionStackSwitchHandlers ();\r
 \r
   //\r
   // Update and publish CPU BIST information\r
@@ -461,7 +593,38 @@ CpuMpPeimInit (
   //\r
   // Install CPU MP PPI\r
   //\r
-  Status = PeiServicesInstallPpi(&mPeiCpuMpPpiDesc);\r
+  Status = PeiServicesInstallPpi (mPeiCpuMpPpiList);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The Entry point of the MP CPU PEIM.\r
+\r
+  This function will wakeup APs and collect CPU AP count and install the\r
+  Mp Service Ppi.\r
+\r
+  @param  FileHandle    Handle of the file being invoked.\r
+  @param  PeiServices   Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_SUCCESS   MpServicePpi is installed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuMpPeimInit (\r
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // For the sake of special initialization needing to be done right after\r
+  // memory discovery.\r
+  //\r
+  Status = PeiServicesNotifyPpi (&mPostMemNotifyList[0]);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   return Status;\r