diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index a21a980b58..e5842ef505 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -109,6 +109,53 @@ SetApState ( ReleaseSpinLock (&CpuData->ApLock); } +/** + Save BSP's local APIC timer setting + + @param[in] CpuMpData Pointer to CPU MP Data +**/ +VOID +SaveLocalApicTimerSetting ( + IN CPU_MP_DATA *CpuMpData + ) +{ + // + // Record the current local APIC timer setting of BSP + // + GetApicTimerState ( + &CpuMpData->DivideValue, + &CpuMpData->PeriodicMode, + &CpuMpData->Vector + ); + CpuMpData->CurrentTimerCount = GetApicTimerCurrentCount (); + CpuMpData->TimerInterruptState = GetApicTimerInterruptState (); +} + +/** + Sync local APIC timer setting from BSP to AP. + + @param[in] CpuMpData Pointer to CPU MP Data +**/ +VOID +SyncLocalApicTimerSetting ( + IN CPU_MP_DATA *CpuMpData + ) +{ + // + // Sync local APIC timer setting from BSP to AP + // + InitializeApicTimer ( + CpuMpData->DivideValue, + CpuMpData->CurrentTimerCount, + CpuMpData->PeriodicMode, + CpuMpData->Vector + ); + // + // Disable AP's local APIC timer interrupt + // + DisableApicTimerInterrupt (); +} + /** Save the volatile registers required to be restored following INIT IPI. @@ -488,7 +535,12 @@ ApWakeupFunction ( // CpuMpData = ExchangeInfo->CpuMpData; - ProgramVirtualWireMode (); + // + // AP's local APIC settings will be lost after received INIT IPI + // We need to re-initialize them at here + // + ProgramVirtualWireMode (); + SyncLocalApicTimerSetting (CpuMpData); while (TRUE) { if (CpuMpData->InitFlag == ApInitConfig) { @@ -736,6 +788,7 @@ WakeUpAP ( ResetVectorRequired = TRUE; AllocateResetVector (CpuMpData); FillExchangeInfoData (CpuMpData); + SaveLocalApicTimerSetting (CpuMpData); } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) { // // Get AP target C-state each time when waking up AP, diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index b67ea9d11f..7a272d78ec 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -227,6 +227,12 @@ struct _CPU_MP_DATA { UINT16 PmCodeSegment; CPU_AP_DATA *CpuData; volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo; + + UINT32 CurrentTimerCount; + UINTN DivideValue; + UINT8 Vector; + BOOLEAN PeriodicMode; + BOOLEAN TimerInterruptState; }; extern EFI_GUID mCpuInitMpLibHobGuid;