UefiCpuPkg/MpInitLib: Sync BSP's local APIC timer settings to APs

If APs are waken up by INIT-SIPI-SIPI command, they will lose original local
APIC timer setting. As a result, the timer library instance based on local APIC
timer cannot work on APs function.

This fix is to save BSP's local APIC timer settings before waking up APs and
to sync to APs when APs wakeup by INIT-SIPI-SIPI command.

Setting BSP's current counter to AP's initial counter could make sure BSP and
APs have same counter value across BSP switching.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Kinney Michael D <michael.d.kinney@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
This commit is contained in:
Jeff Fan 2016-12-26 16:44:24 +08:00
parent 43c9fdcccd
commit ffab244280
2 changed files with 60 additions and 1 deletions

View File

@ -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,

View File

@ -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;