/** @file CPU Register Table Library functions. Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include "RegisterCpuFeatures.h" #define REGISTER_CPU_FEATURES_GUID \ { \ 0xa694c467, 0x697a, 0x446b, { 0xb9, 0x29, 0x5b, 0x14, 0xa0, 0xcf, 0x39, 0xf } \ } EFI_GUID mRegisterCpuFeaturesHobGuid = REGISTER_CPU_FEATURES_GUID; /** Worker function to get CPU_FEATURES_DATA pointer. @return Pointer to CPU_FEATURES_DATA. **/ CPU_FEATURES_DATA * GetCpuFeaturesData ( VOID ) { CPU_FEATURES_DATA *CpuInitData; EFI_HOB_GUID_TYPE *GuidHob; VOID *DataInHob; UINT64 Data64; CpuInitData = NULL; GuidHob = GetFirstGuidHob (&mRegisterCpuFeaturesHobGuid); if (GuidHob != NULL) { DataInHob = GET_GUID_HOB_DATA (GuidHob); CpuInitData = (CPU_FEATURES_DATA *) (*(UINTN *) DataInHob); ASSERT (CpuInitData != NULL); } else { CpuInitData = AllocateZeroPool (sizeof (CPU_FEATURES_DATA)); ASSERT (CpuInitData != NULL); // // Build location of CPU MP DATA buffer in HOB // Data64 = (UINT64) (UINTN) CpuInitData; BuildGuidDataHob ( &mRegisterCpuFeaturesHobGuid, (VOID *) &Data64, sizeof (UINT64) ); } return CpuInitData; } /** Worker function to get MP PPI service pointer. @return MP_SERVICES variable. **/ MP_SERVICES GetMpService ( VOID ) { EFI_STATUS Status; MP_SERVICES MpService; // // Get MP Services Protocol // Status = PeiServicesLocatePpi ( &gEfiPeiMpServicesPpiGuid, 0, NULL, (VOID **)&MpService.Ppi ); 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; 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 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 StartupAllAPsWorker ( 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 CPUs. @param[in] Procedure A pointer to the function to be run on enabled CPUs of the system. **/ VOID StartupAllCPUsWorker ( IN EFI_AP_PROCEDURE Procedure ) { EFI_STATUS Status; EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi; CPU_FEATURES_DATA *CpuFeaturesData; CpuFeaturesData = GetCpuFeaturesData (); // // Get MP Services2 Ppi // Status = PeiServicesLocatePpi ( &gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOID **)&CpuMp2Ppi ); ASSERT_EFI_ERROR (Status); // // Wakeup all APs for data collection. // Status = CpuMp2Ppi->StartupAllCPUs ( CpuMp2Ppi, Procedure, 0, CpuFeaturesData ); 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_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); } /** 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); } /** 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; CpuFeaturesData = GetCpuFeaturesData (); OldBspNumber = GetProcessorIndex (CpuFeaturesData); CpuFeaturesData->BspNumber = OldBspNumber; // // Start to program register for all CPUs. // StartupAllCPUsWorker (SetProcessorRegister); // // Switch to new BSP if required // if (CpuFeaturesData->BspNumber != OldBspNumber) { SwitchNewBsp (CpuFeaturesData->BspNumber); } }