]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: Allocate AP reset vector buffer under 1MB
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
index f05db7c2a5dc7420b5e63f4a4db4b9e370fb8b86..8dfbf5706ae45b817db8aef390a90d3118cc3627 100644 (file)
 \r
 #include "MpLib.h"\r
 \r
+EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;\r
+\r
+/**\r
+  Get the Application Processors state.\r
+\r
+  @param[in]  CpuData    The pointer to CPU_AP_DATA of specified AP\r
+\r
+  @return  The AP status\r
+**/\r
+CPU_STATE\r
+GetApState (\r
+  IN  CPU_AP_DATA     *CpuData\r
+  )\r
+{\r
+  return CpuData->State;\r
+}\r
+\r
+/**\r
+  Set the Application Processors state.\r
+\r
+  @param[in]   CpuData    The pointer to CPU_AP_DATA of specified AP\r
+  @param[in]   State      The AP status\r
+**/\r
+VOID\r
+SetApState (\r
+  IN  CPU_AP_DATA     *CpuData,\r
+  IN  CPU_STATE       State\r
+  )\r
+{\r
+  AcquireSpinLock (&CpuData->ApLock);\r
+  CpuData->State = State;\r
+  ReleaseSpinLock (&CpuData->ApLock);\r
+}\r
+\r
+/**\r
+  Save the volatile registers required to be restored following INIT IPI.\r
+\r
+  @param[out]  VolatileRegisters    Returns buffer saved the volatile resisters\r
+**/\r
+VOID\r
+SaveVolatileRegisters (\r
+  OUT CPU_VOLATILE_REGISTERS    *VolatileRegisters\r
+  )\r
+{\r
+  CPUID_VERSION_INFO_EDX        VersionInfoEdx;\r
+\r
+  VolatileRegisters->Cr0 = AsmReadCr0 ();\r
+  VolatileRegisters->Cr3 = AsmReadCr3 ();\r
+  VolatileRegisters->Cr4 = AsmReadCr4 ();\r
+\r
+  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);\r
+  if (VersionInfoEdx.Bits.DE != 0) {\r
+    //\r
+    // If processor supports Debugging Extensions feature\r
+    // by CPUID.[EAX=01H]:EDX.BIT2\r
+    //\r
+    VolatileRegisters->Dr0 = AsmReadDr0 ();\r
+    VolatileRegisters->Dr1 = AsmReadDr1 ();\r
+    VolatileRegisters->Dr2 = AsmReadDr2 ();\r
+    VolatileRegisters->Dr3 = AsmReadDr3 ();\r
+    VolatileRegisters->Dr6 = AsmReadDr6 ();\r
+    VolatileRegisters->Dr7 = AsmReadDr7 ();\r
+  }\r
+}\r
+\r
+/**\r
+  Restore the volatile registers following INIT IPI.\r
+\r
+  @param[in]  VolatileRegisters   Pointer to volatile resisters\r
+  @param[in]  IsRestoreDr         TRUE:  Restore DRx if supported\r
+                                  FALSE: Do not restore DRx\r
+**/\r
+VOID\r
+RestoreVolatileRegisters (\r
+  IN CPU_VOLATILE_REGISTERS    *VolatileRegisters,\r
+  IN BOOLEAN                   IsRestoreDr\r
+  )\r
+{\r
+  CPUID_VERSION_INFO_EDX        VersionInfoEdx;\r
+\r
+  AsmWriteCr0 (VolatileRegisters->Cr0);\r
+  AsmWriteCr3 (VolatileRegisters->Cr3);\r
+  AsmWriteCr4 (VolatileRegisters->Cr4);\r
+\r
+  if (IsRestoreDr) {\r
+    AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);\r
+    if (VersionInfoEdx.Bits.DE != 0) {\r
+      //\r
+      // If processor supports Debugging Extensions feature\r
+      // by CPUID.[EAX=01H]:EDX.BIT2\r
+      //\r
+      AsmWriteDr0 (VolatileRegisters->Dr0);\r
+      AsmWriteDr1 (VolatileRegisters->Dr1);\r
+      AsmWriteDr2 (VolatileRegisters->Dr2);\r
+      AsmWriteDr3 (VolatileRegisters->Dr3);\r
+      AsmWriteDr6 (VolatileRegisters->Dr6);\r
+      AsmWriteDr7 (VolatileRegisters->Dr7);\r
+    }\r
+  }\r
+}\r
 \r
 /**\r
   Detect whether Mwait-monitor feature is supported.\r
@@ -74,6 +174,40 @@ GetApLoopMode (
 \r
   return ApLoopMode;\r
 }\r
+/*\r
+  Initialize CPU AP Data when AP is wakeup at the first time.\r
+\r
+  @param[in, out] CpuMpData        Pointer to PEI CPU MP Data\r
+  @param[in]      ProcessorNumber  The handle number of processor\r
+  @param[in]      BistData         Processor BIST data\r
+\r
+**/\r
+VOID\r
+InitializeApData (\r
+  IN OUT CPU_MP_DATA      *CpuMpData,\r
+  IN     UINTN            ProcessorNumber,\r
+  IN     UINT32           BistData\r
+  )\r
+{\r
+  CpuMpData->CpuData[ProcessorNumber].Waiting    = FALSE;\r
+  CpuMpData->CpuData[ProcessorNumber].Health     = BistData;\r
+  CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;\r
+  CpuMpData->CpuData[ProcessorNumber].ApicId     = GetApicId ();\r
+  CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
+  if (CpuMpData->CpuData[ProcessorNumber].InitialApicId >= 0xFF) {\r
+    //\r
+    // Set x2APIC mode if there are any logical processor reporting\r
+    // an Initial APIC ID of 255 or greater.\r
+    //\r
+    AcquireSpinLock(&CpuMpData->MpLock);\r
+    CpuMpData->X2ApicEnable = TRUE;\r
+    ReleaseSpinLock(&CpuMpData->MpLock);\r
+  }\r
+\r
+  InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock);\r
+  SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);\r
+}\r
+\r
 /**\r
   MP Initialize Library initialization.\r
 \r
@@ -103,6 +237,7 @@ MpInitLibInitialize (
   CPU_MP_DATA              *CpuMpData;\r
   UINT8                    ApLoopMode;\r
   UINT8                    *MonitorBuffer;\r
+  UINTN                    Index;\r
   UINTN                    ApResetVectorSize;\r
   UINTN                    BackupBufferAddr;\r
   MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);\r
@@ -138,6 +273,14 @@ MpInitLibInitialize (
   CpuMpData->CpuInfoInHob     = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);\r
   InitializeSpinLock(&CpuMpData->MpLock);\r
   //\r
+  // Save BSP's Control registers to APs\r
+  //\r
+  SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters);\r
+  //\r
+  // Set BSP basic information\r
+  //\r
+  InitializeApData (CpuMpData, 0, 0);\r
+  //\r
   // Save assembly code information\r
   //\r
   CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));\r
@@ -147,10 +290,27 @@ MpInitLibInitialize (
   CpuMpData->ApLoopMode = ApLoopMode;\r
   DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));\r
   //\r
+  // Set up APs wakeup signal buffer\r
+  //\r
+  for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {\r
+    CpuMpData->CpuData[Index].StartupApSignal =\r
+      (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);\r
+  }\r
+  //\r
+  // Load Microcode on BSP\r
+  //\r
+  MicrocodeDetect (CpuMpData);\r
+  //\r
   // Store BSP's MTRR setting\r
   //\r
   MtrrGetAllMtrrs (&CpuMpData->MtrrTable);\r
 \r
+\r
+  //\r
+  // Initialize global data for MP support\r
+  //\r
+  InitMpGlobalData (CpuMpData);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -234,3 +394,25 @@ MpInitLibGetNumberOfProcessors (
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
+/**\r
+  Get pointer to CPU MP Data structure from GUIDed HOB.\r
+\r
+  @return  The pointer to CPU MP Data structure.\r
+**/\r
+CPU_MP_DATA *\r
+GetCpuMpDataFromGuidedHob (\r
+  VOID\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE       *GuidHob;\r
+  VOID                    *DataInHob;\r
+  CPU_MP_DATA             *CpuMpData;\r
+\r
+  CpuMpData = NULL;\r
+  GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid);\r
+  if (GuidHob != NULL) {\r
+    DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
+    CpuMpData = (CPU_MP_DATA *) (*(UINTN *) DataInHob);\r
+  }\r
+  return CpuMpData;\r
+}\r