]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/DxeMpInitLib: Support source debugging on AP function
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
index 3c2e6d6b89d98ecc09901a48c4757db3646acd46..a21a980b58b1f48f5642608237c32fceb1f936c5 100644 (file)
@@ -337,8 +337,8 @@ ApInitializeSync (
 /**\r
   Find the current Processor number by APIC ID.\r
 \r
-  @param[in] CpuMpData         Pointer to PEI CPU MP Data\r
-  @param[in] ProcessorNumber   Return the pocessor number found\r
+  @param[in]  CpuMpData         Pointer to PEI CPU MP Data\r
+  @param[out] ProcessorNumber   Return the pocessor number found\r
 \r
   @retval EFI_SUCCESS          ProcessorNumber is found and returned.\r
   @retval EFI_NOT_FOUND        ProcessorNumber is not found.\r
@@ -420,12 +420,13 @@ CollectProcessorCount (
   return CpuMpData->CpuCount;\r
 }\r
 \r
-/*\r
+/**\r
   Initialize CPU AP Data when AP is wakeup at the first time.\r
 \r
   @param[in, out] CpuMpData        Pointer to PEI CPU MP Data\r
   @param[in]      ProcessorNumber  The handle number of processor\r
   @param[in]      BistData         Processor BIST data\r
+  @param[in]      ApTopOfStack     Top of AP stack\r
 \r
 **/\r
 VOID\r
@@ -433,7 +434,7 @@ InitializeApData (
   IN OUT CPU_MP_DATA      *CpuMpData,\r
   IN     UINTN            ProcessorNumber,\r
   IN     UINT32           BistData,\r
-  IN     UINT           ApTopOfStack\r
+  IN     UINT64           ApTopOfStack\r
   )\r
 {\r
   CPU_INFO_IN_HOB          *CpuInfoInHob;\r
@@ -442,7 +443,7 @@ InitializeApData (
   CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
   CpuInfoInHob[ProcessorNumber].ApicId        = GetApicId ();\r
   CpuInfoInHob[ProcessorNumber].Health        = BistData;\r
-  CpuInfoInHob[ProcessorNumber].ApTopOfStack  = (UINT32) ApTopOfStack;\r
+  CpuInfoInHob[ProcessorNumber].ApTopOfStack  = ApTopOfStack;\r
 \r
   CpuMpData->CpuData[ProcessorNumber].Waiting    = FALSE;\r
   CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;\r
@@ -480,7 +481,7 @@ ApWakeupFunction (
   UINT32                     BistData;\r
   volatile UINT32            *ApStartupSignalBuffer;\r
   CPU_INFO_IN_HOB            *CpuInfoInHob;\r
-  UINT                     ApTopOfStack;\r
+  UINT64                     ApTopOfStack;\r
 \r
   //\r
   // AP finished assembly code and begin to execute C code\r
@@ -500,7 +501,7 @@ 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 *) (ApTopOfStack - sizeof (UINTN));\r
+      BistData = *(UINT32 *) ((UINTN) ApTopOfStack - sizeof (UINTN));\r
       //\r
       // Do some AP initialize sync\r
       //\r
@@ -538,6 +539,10 @@ ApWakeupFunction (
         if (Procedure != NULL) {\r
           SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);\r
           //\r
+          // Enable source debugging on AP function\r
+          //         \r
+          EnableDebugAgent ();\r
+          //\r
           // Invoke AP function here\r
           //\r
           Procedure (Parameter);\r
@@ -683,6 +688,21 @@ FillExchangeInfoData (
   AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);\r
 }\r
 \r
+/**\r
+  Helper function that waits until the finished AP count reaches the specified\r
+  limit, or the specified timeout elapses (whichever comes first).\r
+\r
+  @param[in] CpuMpData        Pointer to CPU MP Data.\r
+  @param[in] FinishedApLimit  The number of finished APs to wait for.\r
+  @param[in] TimeLimit        The number of microseconds to wait for.\r
+**/\r
+VOID\r
+TimedWaitForApFinish (\r
+  IN CPU_MP_DATA               *CpuMpData,\r
+  IN UINT32                    FinishedApLimit,\r
+  IN UINT32                    TimeLimit\r
+  );\r
+\r
 /**\r
   This function will be called by BSP to wakeup AP.\r
 \r
@@ -748,7 +768,11 @@ WakeUpAP (
       //\r
       // Wait for all potential APs waken up in one specified period\r
       //\r
-      MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds));\r
+      TimedWaitForApFinish (\r
+        CpuMpData,\r
+        PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1,\r
+        PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)\r
+        );\r
     } else {\r
       //\r
       // Wait all APs waken up if this is not the 1st broadcast of SIPI\r
@@ -894,6 +918,58 @@ CheckTimeout (
   return FALSE;\r
 }\r
 \r
+/**\r
+  Helper function that waits until the finished AP count reaches the specified\r
+  limit, or the specified timeout elapses (whichever comes first).\r
+\r
+  @param[in] CpuMpData        Pointer to CPU MP Data.\r
+  @param[in] FinishedApLimit  The number of finished APs to wait for.\r
+  @param[in] TimeLimit        The number of microseconds to wait for.\r
+**/\r
+VOID\r
+TimedWaitForApFinish (\r
+  IN CPU_MP_DATA               *CpuMpData,\r
+  IN UINT32                    FinishedApLimit,\r
+  IN UINT32                    TimeLimit\r
+  )\r
+{\r
+  //\r
+  // CalculateTimeout() and CheckTimeout() consider a TimeLimit of 0\r
+  // "infinity", so check for (TimeLimit == 0) explicitly.\r
+  //\r
+  if (TimeLimit == 0) {\r
+    return;\r
+  }\r
+\r
+  CpuMpData->TotalTime = 0;\r
+  CpuMpData->ExpectedTime = CalculateTimeout (\r
+                              TimeLimit,\r
+                              &CpuMpData->CurrentTime\r
+                              );\r
+  while (CpuMpData->FinishedCount < FinishedApLimit &&\r
+         !CheckTimeout (\r
+            &CpuMpData->CurrentTime,\r
+            &CpuMpData->TotalTime,\r
+            CpuMpData->ExpectedTime\r
+            )) {\r
+    CpuPause ();\r
+  }\r
+\r
+  if (CpuMpData->FinishedCount >= FinishedApLimit) {\r
+    DEBUG ((\r
+      DEBUG_VERBOSE,\r
+      "%a: reached FinishedApLimit=%u in %Lu microseconds\n",\r
+      __FUNCTION__,\r
+      FinishedApLimit,\r
+      DivU64x64Remainder (\r
+        MultU64x32 (CpuMpData->TotalTime, 1000000),\r
+        GetPerformanceCounterProperties (NULL, NULL),\r
+        NULL\r
+        )\r
+      ));\r
+  }\r
+}\r
+\r
 /**\r
   Reset an AP to Idle state.\r
 \r
@@ -1635,7 +1711,7 @@ MpInitLibGetNumberOfProcessors (
                                       simultaneously.\r
   @param[in]  WaitEvent               The event created by the caller with CreateEvent()\r
                                       service.\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.\r
   @param[in]  ProcedureArgument       The parameter passed into Procedure for\r
@@ -1789,7 +1865,7 @@ StartupAllAPsWorker (
   @param[in]  ProcessorNumber         The handle number of the AP.\r
   @param[in]  WaitEvent               The event created by the caller with CreateEvent()\r
                                       service.\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.\r
   @param[in]  ProcedureArgument       The parameter passed into Procedure for\r