]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
UefiCpuPkg MpInitLib: Save/restore original WakeupBuffer for DxeMpLib
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / PeiMpLib.c
index 6211e71795a6f3343bb1057efa8379d293385baa..70c2bc7323f6d05d418a8b823cab21f1c3e49de5 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 - 2017, 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
 #include "MpLib.h"\r
 \r
+/**\r
+  Enable Debug Agent to support source debugging on AP function.\r
+\r
+**/\r
+VOID\r
+EnableDebugAgent (\r
+  VOID\r
+  )\r
+{\r
+}\r
+\r
 /**\r
   Get pointer to CPU MP Data structure.\r
 \r
@@ -53,6 +64,139 @@ SaveCpuMpData (
     );\r
 }\r
 \r
+/**\r
+  Check if AP wakeup buffer is overlapped with existing allocated buffer.\r
+\r
+  @param[in]  WakeupBufferStart     AP wakeup buffer start address.\r
+  @param[in]  WakeupBufferEnd       AP wakeup buffer end address.\r
+\r
+  @retval  TRUE       There is overlap.\r
+  @retval  FALSE      There is no overlap.\r
+**/\r
+BOOLEAN\r
+CheckOverlapWithAllocatedBuffer (\r
+  IN UINTN                WakeupBufferStart,\r
+  IN UINTN                WakeupBufferEnd\r
+  )\r
+{\r
+  EFI_PEI_HOB_POINTERS      Hob;\r
+  EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
+  BOOLEAN                   Overlapped;\r
+  UINTN                     MemoryStart;\r
+  UINTN                     MemoryEnd;\r
+\r
+  Overlapped = FALSE;\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
+      MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
+      MemoryEnd   = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress +\r
+                             MemoryHob->AllocDescriptor.MemoryLength);\r
+      if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {\r
+        Overlapped = TRUE;\r
+        break;\r
+      }\r
+    }\r
+    Hob.Raw = GET_NEXT_HOB (Hob);\r
+  }\r
+  return Overlapped;\r
+}\r
+\r
+/**\r
+  Get available system memory below 1MB by specified size.\r
+\r
+  @param[in] WakeupBufferSize   Wakeup buffer size required\r
+\r
+  @retval other   Return wakeup buffer address below 1MB.\r
+  @retval -1      Cannot find free memory below 1MB.\r
+**/\r
+UINTN\r
+GetWakeupBuffer (\r
+  IN UINTN                WakeupBufferSize\r
+  )\r
+{\r
+  EFI_PEI_HOB_POINTERS    Hob;\r
+  UINTN                   WakeupBufferStart;\r
+  UINTN                   WakeupBufferEnd;\r
+\r
+  WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
+\r
+  //\r
+  // Get the HOB list for processing\r
+  //\r
+  Hob.Raw = GetHobList ();\r
+\r
+  //\r
+  // Collect memory ranges\r
+  //\r
+  while (!END_OF_HOB_LIST (Hob)) {\r
+    if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+      if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&\r
+          (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
+          ((Hob.ResourceDescriptor->ResourceAttribute &\r
+            (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
+             EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
+             EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
+             )) == 0)\r
+           ) {\r
+        //\r
+        // Need memory under 1MB to be collected here\r
+        //\r
+        WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);\r
+        if (WakeupBufferEnd > BASE_1MB) {\r
+          //\r
+          // Wakeup buffer should be under 1MB\r
+          //\r
+          WakeupBufferEnd = BASE_1MB;\r
+        }\r
+        while (WakeupBufferEnd > WakeupBufferSize) {\r
+          //\r
+          // Wakeup buffer should be aligned on 4KB\r
+          //\r
+          WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);\r
+          if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
+            break;\r
+          }\r
+          if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {\r
+            //\r
+            // If this range is overlapped with existing allocated buffer, skip it\r
+            // and find the next range\r
+            //\r
+            WakeupBufferEnd -= WakeupBufferSize;\r
+            continue;\r
+          }\r
+          DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
+                               WakeupBufferStart, WakeupBufferSize));\r
+          return WakeupBufferStart;\r
+        }\r
+      }\r
+    }\r
+    //\r
+    // Find the next HOB\r
+    //\r
+    Hob.Raw = GET_NEXT_HOB (Hob);\r
+  }\r
+\r
+  return (UINTN) -1;\r
+}\r
+\r
+/**\r
+  Checks APs status and updates APs status if needed.\r
+\r
+**/\r
+VOID\r
+CheckAndUpdateApsStatus (\r
+  VOID\r
+  )\r
+{\r
+}\r
 \r
 /**\r
   Initialize global data for MP support.\r
@@ -64,7 +208,6 @@ InitMpGlobalData (
   IN CPU_MP_DATA               *CpuMpData\r
   )\r
 {\r
-\r
   SaveCpuMpData (CpuMpData);\r
 }\r
 \r
@@ -95,7 +238,7 @@ InitMpGlobalData (
                                       EFI_EVENT is defined in CreateEvent() in\r
                                       the Unified Extensible Firmware Interface\r
                                       Specification.\r
-  @param[in]  TimeoutInMicrosecsond   Indicates the time limit in microseconds for\r
+  @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for\r
                                       APs to return from Procedure, either for\r
                                       blocking or non-blocking mode. Zero means\r
                                       infinity.  If the timeout expires before\r
@@ -154,7 +297,18 @@ MpInitLibStartupAllAPs (
   OUT UINTN                     **FailedCpuList         OPTIONAL\r
   )\r
 {\r
-  return EFI_UNSUPPORTED;\r
+  if (WaitEvent != NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return StartupAllAPsWorker (\r
+           Procedure,\r
+           SingleThread,\r
+           NULL,\r
+           TimeoutInMicroseconds,\r
+           ProcedureArgument,\r
+           FailedCpuList\r
+           );\r
 }\r
 \r
 /**\r
@@ -184,7 +338,7 @@ MpInitLibStartupAllAPs (
                                       EFI_EVENT is defined in CreateEvent() in\r
                                       the Unified Extensible Firmware Interface\r
                                       Specification.\r
-  @param[in]  TimeoutInMicrosecsond   Indicates the time limit in microseconds for\r
+  @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for\r
                                       this AP to finish this Procedure, either for\r
                                       blocking or non-blocking mode. Zero means\r
                                       infinity.  If the timeout expires before\r
@@ -239,7 +393,18 @@ MpInitLibStartupThisAP (
   OUT BOOLEAN                   *Finished               OPTIONAL\r
   )\r
 {\r
-  return EFI_UNSUPPORTED;\r
+  if (WaitEvent != NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return StartupThisAPWorker (\r
+           Procedure,\r
+           ProcessorNumber,\r
+           NULL,\r
+           TimeoutInMicroseconds,\r
+           ProcedureArgument,\r
+           Finished\r
+           );\r
 }\r
 \r
 /**\r
@@ -275,7 +440,7 @@ MpInitLibSwitchBSP (
   IN  BOOLEAN                  EnableOldBSP\r
   )\r
 {\r
-  return EFI_UNSUPPORTED;\r
+  return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);\r
 }\r
 \r
 /**\r
@@ -316,7 +481,7 @@ MpInitLibEnableDisableAP (
   IN  UINT32                    *HealthFlag OPTIONAL\r
   )\r
 {\r
-  return EFI_UNSUPPORTED;\r
+  return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);\r
 }\r
 \r
 \r