]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
UefiCpuPkg/MpInitLib: Avoid calling PEI services from AP
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / PeiMpLib.c
index fb1d48fad848f6d3d36fef81e97e93cc55c1a01a..92f28681e45a72a254a52e25dda0c86d225de22a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   MP initialize support functions for PEI phase.\r
 \r
-  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2018, 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
 **/\r
 \r
 #include "MpLib.h"\r
-#include <Ppi/EndOfPeiPhase.h>\r
-#include <Library/PeiServicesLib.h>\r
-\r
-//\r
-// Global PEI notify function descriptor on EndofPei event\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mMpInitLibNotifyList = {\r
-  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-  &gEfiEndOfPeiSignalPpiGuid,\r
-  CpuMpEndOfPeiCallback\r
-};\r
-\r
 \r
 /**\r
   Enable Debug Agent to support source debugging on AP function.\r
@@ -39,6 +27,8 @@ EnableDebugAgent (
 \r
 /**\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
 \r
   @return  The pointer to CPU MP Data structure.\r
 **/\r
@@ -47,10 +37,18 @@ GetCpuMpData (
   VOID\r
   )\r
 {\r
-  CPU_MP_DATA      *CpuMpData;\r
-\r
-  CpuMpData = GetCpuMpDataFromGuidedHob ();\r
-  ASSERT (CpuMpData != NULL);\r
+  CPU_MP_DATA                  *CpuMpData;\r
+  MSR_IA32_APIC_BASE_REGISTER  ApicBaseMsr;\r
+  IA32_DESCRIPTOR              Idtr;\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
+  }\r
   return CpuMpData;\r
 }\r
 \r
@@ -76,66 +74,6 @@ SaveCpuMpData (
     );\r
 }\r
 \r
-/**\r
-  Notify function on End Of PEI PPI.\r
-\r
-  On S3 boot, this function will restore wakeup buffer data.\r
-  On normal boot, this function will flag wakeup buffer to be un-used type.\r
-\r
-  @param[in]  PeiServices        The pointer to the PEI Services Table.\r
-  @param[in]  NotifyDescriptor   Address of the notification descriptor data structure.\r
-  @param[in]  Ppi                Address of the PPI that was installed.\r
-\r
-  @retval EFI_SUCCESS        When everything is OK.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CpuMpEndOfPeiCallback (\r
-  IN EFI_PEI_SERVICES             **PeiServices,\r
-  IN EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDescriptor,\r
-  IN VOID                         *Ppi\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  EFI_BOOT_MODE             BootMode;\r
-  CPU_MP_DATA               *CpuMpData;\r
-  EFI_PEI_HOB_POINTERS      Hob;\r
-  EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
-\r
-  DEBUG ((DEBUG_INFO, "PeiMpInitLib: CpuMpEndOfPeiCallback () invoked\n"));\r
-\r
-  Status = PeiServicesGetBootMode (&BootMode);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  CpuMpData = GetCpuMpData ();\r
-  if (BootMode != BOOT_ON_S3_RESUME) {\r
-    //\r
-    // Get the HOB list for processing\r
-    //\r
-    Hob.Raw = GetHobList ();\r
-    //\r
-    // Collect memory ranges\r
-    //\r
-    while (!END_OF_HOB_LIST (Hob)) {\r
-      if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
-        MemoryHob = Hob.MemoryAllocation;\r
-        if (MemoryHob->AllocDescriptor.MemoryBaseAddress == CpuMpData->WakeupBuffer) {\r
-          //\r
-          // Flag this HOB type to un-used\r
-          //\r
-          GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED;\r
-          break;\r
-        }\r
-      }\r
-      Hob.Raw = GET_NEXT_HOB (Hob);\r
-    }\r
-  } else {\r
-    CpuMpData->SaveRestoreFlag = TRUE;\r
-    RestoreWakeupBuffer (CpuMpData);\r
-  }\r
-  return EFI_SUCCESS;\r
-}\r
-\r
 /**\r
   Check if AP wakeup buffer is overlapped with existing allocated buffer.\r
 \r
@@ -147,15 +85,15 @@ CpuMpEndOfPeiCallback (
 **/\r
 BOOLEAN\r
 CheckOverlapWithAllocatedBuffer (\r
-  IN UINT               WakeupBufferStart,\r
-  IN UINT               WakeupBufferEnd\r
+  IN UINT64               WakeupBufferStart,\r
+  IN UINT64               WakeupBufferEnd\r
   )\r
 {\r
   EFI_PEI_HOB_POINTERS      Hob;\r
   EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
   BOOLEAN                   Overlapped;\r
-  UINT                    MemoryStart;\r
-  UINT                    MemoryEnd;\r
+  UINT64                    MemoryStart;\r
+  UINT64                    MemoryEnd;\r
 \r
   Overlapped = FALSE;\r
   //\r
@@ -168,9 +106,8 @@ CheckOverlapWithAllocatedBuffer (
   while (!END_OF_HOB_LIST (Hob)) {\r
     if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
       MemoryHob   = Hob.MemoryAllocation;\r
-      MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
-      MemoryEnd   = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress +\r
-                             MemoryHob->AllocDescriptor.MemoryLength);\r
+      MemoryStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
+      MemoryEnd   = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;\r
       if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {\r
         Overlapped = TRUE;\r
         break;\r
@@ -195,8 +132,8 @@ GetWakeupBuffer (
   )\r
 {\r
   EFI_PEI_HOB_POINTERS    Hob;\r
-  UINT                  WakeupBufferStart;\r
-  UINT                  WakeupBufferEnd;\r
+  UINT64                  WakeupBufferStart;\r
+  UINT64                  WakeupBufferEnd;\r
 \r
   WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
 \r
@@ -221,7 +158,7 @@ GetWakeupBuffer (
         //\r
         // Need memory under 1MB to be collected here\r
         //\r
-        WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);\r
+        WakeupBufferEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;\r
         if (WakeupBufferEnd > BASE_1MB) {\r
           //\r
           // Wakeup buffer should be under 1MB\r
@@ -246,15 +183,7 @@ GetWakeupBuffer (
           }\r
           DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
                                WakeupBufferStart, WakeupBufferSize));\r
-          //\r
-          // Create a memory allocation HOB.\r
-          //\r
-          BuildMemoryAllocationHob (\r
-            WakeupBufferStart,\r
-            WakeupBufferSize,\r
-            EfiBootServicesData\r
-            );\r
-          return WakeupBufferStart;\r
+          return (UINTN)WakeupBufferStart;\r
         }\r
       }\r
     }\r
@@ -268,45 +197,26 @@ GetWakeupBuffer (
 }\r
 \r
 /**\r
-  Allocate reset vector buffer.\r
+  Get available EfiBootServicesCode memory below 4GB by specified size.\r
 \r
-  @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.\r
-**/\r
-VOID\r
-AllocateResetVector (\r
-  IN OUT CPU_MP_DATA          *CpuMpData\r
-  )\r
-{\r
-  UINTN           ApResetVectorSize;\r
-\r
-  if (CpuMpData->WakeupBuffer == (UINTN) -1) {\r
-    ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +\r
-                          sizeof (MP_CPU_EXCHANGE_INFO);\r
+  This buffer is required to safely transfer AP from real address mode to\r
+  protected mode or long mode, due to the fact that the buffer returned by\r
+  GetWakeupBuffer() may be marked as non-executable.\r
 \r
-    CpuMpData->WakeupBuffer      = GetWakeupBuffer (ApResetVectorSize);\r
-    CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)\r
-                    (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);\r
-    BackupAndPrepareWakeupBuffer (CpuMpData);\r
-  }\r
+  @param[in] BufferSize   Wakeup transition buffer size.\r
 \r
-  if (CpuMpData->SaveRestoreFlag) {\r
-    BackupAndPrepareWakeupBuffer (CpuMpData);\r
-  }\r
-}\r
-\r
-/**\r
-  Free AP reset vector buffer.\r
-\r
-  @param[in]  CpuMpData  The pointer to CPU MP Data structure.\r
+  @retval other   Return wakeup transition buffer address below 4GB.\r
+  @retval 0       Cannot find free memory below 4GB.\r
 **/\r
-VOID\r
-FreeResetVector (\r
-  IN CPU_MP_DATA              *CpuMpData\r
+UINTN\r
+GetModeTransitionBuffer (\r
+  IN UINTN                BufferSize\r
   )\r
 {\r
-  if (CpuMpData->SaveRestoreFlag) {\r
-    RestoreWakeupBuffer (CpuMpData);\r
-  }\r
+  //\r
+  // PEI phase doesn't need to do such transition. So simply return 0.\r
+  //\r
+  return 0;\r
 }\r
 \r
 /**\r
@@ -330,22 +240,7 @@ InitMpGlobalData (
   IN CPU_MP_DATA               *CpuMpData\r
   )\r
 {\r
-  EFI_STATUS      Status;\r
-\r
   SaveCpuMpData (CpuMpData);\r
-\r
-  if (CpuMpData->CpuCount == 1) {\r
-    //\r
-    // If only BSP exists, return\r
-    //\r
-    return;\r
-  }\r
-\r
-  //\r
-  // Register an event for EndOfPei\r
-  //\r
-  Status  = PeiServicesNotifyPpi (&mMpInitLibNotifyList);\r
-  ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r