]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
UefiCpuPkg/PiSmmCpuDxeSmm: Pre-allocate PROCEDURE_TOKEN buffer
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / MpService.c
index 4808045f71adf39ce8612e5753291687e27a306b..870250b0c55d0209c113c9cd8a6b2328d81e8e06 100644 (file)
@@ -429,38 +429,29 @@ ReleaseToken (
 \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
@@ -685,9 +676,9 @@ BSPHandler (
   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
@@ -1056,7 +1047,7 @@ IsTokenInUse (
   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
@@ -1067,61 +1058,112 @@ IsTokenInUse (
 }\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
@@ -1231,7 +1273,7 @@ InternalSmmStartupThisAp (
   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
@@ -1320,7 +1362,7 @@ InternalSmmStartupAllAPs (
   }\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
@@ -1732,28 +1774,12 @@ InitializeDataForMmMp (
   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