\r
**/\r
VOID\r
-FreeTokens (\r
+ResetTokens (\r
VOID\r
)\r
{\r
LIST_ENTRY *Link;\r
PROCEDURE_TOKEN *ProcToken;\r
- TOKEN_BUFFER *TokenBuf;\r
\r
- //\r
- // Only free the token buffer recorded in the OldTOkenBufList\r
- // upon exiting SMI. Current token buffer stays allocated so\r
- // next SMI doesn't need to re-allocate.\r
- //\r
- gSmmCpuPrivate->UsedTokenNum = 0;\r
-\r
- Link = GetFirstNode (&gSmmCpuPrivate->OldTokenBufList);\r
- while (!IsNull (&gSmmCpuPrivate->OldTokenBufList, Link)) {\r
- TokenBuf = TOKEN_BUFFER_FROM_LINK (Link);\r
-\r
- Link = RemoveEntryList (&TokenBuf->Link);\r
-\r
- FreePool (TokenBuf->Buffer);\r
- FreePool (TokenBuf);\r
- }\r
-\r
- while (!IsListEmpty (&gSmmCpuPrivate->TokenList)) {\r
- Link = GetFirstNode (&gSmmCpuPrivate->TokenList);\r
+ Link = GetFirstNode (&gSmmCpuPrivate->TokenList);\r
+ while (!IsNull (&gSmmCpuPrivate->TokenList, Link)) {\r
ProcToken = PROCEDURE_TOKEN_FROM_LINK (Link);\r
\r
- RemoveEntryList (&ProcToken->Link);\r
+ ProcToken->RunningApCount = 0;\r
+ ProcToken->Used = FALSE;\r
+\r
+ //\r
+ // Check the spinlock status and release it if not released yet.\r
+ //\r
+ if (!AcquireSpinLockOrFail(ProcToken->SpinLock)) {\r
+ DEBUG((DEBUG_ERROR, "Risk::SpinLock still not released!"));\r
+ }\r
+ ReleaseSpinLock (ProcToken->SpinLock);\r
\r
- FreePool (ProcToken);\r
+ Link = GetNextNode (&gSmmCpuPrivate->TokenList, Link);\r
}\r
}\r
\r
WaitForAllAPs (ApCount);\r
\r
//\r
- // Clean the tokens buffer.\r
+ // Reset the tokens buffer.\r
//\r
- FreeTokens ();\r
+ ResetTokens ();\r
\r
//\r
// Reset BspIndex to -1, meaning BSP has not been elected.\r
while (!IsNull (&gSmmCpuPrivate->TokenList, Link)) {\r
ProcToken = PROCEDURE_TOKEN_FROM_LINK (Link);\r
\r
- if (ProcToken->SpinLock == Token) {\r
+ if (ProcToken->Used && ProcToken->SpinLock == Token) {\r
return TRUE;\r
}\r
\r
}\r
\r
/**\r
- create token and save it to the maintain list.\r
-\r
- @param RunningApCount Input running AP count.\r
-\r
- @retval return the spin lock used as token.\r
+ Allocate buffer for the SPIN_LOCK and PROCEDURE_TOKEN.\r
\r
**/\r
-PROCEDURE_TOKEN *\r
-CreateToken (\r
- IN UINT32 RunningApCount\r
+VOID\r
+AllocateTokenBuffer (\r
+ VOID\r
)\r
{\r
- PROCEDURE_TOKEN *ProcToken;\r
- SPIN_LOCK *SpinLock;\r
UINTN SpinLockSize;\r
- TOKEN_BUFFER *TokenBuf;\r
UINT32 TokenCountPerChunk;\r
+ UINTN ProcTokenSize;\r
+ UINTN Index;\r
+ PROCEDURE_TOKEN *ProcToken;\r
+ SPIN_LOCK *SpinLock;\r
+ UINT8 *SpinLockBuffer;\r
+ UINT8 *ProcTokenBuffer;\r
\r
SpinLockSize = GetSpinLockProperties ();\r
+ ProcTokenSize = sizeof (PROCEDURE_TOKEN);\r
+\r
TokenCountPerChunk = FixedPcdGet32 (PcdCpuSmmMpTokenCountPerChunk);\r
+ ASSERT (TokenCountPerChunk != 0);\r
+ if (TokenCountPerChunk == 0) {\r
+ DEBUG ((DEBUG_ERROR, "PcdCpuSmmMpTokenCountPerChunk should not be Zero!\n"));\r
+ CpuDeadLoop ();\r
+ }\r
+ DEBUG ((DEBUG_INFO, "CpuSmm: SpinLock Size = 0x%x, PcdCpuSmmMpTokenCountPerChunk = 0x%x\n", SpinLockSize, TokenCountPerChunk));\r
\r
- if (gSmmCpuPrivate->UsedTokenNum == TokenCountPerChunk) {\r
- DEBUG ((DEBUG_VERBOSE, "CpuSmm: No free token buffer, allocate new buffer!\n"));\r
+ //\r
+ // Separate the Spin_lock and Proc_token because the alignment requires by Spin_Lock.\r
+ //\r
+ SpinLockBuffer = AllocatePool (SpinLockSize * TokenCountPerChunk);\r
+ ASSERT (SpinLockBuffer != NULL);\r
\r
- //\r
- // Record current token buffer for later free action usage.\r
- // Current used token buffer not in this list.\r
- //\r
- TokenBuf = AllocatePool (sizeof (TOKEN_BUFFER));\r
- ASSERT (TokenBuf != NULL);\r
- TokenBuf->Signature = TOKEN_BUFFER_SIGNATURE;\r
- TokenBuf->Buffer = gSmmCpuPrivate->CurrentTokenBuf;\r
+ ProcTokenBuffer = AllocatePool (ProcTokenSize * TokenCountPerChunk);\r
+ ASSERT (ProcTokenBuffer != NULL);\r
+\r
+ for (Index = 0; Index < TokenCountPerChunk; Index++) {\r
+ SpinLock = (SPIN_LOCK *)(SpinLockBuffer + SpinLockSize * Index);\r
+ InitializeSpinLock (SpinLock);\r
+\r
+ ProcToken = (PROCEDURE_TOKEN *)(ProcTokenBuffer + ProcTokenSize * Index);\r
+ ProcToken->Signature = PROCEDURE_TOKEN_SIGNATURE;\r
+ ProcToken->SpinLock = SpinLock;\r
+ ProcToken->Used = FALSE;\r
+ ProcToken->RunningApCount = 0;\r
+\r
+ InsertTailList (&gSmmCpuPrivate->TokenList, &ProcToken->Link);\r
+ }\r
+}\r
\r
- InsertTailList (&gSmmCpuPrivate->OldTokenBufList, &TokenBuf->Link);\r
+/**\r
+ Find first free token in the allocated token list.\r
+\r
+ @retval return the first free PROCEDURE_TOKEN.\r
+\r
+**/\r
+PROCEDURE_TOKEN *\r
+FindFirstFreeToken (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PROCEDURE_TOKEN *ProcToken;\r
\r
- gSmmCpuPrivate->CurrentTokenBuf = AllocatePool (SpinLockSize * TokenCountPerChunk);\r
- ASSERT (gSmmCpuPrivate->CurrentTokenBuf != NULL);\r
- gSmmCpuPrivate->UsedTokenNum = 0;\r
+ Link = GetFirstNode (&gSmmCpuPrivate->TokenList);\r
+ while (!IsNull (&gSmmCpuPrivate->TokenList, Link)) {\r
+ ProcToken = PROCEDURE_TOKEN_FROM_LINK (Link);\r
+\r
+ if (!ProcToken->Used) {\r
+ return ProcToken;\r
+ }\r
+\r
+ Link = GetNextNode (&gSmmCpuPrivate->TokenList, Link);\r
}\r
\r
- SpinLock = (SPIN_LOCK *)(gSmmCpuPrivate->CurrentTokenBuf + SpinLockSize * gSmmCpuPrivate->UsedTokenNum);\r
- gSmmCpuPrivate->UsedTokenNum++;\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Get the free token.\r
+\r
+ If no free token, allocate new tokens then return the free one.\r
+\r
+ @retval return the first free PROCEDURE_TOKEN.\r
\r
- InitializeSpinLock (SpinLock);\r
- AcquireSpinLock (SpinLock);\r
+**/\r
+PROCEDURE_TOKEN *\r
+GetFreeToken (\r
+ IN UINT32 RunningApsCount\r
+ )\r
+{\r
+ PROCEDURE_TOKEN *NewToken;\r
\r
- ProcToken = AllocatePool (sizeof (PROCEDURE_TOKEN));\r
- ASSERT (ProcToken != NULL);\r
- ProcToken->Signature = PROCEDURE_TOKEN_SIGNATURE;\r
- ProcToken->SpinLock = SpinLock;\r
- ProcToken->RunningApCount = RunningApCount;\r
+ NewToken = FindFirstFreeToken ();\r
+ if (NewToken == NULL) {\r
+ AllocateTokenBuffer ();\r
+ NewToken = FindFirstFreeToken ();\r
+ }\r
+ ASSERT (NewToken != NULL);\r
\r
- InsertTailList (&gSmmCpuPrivate->TokenList, &ProcToken->Link);\r
+ NewToken->Used = TRUE;\r
+ NewToken->RunningApCount = RunningApsCount;\r
+ AcquireSpinLock (NewToken->SpinLock);\r
\r
- return ProcToken;\r
+ return NewToken;\r
}\r
\r
/**\r
mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;\r
mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;\r
if (Token != NULL) {\r
- ProcToken= CreateToken (1);\r
+ ProcToken= GetFreeToken (1);\r
mSmmMpSyncData->CpuData[CpuIndex].Token = ProcToken;\r
*Token = (MM_COMPLETION)ProcToken->SpinLock;\r
}\r
}\r
\r
if (Token != NULL) {\r
- ProcToken = CreateToken ((UINT32)mMaxNumberOfCpus);\r
+ ProcToken = GetFreeToken ((UINT32)mMaxNumberOfCpus);\r
*Token = (MM_COMPLETION)ProcToken->SpinLock;\r
} else {\r
ProcToken = NULL;\r
VOID\r
)\r
{\r
- UINTN SpinLockSize;\r
- UINT32 TokenCountPerChunk;\r
-\r
- SpinLockSize = GetSpinLockProperties ();\r
- TokenCountPerChunk = FixedPcdGet32 (PcdCpuSmmMpTokenCountPerChunk);\r
- ASSERT (TokenCountPerChunk != 0);\r
- if (TokenCountPerChunk == 0) {\r
- DEBUG ((DEBUG_ERROR, "PcdCpuSmmMpTokenCountPerChunk should not be Zero!\n"));\r
- CpuDeadLoop ();\r
- }\r
- DEBUG ((DEBUG_INFO, "CpuSmm: SpinLock Size = 0x%x, PcdCpuSmmMpTokenCountPerChunk = 0x%x\n", SpinLockSize, TokenCountPerChunk));\r
-\r
- gSmmCpuPrivate->CurrentTokenBuf = AllocatePool (SpinLockSize * TokenCountPerChunk);\r
- ASSERT (gSmmCpuPrivate->CurrentTokenBuf != NULL);\r
-\r
- gSmmCpuPrivate->UsedTokenNum = 0;\r
-\r
gSmmCpuPrivate->ApWrapperFunc = AllocatePool (sizeof (PROCEDURE_WRAPPER) * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus);\r
ASSERT (gSmmCpuPrivate->ApWrapperFunc != NULL);\r
\r
InitializeListHead (&gSmmCpuPrivate->TokenList);\r
- InitializeListHead (&gSmmCpuPrivate->OldTokenBufList);\r
+\r
+ AllocateTokenBuffer ();\r
}\r
\r
/**\r