BOOLEAN mMachineCheckSupported = FALSE;\r
MM_COMPLETION mSmmStartupThisApToken;\r
\r
+//\r
+// Processor specified by mPackageFirstThreadIndex[PackageIndex] will do the package-scope register check.\r
+//\r
+UINT32 *mPackageFirstThreadIndex = NULL;\r
+\r
extern UINTN mSmmShadowStackSize;\r
\r
/**\r
}\r
\r
/**\r
- Checks if all CPUs (with certain exceptions) have checked in for this SMI run\r
+ Check whether the index of CPU perform the package level register\r
+ programming during System Management Mode initialization.\r
\r
- @param Exceptions CPU Arrival exception flags.\r
+ The index of Processor specified by mPackageFirstThreadIndex[PackageIndex]\r
+ will do the package-scope register programming.\r
\r
- @retval TRUE if all CPUs the have checked in.\r
- @retval FALSE if at least one Normal AP hasn't checked in.\r
+ @param[in] CpuIndex Processor Index.\r
+\r
+ @retval TRUE Perform the package level register programming.\r
+ @retval FALSE Don't perform the package level register programming.\r
\r
**/\r
BOOLEAN\r
-AllCpusInSmmWithExceptions (\r
- SMM_CPU_ARRIVAL_EXCEPTIONS Exceptions\r
+IsPackageFirstThread (\r
+ IN UINTN CpuIndex\r
)\r
{\r
- UINTN Index;\r
- SMM_CPU_DATA_BLOCK *CpuData;\r
- EFI_PROCESSOR_INFORMATION *ProcessorInfo;\r
+ UINT32 PackageIndex;\r
\r
- ASSERT (*mSmmMpSyncData->Counter <= mNumberOfCpus);\r
+ PackageIndex = gSmmCpuPrivate->ProcessorInfo[CpuIndex].Location.Package;\r
\r
- if (*mSmmMpSyncData->Counter == mNumberOfCpus) {\r
- return TRUE;\r
+ ASSERT (mPackageFirstThreadIndex != NULL);\r
+\r
+ //\r
+ // Set the value of mPackageFirstThreadIndex[PackageIndex].\r
+ // The package-scope register are checked by the first processor (CpuIndex) in Package.\r
+ //\r
+ // If mPackageFirstThreadIndex[PackageIndex] equals to (UINT32)-1, then update\r
+ // to current CpuIndex. If it doesn't equal to (UINT32)-1, don't change it.\r
+ //\r
+ if (mPackageFirstThreadIndex[PackageIndex] == (UINT32)-1) {\r
+ mPackageFirstThreadIndex[PackageIndex] = (UINT32)CpuIndex;\r
}\r
\r
- CpuData = mSmmMpSyncData->CpuData;\r
- ProcessorInfo = gSmmCpuPrivate->ProcessorInfo;\r
- for (Index = 0; Index < mMaxNumberOfCpus; Index++) {\r
- if (!(*(CpuData[Index].Present)) && (ProcessorInfo[Index].ProcessorId != INVALID_APIC_ID)) {\r
- if (((Exceptions & ARRIVAL_EXCEPTION_DELAYED) != 0) && (SmmCpuFeaturesGetSmmRegister (Index, SmmRegSmmDelayed) != 0)) {\r
- continue;\r
- }\r
+ return (BOOLEAN)(mPackageFirstThreadIndex[PackageIndex] == CpuIndex);\r
+}\r
+\r
+/**\r
+ Returns the Number of SMM Delayed & Blocked & Disabled Thread Count.\r
+\r
+ @param[in,out] DelayedCount The Number of SMM Delayed Thread Count.\r
+ @param[in,out] BlockedCount The Number of SMM Blocked Thread Count.\r
+ @param[in,out] DisabledCount The Number of SMM Disabled Thread Count.\r
+\r
+**/\r
+VOID\r
+GetSmmDelayedBlockedDisabledCount (\r
+ IN OUT UINT32 *DelayedCount,\r
+ IN OUT UINT32 *BlockedCount,\r
+ IN OUT UINT32 *DisabledCount\r
+ )\r
+{\r
+ UINTN Index;\r
\r
- if (((Exceptions & ARRIVAL_EXCEPTION_BLOCKED) != 0) && (SmmCpuFeaturesGetSmmRegister (Index, SmmRegSmmBlocked) != 0)) {\r
- continue;\r
+ for (Index = 0; Index < mNumberOfCpus; Index++) {\r
+ if (IsPackageFirstThread (Index)) {\r
+ if (DelayedCount != NULL) {\r
+ *DelayedCount += (UINT32)SmmCpuFeaturesGetSmmRegister (Index, SmmRegSmmDelayed);\r
}\r
\r
- if (((Exceptions & ARRIVAL_EXCEPTION_SMI_DISABLED) != 0) && (SmmCpuFeaturesGetSmmRegister (Index, SmmRegSmmEnable) != 0)) {\r
- continue;\r
+ if (BlockedCount != NULL) {\r
+ *BlockedCount += (UINT32)SmmCpuFeaturesGetSmmRegister (Index, SmmRegSmmBlocked);\r
}\r
\r
- return FALSE;\r
+ if (DisabledCount != NULL) {\r
+ *DisabledCount += (UINT32)SmmCpuFeaturesGetSmmRegister (Index, SmmRegSmmEnable);\r
+ }\r
}\r
}\r
+}\r
\r
- return TRUE;\r
+/**\r
+ Checks if all CPUs (except Blocked & Disabled) have checked in for this SMI run\r
+\r
+ @retval TRUE if all CPUs the have checked in.\r
+ @retval FALSE if at least one Normal AP hasn't checked in.\r
+\r
+**/\r
+BOOLEAN\r
+AllCpusInSmmExceptBlockedDisabled (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 BlockedCount;\r
+ UINT32 DisabledCount;\r
+\r
+ BlockedCount = 0;\r
+ DisabledCount = 0;\r
+\r
+ //\r
+ // Check to make sure mSmmMpSyncData->Counter is valid and not locked.\r
+ //\r
+ ASSERT (*mSmmMpSyncData->Counter <= mNumberOfCpus);\r
+\r
+ //\r
+ // Check whether all CPUs in SMM.\r
+ //\r
+ if (*mSmmMpSyncData->Counter == mNumberOfCpus) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check for the Blocked & Disabled Exceptions Case.\r
+ //\r
+ GetSmmDelayedBlockedDisabledCount (NULL, &BlockedCount, &DisabledCount);\r
+\r
+ //\r
+ // *mSmmMpSyncData->Counter might be updated by all APs concurrently. The value\r
+ // can be dynamic changed. If some Aps enter the SMI after the BlockedCount &\r
+ // DisabledCount check, then the *mSmmMpSyncData->Counter will be increased, thus\r
+ // leading the *mSmmMpSyncData->Counter + BlockedCount + DisabledCount > mNumberOfCpus.\r
+ // since the BlockedCount & DisabledCount are local variable, it's ok here only for\r
+ // the checking of all CPUs In Smm.\r
+ //\r
+ if (*mSmmMpSyncData->Counter + BlockedCount + DisabledCount >= mNumberOfCpus) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
}\r
\r
/**\r
UINTN Index;\r
BOOLEAN LmceEn;\r
BOOLEAN LmceSignal;\r
+ UINT32 DelayedCount;\r
+ UINT32 BlockedCount;\r
+\r
+ DelayedCount = 0;\r
+ BlockedCount = 0;\r
\r
ASSERT (*mSmmMpSyncData->Counter <= mNumberOfCpus);\r
\r
!IsSyncTimerTimeout (Timer) && !(LmceEn && LmceSignal);\r
)\r
{\r
- mSmmMpSyncData->AllApArrivedWithException = AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED);\r
+ mSmmMpSyncData->AllApArrivedWithException = AllCpusInSmmExceptBlockedDisabled ();\r
if (mSmmMpSyncData->AllApArrivedWithException) {\r
break;\r
}\r
!IsSyncTimerTimeout (Timer);\r
)\r
{\r
- mSmmMpSyncData->AllApArrivedWithException = AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED);\r
+ mSmmMpSyncData->AllApArrivedWithException = AllCpusInSmmExceptBlockedDisabled ();\r
if (mSmmMpSyncData->AllApArrivedWithException) {\r
break;\r
}\r
}\r
}\r
\r
+ if (!mSmmMpSyncData->AllApArrivedWithException) {\r
+ //\r
+ // Check for the Blocked & Delayed Case.\r
+ //\r
+ GetSmmDelayedBlockedDisabledCount (&DelayedCount, &BlockedCount, NULL);\r
+ DEBUG ((DEBUG_INFO, "SmmWaitForApArrival: Delayed AP Count = %d, Blocked AP Count = %d\n", DelayedCount, BlockedCount));\r
+ }\r
+\r
return;\r
}\r
\r
if (mSmmMpSyncData->BspIndex != -1) {\r
//\r
// BSP Index is known\r
+ // Existing AP is in SMI now but BSP not in, so, try bring BSP in SMM.\r
//\r
BspIndex = mSmmMpSyncData->BspIndex;\r
ASSERT (CpuIndex != BspIndex);\r
//\r
// Give up since BSP is unable to enter SMM\r
// and signal the completion of this AP\r
+ // Reduce the mSmmMpSyncData->Counter!\r
+ //\r
WaitForSemaphore (mSmmMpSyncData->Counter);\r
return;\r
}\r
} else {\r
//\r
// Don't know BSP index. Give up without sending IPI to BSP.\r
+ // Reduce the mSmmMpSyncData->Counter!\r
//\r
WaitForSemaphore (mSmmMpSyncData->Counter);\r
return;\r
} else {\r
//\r
// Signal presence of this processor\r
+ // mSmmMpSyncData->Counter is increased here!\r
+ // "ReleaseSemaphore (mSmmMpSyncData->Counter) == 0" means BSP has already ended the synchronization.\r
//\r
if (ReleaseSemaphore (mSmmMpSyncData->Counter) == 0) {\r
//\r
// BSP has already ended the synchronization, so QUIT!!!\r
+ // Existing AP is too late now to enter SMI since BSP has already ended the synchronization!!!\r
//\r
\r
//\r
RestoreCr2 (Cr2);\r
}\r
\r
+/**\r
+ Initialize PackageBsp Info. Processor specified by mPackageFirstThreadIndex[PackageIndex]\r
+ will do the package-scope register programming. Set default CpuIndex to (UINT32)-1, which\r
+ means not specified yet.\r
+\r
+**/\r
+VOID\r
+InitPackageFirstThreadIndexInfo (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 Index;\r
+ UINT32 PackageId;\r
+ UINT32 PackageCount;\r
+\r
+ PackageId = 0;\r
+ PackageCount = 0;\r
+\r
+ //\r
+ // Count the number of package, set to max PackageId + 1\r
+ //\r
+ for (Index = 0; Index < mNumberOfCpus; Index++) {\r
+ if (PackageId < gSmmCpuPrivate->ProcessorInfo[Index].Location.Package) {\r
+ PackageId = gSmmCpuPrivate->ProcessorInfo[Index].Location.Package;\r
+ }\r
+ }\r
+\r
+ PackageCount = PackageId + 1;\r
+\r
+ mPackageFirstThreadIndex = (UINT32 *)AllocatePool (sizeof (UINT32) * PackageCount);\r
+ ASSERT (mPackageFirstThreadIndex != NULL);\r
+ if (mPackageFirstThreadIndex == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Set default CpuIndex to (UINT32)-1, which means not specified yet.\r
+ //\r
+ SetMem32 (mPackageFirstThreadIndex, sizeof (UINT32) * PackageCount, (UINT32)-1);\r
+}\r
+\r
/**\r
Allocate buffer for SpinLock and Wrapper function buffer.\r
\r