/** 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); }
/** 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); }
/** 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); }
/** 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); }
/** 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; }
/** 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; }
/** 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; }
/** 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; }
/** 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); }
/** 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; }
/** 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); }
/** 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; }