]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
UefiCpuPkg/PiSmmCpuDxeSmm: Remove duplicate aligned buffer on S3 path
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / MpService.c
index 80378a3faf4262601a69826337b4297865934834..62d037cdb17867b82a20a3c16c7dfbee9e485cf6 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 SMM MP service implementation\r
 \r
-Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -21,6 +21,9 @@ UINT64                                      gSmiMtrrs[MTRR_NUMBER_OF_FIXED_MTRR
 UINT64                                      gPhyMask;\r
 SMM_DISPATCHER_MP_SYNC_DATA                 *mSmmMpSyncData = NULL;\r
 UINTN                                       mSmmMpSyncDataSize;\r
+SMM_CPU_SEMAPHORES                          mSmmCpuSemaphores;\r
+UINTN                                       mSemaphoreSize;\r
+SPIN_LOCK                                   *mPFLock = NULL;\r
 \r
 /**\r
   Performs an atomic compare exchange operation to get semaphore.\r
@@ -120,7 +123,7 @@ WaitForAllAPs (
 \r
   BspIndex = mSmmMpSyncData->BspIndex;\r
   while (NumberOfAPs-- > 0) {\r
-    WaitForSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);\r
+    WaitForSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run);\r
   }\r
 }\r
 \r
@@ -139,8 +142,8 @@ ReleaseAllAPs (
 \r
   BspIndex = mSmmMpSyncData->BspIndex;\r
   for (Index = mMaxNumberOfCpus; Index-- > 0;) {\r
-    if (Index != BspIndex && mSmmMpSyncData->CpuData[Index].Present) {\r
-      ReleaseSemaphore (&mSmmMpSyncData->CpuData[Index].Run);\r
+    if (Index != BspIndex && *(mSmmMpSyncData->CpuData[Index].Present)) {\r
+      ReleaseSemaphore (mSmmMpSyncData->CpuData[Index].Run);\r
     }\r
   }\r
 }\r
@@ -163,16 +166,16 @@ AllCpusInSmmWithExceptions (
   SMM_CPU_DATA_BLOCK                *CpuData;\r
   EFI_PROCESSOR_INFORMATION         *ProcessorInfo;\r
 \r
-  ASSERT (mSmmMpSyncData->Counter <= mNumberOfCpus);\r
+  ASSERT (*mSmmMpSyncData->Counter <= mNumberOfCpus);\r
 \r
-  if (mSmmMpSyncData->Counter == mNumberOfCpus) {\r
+  if (*mSmmMpSyncData->Counter == mNumberOfCpus) {\r
     return TRUE;\r
   }\r
 \r
   CpuData = mSmmMpSyncData->CpuData;\r
   ProcessorInfo = gSmmCpuPrivate->ProcessorInfo;\r
   for (Index = mMaxNumberOfCpus; Index-- > 0;) {\r
-    if (!CpuData[Index].Present && ProcessorInfo[Index].ProcessorId != INVALID_APIC_ID) {\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
@@ -204,7 +207,7 @@ SmmWaitForApArrival (
   UINT64                            Timer;\r
   UINTN                             Index;\r
 \r
-  ASSERT (mSmmMpSyncData->Counter <= mNumberOfCpus);\r
+  ASSERT (*mSmmMpSyncData->Counter <= mNumberOfCpus);\r
 \r
   //\r
   // Platform implementor should choose a timeout value appropriately:\r
@@ -243,12 +246,12 @@ SmmWaitForApArrival (
   //    - In relaxed flow, CheckApArrival() will check SMI disabling status before calling this function.\r
   //    In both cases, adding SMI-disabling checking code increases overhead.\r
   //\r
-  if (mSmmMpSyncData->Counter < mNumberOfCpus) {\r
+  if (*mSmmMpSyncData->Counter < mNumberOfCpus) {\r
     //\r
     // Send SMI IPIs to bring outside processors in\r
     //\r
     for (Index = mMaxNumberOfCpus; Index-- > 0;) {\r
-      if (!mSmmMpSyncData->CpuData[Index].Present && gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId != INVALID_APIC_ID) {\r
+      if (!(*(mSmmMpSyncData->CpuData[Index].Present)) && gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId != INVALID_APIC_ID) {\r
         SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId);\r
       }\r
     }\r
@@ -320,7 +323,7 @@ BSPHandler (
   //\r
   // Flag BSP's presence\r
   //\r
-  mSmmMpSyncData->InsideSmm = TRUE;\r
+  *mSmmMpSyncData->InsideSmm = TRUE;\r
 \r
   //\r
   // Initialize Debug Agent to start source level debug in BSP handler\r
@@ -330,7 +333,7 @@ BSPHandler (
   //\r
   // Mark this processor's presence\r
   //\r
-  mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;\r
+  *(mSmmMpSyncData->CpuData[CpuIndex].Present) = TRUE;\r
 \r
   //\r
   // Clear platform top level SMI status bit before calling SMI handlers. If\r
@@ -358,8 +361,8 @@ BSPHandler (
     //\r
     // Lock the counter down and retrieve the number of APs\r
     //\r
-    mSmmMpSyncData->AllCpusInSync = TRUE;\r
-    ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;\r
+    *mSmmMpSyncData->AllCpusInSync = TRUE;\r
+    ApCount = LockdownSemaphore (mSmmMpSyncData->Counter) - 1;\r
 \r
     //\r
     // Wait for all APs to get ready for programming MTRRs\r
@@ -409,18 +412,12 @@ BSPHandler (
   //\r
   // The BUSY lock is initialized to Acquired state\r
   //\r
-  AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
+  AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
 \r
   //\r
-  // Restore SMM Configuration in S3 boot path.\r
+  // Perform the pre tasks\r
   //\r
-  if (mRestoreSmmConfigurationInS3) {\r
-    //\r
-    // Configure SMM Code Access Check feature if available.\r
-    //\r
-    ConfigSmmCodeAccessCheck ();\r
-    mRestoreSmmConfigurationInS3 = FALSE;\r
-  }\r
+  PerformPreTasks ();\r
 \r
   //\r
   // Invoke SMM Foundation EntryPoint with the processor information context.\r
@@ -431,9 +428,9 @@ BSPHandler (
   // Make sure all APs have completed their pending none-block tasks\r
   //\r
   for (Index = mMaxNumberOfCpus; Index-- > 0;) {\r
-    if (Index != CpuIndex && mSmmMpSyncData->CpuData[Index].Present) {\r
-      AcquireSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);\r
-      ReleaseSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);;\r
+    if (Index != CpuIndex && *(mSmmMpSyncData->CpuData[Index].Present)) {\r
+      AcquireSpinLock (mSmmMpSyncData->CpuData[Index].Busy);\r
+      ReleaseSpinLock (mSmmMpSyncData->CpuData[Index].Busy);\r
     }\r
   }\r
 \r
@@ -452,15 +449,15 @@ BSPHandler (
     //\r
     // Lock the counter down and retrieve the number of APs\r
     //\r
-    mSmmMpSyncData->AllCpusInSync = TRUE;\r
-    ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;\r
+    *mSmmMpSyncData->AllCpusInSync = TRUE;\r
+    ApCount = LockdownSemaphore (mSmmMpSyncData->Counter) - 1;\r
     //\r
     // Make sure all APs have their Present flag set\r
     //\r
     while (TRUE) {\r
       PresentCount = 0;\r
       for (Index = mMaxNumberOfCpus; Index-- > 0;) {\r
-        if (mSmmMpSyncData->CpuData[Index].Present) {\r
+        if (*(mSmmMpSyncData->CpuData[Index].Present)) {\r
           PresentCount ++;\r
         }\r
       }\r
@@ -473,7 +470,7 @@ BSPHandler (
   //\r
   // Notify all APs to exit\r
   //\r
-  mSmmMpSyncData->InsideSmm = FALSE;\r
+  *mSmmMpSyncData->InsideSmm = FALSE;\r
   ReleaseAllAPs ();\r
 \r
   //\r
@@ -518,7 +515,7 @@ BSPHandler (
   //\r
   // Clear the Present flag of BSP\r
   //\r
-  mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;\r
+  *(mSmmMpSyncData->CpuData[CpuIndex].Present) = FALSE;\r
 \r
   //\r
   // Gather APs to exit SMM synchronously. Note the Present flag is cleared by now but\r
@@ -536,8 +533,8 @@ BSPHandler (
   //\r
   // Allow APs to check in from this point on\r
   //\r
-  mSmmMpSyncData->Counter = 0;\r
-  mSmmMpSyncData->AllCpusInSync = FALSE;\r
+  *mSmmMpSyncData->Counter = 0;\r
+  *mSmmMpSyncData->AllCpusInSync = FALSE;\r
 }\r
 \r
 /**\r
@@ -564,12 +561,12 @@ APHandler (
   //\r
   for (Timer = StartSyncTimer ();\r
        !IsSyncTimerTimeout (Timer) &&\r
-       !mSmmMpSyncData->InsideSmm;\r
+       !(*mSmmMpSyncData->InsideSmm);\r
        ) {\r
     CpuPause ();\r
   }\r
 \r
-  if (!mSmmMpSyncData->InsideSmm) {\r
+  if (!(*mSmmMpSyncData->InsideSmm)) {\r
     //\r
     // BSP timeout in the first round\r
     //\r
@@ -590,23 +587,23 @@ APHandler (
       //\r
       for (Timer = StartSyncTimer ();\r
            !IsSyncTimerTimeout (Timer) &&\r
-           !mSmmMpSyncData->InsideSmm;\r
+           !(*mSmmMpSyncData->InsideSmm);\r
            ) {\r
         CpuPause ();\r
       }\r
 \r
-      if (!mSmmMpSyncData->InsideSmm) {\r
+      if (!(*mSmmMpSyncData->InsideSmm)) {\r
         //\r
         // Give up since BSP is unable to enter SMM\r
         // and signal the completion of this AP\r
-        WaitForSemaphore (&mSmmMpSyncData->Counter);\r
+        WaitForSemaphore (mSmmMpSyncData->Counter);\r
         return;\r
       }\r
     } else {\r
       //\r
       // Don't know BSP index. Give up without sending IPI to BSP.\r
       //\r
-      WaitForSemaphore (&mSmmMpSyncData->Counter);\r
+      WaitForSemaphore (mSmmMpSyncData->Counter);\r
       return;\r
     }\r
   }\r
@@ -620,20 +617,20 @@ APHandler (
   //\r
   // Mark this processor's presence\r
   //\r
-  mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;\r
+  *(mSmmMpSyncData->CpuData[CpuIndex].Present) = TRUE;\r
 \r
   if (SyncMode == SmmCpuSyncModeTradition || SmmCpuFeaturesNeedConfigureMtrrs()) {\r
     //\r
     // Notify BSP of arrival at this point\r
     //\r
-    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);\r
+    ReleaseSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run);\r
   }\r
 \r
   if (SmmCpuFeaturesNeedConfigureMtrrs()) {\r
     //\r
     // Wait for the signal from BSP to backup MTRRs\r
     //\r
-    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);\r
+    WaitForSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);\r
 \r
     //\r
     // Backup OS MTRRs\r
@@ -643,12 +640,12 @@ APHandler (
     //\r
     // Signal BSP the completion of this AP\r
     //\r
-    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);\r
+    ReleaseSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run);\r
 \r
     //\r
     // Wait for BSP's signal to program MTRRs\r
     //\r
-    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);\r
+    WaitForSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);\r
 \r
     //\r
     // Replace OS MTRRs with SMI MTRRs\r
@@ -658,19 +655,19 @@ APHandler (
     //\r
     // Signal BSP the completion of this AP\r
     //\r
-    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);\r
+    ReleaseSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run);\r
   }\r
 \r
   while (TRUE) {\r
     //\r
     // Wait for something to happen\r
     //\r
-    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);\r
+    WaitForSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);\r
 \r
     //\r
     // Check if BSP wants to exit SMM\r
     //\r
-    if (!mSmmMpSyncData->InsideSmm) {\r
+    if (!(*mSmmMpSyncData->InsideSmm)) {\r
       break;\r
     }\r
 \r
@@ -678,7 +675,7 @@ APHandler (
     // BUSY should be acquired by SmmStartupThisAp()\r
     //\r
     ASSERT (\r
-      !AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy)\r
+      !AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy)\r
       );\r
 \r
     //\r
@@ -691,19 +688,19 @@ APHandler (
     //\r
     // Release BUSY\r
     //\r
-    ReleaseSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
+    ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
   }\r
 \r
   if (SmmCpuFeaturesNeedConfigureMtrrs()) {\r
     //\r
     // Notify BSP the readiness of this AP to program MTRRs\r
     //\r
-    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);\r
+    ReleaseSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run);\r
 \r
     //\r
     // Wait for the signal from BSP to program MTRRs\r
     //\r
-    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);\r
+    WaitForSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);\r
 \r
     //\r
     // Restore OS MTRRs\r
@@ -715,22 +712,22 @@ APHandler (
   //\r
   // Notify BSP the readiness of this AP to Reset states/semaphore for this processor\r
   //\r
-  ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);\r
+  ReleaseSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run);\r
 \r
   //\r
   // Wait for the signal from BSP to Reset states/semaphore for this processor\r
   //\r
-  WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);\r
+  WaitForSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);\r
 \r
   //\r
   // Reset states/semaphore for this processor\r
   //\r
-  mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;\r
+  *(mSmmMpSyncData->CpuData[CpuIndex].Present) = FALSE;\r
 \r
   //\r
   // Notify BSP the readiness of this AP to exit SMM\r
   //\r
-  ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);\r
+  ReleaseSemaphore (mSmmMpSyncData->CpuData[BspIndex].Run);\r
 \r
 }\r
 \r
@@ -738,12 +735,14 @@ APHandler (
   Create 4G PageTable in SMRAM.\r
 \r
   @param          ExtraPages       Additional page numbers besides for 4G memory\r
+  @param          Is32BitPageTable Whether the page table is 32-bit PAE\r
   @return         PageTable Address\r
 \r
 **/\r
 UINT32\r
 Gen4GPageTable (\r
-  IN      UINTN                     ExtraPages\r
+  IN      UINTN                     ExtraPages,\r
+  IN      BOOLEAN                   Is32BitPageTable\r
   )\r
 {\r
   VOID    *PageTable;\r
@@ -776,7 +775,7 @@ Gen4GPageTable (
   //\r
   // Allocate the page table\r
   //\r
-  PageTable = AllocatePages (ExtraPages + 5 + PagesNeeded);\r
+  PageTable = AllocatePageTableMemory (ExtraPages + 5 + PagesNeeded);\r
   ASSERT (PageTable != NULL);\r
 \r
   PageTable = (VOID *)((UINTN)PageTable + EFI_PAGES_TO_SIZE (ExtraPages));\r
@@ -791,7 +790,7 @@ Gen4GPageTable (
   // Set Page Directory Pointers\r
   //\r
   for (Index = 0; Index < 4; Index++) {\r
-    Pte[Index] = (UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1) + IA32_PG_P;\r
+    Pte[Index] = (UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1) + (Is32BitPageTable ? IA32_PAE_PDPTE_ATTRIBUTE_BITS : PAGE_ATTRIBUTE_BITS);\r
   }\r
   Pte += EFI_PAGE_SIZE / sizeof (*Pte);\r
 \r
@@ -799,7 +798,7 @@ Gen4GPageTable (
   // Fill in Page Directory Entries\r
   //\r
   for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) {\r
-    Pte[Index] = (Index << 21) + IA32_PG_PS + IA32_PG_RW + IA32_PG_P;\r
+    Pte[Index] = (Index << 21) | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;\r
   }\r
 \r
   if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
@@ -808,7 +807,7 @@ Gen4GPageTable (
     Pdpte = (UINT64*)PageTable;\r
     for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) {\r
       Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~(EFI_PAGE_SIZE - 1));\r
-      Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages + IA32_PG_RW + IA32_PG_P;\r
+      Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | PAGE_ATTRIBUTE_BITS;\r
       //\r
       // Fill in Page Table Entries\r
       //\r
@@ -825,7 +824,7 @@ Gen4GPageTable (
             GuardPage = 0;\r
           }\r
         } else {\r
-          Pte[Index] = PageAddress + IA32_PG_RW + IA32_PG_P;\r
+          Pte[Index] = PageAddress | PAGE_ATTRIBUTE_BITS;\r
         }\r
         PageAddress+= EFI_PAGE_SIZE;\r
       }\r
@@ -878,7 +877,7 @@ SetCacheability (
     //\r
     // Allocate a page from SMRAM\r
     //\r
-    NewPageTableAddress = AllocatePages (1);\r
+    NewPageTableAddress = AllocatePageTableMemory (1);\r
     ASSERT (NewPageTableAddress != NULL);\r
 \r
     NewPageTable = (UINT64 *)NewPageTableAddress;\r
@@ -892,7 +891,7 @@ SetCacheability (
       NewPageTable[Index] |= (UINT64)(Index << EFI_PAGE_SHIFT);\r
     }\r
 \r
-    PageTable[PTIndex] = ((UINTN)NewPageTableAddress & gPhyMask) | IA32_PG_P;\r
+    PageTable[PTIndex] = ((UINTN)NewPageTableAddress & gPhyMask) | PAGE_ATTRIBUTE_BITS;\r
   }\r
 \r
   ASSERT (PageTable[PTIndex] & IA32_PG_P);\r
@@ -929,23 +928,82 @@ SmmStartupThisAp (
 {\r
   if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus ||\r
       CpuIndex == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu ||\r
-      !mSmmMpSyncData->CpuData[CpuIndex].Present ||\r
+      !(*(mSmmMpSyncData->CpuData[CpuIndex].Present)) ||\r
       gSmmCpuPrivate->Operation[CpuIndex] == SmmCpuRemove ||\r
-      !AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy)) {\r
+      !AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;\r
   mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;\r
-  ReleaseSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);\r
+  ReleaseSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);\r
 \r
   if (FeaturePcdGet (PcdCpuSmmBlockStartupThisAp)) {\r
-    AcquireSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
-    ReleaseSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
+    AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
+    ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
   }\r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This function sets DR6 & DR7 according to SMM save state, before running SMM C code.\r
+  They are useful when you want to enable hardware breakpoints in SMM without entry SMM mode.\r
+\r
+  NOTE: It might not be appreciated in runtime since it might\r
+        conflict with OS debugging facilities. Turn them off in RELEASE.\r
+\r
+  @param    CpuIndex              CPU Index\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CpuSmmDebugEntry (\r
+  IN UINTN  CpuIndex\r
+  )\r
+{\r
+  SMRAM_SAVE_STATE_MAP *CpuSaveState;\r
+  \r
+  if (FeaturePcdGet (PcdCpuSmmDebug)) {\r
+    CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmmCpuPrivate->CpuSaveState[CpuIndex];\r
+    if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {\r
+      AsmWriteDr6 (CpuSaveState->x86._DR6);\r
+      AsmWriteDr7 (CpuSaveState->x86._DR7);\r
+    } else {\r
+      AsmWriteDr6 ((UINTN)CpuSaveState->x64._DR6);\r
+      AsmWriteDr7 ((UINTN)CpuSaveState->x64._DR7);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  This function restores DR6 & DR7 to SMM save state.\r
+\r
+  NOTE: It might not be appreciated in runtime since it might\r
+        conflict with OS debugging facilities. Turn them off in RELEASE.\r
+\r
+  @param    CpuIndex              CPU Index\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CpuSmmDebugExit (\r
+  IN UINTN  CpuIndex\r
+  )\r
+{\r
+  SMRAM_SAVE_STATE_MAP *CpuSaveState;\r
+\r
+  if (FeaturePcdGet (PcdCpuSmmDebug)) {\r
+    CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmmCpuPrivate->CpuSaveState[CpuIndex];\r
+    if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {\r
+      CpuSaveState->x86._DR7 = (UINT32)AsmReadDr7 ();\r
+      CpuSaveState->x86._DR6 = (UINT32)AsmReadDr6 ();\r
+    } else {\r
+      CpuSaveState->x64._DR7 = AsmReadDr7 ();\r
+      CpuSaveState->x64._DR6 = AsmReadDr6 ();\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   C function for SMI entry, each processor comes here upon SMI trigger.\r
 \r
@@ -958,12 +1016,14 @@ SmiRendezvous (
   IN      UINTN                     CpuIndex\r
   )\r
 {\r
-  EFI_STATUS        Status;\r
-  BOOLEAN           ValidSmi;\r
-  BOOLEAN           IsBsp;\r
-  BOOLEAN           BspInProgress;\r
-  UINTN             Index;\r
-  UINTN             Cr2;\r
+  EFI_STATUS                     Status;\r
+  BOOLEAN                        ValidSmi;\r
+  BOOLEAN                        IsBsp;\r
+  BOOLEAN                        BspInProgress;\r
+  UINTN                          Index;\r
+  UINTN                          Cr2;\r
+  BOOLEAN                        XdDisableFlag;\r
+  MSR_IA32_MISC_ENABLE_REGISTER  MiscEnableMsr;\r
 \r
   //\r
   // Save Cr2 because Page Fault exception in SMM may override its value\r
@@ -984,7 +1044,7 @@ SmiRendezvous (
   // Determine if BSP has been already in progress. Note this must be checked after\r
   // ValidSmi because BSP may clear a valid SMI source after checking in.\r
   //\r
-  BspInProgress = mSmmMpSyncData->InsideSmm;\r
+  BspInProgress = *mSmmMpSyncData->InsideSmm;\r
 \r
   if (!BspInProgress && !ValidSmi) {\r
     //\r
@@ -999,7 +1059,7 @@ SmiRendezvous (
     //\r
     // Signal presence of this processor\r
     //\r
-    if (ReleaseSemaphore (&mSmmMpSyncData->Counter) == 0) {\r
+    if (ReleaseSemaphore (mSmmMpSyncData->Counter) == 0) {\r
       //\r
       // BSP has already ended the synchronization, so QUIT!!!\r
       //\r
@@ -1007,7 +1067,7 @@ SmiRendezvous (
       //\r
       // Wait for BSP's signal to finish SMI\r
       //\r
-      while (mSmmMpSyncData->AllCpusInSync) {\r
+      while (*mSmmMpSyncData->AllCpusInSync) {\r
         CpuPause ();\r
       }\r
       goto Exit;\r
@@ -1019,13 +1079,20 @@ SmiRendezvous (
       // E.g., with Relaxed AP flow, SmmStartupThisAp() may be called immediately\r
       // after AP's present flag is detected.\r
       //\r
-      InitializeSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
+      InitializeSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
     }\r
 \r
     //\r
-    // Try to enable NX\r
+    // Try to enable XD\r
     //\r
+    XdDisableFlag = FALSE;\r
     if (mXdSupported) {\r
+      MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);\r
+      if (MiscEnableMsr.Bits.XD == 1) {\r
+        XdDisableFlag = TRUE;\r
+        MiscEnableMsr.Bits.XD = 0;\r
+        AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MiscEnableMsr.Uint64);\r
+      }\r
       ActivateXd ();\r
     }\r
 \r
@@ -1097,19 +1164,27 @@ SmiRendezvous (
         // BSP Handler is always called with a ValidSmi == TRUE\r
         //\r
         BSPHandler (CpuIndex, mSmmMpSyncData->EffectiveSyncMode);\r
-\r
       } else {\r
         APHandler (CpuIndex, ValidSmi, mSmmMpSyncData->EffectiveSyncMode);\r
       }\r
     }\r
 \r
-    ASSERT (mSmmMpSyncData->CpuData[CpuIndex].Run == 0);\r
+    ASSERT (*mSmmMpSyncData->CpuData[CpuIndex].Run == 0);\r
 \r
     //\r
     // Wait for BSP's signal to exit SMI\r
     //\r
-    while (mSmmMpSyncData->AllCpusInSync) {\r
+    while (*mSmmMpSyncData->AllCpusInSync) {\r
       CpuPause ();\r
+     }\r
+\r
+    //\r
+    // Restore XD\r
+    //\r
+    if (XdDisableFlag) {\r
+      MiscEnableMsr.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);\r
+      MiscEnableMsr.Bits.XD = 1;\r
+      AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MiscEnableMsr.Uint64);\r
     }\r
   }\r
 \r
@@ -1121,6 +1196,67 @@ Exit:
   AsmWriteCr2 (Cr2);\r
 }\r
 \r
+/**\r
+  Allocate buffer for all semaphores and spin locks.\r
+\r
+**/\r
+VOID\r
+InitializeSmmCpuSemaphores (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                      ProcessorCount;\r
+  UINTN                      TotalSize;\r
+  UINTN                      GlobalSemaphoresSize;\r
+  UINTN                      CpuSemaphoresSize;\r
+  UINTN                      MsrSemahporeSize;\r
+  UINTN                      SemaphoreSize;\r
+  UINTN                      Pages;\r
+  UINTN                      *SemaphoreBlock;\r
+  UINTN                      SemaphoreAddr;\r
+\r
+  SemaphoreSize   = GetSpinLockProperties ();\r
+  ProcessorCount = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
+  GlobalSemaphoresSize = (sizeof (SMM_CPU_SEMAPHORE_GLOBAL) / sizeof (VOID *)) * SemaphoreSize;\r
+  CpuSemaphoresSize    = (sizeof (SMM_CPU_SEMAPHORE_CPU) / sizeof (VOID *)) * ProcessorCount * SemaphoreSize;\r
+  MsrSemahporeSize     = MSR_SPIN_LOCK_INIT_NUM * SemaphoreSize;\r
+  TotalSize = GlobalSemaphoresSize + CpuSemaphoresSize + MsrSemahporeSize;\r
+  DEBUG((EFI_D_INFO, "One Semaphore Size    = 0x%x\n", SemaphoreSize));\r
+  DEBUG((EFI_D_INFO, "Total Semaphores Size = 0x%x\n", TotalSize));\r
+  Pages = EFI_SIZE_TO_PAGES (TotalSize);\r
+  SemaphoreBlock = AllocatePages (Pages);\r
+  ASSERT (SemaphoreBlock != NULL);\r
+  ZeroMem (SemaphoreBlock, TotalSize);\r
+\r
+  SemaphoreAddr = (UINTN)SemaphoreBlock;\r
+  mSmmCpuSemaphores.SemaphoreGlobal.Counter       = (UINT32 *)SemaphoreAddr;\r
+  SemaphoreAddr += SemaphoreSize;\r
+  mSmmCpuSemaphores.SemaphoreGlobal.InsideSmm     = (BOOLEAN *)SemaphoreAddr;\r
+  SemaphoreAddr += SemaphoreSize;\r
+  mSmmCpuSemaphores.SemaphoreGlobal.AllCpusInSync = (BOOLEAN *)SemaphoreAddr;\r
+  SemaphoreAddr += SemaphoreSize;\r
+  mSmmCpuSemaphores.SemaphoreGlobal.PFLock        = (SPIN_LOCK *)SemaphoreAddr;\r
+  SemaphoreAddr += SemaphoreSize;\r
+  mSmmCpuSemaphores.SemaphoreGlobal.CodeAccessCheckLock\r
+                                                  = (SPIN_LOCK *)SemaphoreAddr;\r
+  SemaphoreAddr = (UINTN)SemaphoreBlock + GlobalSemaphoresSize;\r
+  mSmmCpuSemaphores.SemaphoreCpu.Busy    = (SPIN_LOCK *)SemaphoreAddr;\r
+  SemaphoreAddr += ProcessorCount * SemaphoreSize;\r
+  mSmmCpuSemaphores.SemaphoreCpu.Run     = (UINT32 *)SemaphoreAddr;\r
+  SemaphoreAddr += ProcessorCount * SemaphoreSize;\r
+  mSmmCpuSemaphores.SemaphoreCpu.Present = (BOOLEAN *)SemaphoreAddr;\r
+\r
+  SemaphoreAddr = (UINTN)SemaphoreBlock + GlobalSemaphoresSize + CpuSemaphoresSize;\r
+  mSmmCpuSemaphores.SemaphoreMsr.Msr              = (SPIN_LOCK *)SemaphoreAddr;\r
+  mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter =\r
+        ((UINTN)SemaphoreBlock + Pages * SIZE_4KB - SemaphoreAddr) / SemaphoreSize;\r
+  ASSERT (mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter >= MSR_SPIN_LOCK_INIT_NUM);\r
+\r
+  mPFLock                       = mSmmCpuSemaphores.SemaphoreGlobal.PFLock;\r
+  mConfigSmmCodeAccessCheckLock = mSmmCpuSemaphores.SemaphoreGlobal.CodeAccessCheckLock;\r
+\r
+  mSemaphoreSize = SemaphoreSize;\r
+}\r
 \r
 /**\r
   Initialize un-cacheable data.\r
@@ -1132,8 +1268,10 @@ InitializeMpSyncData (
   VOID\r
   )\r
 {\r
+  UINTN                      CpuIndex;\r
+\r
   if (mSmmMpSyncData != NULL) {\r
-    ZeroMem (mSmmMpSyncData, mSmmMpSyncDataSize);\r
+    mSmmMpSyncData->SwitchBsp = FALSE;\r
     mSmmMpSyncData->CpuData = (SMM_CPU_DATA_BLOCK *)((UINT8 *)mSmmMpSyncData + sizeof (SMM_DISPATCHER_MP_SYNC_DATA));\r
     mSmmMpSyncData->CandidateBsp = (BOOLEAN *)(mSmmMpSyncData->CpuData + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus);\r
     if (FeaturePcdGet (PcdCpuSmmEnableBspElection)) {\r
@@ -1143,6 +1281,24 @@ InitializeMpSyncData (
       mSmmMpSyncData->BspIndex = (UINT32)-1;\r
     }\r
     mSmmMpSyncData->EffectiveSyncMode = (SMM_CPU_SYNC_MODE) PcdGet8 (PcdCpuSmmSyncMode);\r
+\r
+    mSmmMpSyncData->Counter       = mSmmCpuSemaphores.SemaphoreGlobal.Counter;\r
+    mSmmMpSyncData->InsideSmm     = mSmmCpuSemaphores.SemaphoreGlobal.InsideSmm;\r
+    mSmmMpSyncData->AllCpusInSync = mSmmCpuSemaphores.SemaphoreGlobal.AllCpusInSync;\r
+    ASSERT (mSmmMpSyncData->Counter != NULL && mSmmMpSyncData->InsideSmm != NULL &&\r
+            mSmmMpSyncData->AllCpusInSync != NULL);\r
+    *mSmmMpSyncData->Counter       = 0;\r
+    *mSmmMpSyncData->InsideSmm     = FALSE;\r
+    *mSmmMpSyncData->AllCpusInSync = FALSE;\r
+\r
+    for (CpuIndex = 0; CpuIndex < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; CpuIndex ++) {\r
+      mSmmMpSyncData->CpuData[CpuIndex].Busy    =\r
+        (SPIN_LOCK *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Busy + mSemaphoreSize * CpuIndex);\r
+      mSmmMpSyncData->CpuData[CpuIndex].Run     =\r
+        (UINT32 *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Run + mSemaphoreSize * CpuIndex);\r
+      mSmmMpSyncData->CpuData[CpuIndex].Present =\r
+        (BOOLEAN *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Present + mSemaphoreSize * CpuIndex);\r
+    }\r
   }\r
 }\r
 \r
@@ -1166,6 +1322,20 @@ InitializeMpServiceData (
   UINT8                     *GdtTssTables;\r
   UINTN                     GdtTableStepSize;\r
 \r
+  //\r
+  // Allocate memory for all locks and semaphores\r
+  //\r
+  InitializeSmmCpuSemaphores ();\r
+\r
+  //\r
+  // Initialize mSmmMpSyncData\r
+  //\r
+  mSmmMpSyncDataSize = sizeof (SMM_DISPATCHER_MP_SYNC_DATA) +\r
+                       (sizeof (SMM_CPU_DATA_BLOCK) + sizeof (BOOLEAN)) * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
+  mSmmMpSyncData = (SMM_DISPATCHER_MP_SYNC_DATA*) AllocatePages (EFI_SIZE_TO_PAGES (mSmmMpSyncDataSize));\r
+  ASSERT (mSmmMpSyncData != NULL);\r
+  InitializeMpSyncData ();\r
+\r
   //\r
   // Initialize physical address mask\r
   // NOTE: Physical memory above virtual address limit is not supported !!!\r
@@ -1206,15 +1376,6 @@ InitializeMpServiceData (
       );\r
   }\r
 \r
-  //\r
-  // Initialize mSmmMpSyncData\r
-  //\r
-  mSmmMpSyncDataSize = sizeof (SMM_DISPATCHER_MP_SYNC_DATA) +\r
-                       (sizeof (SMM_CPU_DATA_BLOCK) + sizeof (BOOLEAN)) * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
-  mSmmMpSyncData = (SMM_DISPATCHER_MP_SYNC_DATA*) AllocatePages (EFI_SIZE_TO_PAGES (mSmmMpSyncDataSize));\r
-  ASSERT (mSmmMpSyncData != NULL);\r
-  InitializeMpSyncData ();\r
-\r
   //\r
   // Record current MTRR settings\r
   //\r