]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/PiSmmCpuDxeSmm: Remove dependence between APs
authorEric Dong <eric.dong@intel.com>
Mon, 23 Dec 2019 06:15:04 +0000 (14:15 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Tue, 24 Dec 2019 03:59:14 +0000 (03:59 +0000)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2268

In current implementation, when check whether APs called by StartUpAllAPs
or StartUpThisAp, it checks the Tokens value used by other APs. Also the AP
will update the Token value for itself if its task finished. In this
case, the potential race condition  issues happens for the tokens.
Because of this, system may trig ASSERT during cycling test.

This change enhance the code logic, add new attributes for the token to
remove the reference for the tokens belongs to other APs.

Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Eric Dong <eric.dong@intel.com>
UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h

index 757f1056f78dd62fa3fb3b904ed7f212171f58a1..35951cc43e149815d96b5827d506b6bbe55ad39a 100644 (file)
@@ -402,38 +402,6 @@ IsPresentAp (
     *(mSmmMpSyncData->CpuData[CpuIndex].Present));\r
 }\r
 \r
-/**\r
-  Check whether execute in single AP or all APs.\r
-\r
-  Compare two Tokens used by different APs to know whether in StartAllAps call.\r
-\r
-  Whether is an valid AP base on AP's Present flag.\r
-\r
-  @retval  TRUE      IN StartAllAps call.\r
-  @retval  FALSE     Not in StartAllAps call.\r
-\r
-**/\r
-BOOLEAN\r
-InStartAllApsCall (\r
-  VOID\r
-  )\r
-{\r
-  UINTN      ApIndex;\r
-  UINTN      ApIndex2;\r
-\r
-  for (ApIndex = mMaxNumberOfCpus; ApIndex-- > 0;) {\r
-    if (IsPresentAp (ApIndex) && (mSmmMpSyncData->CpuData[ApIndex].Token != NULL)) {\r
-      for (ApIndex2 = ApIndex; ApIndex2-- > 0;) {\r
-        if (IsPresentAp (ApIndex2) && (mSmmMpSyncData->CpuData[ApIndex2].Token != NULL)) {\r
-          return mSmmMpSyncData->CpuData[ApIndex2].Token == mSmmMpSyncData->CpuData[ApIndex].Token;\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
 /**\r
   Clean up the status flags used during executing the procedure.\r
 \r
@@ -445,40 +413,15 @@ ReleaseToken (
   IN UINTN                  CpuIndex\r
   )\r
 {\r
-  UINTN                             Index;\r
-  BOOLEAN                           Released;\r
+  PROCEDURE_TOKEN                         *Token;\r
 \r
-  if (InStartAllApsCall ()) {\r
-    //\r
-    // In Start All APs mode, make sure all APs have finished task.\r
-    //\r
-    if (WaitForAllAPsNotBusy (FALSE)) {\r
-      //\r
-      // Clean the flags update in the function call.\r
-      //\r
-      Released = FALSE;\r
-      for (Index = mMaxNumberOfCpus; Index-- > 0;) {\r
-        //\r
-        // Only In SMM APs need to be clean up.\r
-        //\r
-        if (mSmmMpSyncData->CpuData[Index].Present && mSmmMpSyncData->CpuData[Index].Token != NULL) {\r
-          if (!Released) {\r
-            ReleaseSpinLock (mSmmMpSyncData->CpuData[Index].Token);\r
-            Released = TRUE;\r
-          }\r
-          mSmmMpSyncData->CpuData[Index].Token = NULL;\r
-        }\r
-      }\r
-    }\r
-  } else {\r
-    //\r
-    // In single AP mode.\r
-    //\r
-    if (mSmmMpSyncData->CpuData[CpuIndex].Token != NULL) {\r
-      ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Token);\r
-      mSmmMpSyncData->CpuData[CpuIndex].Token = NULL;\r
-    }\r
+  Token = mSmmMpSyncData->CpuData[CpuIndex].Token;\r
+\r
+  if (InterlockedDecrement (&Token->RunningApCount) == 0) {\r
+    ReleaseSpinLock (Token->SpinLock);\r
   }\r
+\r
+  mSmmMpSyncData->CpuData[CpuIndex].Token = NULL;\r
 }\r
 \r
 /**\r
@@ -912,12 +855,14 @@ APHandler (
       *mSmmMpSyncData->CpuData[CpuIndex].Status = ProcedureStatus;\r
     }\r
 \r
+    if (mSmmMpSyncData->CpuData[CpuIndex].Token != NULL) {\r
+      ReleaseToken (CpuIndex);\r
+    }\r
+\r
     //\r
     // Release BUSY\r
     //\r
     ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
-\r
-    ReleaseToken (CpuIndex);\r
   }\r
 \r
   if (SmmCpuFeaturesNeedConfigureMtrrs()) {\r
@@ -1111,7 +1056,7 @@ IsTokenInUse (
   while (!IsNull (&gSmmCpuPrivate->TokenList, Link)) {\r
     ProcToken = PROCEDURE_TOKEN_FROM_LINK (Link);\r
 \r
-    if (ProcToken->ProcedureToken == Token) {\r
+    if (ProcToken->SpinLock == Token) {\r
       return TRUE;\r
     }\r
 \r
@@ -1124,16 +1069,18 @@ IsTokenInUse (
 /**\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
 \r
 **/\r
-SPIN_LOCK *\r
+PROCEDURE_TOKEN *\r
 CreateToken (\r
-  VOID\r
+  IN UINT32              RunningApCount\r
   )\r
 {\r
   PROCEDURE_TOKEN     *ProcToken;\r
-  SPIN_LOCK           *CpuToken;\r
+  SPIN_LOCK           *SpinLock;\r
   UINTN               SpinLockSize;\r
   TOKEN_BUFFER        *TokenBuf;\r
   UINT32              TokenCountPerChunk;\r
@@ -1160,20 +1107,21 @@ CreateToken (
     gSmmCpuPrivate->UsedTokenNum = 0;\r
   }\r
 \r
-  CpuToken = (SPIN_LOCK *)(gSmmCpuPrivate->CurrentTokenBuf + SpinLockSize * gSmmCpuPrivate->UsedTokenNum);\r
+  SpinLock = (SPIN_LOCK *)(gSmmCpuPrivate->CurrentTokenBuf + SpinLockSize * gSmmCpuPrivate->UsedTokenNum);\r
   gSmmCpuPrivate->UsedTokenNum++;\r
 \r
-  InitializeSpinLock (CpuToken);\r
-  AcquireSpinLock (CpuToken);\r
+  InitializeSpinLock (SpinLock);\r
+  AcquireSpinLock (SpinLock);\r
 \r
   ProcToken = AllocatePool (sizeof (PROCEDURE_TOKEN));\r
   ASSERT (ProcToken != NULL);\r
   ProcToken->Signature = PROCEDURE_TOKEN_SIGNATURE;\r
-  ProcToken->ProcedureToken = CpuToken;\r
+  ProcToken->SpinLock = SpinLock;\r
+  ProcToken->RunningApCount = RunningApCount;\r
 \r
   InsertTailList (&gSmmCpuPrivate->TokenList, &ProcToken->Link);\r
 \r
-  return CpuToken;\r
+  return ProcToken;\r
 }\r
 \r
 /**\r
@@ -1246,6 +1194,8 @@ InternalSmmStartupThisAp (
   IN OUT  EFI_STATUS                     *CpuStatus\r
   )\r
 {\r
+  PROCEDURE_TOKEN    *ProcToken;\r
+\r
   if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus) {\r
     DEBUG((DEBUG_ERROR, "CpuIndex(%d) >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus(%d)\n", CpuIndex, gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));\r
     return EFI_INVALID_PARAMETER;\r
@@ -1278,14 +1228,12 @@ InternalSmmStartupThisAp (
 \r
   AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
 \r
-  if (Token != NULL) {\r
-    *Token = (MM_COMPLETION) CreateToken ();\r
-  }\r
-\r
   mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;\r
   mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;\r
   if (Token != NULL) {\r
-    mSmmMpSyncData->CpuData[CpuIndex].Token   = (SPIN_LOCK *)(*Token);\r
+    ProcToken= CreateToken (1);\r
+    mSmmMpSyncData->CpuData[CpuIndex].Token = ProcToken;\r
+    *Token = (MM_COMPLETION)ProcToken->SpinLock;\r
   }\r
   mSmmMpSyncData->CpuData[CpuIndex].Status    = CpuStatus;\r
   if (mSmmMpSyncData->CpuData[CpuIndex].Status != NULL) {\r
@@ -1343,6 +1291,7 @@ InternalSmmStartupAllAPs (
 {\r
   UINTN               Index;\r
   UINTN               CpuCount;\r
+  PROCEDURE_TOKEN     *ProcToken;\r
 \r
   if ((TimeoutInMicroseconds != 0) && ((mSmmMp.Attributes & EFI_MM_MP_TIMEOUT_SUPPORTED) == 0)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1371,7 +1320,10 @@ InternalSmmStartupAllAPs (
   }\r
 \r
   if (Token != NULL) {\r
-    *Token = (MM_COMPLETION) CreateToken ();\r
+    ProcToken = CreateToken ((UINT32)mMaxNumberOfCpus);\r
+    *Token = (MM_COMPLETION)ProcToken->SpinLock;\r
+  } else {\r
+    ProcToken = NULL;\r
   }\r
 \r
   //\r
@@ -1391,8 +1343,8 @@ InternalSmmStartupAllAPs (
     if (IsPresentAp (Index)) {\r
       mSmmMpSyncData->CpuData[Index].Procedure = (EFI_AP_PROCEDURE2) Procedure;\r
       mSmmMpSyncData->CpuData[Index].Parameter = ProcedureArguments;\r
-      if (Token != NULL) {\r
-        mSmmMpSyncData->CpuData[Index].Token   = (SPIN_LOCK *)(*Token);\r
+      if (ProcToken != NULL) {\r
+        mSmmMpSyncData->CpuData[Index].Token   = ProcToken;\r
       }\r
       if (CPUStatus != NULL) {\r
         mSmmMpSyncData->CpuData[Index].Status    = &CPUStatus[Index];\r
@@ -1408,6 +1360,13 @@ InternalSmmStartupAllAPs (
       if (CPUStatus != NULL) {\r
         CPUStatus[Index] = EFI_NOT_STARTED;\r
       }\r
+\r
+      //\r
+      // Decrease the count to mark this processor(AP or BSP) as finished.\r
+      //\r
+      if (ProcToken != NULL) {\r
+        WaitForSemaphore (&ProcToken->RunningApCount);\r
+      }\r
     }\r
   }\r
 \r
index 5c1a01e42bf33ebd4eb2e04640bfb583563d07f7..5c98494e2c53eda8d826bf173fa93ddd52b8eb92 100644 (file)
@@ -212,7 +212,8 @@ typedef struct {
   UINTN                   Signature;\r
   LIST_ENTRY              Link;\r
 \r
-  SPIN_LOCK               *ProcedureToken;\r
+  SPIN_LOCK               *SpinLock;\r
+  volatile UINT32         RunningApCount;\r
 } PROCEDURE_TOKEN;\r
 \r
 #define PROCEDURE_TOKEN_FROM_LINK(a)  CR (a, PROCEDURE_TOKEN, Link, PROCEDURE_TOKEN_SIGNATURE)\r
@@ -407,7 +408,7 @@ typedef struct {
   volatile VOID                     *Parameter;\r
   volatile UINT32                   *Run;\r
   volatile BOOLEAN                  *Present;\r
-  SPIN_LOCK                         *Token;\r
+  PROCEDURE_TOKEN                   *Token;\r
   EFI_STATUS                        *Status;\r
 } SMM_CPU_DATA_BLOCK;\r
 \r