summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c
new file mode 100644
index 00000000..df43c63d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c
@@ -0,0 +1,276 @@
+/** @file
+ CPU Register Table Library functions.
+
+ Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#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);
+ }
+}
+