예제 #1
0
/**
  Worker function to switch the requested AP to be the BSP from that point onward.

  @param[in] ProcessorNumber   The handle number of AP that is to become the new BSP.
**/
VOID
SwitchNewBsp (
  IN  UINTN                            ProcessorNumber
  )
{
  EFI_STATUS                           Status;
  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;

  //
  // Get MP Services Protocol
  //
  Status = PeiServicesLocatePpi (
             &gEfiPeiMpServicesPpiGuid,
             0,
             NULL,
             (VOID **)&CpuMpPpi
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Wakeup all APs for data collection.
  //
  Status = CpuMpPpi->SwitchBSP (
                 GetPeiServicesTablePointer (),
                 CpuMpPpi,
                 ProcessorNumber,
                 TRUE
                 );
  ASSERT_EFI_ERROR (Status);
}
예제 #2
0
/**
  Worker function to retrieve the number of logical processor in the platform.

  @param[out] NumberOfCpus                Pointer to the total number of logical
                                          processors in the system, including the BSP
                                          and disabled APs.
  @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled logical
                                          processors that exist in system, including
                                          the BSP.
**/
VOID
GetNumberOfProcessor (
  OUT UINTN                            *NumberOfCpus,
  OUT UINTN                            *NumberOfEnabledProcessors
  )
{
  EFI_STATUS                 Status;
  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;

  //
  // Get MP Services Protocol
  //
  Status = PeiServicesLocatePpi (
             &gEfiPeiMpServicesPpiGuid,
             0,
             NULL,
             (VOID **)&CpuMpPpi
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Get the number of CPUs
  //
  Status = CpuMpPpi->GetNumberOfProcessors (
                         GetPeiServicesTablePointer (),
                         CpuMpPpi,
                         NumberOfCpus,
                         NumberOfEnabledProcessors
                         );
  ASSERT_EFI_ERROR (Status);
}
예제 #3
0
/**
  Worker function to execute a caller provided function on all enabled APs.

  @param[in]  Procedure               A pointer to the function to be run on
                                      enabled APs of the system.
  @param[in]  MpEvent                 The Event used to sync the result.

**/
VOID
StartupAPsWorker (
  IN  EFI_AP_PROCEDURE                 Procedure,
  IN  EFI_EVENT                        MpEvent
  )
{
  EFI_STATUS                           Status;
  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;
  CPU_FEATURES_DATA                    *CpuFeaturesData;

  CpuFeaturesData = GetCpuFeaturesData ();
  CpuMpPpi = CpuFeaturesData->MpService.Ppi;

  //
  // Wakeup all APs for data collection.
  //
  Status = CpuMpPpi->StartupAllAPs (
                 GetPeiServicesTablePointer (),
                 CpuMpPpi,
                 Procedure,
                 FALSE,
                 0,
                 CpuFeaturesData
                 );
  ASSERT_EFI_ERROR (Status);
}
예제 #4
0
/**
  Worker function to execute a caller provided function on all enabled APs.

  @param[in]  Procedure               A pointer to the function to be run on
                                      enabled APs of the system.
**/
VOID
StartupAPsWorker (
  IN  EFI_AP_PROCEDURE                 Procedure
  )
{
  EFI_STATUS                           Status;
  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;

  //
  // Get MP Services Protocol
  //
  Status = PeiServicesLocatePpi (
             &gEfiPeiMpServicesPpiGuid,
             0,
             NULL,
             (VOID **)&CpuMpPpi
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Wakeup all APs for data collection.
  //
  Status = CpuMpPpi->StartupAllAPs (
                 GetPeiServicesTablePointer (),
                 CpuMpPpi,
                 Procedure,
                 FALSE,
                 0,
                 NULL
                 );
  ASSERT_EFI_ERROR (Status);
}
예제 #5
0
/**
  Worker function to return processor index.

  @return  The processor index.
**/
UINTN
GetProcessorIndex (
  VOID
  )
{
  EFI_STATUS                 Status;
  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
  UINTN                      ProcessorIndex;

  CpuMpPpi = GetMpPpi ();

  Status = CpuMpPpi->WhoAmI(GetPeiServicesTablePointer (), CpuMpPpi, &ProcessorIndex);
  ASSERT_EFI_ERROR (Status);
  return ProcessorIndex;
}
예제 #6
0
/**
  Worker function to MP-related information on the requested processor at the
  instant this call is made.

  @param[in]  ProcessorNumber       The handle number of processor.
  @param[out] ProcessorInfoBuffer   A pointer to the buffer where information for
                                    the requested processor is deposited.

  @return Status of MpServices->GetProcessorInfo().
**/
EFI_STATUS
GetProcessorInformation (
  IN  UINTN                            ProcessorNumber,
  OUT EFI_PROCESSOR_INFORMATION        *ProcessorInfoBuffer
  )
{
  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
  EFI_STATUS                 Status;

  CpuMpPpi = GetMpPpi ();
  Status = CpuMpPpi->GetProcessorInfo (
               GetPeiServicesTablePointer(),
               CpuMpPpi,
               ProcessorNumber,
               ProcessorInfoBuffer
               );
  return Status;
}
예제 #7
0
/**
  Worker function to return processor index.

  @param  CpuFeaturesData    Cpu Feature Data structure.

  @return  The processor index.
**/
UINTN
GetProcessorIndex (
  IN CPU_FEATURES_DATA        *CpuFeaturesData
  )
{
  EFI_STATUS                 Status;
  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
  UINTN                      ProcessorIndex;

  CpuMpPpi = CpuFeaturesData->MpService.Ppi;

  //
  // For two reasons which use NULL for WhoAmI:
  // 1. This function will be called by APs and AP should not use PeiServices Table
  // 2. Check WhoAmI implementation, this parameter will not be used.
  //
  Status = CpuMpPpi->WhoAmI(NULL, CpuMpPpi, &ProcessorIndex);
  ASSERT_EFI_ERROR (Status);
  return ProcessorIndex;
}
예제 #8
0
/**
  Worker function to MP-related information on the requested processor at the
  instant this call is made.

  @param[in]  ProcessorNumber       The handle number of processor.
  @param[out] ProcessorInfoBuffer   A pointer to the buffer where information for
                                    the requested processor is deposited.

  @return Status of MpServices->GetProcessorInfo().
**/
EFI_STATUS
GetProcessorInformation (
  IN  UINTN                            ProcessorNumber,
  OUT EFI_PROCESSOR_INFORMATION        *ProcessorInfoBuffer
  )
{
  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
  EFI_STATUS                 Status;
  CPU_FEATURES_DATA          *CpuFeaturesData;

  CpuFeaturesData = GetCpuFeaturesData ();
  CpuMpPpi = CpuFeaturesData->MpService.Ppi;

  Status = CpuMpPpi->GetProcessorInfo (
               GetPeiServicesTablePointer(),
               CpuMpPpi,
               ProcessorNumber,
               ProcessorInfoBuffer
               );
  return Status;
}
예제 #9
0
/**
  Worker function to switch the requested AP to be the BSP from that point onward.

  @param[in] ProcessorNumber   The handle number of AP that is to become the new BSP.
**/
VOID
SwitchNewBsp (
  IN  UINTN                            ProcessorNumber
  )
{
  EFI_STATUS                           Status;
  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;
  CPU_FEATURES_DATA                    *CpuFeaturesData;

  CpuFeaturesData = GetCpuFeaturesData ();
  CpuMpPpi = CpuFeaturesData->MpService.Ppi;

  //
  // Wakeup all APs for data collection.
  //
  Status = CpuMpPpi->SwitchBSP (
                 GetPeiServicesTablePointer (),
                 CpuMpPpi,
                 ProcessorNumber,
                 TRUE
                 );
  ASSERT_EFI_ERROR (Status);
}
예제 #10
0
/**
  Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.

  @param[in] PeiServices      Indirect reference to the PEI Services Table.
  @param[in] NotifyDescriptor Address of the notification descriptor data
                              structure.
  @param[in] Ppi              Address of the PPI that was installed.

  @return  Status of the notification. The status code returned from this
           function is ignored.
**/
STATIC
EFI_STATUS
EFIAPI
OnMpServicesAvailable (
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
  IN VOID                       *Ppi
  )
{
  EFI_PEI_MP_SERVICES_PPI *MpServices;
  EFI_STATUS              Status;

  DEBUG ((EFI_D_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));

  //
  // Write the MSR on all the APs in parallel.
  //
  MpServices = Ppi;
  Status = MpServices->StartupAllAPs (
                         (CONST EFI_PEI_SERVICES **)PeiServices,
                         MpServices,
                         WriteFeatureControl, // Procedure
                         FALSE,               // SingleThread
                         0,                   // TimeoutInMicroSeconds: inf.
                         NULL                 // ProcedureArgument
                         );
  if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {
    DEBUG ((EFI_D_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
    return Status;
  }

  //
  // Now write the MSR on the BSP too.
  //
  WriteFeatureControl (NULL);
  return EFI_SUCCESS;
}
예제 #11
0
/**
  Worker function to retrieve the number of logical processor in the platform.

  @param[out] NumberOfCpus                Pointer to the total number of logical
                                          processors in the system, including the BSP
                                          and disabled APs.
  @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled logical
                                          processors that exist in system, including
                                          the BSP.
**/
VOID
GetNumberOfProcessor (
  OUT UINTN                            *NumberOfCpus,
  OUT UINTN                            *NumberOfEnabledProcessors
  )
{
  EFI_STATUS                 Status;
  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
  CPU_FEATURES_DATA          *CpuFeaturesData;

  CpuFeaturesData = GetCpuFeaturesData ();
  CpuMpPpi = CpuFeaturesData->MpService.Ppi;

  //
  // Get the number of CPUs
  //
  Status = CpuMpPpi->GetNumberOfProcessors (
                         GetPeiServicesTablePointer (),
                         CpuMpPpi,
                         NumberOfCpus,
                         NumberOfEnabledProcessors
                         );
  ASSERT_EFI_ERROR (Status);
}
예제 #12
0
/**
  Allocates ACPI NVS memory to save ACPI_CPU_DATA.

  @return  Pointer to allocated ACPI_CPU_DATA.
**/
ACPI_CPU_DATA *
AllocateAcpiCpuData (
  VOID
  )
{
  EFI_STATUS                           Status;
  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;
  UINTN                                NumberOfCpus;
  UINTN                                NumberOfEnabledProcessors;
  ACPI_CPU_DATA                        *AcpiCpuData;
  EFI_PHYSICAL_ADDRESS                 Address;
  UINTN                                TableSize;
  CPU_REGISTER_TABLE                   *RegisterTable;
  UINTN                                Index;
  EFI_PROCESSOR_INFORMATION            ProcessorInfoBuffer;

  Status = PeiServicesAllocatePages (
             EfiACPIMemoryNVS,
             EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)),
             &Address
             );
  ASSERT_EFI_ERROR (Status);
  AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) Address;
  ASSERT (AcpiCpuData != NULL);

  //
  // Get MP Services Protocol
  //
  Status = PeiServicesLocatePpi (
             &gEfiPeiMpServicesPpiGuid,
             0,
             NULL,
             (VOID **)&CpuMpPpi
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Get the number of CPUs
  //
  Status = CpuMpPpi->GetNumberOfProcessors (
                         GetPeiServicesTablePointer (),
                         CpuMpPpi,
                         &NumberOfCpus,
                         &NumberOfEnabledProcessors
                         );
  ASSERT_EFI_ERROR (Status);
  AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;

  //
  // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
  //
  TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
  Status = PeiServicesAllocatePages (
             EfiACPIMemoryNVS,
             EFI_SIZE_TO_PAGES (TableSize),
             &Address
             );
  ASSERT_EFI_ERROR (Status);
  RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) Address;

  for (Index = 0; Index < NumberOfCpus; Index++) {
    Status = CpuMpPpi->GetProcessorInfo (
                         GetPeiServicesTablePointer (),
                         CpuMpPpi,
                         Index,
                         &ProcessorInfoBuffer
                         );
    ASSERT_EFI_ERROR (Status);

    RegisterTable[Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;
    RegisterTable[Index].TableLength        = 0;
    RegisterTable[Index].AllocatedSize      = 0;
    RegisterTable[Index].RegisterTableEntry = 0;

    RegisterTable[NumberOfCpus + Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;
    RegisterTable[NumberOfCpus + Index].TableLength        = 0;
    RegisterTable[NumberOfCpus + Index].AllocatedSize      = 0;
    RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
  }
  AcpiCpuData->RegisterTable           = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
  AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);

  return AcpiCpuData;
}