-/** @file
- CPU Register Table Library functions.
-
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <PiDxe.h>
-
-#include <Library/UefiBootServicesTableLib.h>
-
-#include "RegisterCpuFeatures.h"
-
-CPU_FEATURES_DATA mCpuFeaturesData = {0};
-EFI_MP_SERVICES_PROTOCOL *mCpuFeaturesMpServices = NULL;
-
-/**
- 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 Pointer to EFI_MP_SERVICES_PROTOCOL.
-**/
-EFI_MP_SERVICES_PROTOCOL *
-GetMpProtocol (
- VOID
- )
-{
- EFI_STATUS Status;
-
- if (mCpuFeaturesMpServices == NULL) {
- //
- // Get MP Services Protocol
- //
- Status = gBS->LocateProtocol (
- &gEfiMpServiceProtocolGuid,
- NULL,
- (VOID **)&mCpuFeaturesMpServices
- );
- ASSERT_EFI_ERROR (Status);
- }
-
- ASSERT (mCpuFeaturesMpServices != NULL);
- return mCpuFeaturesMpServices;
-}
-
-/**
- Worker function to return processor index.
-
- @return The processor index.
-**/
-UINTN
-GetProcessorIndex (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN ProcessorIndex;
- EFI_MP_SERVICES_PROTOCOL *MpServices;
-
- MpServices = GetMpProtocol ();
- 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;
-
- MpServices = GetMpProtocol ();
- 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.
-**/
-VOID
-StartupAPsWorker (
- IN EFI_AP_PROCEDURE Procedure
- )
-{
- EFI_STATUS Status;
- EFI_MP_SERVICES_PROTOCOL *MpServices;
-
- MpServices = GetMpProtocol ();
- //
- // Wakeup all APs
- //
- Status = MpServices->StartupAllAPs (
- MpServices,
- Procedure,
- FALSE,
- NULL,
- 0,
- NULL,
- 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;
-
- MpServices = GetMpProtocol ();
- //
- // 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;
-
- MpServices = GetMpProtocol ();
-
- //
- // Get the number of CPUs
- //
- Status = MpServices->GetNumberOfProcessors (
- MpServices,
- 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
- )
-{
- //
- // CpuS3DataDxe will do it.
- //
- ASSERT (FALSE);
- return NULL;
-}
-
-/**
- Enlarges CPU register table for each processor.
-
- @param[in, out] RegisterTable Pointer processor's CPU register table
-**/
-VOID
-EnlargeRegisterTable (
- IN OUT CPU_REGISTER_TABLE *RegisterTable
- )
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS Address;
- UINTN AllocatePages;
-
- Address = BASE_4GB - 1;
- AllocatePages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiACPIMemoryNVS,
- AllocatePages + 1,
- &Address
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // If there are records existing in the register table, then copy its contents
- // to new region and free the old one.
- //
- if (RegisterTable->AllocatedSize > 0) {
- CopyMem (
- (VOID *) (UINTN) Address,
- (VOID *) (UINTN) RegisterTable->RegisterTableEntry,
- RegisterTable->AllocatedSize
- );
- //
- // RegisterTableEntry is allocated by gBS->AllocatePages() service.
- // So, gBS->FreePages() service is used to free it.
- //
- gBS->FreePages (
- RegisterTable->RegisterTableEntry,
- AllocatePages
- );
- }
-
- //
- // Adjust the allocated size and register table base address.
- //
- RegisterTable->AllocatedSize += EFI_PAGE_SIZE;
- RegisterTable->RegisterTableEntry = Address;
-}
+/** @file\r
+ CPU Register Table Library functions.\r
+\r
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include "RegisterCpuFeatures.h"\r
+\r
+CPU_FEATURES_DATA mCpuFeaturesData = {0};\r
+\r
+/**\r
+ Worker function to get CPU_FEATURES_DATA pointer.\r
+\r
+ @return Pointer to CPU_FEATURES_DATA.\r
+**/\r
+CPU_FEATURES_DATA *\r
+GetCpuFeaturesData (\r
+ VOID\r
+ )\r
+{\r
+ return &mCpuFeaturesData;\r
+}\r
+\r
+/**\r
+ Worker function to get EFI_MP_SERVICES_PROTOCOL pointer.\r
+\r
+ @return MP_SERVICES variable.\r
+**/\r
+MP_SERVICES\r
+GetMpService (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ MP_SERVICES MpService;\r
+\r
+ //\r
+ // Get MP Services Protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiMpServiceProtocolGuid,\r
+ NULL,\r
+ (VOID **)&MpService.Protocol\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return MpService;\r
+}\r
+\r
+/**\r
+ Worker function to return processor index.\r
+\r
+ @param CpuFeaturesData Cpu Feature Data structure.\r
+\r
+ @return The processor index.\r
+**/\r
+UINTN\r
+GetProcessorIndex (\r
+ IN CPU_FEATURES_DATA *CpuFeaturesData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ProcessorIndex;\r
+ EFI_MP_SERVICES_PROTOCOL *MpServices;\r
+\r
+ MpServices = CpuFeaturesData->MpService.Protocol;\r
+ Status = MpServices->WhoAmI(MpServices, &ProcessorIndex);\r
+ ASSERT_EFI_ERROR (Status);\r
+ return ProcessorIndex;\r
+}\r
+\r
+/**\r
+ Gets detailed MP-related information on the requested processor at the\r
+ instant this call is made.\r
+\r
+ @param[in] ProcessorNumber The handle number of processor.\r
+ @param[out] ProcessorInfoBuffer A pointer to the buffer where information for\r
+ the requested processor is deposited.\r
+\r
+ @return Status of MpServices->GetProcessorInfo().\r
+**/\r
+EFI_STATUS\r
+GetProcessorInformation (\r
+ IN UINTN ProcessorNumber,\r
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MP_SERVICES_PROTOCOL *MpServices;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+ MpServices = CpuFeaturesData->MpService.Protocol;\r
+\r
+ Status = MpServices->GetProcessorInfo (\r
+ MpServices,\r
+ ProcessorNumber,\r
+ ProcessorInfoBuffer\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Worker function to execute a caller provided function on all enabled APs.\r
+\r
+ @param[in] Procedure A pointer to the function to be run on\r
+ enabled APs of the system.\r
+ @param[in] MpEvent A pointer to the event to be used later\r
+ to check whether procedure has done.\r
+**/\r
+VOID\r
+StartupAPsWorker (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN EFI_EVENT MpEvent\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MP_SERVICES_PROTOCOL *MpServices;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+ MpServices = CpuFeaturesData->MpService.Protocol;\r
+\r
+ //\r
+ // Wakeup all APs\r
+ //\r
+ Status = MpServices->StartupAllAPs (\r
+ MpServices,\r
+ Procedure,\r
+ FALSE,\r
+ MpEvent,\r
+ 0,\r
+ CpuFeaturesData,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Worker function to switch the requested AP to be the BSP from that point onward.\r
+\r
+ @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.\r
+**/\r
+VOID\r
+SwitchNewBsp (\r
+ IN UINTN ProcessorNumber\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MP_SERVICES_PROTOCOL *MpServices;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+ MpServices = CpuFeaturesData->MpService.Protocol;\r
+\r
+ //\r
+ // Wakeup all APs\r
+ //\r
+ Status = MpServices->SwitchBSP (\r
+ MpServices,\r
+ ProcessorNumber,\r
+ TRUE\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Worker function to retrieve the number of logical processor in the platform.\r
+\r
+ @param[out] NumberOfCpus Pointer to the total number of logical\r
+ processors in the system, including the BSP\r
+ and disabled APs.\r
+ @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical\r
+ processors that exist in system, including\r
+ the BSP.\r
+**/\r
+VOID\r
+GetNumberOfProcessor (\r
+ OUT UINTN *NumberOfCpus,\r
+ OUT UINTN *NumberOfEnabledProcessors\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MP_SERVICES_PROTOCOL *MpServices;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+ MpServices = CpuFeaturesData->MpService.Protocol;\r
+\r
+ //\r
+ // Get the number of CPUs\r
+ //\r
+ Status = MpServices->GetNumberOfProcessors (\r
+ MpServices,\r
+ NumberOfCpus,\r
+ NumberOfEnabledProcessors\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ Performs CPU features Initialization.\r
+\r
+ This service will invoke MP service to perform CPU features\r
+ initialization on BSP/APs per user configuration.\r
+\r
+ @note This service could be called by BSP only.\r
+**/\r
+VOID\r
+EFIAPI\r
+CpuFeaturesInitialize (\r
+ VOID\r
+ )\r
+{\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+ UINTN OldBspNumber;\r
+ EFI_EVENT MpEvent;\r
+ EFI_STATUS Status;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+\r
+ OldBspNumber = GetProcessorIndex (CpuFeaturesData);\r
+ CpuFeaturesData->BspNumber = OldBspNumber;\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_CALLBACK,\r
+ EfiEventEmptyFunction,\r
+ NULL,\r
+ &MpEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Wakeup all APs for programming.\r
+ //\r
+ StartupAPsWorker (SetProcessorRegister, MpEvent);\r
+ //\r
+ // Programming BSP\r
+ //\r
+ SetProcessorRegister (CpuFeaturesData);\r
+\r
+ //\r
+ // Wait all processors to finish the task.\r
+ //\r
+ do {\r
+ Status = gBS->CheckEvent (MpEvent);\r
+ } while (Status == EFI_NOT_READY);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Switch to new BSP if required\r
+ //\r
+ if (CpuFeaturesData->BspNumber != OldBspNumber) {\r
+ SwitchNewBsp (CpuFeaturesData->BspNumber);\r
+ }\r
+}\r
+\r