/** @file CPU Register Table Library functions. Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include "RegisterCpuFeatures.h" CPU_FEATURES_DATA mCpuFeaturesData = {0}; /** Worker function to get CPU_FEATURES_DATA pointer. @return Pointer to CPU_FEATURES_DATA. **/ CPU_FEATURES_DATA * GetCpuFeaturesData ( VOID ) { return &mCpuFeaturesData; } /** Worker function to get EFI_MP_SERVICES_PROTOCOL pointer. @return MP_SERVICES variable. **/ MP_SERVICES GetMpService ( VOID ) { EFI_STATUS Status; MP_SERVICES MpService; // // Get MP Services Protocol // Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService.Protocol ); ASSERT_EFI_ERROR (Status); return MpService; } /** 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; UINTN ProcessorIndex; EFI_MP_SERVICES_PROTOCOL *MpServices; MpServices = CpuFeaturesData->MpService.Protocol; Status = MpServices->WhoAmI(MpServices, &ProcessorIndex); ASSERT_EFI_ERROR (Status); return ProcessorIndex; } /** Gets detailed 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_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpServices; CPU_FEATURES_DATA *CpuFeaturesData; CpuFeaturesData = GetCpuFeaturesData (); MpServices = CpuFeaturesData->MpService.Protocol; Status = MpServices->GetProcessorInfo ( MpServices, ProcessorNumber, ProcessorInfoBuffer ); return 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 A pointer to the event to be used later to check whether procedure has done. **/ VOID StartupAllAPsWorker ( IN EFI_AP_PROCEDURE Procedure, IN EFI_EVENT MpEvent ) { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpServices; CPU_FEATURES_DATA *CpuFeaturesData; CpuFeaturesData = GetCpuFeaturesData (); MpServices = CpuFeaturesData->MpService.Protocol; // // Wakeup all APs // Status = MpServices->StartupAllAPs ( MpServices, Procedure, FALSE, MpEvent, 0, CpuFeaturesData, NULL ); ASSERT_EFI_ERROR (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_MP_SERVICES_PROTOCOL *MpServices; CPU_FEATURES_DATA *CpuFeaturesData; CpuFeaturesData = GetCpuFeaturesData (); MpServices = CpuFeaturesData->MpService.Protocol; // // Wakeup all APs // Status = MpServices->SwitchBSP ( MpServices, 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_MP_SERVICES_PROTOCOL *MpServices; CPU_FEATURES_DATA *CpuFeaturesData; CpuFeaturesData = GetCpuFeaturesData (); MpServices = CpuFeaturesData->MpService.Protocol; // // Get the number of CPUs // Status = MpServices->GetNumberOfProcessors ( MpServices, NumberOfCpus, NumberOfEnabledProcessors ); ASSERT_EFI_ERROR (Status); } /** Performs CPU features Initialization. This service will invoke MP service to perform CPU features initialization on BSP/APs per user configuration. @note This service could be called by BSP only. **/ VOID EFIAPI CpuFeaturesInitialize ( VOID ) { CPU_FEATURES_DATA *CpuFeaturesData; UINTN OldBspNumber; EFI_EVENT MpEvent; EFI_STATUS Status; CpuFeaturesData = GetCpuFeaturesData (); OldBspNumber = GetProcessorIndex (CpuFeaturesData); CpuFeaturesData->BspNumber = OldBspNumber; // // // Initialize MpEvent to suppress incorrect compiler/analyzer warnings. // MpEvent = NULL; if (CpuFeaturesData->NumberOfCpus > 1) { Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_CALLBACK, EfiEventEmptyFunction, NULL, &MpEvent ); ASSERT_EFI_ERROR (Status); // // Wakeup all APs for programming. // StartupAllAPsWorker (SetProcessorRegister, MpEvent); } // // Programming BSP // SetProcessorRegister (CpuFeaturesData); if (CpuFeaturesData->NumberOfCpus > 1) { // // Wait all processors to finish the task. // do { Status = gBS->CheckEvent (MpEvent); } while (Status == EFI_NOT_READY); ASSERT_EFI_ERROR (Status); } // // Switch to new BSP if required // if (CpuFeaturesData->BspNumber != OldBspNumber) { SwitchNewBsp (CpuFeaturesData->BspNumber); } }