]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
UefiCpuPkg/PiSmmCpuDxeSmm: Improve the performance of GetFreeToken()
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / CpuS3.c
index a45e2dd3d7aaac7eec0fc5182d64f8a265bff6e3..29e9ba92b453ea7760d220c395d4601cb93f2a0d 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
 Code for Processor S3 restoration\r
 \r
-Copyright (c) 2006 - 2018, 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -41,9 +35,11 @@ typedef struct {
 // Flags used when program the register.\r
 //\r
 typedef struct {\r
-  volatile UINTN           ConsoleLogLock;       // Spinlock used to control console.\r
-  volatile UINTN           MemoryMappedLock;     // Spinlock used to program mmio\r
-  volatile UINT32          *SemaphoreCount;      // Semaphore used to program semaphore.\r
+  volatile UINTN           MemoryMappedLock;        // Spinlock used to program mmio\r
+  volatile UINT32          *CoreSemaphoreCount;     // Semaphore container used to program\r
+                                                    // core level semaphore.\r
+  volatile UINT32          *PackageSemaphoreCount;  // Semaphore container used to program\r
+                                                    // package level semaphore.\r
 } PROGRAM_CPU_REGISTER_FLAGS;\r
 \r
 //\r
@@ -93,8 +89,6 @@ UINT8                        mApHltLoopCodeTemplate[] = {
                                0xEB, 0xFC               // jmp $-2\r
                                };\r
 \r
-CHAR16 *mRegisterTypeStr[] = {L"MSR", L"CR", L"MMIO", L"CACHE", L"SEMAP", L"INVALID" };\r
-\r
 /**\r
   Sync up the MTRR values for all processors.\r
 \r
@@ -165,6 +159,58 @@ S3WaitForSemaphore (
              ) != Value);\r
 }\r
 \r
+/**\r
+  Read / write CR value.\r
+\r
+  @param[in]      CrIndex         The CR index which need to read/write.\r
+  @param[in]      Read            Read or write. TRUE is read.\r
+  @param[in,out]  CrValue         CR value.\r
+\r
+  @retval    EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.\r
+**/\r
+UINTN\r
+ReadWriteCr (\r
+  IN     UINT32       CrIndex,\r
+  IN     BOOLEAN      Read,\r
+  IN OUT UINTN        *CrValue\r
+  )\r
+{\r
+  switch (CrIndex) {\r
+  case 0:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr0 ();\r
+    } else {\r
+      AsmWriteCr0 (*CrValue);\r
+    }\r
+    break;\r
+  case 2:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr2 ();\r
+    } else {\r
+      AsmWriteCr2 (*CrValue);\r
+    }\r
+    break;\r
+  case 3:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr3 ();\r
+    } else {\r
+      AsmWriteCr3 (*CrValue);\r
+    }\r
+    break;\r
+  case 4:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr4 ();\r
+    } else {\r
+      AsmWriteCr4 (*CrValue);\r
+    }\r
+    break;\r
+  default:\r
+    return EFI_UNSUPPORTED;;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Initialize the CPU registers from a register table.\r
 \r
@@ -192,9 +238,10 @@ ProgramProcessorRegister (
   UINT32                    PackageThreadsCount;\r
   UINT32                    CurrentThread;\r
   UINTN                     ProcessorIndex;\r
-  UINTN                     ThreadIndex;\r
   UINTN                     ValidThreadCount;\r
   UINT32                    *ValidCoreCountPerPackage;\r
+  EFI_STATUS                Status;\r
+  UINT64                    CurrentValue;\r
 \r
   //\r
   // Traverse Register Table of this logical processor\r
@@ -205,23 +252,6 @@ ProgramProcessorRegister (
 \r
     RegisterTableEntry = &RegisterTableEntryHead[Index];\r
 \r
-    DEBUG_CODE_BEGIN ();\r
-      if (ApLocation != NULL) {\r
-        AcquireSpinLock (&CpuFlags->ConsoleLogLock);\r
-        ThreadIndex = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount +\r
-              ApLocation->Core * CpuStatus->MaxThreadCount +\r
-              ApLocation->Thread;\r
-        DEBUG ((\r
-          DEBUG_INFO,\r
-          "Processor = %lu, Entry Index %lu, Type = %s!\n",\r
-          (UINT64)ThreadIndex,\r
-          (UINT64)Index,\r
-          mRegisterTypeStr[MIN ((REGISTER_TYPE)RegisterTableEntry->RegisterType, InvalidReg)]\r
-          ));\r
-        ReleaseSpinLock (&CpuFlags->ConsoleLogLock);\r
-      }\r
-    DEBUG_CODE_END ();\r
-\r
     //\r
     // Check the type of specified register\r
     //\r
@@ -230,55 +260,50 @@ ProgramProcessorRegister (
     // The specified register is Control Register\r
     //\r
     case ControlRegister:\r
-      switch (RegisterTableEntry->Index) {\r
-      case 0:\r
-        Value = AsmReadCr0 ();\r
-        Value = (UINTN) BitFieldWrite64 (\r
-                          Value,\r
-                          RegisterTableEntry->ValidBitStart,\r
-                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
-                          (UINTN) RegisterTableEntry->Value\r
-                          );\r
-        AsmWriteCr0 (Value);\r
-        break;\r
-      case 2:\r
-        Value = AsmReadCr2 ();\r
-        Value = (UINTN) BitFieldWrite64 (\r
-                          Value,\r
-                          RegisterTableEntry->ValidBitStart,\r
-                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
-                          (UINTN) RegisterTableEntry->Value\r
-                          );\r
-        AsmWriteCr2 (Value);\r
-        break;\r
-      case 3:\r
-        Value = AsmReadCr3 ();\r
-        Value = (UINTN) BitFieldWrite64 (\r
-                          Value,\r
-                          RegisterTableEntry->ValidBitStart,\r
-                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
-                          (UINTN) RegisterTableEntry->Value\r
-                          );\r
-        AsmWriteCr3 (Value);\r
-        break;\r
-      case 4:\r
-        Value = AsmReadCr4 ();\r
-        Value = (UINTN) BitFieldWrite64 (\r
-                          Value,\r
-                          RegisterTableEntry->ValidBitStart,\r
-                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
-                          (UINTN) RegisterTableEntry->Value\r
-                          );\r
-        AsmWriteCr4 (Value);\r
-        break;\r
-      default:\r
+      Status = ReadWriteCr (RegisterTableEntry->Index, TRUE, &Value);\r
+      if (EFI_ERROR (Status)) {\r
         break;\r
       }\r
+      if (RegisterTableEntry->TestThenWrite) {\r
+        CurrentValue = BitFieldRead64 (\r
+                         Value,\r
+                         RegisterTableEntry->ValidBitStart,\r
+                         RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
+                         );\r
+        if (CurrentValue == RegisterTableEntry->Value) {\r
+          break;\r
+        }\r
+      }\r
+      Value = (UINTN) BitFieldWrite64 (\r
+                        Value,\r
+                        RegisterTableEntry->ValidBitStart,\r
+                        RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
+                        RegisterTableEntry->Value\r
+                        );\r
+      ReadWriteCr (RegisterTableEntry->Index, FALSE, &Value);\r
       break;\r
     //\r
     // The specified register is Model Specific Register\r
     //\r
     case Msr:\r
+      if (RegisterTableEntry->TestThenWrite) {\r
+        Value = (UINTN)AsmReadMsr64 (RegisterTableEntry->Index);\r
+        if (RegisterTableEntry->ValidBitLength >= 64) {\r
+          if (Value == RegisterTableEntry->Value) {\r
+            break;\r
+          }\r
+        } else {\r
+          CurrentValue = BitFieldRead64 (\r
+                           Value,\r
+                           RegisterTableEntry->ValidBitStart,\r
+                           RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
+                           );\r
+          if (CurrentValue == RegisterTableEntry->Value) {\r
+            break;\r
+          }\r
+        }\r
+      }\r
+\r
       //\r
       // If this function is called to restore register setting after INIT signal,\r
       // there is no need to restore MSRs in register table.\r
@@ -348,11 +373,12 @@ ProgramProcessorRegister (
       ASSERT (\r
         (ApLocation != NULL) &&\r
         (CpuStatus->ValidCoreCountPerPackage != 0) &&\r
-        (CpuFlags->SemaphoreCount) != NULL\r
+        (CpuFlags->CoreSemaphoreCount != NULL) &&\r
+        (CpuFlags->PackageSemaphoreCount != NULL)\r
         );\r
-      SemaphorePtr = CpuFlags->SemaphoreCount;\r
       switch (RegisterTableEntry->Value) {\r
       case CoreDepType:\r
+        SemaphorePtr = CpuFlags->CoreSemaphoreCount;\r
         //\r
         // Get Offset info for the first thread in the core which current thread belongs to.\r
         //\r
@@ -373,6 +399,7 @@ ProgramProcessorRegister (
         break;\r
 \r
       case PackageDepType:\r
+        SemaphorePtr = CpuFlags->PackageSemaphoreCount;\r
         ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;\r
         //\r
         // Get Offset info for the first thread in the package which current thread belongs to.\r
@@ -589,7 +616,12 @@ InitializeCpuBeforeRebase (
 \r
   PrepareApStartupVector (mAcpiCpuData.StartupVector);\r
 \r
-  mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;\r
+  if (FeaturePcdGet (PcdCpuHotPlugSupport)) {\r
+    ASSERT (mNumberOfCpus <= mAcpiCpuData.NumberOfCpus);\r
+  } else {\r
+    ASSERT (mNumberOfCpus == mAcpiCpuData.NumberOfCpus);\r
+  }\r
+  mNumberToFinish = (UINT32)(mNumberOfCpus - 1);\r
   mExchangeInfo->ApFunction  = (VOID *) (UINTN) InitializeAp;\r
 \r
   //\r
@@ -619,7 +651,12 @@ InitializeCpuAfterRebase (
   VOID\r
   )\r
 {\r
-  mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;\r
+  if (FeaturePcdGet (PcdCpuHotPlugSupport)) {\r
+    ASSERT (mNumberOfCpus <= mAcpiCpuData.NumberOfCpus);\r
+  } else {\r
+    ASSERT (mNumberOfCpus == mAcpiCpuData.NumberOfCpus);\r
+  }\r
+  mNumberToFinish = (UINT32)(mNumberOfCpus - 1);\r
 \r
   //\r
   // Signal that SMM base relocation is complete and to continue initialization for all APs.\r
@@ -1037,13 +1074,18 @@ GetAcpiCpuData (
     ASSERT (mAcpiCpuData.ApLocation != 0);\r
   }\r
   if (CpuStatus->PackageCount != 0) {\r
-    mCpuFlags.SemaphoreCount = AllocateZeroPool (\r
-                                 sizeof (UINT32) * CpuStatus->PackageCount *\r
-                                 CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
-    ASSERT (mCpuFlags.SemaphoreCount != NULL);\r
+    mCpuFlags.CoreSemaphoreCount = AllocateZeroPool (\r
+                                     sizeof (UINT32) * CpuStatus->PackageCount *\r
+                                     CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount\r
+                                     );\r
+    ASSERT (mCpuFlags.CoreSemaphoreCount != NULL);\r
+    mCpuFlags.PackageSemaphoreCount = AllocateZeroPool (\r
+                                        sizeof (UINT32) * CpuStatus->PackageCount *\r
+                                        CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount\r
+                                        );\r
+    ASSERT (mCpuFlags.PackageSemaphoreCount != NULL);\r
   }\r
   InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock);\r
-  InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.ConsoleLogLock);\r
 }\r
 \r
 /**\r