VolatileRegisters->Dr6 = AsmReadDr6 ();\r
VolatileRegisters->Dr7 = AsmReadDr7 ();\r
}\r
+\r
+ AsmReadGdtr (&VolatileRegisters->Gdtr);\r
+ AsmReadIdtr (&VolatileRegisters->Idtr);\r
+ VolatileRegisters->Tr = AsmReadTr ();\r
}\r
\r
/**\r
)\r
{\r
CPUID_VERSION_INFO_EDX VersionInfoEdx;\r
+ IA32_TSS_DESCRIPTOR *Tss;\r
\r
AsmWriteCr0 (VolatileRegisters->Cr0);\r
AsmWriteCr3 (VolatileRegisters->Cr3);\r
AsmWriteDr7 (VolatileRegisters->Dr7);\r
}\r
}\r
+\r
+ AsmWriteGdtr (&VolatileRegisters->Gdtr);\r
+ AsmWriteIdtr (&VolatileRegisters->Idtr);\r
+ if (VolatileRegisters->Tr != 0 &&\r
+ VolatileRegisters->Tr < VolatileRegisters->Gdtr.Limit) {\r
+ Tss = (IA32_TSS_DESCRIPTOR *)(VolatileRegisters->Gdtr.Base +\r
+ VolatileRegisters->Tr);\r
+ if (Tss->Bits.P == 1) {\r
+ Tss->Bits.Type &= 0xD; // 1101 - Clear busy bit just in case\r
+ AsmWriteTr (VolatileRegisters->Tr);\r
+ }\r
+ }\r
}\r
\r
/**\r
This function will be called from AP reset code if BSP uses WakeUpAP.\r
\r
@param[in] ExchangeInfo Pointer to the MP exchange info buffer\r
- @param[in] NumApsExecuting Number of current executing AP\r
+ @param[in] ApIndex Number of current executing AP\r
**/\r
VOID\r
EFIAPI\r
ApWakeupFunction (\r
IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,\r
- IN UINTN NumApsExecuting\r
+ IN UINTN ApIndex\r
)\r
{\r
CPU_MP_DATA *CpuMpData;\r
// Add CPU number\r
//\r
InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount);\r
- ProcessorNumber = NumApsExecuting;\r
+ ProcessorNumber = ApIndex;\r
//\r
// This is first time AP wakeup, get BIST information from AP stack\r
//\r
// AP finished executing C code\r
//\r
InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount);\r
+ InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeInfo->NumApsExecuting);\r
\r
//\r
// Place AP is specified loop mode\r
ExchangeInfo->Cr3 = AsmReadCr3 ();\r
\r
ExchangeInfo->CFunction = (UINTN) ApWakeupFunction;\r
+ ExchangeInfo->ApIndex = 0;\r
ExchangeInfo->NumApsExecuting = 0;\r
ExchangeInfo->InitFlag = (UINTN) CpuMpData->InitFlag;\r
ExchangeInfo->CpuInfo = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;\r
}\r
if (CpuMpData->InitFlag == ApInitConfig) {\r
//\r
- // Wait for all potential APs waken up in one specified period\r
+ // Here support two methods to collect AP count through adjust\r
+ // PcdCpuApInitTimeOutInMicroSeconds values.\r
+ //\r
+ // one way is set a value to just let the first AP to start the\r
+ // initialization, then through the later while loop to wait all Aps\r
+ // finsh the initialization.\r
+ // The other way is set a value to let all APs finished the initialzation.\r
+ // In this case, the later while loop is useless.\r
//\r
TimedWaitForApFinish (\r
CpuMpData,\r
PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1,\r
PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)\r
);\r
+\r
+ while (CpuMpData->MpCpuExchangeInfo->NumApsExecuting != 0) {\r
+ CpuPause();\r
+ }\r
} else {\r
//\r
// Wait all APs waken up if this is not the 1st broadcast of SIPI\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->SwitchBspFlag = FALSE;\r
CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);\r
CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);\r
+ CpuMpData->MicrocodePatchAddress = PcdGet64 (PcdCpuMicrocodePatchAddress);\r
+ CpuMpData->MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize);\r
InitializeSpinLock(&CpuMpData->MpLock);\r
//\r
// Save BSP's Control registers to APs\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