]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuMpPei/CpuMpPei.c
UefiCpuPkg/CpuMpPei: Implementation of PeiEnableDisableAP ()
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / CpuMpPei.c
index 8367f0573f22a394f3dd8338b12678495b5b5ed5..bfcf8168298e656bdb2cb98ae77a8868be4f3b03 100644 (file)
@@ -38,6 +38,87 @@ GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {
   (UINTN) mGdtEntries
   };
 
+/**
+  Sort the APIC ID of all processors.
+
+  This function sorts the APIC ID of all processors so that processor number is
+  assigned in the ascending order of APIC ID which eases MP debugging.
+
+  @param PeiCpuMpData        Pointer to PEI CPU MP Data
+**/
+VOID
+SortApicId (
+  IN PEI_CPU_MP_DATA   *PeiCpuMpData
+  )
+{
+  UINTN             Index1;
+  UINTN             Index2;
+  UINTN             Index3;
+  UINT32            ApicId;
+  EFI_HEALTH_FLAGS  Health;
+  UINT32            ApCount;
+
+  ApCount = PeiCpuMpData->CpuCount - 1;
+
+  if (ApCount != 0) {
+    for (Index1 = 0; Index1 < ApCount; Index1++) {
+      Index3 = Index1;
+      //
+      // Sort key is the hardware default APIC ID
+      //
+      ApicId = PeiCpuMpData->CpuData[Index1].ApicId;
+      for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) {
+        if (ApicId > PeiCpuMpData->CpuData[Index2].ApicId) {
+          Index3 = Index2;
+          ApicId = PeiCpuMpData->CpuData[Index2].ApicId;
+        }
+      }
+      if (Index3 != Index1) {
+        PeiCpuMpData->CpuData[Index3].ApicId = PeiCpuMpData->CpuData[Index1].ApicId;
+        PeiCpuMpData->CpuData[Index1].ApicId = ApicId;
+        Health = PeiCpuMpData->CpuData[Index3].Health;
+        PeiCpuMpData->CpuData[Index3].Health = PeiCpuMpData->CpuData[Index1].Health;
+        PeiCpuMpData->CpuData[Index1].Health = Health;
+      }
+    }
+
+    //
+    // Get the processor number for the BSP
+    //
+    ApicId = GetInitialApicId ();
+    for (Index1 = 0; Index1 < PeiCpuMpData->CpuCount; Index1++) {
+      if (PeiCpuMpData->CpuData[Index1].ApicId == ApicId) {
+        PeiCpuMpData->BspNumber = (UINT32) Index1;
+        break;
+      }
+    }
+  }
+}
+
+/**
+  Get CPU MP Data pointer from the Guided HOB.
+
+  @return  Pointer to Pointer to PEI CPU MP Data
+**/
+PEI_CPU_MP_DATA *
+GetMpHobData (
+  VOID
+  )
+{
+  EFI_HOB_GUID_TYPE       *GuidHob;
+  VOID                    *DataInHob;
+  PEI_CPU_MP_DATA         *CpuMpData;
+
+  CpuMpData = NULL;
+  GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+  if (GuidHob != NULL) {
+    DataInHob = GET_GUID_HOB_DATA (GuidHob);
+    CpuMpData = (PEI_CPU_MP_DATA *)(*(UINTN *)DataInHob);
+  }
+  ASSERT (CpuMpData != NULL);
+  return CpuMpData;
+}
+
 /**
   This function will be called from AP reset code if BSP uses WakeUpAP.
 
@@ -52,6 +133,8 @@ ApCFunction (
   )
 {
   PEI_CPU_MP_DATA            *PeiCpuMpData;
+  UINTN                      ProcessorNumber;
+  EFI_AP_PROCEDURE           Procedure;
   UINTN                      BistData;
 
   PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
@@ -62,6 +145,23 @@ ApCFunction (
     BistData = *(UINTN *) (PeiCpuMpData->Buffer + NumApsExecuting * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));
     PeiCpuMpData->CpuData[NumApsExecuting].ApicId        = GetInitialApicId ();
     PeiCpuMpData->CpuData[NumApsExecuting].Health.Uint32 = (UINT32) BistData;
+    //
+    // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.
+    //
+    MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
+    MicrocodeDetect ();
+  } else {
+    //
+    // Execute AP function if AP is not disabled
+    //
+    GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
+    if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
+        (PeiCpuMpData->ApFunction != 0)) {
+      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
+      Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
+      Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
+      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
+    }
   }
 
   //
@@ -228,7 +328,14 @@ CountProcessorNumber (
   IN PEI_CPU_MP_DATA            *PeiCpuMpData
   )
 {
-
+  //
+  // Load Microcode on BSP
+  //
+  MicrocodeDetect ();
+  //
+  // Store BSP's MTRR setting
+  //
+  MtrrGetAllMtrrs (&PeiCpuMpData->MtrrTable);
   //
   // Send broadcast IPI to APs to wakeup APs
   //
@@ -240,6 +347,10 @@ CountProcessorNumber (
   MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
   PeiCpuMpData->InitFlag  = 0;
   PeiCpuMpData->CpuCount += (UINT32) PeiCpuMpData->MpCpuExchangeInfo->NumApsExecuting;
+  //
+  // Sort BSP/Aps by CPU APIC ID in ascending order
+  //
+  SortApicId (PeiCpuMpData);
 
   DEBUG ((EFI_D_INFO, "CpuMpPei: Find %d processors in system.\n", PeiCpuMpData->CpuCount));
   return PeiCpuMpData->CpuCount;
@@ -341,6 +452,18 @@ CpuMpPeimInit (
   // Count processor number and collect processor information
   //
   ProcessorCount = CountProcessorNumber (PeiCpuMpData);
+  //
+  // Build location of PEI CPU MP DATA buffer in HOB
+  //
+  BuildGuidDataHob (
+    &gEfiCallerIdGuid,
+    (VOID *)&PeiCpuMpData,
+    sizeof(UINT64)
+    );
+  //
+  // Update and publish CPU BIST information
+  //
+  CollectBistDataFromPpi (PeiServices, PeiCpuMpData);
 
   return EFI_SUCCESS;
 }