]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuMpPei/PeiMpServices.c
ShellPkg: Fix issue about ping fail with IPv4
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / PeiMpServices.c
index 2f82130efd719d83f603ded1455a756a72c8ad28..4689d2fcc02418c1ac4473423ff1736ddb1d7c71 100644 (file)
 
 #include "PeiMpServices.h"
 
+//
+// CPU MP PPI to be installed
+//
+EFI_PEI_MP_SERVICES_PPI                mMpServicesPpi = {
+  PeiGetNumberOfProcessors,
+  PeiGetProcessorInfo,
+  PeiStartupAllAPs,
+  PeiStartupThisAP,
+  PeiSwitchBSP,
+  PeiEnableDisableAP,
+  PeiWhoAmI,
+};
+
+EFI_PEI_PPI_DESCRIPTOR           mPeiCpuMpPpiDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiPeiMpServicesPpiGuid,
+  &mMpServicesPpi
+};
 
 /**
   Get CPU Package/Core/Thread location information.
@@ -153,6 +171,25 @@ GetProcessorNumber (
   return EFI_NOT_FOUND;
 }
 
+/**
+  Worker function for SwitchBSP().
+
+  Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.
+
+  @param Buffer        Pointer to CPU MP Data
+**/
+VOID
+EFIAPI
+FutureBSPProc (
+  IN  VOID                *Buffer
+  )
+{
+  PEI_CPU_MP_DATA         *DataInHob;
+
+  DataInHob = (PEI_CPU_MP_DATA *) Buffer;
+  AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
+}
+
 /**
   This service retrieves the number of logical processor in the platform
   and the number of those logical processors that are enabled on this boot.
@@ -443,6 +480,13 @@ PeiStartupAllAPs (
     return EFI_NOT_READY;
   }
 
+  if (PeiCpuMpData->EndOfPeiFlag) {
+    //
+    // Backup original data and copy AP reset vector in it
+    //
+    BackupAndPrepareWakeupBuffer(PeiCpuMpData);
+  }
+
   WaitCountNumber = TimeoutInMicroSeconds / CPU_CHECK_AP_INTERVAL + 1;
   WaitCountIndex = 0;
   FinishedCount = &PeiCpuMpData->FinishedCount;
@@ -494,6 +538,13 @@ PeiStartupAllAPs (
     }
   }
 
+  if (PeiCpuMpData->EndOfPeiFlag) {
+    //
+    // Restore original data
+    //
+    RestoreWakeupBuffer(PeiCpuMpData);
+  }
+
   return Status;
 }
 
@@ -589,6 +640,13 @@ PeiStartupThisAP (
     return EFI_INVALID_PARAMETER;
   }
 
+  if (PeiCpuMpData->EndOfPeiFlag) {
+    //
+    // Backup original data and copy AP reset vector in it
+    //
+    BackupAndPrepareWakeupBuffer(PeiCpuMpData);
+  }
+
   WaitCountNumber = TimeoutInMicroseconds / CPU_CHECK_AP_INTERVAL + 1;
   WaitCountIndex = 0;
   FinishedCount = &PeiCpuMpData->FinishedCount;
@@ -614,9 +672,227 @@ PeiStartupThisAP (
     }
   }
 
+  if (PeiCpuMpData->EndOfPeiFlag) {
+    //
+    // Backup original data and copy AP reset vector in it
+    //
+    RestoreWakeupBuffer(PeiCpuMpData);
+  }
+
   return Status;
 }
 
+/**
+  This service switches the requested AP to be the BSP from that point onward.
+  This service changes the BSP for all purposes.   This call can only be performed
+  by the current BSP.
+
+  This service switches the requested AP to be the BSP from that point onward.
+  This service changes the BSP for all purposes. The new BSP can take over the
+  execution of the old BSP and continue seamlessly from where the old one left
+  off.
+
+  If the BSP cannot be switched prior to the return from this service, then
+  EFI_UNSUPPORTED must be returned.
+
+  @param[in] PeiServices          An indirect pointer to the PEI Services Table
+                                  published by the PEI Foundation.
+  @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
+  @param[in] ProcessorNumber      The handle number of the AP. The range is from 0 to the
+                                  total number of logical processors minus 1. The total
+                                  number of logical processors can be retrieved by
+                                  EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
+  @param[in] EnableOldBSP         If TRUE, then the old BSP will be listed as an enabled
+                                  AP. Otherwise, it will be disabled.
+
+  @retval EFI_SUCCESS             BSP successfully switched.
+  @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to this
+                                  service returning.
+  @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
+  @retval EFI_SUCCESS             The calling processor is an AP.
+  @retval EFI_NOT_FOUND           The processor with the handle specified by
+                                  ProcessorNumber does not exist.
+  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or a disabled
+                                  AP.
+  @retval EFI_NOT_READY           The specified AP is busy.
+**/
+EFI_STATUS
+EFIAPI
+PeiSwitchBSP (
+  IN  CONST EFI_PEI_SERVICES   **PeiServices,
+  IN  EFI_PEI_MP_SERVICES_PPI  *This,
+  IN  UINTN                    ProcessorNumber,
+  IN  BOOLEAN                  EnableOldBSP
+  )
+{
+  PEI_CPU_MP_DATA         *PeiCpuMpData;
+  UINTN                   CallerNumber;
+  MSR_IA32_APIC_BASE      ApicBaseMsr;
+
+  PeiCpuMpData = GetMpHobData ();
+  if (PeiCpuMpData == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check whether caller processor is BSP
+  //
+  PeiWhoAmI (PeiServices, This, &CallerNumber);
+  if (CallerNumber != PeiCpuMpData->BspNumber) {
+    return EFI_SUCCESS;
+  }
+
+  if (ProcessorNumber >= PeiCpuMpData->CpuCount) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check whether specified AP is disabled
+  //
+  if (PeiCpuMpData->CpuData[ProcessorNumber].State == CpuStateDisabled) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check whether ProcessorNumber specifies the current BSP
+  //
+  if (ProcessorNumber == PeiCpuMpData->BspNumber) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check whether specified AP is busy
+  //
+  if (PeiCpuMpData->CpuData[ProcessorNumber].State == CpuStateBusy) {
+    return EFI_NOT_READY;
+  }
+
+  //
+  // Clear the BSP bit of MSR_IA32_APIC_BASE
+  //
+  ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
+  ApicBaseMsr.Bits.Bsp = 0;
+  AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
+
+  PeiCpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE;
+  PeiCpuMpData->APInfo.State  = CPU_SWITCH_STATE_IDLE;
+
+  if (PeiCpuMpData->EndOfPeiFlag) {
+    //
+    // Backup original data and copy AP reset vector in it
+    //
+    BackupAndPrepareWakeupBuffer(PeiCpuMpData);
+  }
+
+  //
+  // Need to wakeUp AP (future BSP).
+  //
+  WakeUpAP (PeiCpuMpData, FALSE, PeiCpuMpData->CpuData[ProcessorNumber].ApicId, FutureBSPProc, PeiCpuMpData);
+
+  AsmExchangeRole (&PeiCpuMpData->BSPInfo, &PeiCpuMpData->APInfo);
+
+  if (PeiCpuMpData->EndOfPeiFlag) {
+    //
+    // Backup original data and copy AP reset vector in it
+    //
+    RestoreWakeupBuffer(PeiCpuMpData);
+  }
+
+  //
+  // Set the BSP bit of MSR_IA32_APIC_BASE on new BSP
+  //
+  ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
+  ApicBaseMsr.Bits.Bsp = 1;
+  AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This service lets the caller enable or disable an AP from this point onward.
+  This service may only be called from the BSP.
+
+  This service allows the caller enable or disable an AP from this point onward.
+  The caller can optionally specify the health status of the AP by Health. If
+  an AP is being disabled, then the state of the disabled AP is implementation
+  dependent. If an AP is enabled, then the implementation must guarantee that a
+  complete initialization sequence is performed on the AP, so the AP is in a state
+  that is compatible with an MP operating system.
+
+  If the enable or disable AP operation cannot be completed prior to the return
+  from this service, then EFI_UNSUPPORTED must be returned.
+
+  @param[in] PeiServices          An indirect pointer to the PEI Services Table
+                                  published by the PEI Foundation.
+  @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
+  @param[in] ProcessorNumber      The handle number of the AP. The range is from 0 to the
+                                  total number of logical processors minus 1. The total
+                                  number of logical processors can be retrieved by
+                                  EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
+  @param[in] EnableAP             Specifies the new state for the processor for enabled,
+                                  FALSE for disabled.
+  @param[in] HealthFlag           If not NULL, a pointer to a value that specifies the
+                                  new health status of the AP. This flag corresponds to
+                                  StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo().
+                                  Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other
+                                  bits are ignored. If it is NULL, this parameter is
+                                  ignored.
+
+  @retval EFI_SUCCESS             The specified AP was enabled or disabled successfully.
+  @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be completed prior
+                                  to this service returning.
+  @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
+  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
+  @retval EFI_NOT_FOUND           Processor with the handle specified by ProcessorNumber
+                                  does not exist.
+  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
+**/
+EFI_STATUS
+EFIAPI
+PeiEnableDisableAP (
+  IN  CONST EFI_PEI_SERVICES    **PeiServices,
+  IN  EFI_PEI_MP_SERVICES_PPI   *This,
+  IN  UINTN                     ProcessorNumber,
+  IN  BOOLEAN                   EnableAP,
+  IN  UINT32                    *HealthFlag OPTIONAL
+  )
+{
+  PEI_CPU_MP_DATA         *PeiCpuMpData;
+  UINTN                   CallerNumber;
+
+  PeiCpuMpData = GetMpHobData ();
+  if (PeiCpuMpData == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check whether caller processor is BSP
+  //
+  PeiWhoAmI (PeiServices, This, &CallerNumber);
+  if (CallerNumber != PeiCpuMpData->BspNumber) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (ProcessorNumber == PeiCpuMpData->BspNumber) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (ProcessorNumber >= PeiCpuMpData->CpuCount) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (!EnableAP) {
+    PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateDisabled;
+  } else {
+    PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
+  }
+
+  if (HealthFlag != NULL) {
+    PeiCpuMpData->CpuData[ProcessorNumber].CpuHealthy =
+          (BOOLEAN) ((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) != 0);
+  }
+  return EFI_SUCCESS;
+}
 
 /**
   This return the handle number for the calling processor.  This service may be