/** @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
// 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
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
) != 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
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
\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
// 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
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
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
\r
InitApicId = GetInitialApicId ();\r
RegisterTable = NULL;\r
+ ProcIndex = (UINTN)-1;\r
for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {\r
if (RegisterTables[Index].InitialApicId == InitApicId) {\r
RegisterTable = &RegisterTables[Index];\r
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