]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: Sync BSP's local APIC timer settings to APs
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
index a21a980b58b1f48f5642608237c32fceb1f936c5..e5842ef505dc7864cc08c81f04f44b571de48d86 100644 (file)
@@ -109,6 +109,53 @@ SetApState (
   ReleaseSpinLock (&CpuData->ApLock);\r
 }\r
 \r
+/**\r
+  Save BSP's local APIC timer setting\r
+\r
+  @param[in] CpuMpData          Pointer to CPU MP Data\r
+**/\r
+VOID\r
+SaveLocalApicTimerSetting (\r
+  IN CPU_MP_DATA   *CpuMpData\r
+  )\r
+{\r
+  //\r
+  // Record the current local APIC timer setting of BSP\r
+  //\r
+  GetApicTimerState (\r
+    &CpuMpData->DivideValue,\r
+    &CpuMpData->PeriodicMode,\r
+    &CpuMpData->Vector\r
+    );\r
+  CpuMpData->CurrentTimerCount   = GetApicTimerCurrentCount ();\r
+  CpuMpData->TimerInterruptState = GetApicTimerInterruptState ();\r
+}\r
+\r
+/**\r
+  Sync local APIC timer setting from BSP to AP.\r
+\r
+  @param[in] CpuMpData          Pointer to CPU MP Data\r
+**/\r
+VOID\r
+SyncLocalApicTimerSetting (\r
+  IN CPU_MP_DATA   *CpuMpData\r
+  )\r
+{\r
+  //\r
+  // Sync local APIC timer setting from BSP to AP\r
+  //\r
+  InitializeApicTimer (\r
+    CpuMpData->DivideValue,\r
+    CpuMpData->CurrentTimerCount,\r
+    CpuMpData->PeriodicMode,\r
+    CpuMpData->Vector\r
+    );\r
+  //\r
+  // Disable AP's local APIC timer interrupt\r
+  //\r
+  DisableApicTimerInterrupt ();\r
+}\r
+\r
 /**\r
   Save the volatile registers required to be restored following INIT IPI.\r
 \r
@@ -488,7 +535,12 @@ ApWakeupFunction (
   //\r
   CpuMpData = ExchangeInfo->CpuMpData;\r
 \r
-  ProgramVirtualWireMode (); \r
+  //\r
+  // AP's local APIC settings will be lost after received INIT IPI\r
+  // We need to re-initialize them at here\r
+  //\r
+  ProgramVirtualWireMode ();\r
+  SyncLocalApicTimerSetting (CpuMpData);\r
 \r
   while (TRUE) {\r
     if (CpuMpData->InitFlag == ApInitConfig) {\r
@@ -736,6 +788,7 @@ WakeUpAP (
     ResetVectorRequired = TRUE;\r
     AllocateResetVector (CpuMpData);\r
     FillExchangeInfoData (CpuMpData);\r
+    SaveLocalApicTimerSetting (CpuMpData);\r
   } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) {\r
     //\r
     // Get AP target C-state each time when waking up AP,\r