IN CPU_MP_DATA *CpuMpData\r
)\r
{\r
+ UINTN Index;\r
+\r
//\r
// Send 1st broadcast IPI to APs to wakeup APs\r
//\r
CpuPause ();\r
}\r
\r
+ if (CpuMpData->CpuCount > 255) {\r
+ //\r
+ // If there are more than 255 processor found, force to enable X2APIC\r
+ //\r
+ CpuMpData->X2ApicEnable = TRUE;\r
+ }\r
if (CpuMpData->X2ApicEnable) {\r
DEBUG ((DEBUG_INFO, "Force x2APIC mode!\n"));\r
//\r
// Enable x2APIC on BSP\r
//\r
SetApicMode (LOCAL_APIC_MODE_X2APIC);\r
+ //\r
+ // Set BSP/Aps state to IDLE\r
+ //\r
+ for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
+ SetApState (&CpuMpData->CpuData[Index], CpuStateIdle);\r
+ }\r
}\r
DEBUG ((DEBUG_INFO, "APIC MODE is %d\n", GetApicMode ()));\r
//\r
volatile UINT32 *ApStartupSignalBuffer;\r
CPU_INFO_IN_HOB *CpuInfoInHob;\r
UINT64 ApTopOfStack;\r
+ UINTN CurrentApicMode;\r
\r
//\r
// AP finished assembly code and begin to execute C code\r
ProgramVirtualWireMode ();\r
SyncLocalApicTimerSetting (CpuMpData);\r
\r
+ CurrentApicMode = GetApicMode ();\r
while (TRUE) {\r
if (CpuMpData->InitFlag == ApInitConfig) {\r
//\r
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
CpuInfoInHob[ProcessorNumber].ApTopOfStack = CpuInfoInHob[CpuMpData->NewBspNumber].ApTopOfStack;\r
} else {\r
- //\r
- // Re-get the CPU APICID and Initial APICID\r
- //\r
- CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();\r
- CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
+ if (CpuInfoInHob[ProcessorNumber].ApicId != GetApicId () ||\r
+ CpuInfoInHob[ProcessorNumber].InitialApicId != GetInitialApicId ()) {\r
+ if (CurrentApicMode != GetApicMode ()) {\r
+ //\r
+ // If APIC mode change happened during AP function execution,\r
+ // we do not support APIC ID value changed.\r
+ //\r
+ ASSERT (FALSE);\r
+ CpuDeadLoop ();\r
+ } else {\r
+ //\r
+ // Re-get the CPU APICID and Initial APICID if they are changed\r
+ //\r
+ CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();\r
+ CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
+ }\r
+ }\r
}\r
}\r
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);\r
\r
ExchangeInfo->EnableExecuteDisable = IsBspExecuteDisableEnabled ();\r
\r
+ ExchangeInfo->InitializeFloatingPointUnitsAddress = (UINTN)InitializeFloatingPointUnits;\r
+\r
//\r
// Get the BSP's data of GDT and IDT\r
//\r
IN UINT32 TimeLimit\r
);\r
\r
+/**\r
+ Get available system memory below 1MB by specified size.\r
+\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+BackupAndPrepareWakeupBuffer(\r
+ IN CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ CopyMem (\r
+ (VOID *) CpuMpData->BackupBuffer,\r
+ (VOID *) CpuMpData->WakeupBuffer,\r
+ CpuMpData->BackupBufferSize\r
+ );\r
+ CopyMem (\r
+ (VOID *) CpuMpData->WakeupBuffer,\r
+ (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,\r
+ CpuMpData->AddressMap.RendezvousFunnelSize\r
+ );\r
+}\r
+\r
+/**\r
+ Restore wakeup buffer data.\r
+\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+RestoreWakeupBuffer(\r
+ IN CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ CopyMem (\r
+ (VOID *) CpuMpData->WakeupBuffer,\r
+ (VOID *) CpuMpData->BackupBuffer,\r
+ CpuMpData->BackupBufferSize\r
+ );\r
+}\r
+\r
+/**\r
+ Allocate reset vector buffer.\r
+\r
+ @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+AllocateResetVector (\r
+ IN OUT CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ UINTN ApResetVectorSize;\r
+\r
+ if (CpuMpData->WakeupBuffer == (UINTN) -1) {\r
+ ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +\r
+ sizeof (MP_CPU_EXCHANGE_INFO);\r
+\r
+ CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize);\r
+ CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)\r
+ (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);\r
+ }\r
+ BackupAndPrepareWakeupBuffer (CpuMpData);\r
+}\r
+\r
+/**\r
+ Free AP reset vector buffer.\r
+\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+FreeResetVector (\r
+ IN CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ RestoreWakeupBuffer (CpuMpData);\r
+}\r
+\r
/**\r
This function will be called by BSP to wakeup AP.\r
\r
OUT UINT64 *CurrentTime\r
)\r
{\r
+ UINT64 TimeoutInSeconds;\r
+ UINT64 TimestampCounterFreq;\r
+\r
//\r
// Read the current value of the performance counter\r
//\r
\r
//\r
// GetPerformanceCounterProperties () returns the timestamp counter's frequency\r
- // in Hz. So multiply the return value with TimeoutInMicroseconds and then divide\r
- // it by 1,000,000, to get the number of ticks for the timeout value.\r
- //\r
- return DivU64x32 (\r
- MultU64x64 (\r
- GetPerformanceCounterProperties (NULL, NULL),\r
- TimeoutInMicroseconds\r
- ),\r
- 1000000\r
- );\r
+ // in Hz. \r
+ //\r
+ TimestampCounterFreq = GetPerformanceCounterProperties (NULL, NULL);\r
+\r
+ //\r
+ // Check the potential overflow before calculate the number of ticks for the timeout value.\r
+ //\r
+ if (DivU64x64Remainder (MAX_UINT64, TimeoutInMicroseconds, NULL) < TimestampCounterFreq) {\r
+ //\r
+ // Convert microseconds into seconds if direct multiplication overflows\r
+ //\r
+ TimeoutInSeconds = DivU64x32 (TimeoutInMicroseconds, 1000000);\r
+ //\r
+ // Assertion if the final tick count exceeds MAX_UINT64\r
+ //\r
+ ASSERT (DivU64x64Remainder (MAX_UINT64, TimeoutInSeconds, NULL) >= TimestampCounterFreq);\r
+ return MultU64x64 (TimestampCounterFreq, TimeoutInSeconds);\r
+ } else {\r
+ //\r
+ // No overflow case, multiply the return value with TimeoutInMicroseconds and then divide\r
+ // it by 1,000,000, to get the number of ticks for the timeout value.\r
+ //\r
+ return DivU64x32 (\r
+ MultU64x64 (\r
+ TimestampCounterFreq,\r
+ TimeoutInMicroseconds\r
+ ),\r
+ 1000000\r
+ );\r
+ }\r
}\r
\r
/**\r
CpuMpData->CpuApStackSize = ApStackSize;\r
CpuMpData->BackupBuffer = BackupBufferAddr;\r
CpuMpData->BackupBufferSize = ApResetVectorSize;\r
- CpuMpData->SaveRestoreFlag = FALSE;\r
CpuMpData->WakeupBuffer = (UINTN) -1;\r
CpuMpData->CpuCount = 1;\r
CpuMpData->BspNumber = 0;\r
CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;\r
for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
InitializeSpinLock(&CpuMpData->CpuData[Index].ApLock);\r
- if (CpuInfoInHob[Index].InitialApicId >= 255) {\r
+ if (CpuInfoInHob[Index].InitialApicId >= 255 || Index > 254) {\r
CpuMpData->X2ApicEnable = TRUE;\r
}\r
CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0)? TRUE:FALSE;\r
//\r
MpInitLibWhoAmI (&CallerNumber);\r
if (CallerNumber != CpuMpData->BspNumber) {\r
- return EFI_SUCCESS;\r
+ return EFI_DEVICE_ERROR;\r
}\r
\r
if (ProcessorNumber >= CpuMpData->CpuCount) {\r
if (!EnableAP) {\r
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateDisabled);\r
} else {\r
- SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);\r
+ ResetProcessorToIdleState (ProcessorNumber);\r
}\r
\r
if (HealthFlag != NULL) {\r
return CpuMpData;\r
}\r
\r
-/**\r
- Get available system memory below 1MB by specified size.\r
-\r
- @param[in] CpuMpData The pointer to CPU MP Data structure.\r
-**/\r
-VOID\r
-BackupAndPrepareWakeupBuffer(\r
- IN CPU_MP_DATA *CpuMpData\r
- )\r
-{\r
- CopyMem (\r
- (VOID *) CpuMpData->BackupBuffer,\r
- (VOID *) CpuMpData->WakeupBuffer,\r
- CpuMpData->BackupBufferSize\r
- );\r
- CopyMem (\r
- (VOID *) CpuMpData->WakeupBuffer,\r
- (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,\r
- CpuMpData->AddressMap.RendezvousFunnelSize\r
- );\r
-}\r
-\r
-/**\r
- Restore wakeup buffer data.\r
-\r
- @param[in] CpuMpData The pointer to CPU MP Data structure.\r
-**/\r
-VOID\r
-RestoreWakeupBuffer(\r
- IN CPU_MP_DATA *CpuMpData\r
- )\r
-{\r
- CopyMem (\r
- (VOID *) CpuMpData->WakeupBuffer,\r
- (VOID *) CpuMpData->BackupBuffer,\r
- CpuMpData->BackupBufferSize\r
- );\r
-}\r