From 38c2cbb9354d7f58e48f9f649f23eb9bd0d3cfca Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 27 Apr 2017 11:22:26 +0800 Subject: UefiCpuPkg: Move to new location Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 75 - UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni | 22 - UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 743 --------- UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc | 43 - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm | 339 ---- UefiCpuPkg/Library/MpInitLib/Microcode.c | 218 --- UefiCpuPkg/Library/MpInitLib/MpLib.c | 2126 ------------------------ UefiCpuPkg/Library/MpInitLib/MpLib.h | 594 ------- UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 70 - UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni | 22 - UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 624 ------- UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc | 43 - UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 398 ----- 13 files changed, 5317 deletions(-) delete mode 100644 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf delete mode 100644 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni delete mode 100644 UefiCpuPkg/Library/MpInitLib/DxeMpLib.c delete mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc delete mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm delete mode 100644 UefiCpuPkg/Library/MpInitLib/Microcode.c delete mode 100644 UefiCpuPkg/Library/MpInitLib/MpLib.c delete mode 100644 UefiCpuPkg/Library/MpInitLib/MpLib.h delete mode 100644 UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf delete mode 100644 UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni delete mode 100644 UefiCpuPkg/Library/MpInitLib/PeiMpLib.c delete mode 100644 UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc delete mode 100644 UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm (limited to 'UefiCpuPkg/Library/MpInitLib') diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf deleted file mode 100644 index 9751ba1f0d..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ /dev/null @@ -1,75 +0,0 @@ -## @file -# MP Initialize Library instance for DXE driver. -# -# Copyright (c) 2016, Intel Corporation. All rights reserved.
-# 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. -# -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = DxeMpInitLib - MODULE_UNI_FILE = DxeMpInitLib.uni - FILE_GUID = B88F7146-9834-4c55-BFAC-481CC0C33736 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.1 - LIBRARY_CLASS = MpInitLib|DXE_DRIVER - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 -# - -[Sources.IA32] - Ia32/MpEqu.inc - Ia32/MpFuncs.nasm - -[Sources.X64] - X64/MpEqu.inc - X64/MpFuncs.nasm - -[Sources.common] - DxeMpLib.c - MpLib.c - MpLib.h - Microcode.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - UefiCpuPkg/UefiCpuPkg.dec - -[LibraryClasses] - BaseLib - LocalApicLib - MemoryAllocationLib - HobLib - MtrrLib - CpuLib - UefiCpuLib - UefiBootServicesTableLib - DebugAgentLib - -[Protocols] - gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES - -[Guids] - gEfiEventExitBootServicesGuid ## CONSUMES ## Event - gEfiEventLegacyBootGuid ## CONSUMES ## Event - -[Pcd] - gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## SOMETIMES_CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES - diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni deleted file mode 100644 index 99d79974be..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.uni +++ /dev/null @@ -1,22 +0,0 @@ -// /** @file -// MP Initialize Library instance for DXE driver. -// -// MP Initialize Library instance for DXE driver. -// -// Copyright (c) 2016, Intel Corporation. All rights reserved.
-// -// 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. -// -// **/ - - -#string STR_MODULE_ABSTRACT #language en-US "MP Initialize Library instance for DXE driver." - -#string STR_MODULE_DESCRIPTION #language en-US "MP Initialize Library instance for DXE driver." - diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c deleted file mode 100644 index b393244e05..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ /dev/null @@ -1,743 +0,0 @@ -/** @file - MP initialize support functions for DXE phase. - - Copyright (c) 2016, Intel Corporation. All rights reserved.
- 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 "MpLib.h" - -#include -#include -#include - -#include - -#define AP_CHECK_INTERVAL (EFI_TIMER_PERIOD_MILLISECONDS (100)) -#define AP_SAFE_STACK_SIZE 128 - -CPU_MP_DATA *mCpuMpData = NULL; -EFI_EVENT mCheckAllApsEvent = NULL; -EFI_EVENT mMpInitExitBootServicesEvent = NULL; -EFI_EVENT mLegacyBootEvent = NULL; -volatile BOOLEAN mStopCheckAllApsStatus = TRUE; -VOID *mReservedApLoopFunc = NULL; -UINTN mReservedTopOfApStack; -volatile UINT32 mNumberToFinish = 0; - -/** - Enable Debug Agent to support source debugging on AP function. - -**/ -VOID -EnableDebugAgent ( - VOID - ) -{ - // - // Initialize Debug Agent to support source level debug in DXE phase - // - InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL); -} - -/** - Get the pointer to CPU MP Data structure. - - @return The pointer to CPU MP Data structure. -**/ -CPU_MP_DATA * -GetCpuMpData ( - VOID - ) -{ - ASSERT (mCpuMpData != NULL); - return mCpuMpData; -} - -/** - Save the pointer to CPU MP Data structure. - - @param[in] CpuMpData The pointer to CPU MP Data structure will be saved. -**/ -VOID -SaveCpuMpData ( - IN CPU_MP_DATA *CpuMpData - ) -{ - mCpuMpData = CpuMpData; -} - -/** - Allocate reset vector buffer. - - @param[in, out] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -AllocateResetVector ( - IN OUT CPU_MP_DATA *CpuMpData - ) -{ - EFI_STATUS Status; - UINTN ApResetVectorSize; - EFI_PHYSICAL_ADDRESS StartAddress; - - if (CpuMpData->SaveRestoreFlag) { - BackupAndPrepareWakeupBuffer (CpuMpData); - } else { - ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize + - sizeof (MP_CPU_EXCHANGE_INFO); - - StartAddress = BASE_1MB; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (ApResetVectorSize), - &StartAddress - ); - ASSERT_EFI_ERROR (Status); - - CpuMpData->WakeupBuffer = (UINTN) StartAddress; - CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) - (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize); - // - // copy AP reset code in it - // - CopyMem ( - (VOID *) CpuMpData->WakeupBuffer, - (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress, - CpuMpData->AddressMap.RendezvousFunnelSize - ); - } -} - -/** - Free AP reset vector buffer. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -FreeResetVector ( - IN CPU_MP_DATA *CpuMpData - ) -{ - EFI_STATUS Status; - UINTN ApResetVectorSize; - - if (CpuMpData->SaveRestoreFlag) { - RestoreWakeupBuffer (CpuMpData); - } else { - ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize + - sizeof (MP_CPU_EXCHANGE_INFO); - Status = gBS->FreePages( - (EFI_PHYSICAL_ADDRESS)CpuMpData->WakeupBuffer, - EFI_SIZE_TO_PAGES (ApResetVectorSize) - ); - ASSERT_EFI_ERROR (Status); - } -} - -/** - Checks APs status and updates APs status if needed. - -**/ -VOID -CheckAndUpdateApsStatus ( - VOID - ) -{ - UINTN ProcessorNumber; - EFI_STATUS Status; - CPU_MP_DATA *CpuMpData; - - CpuMpData = GetCpuMpData (); - - // - // First, check whether pending StartupAllAPs() exists. - // - if (CpuMpData->WaitEvent != NULL) { - - Status = CheckAllAPs (); - // - // If all APs finish for StartupAllAPs(), signal the WaitEvent for it. - // - if (Status != EFI_NOT_READY) { - Status = gBS->SignalEvent (CpuMpData->WaitEvent); - CpuMpData->WaitEvent = NULL; - } - } - - // - // Second, check whether pending StartupThisAPs() callings exist. - // - for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) { - - if (CpuMpData->CpuData[ProcessorNumber].WaitEvent == NULL) { - continue; - } - - Status = CheckThisAP (ProcessorNumber); - - if (Status != EFI_NOT_READY) { - gBS->SignalEvent (CpuMpData->CpuData[ProcessorNumber].WaitEvent); - CpuMpData->CpuData[ProcessorNumber].WaitEvent = NULL; - } - } -} - -/** - Checks APs' status periodically. - - This function is triggered by timer periodically to check the - state of APs for StartupAllAPs() and StartupThisAP() executed - in non-blocking mode. - - @param[in] Event Event triggered. - @param[in] Context Parameter passed with the event. - -**/ -VOID -EFIAPI -CheckApsStatus ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // If CheckApsStatus() is not stopped, otherwise return immediately. - // - if (!mStopCheckAllApsStatus) { - CheckAndUpdateApsStatus (); - } -} - -/** - Get Protected mode code segment from current GDT table. - - @return Protected mode code segment value. -**/ -UINT16 -GetProtectedModeCS ( - VOID - ) -{ - IA32_DESCRIPTOR GdtrDesc; - IA32_SEGMENT_DESCRIPTOR *GdtEntry; - UINTN GdtEntryCount; - UINT16 Index; - - Index = (UINT16) -1; - AsmReadGdtr (&GdtrDesc); - GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR); - GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; - for (Index = 0; Index < GdtEntryCount; Index++) { - if (GdtEntry->Bits.L == 0) { - if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) { - break; - } - } - GdtEntry++; - } - ASSERT (Index != -1); - return Index * 8; -} - -/** - Do sync on APs. - - @param[in, out] Buffer Pointer to private data buffer. -**/ -VOID -EFIAPI -RelocateApLoop ( - IN OUT VOID *Buffer - ) -{ - CPU_MP_DATA *CpuMpData; - BOOLEAN MwaitSupport; - ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc; - UINTN ProcessorNumber; - - MpInitLibWhoAmI (&ProcessorNumber); - CpuMpData = GetCpuMpData (); - MwaitSupport = IsMwaitSupport (); - AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) mReservedApLoopFunc; - AsmRelocateApLoopFunc ( - MwaitSupport, - CpuMpData->ApTargetCState, - CpuMpData->PmCodeSegment, - mReservedTopOfApStack - ProcessorNumber * AP_SAFE_STACK_SIZE, - (UINTN) &mNumberToFinish - ); - // - // It should never reach here - // - ASSERT (FALSE); -} - -/** - Callback function for ExitBootServices. - - @param[in] Event Event whose notification function is being invoked. - @param[in] Context The pointer to the notification function's context, - which is implementation-dependent. - -**/ -VOID -EFIAPI -MpInitChangeApLoopCallback ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - CPU_MP_DATA *CpuMpData; - - CpuMpData = GetCpuMpData (); - CpuMpData->SaveRestoreFlag = TRUE; - CpuMpData->PmCodeSegment = GetProtectedModeCS (); - CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); - mNumberToFinish = CpuMpData->CpuCount - 1; - WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL); - while (mNumberToFinish > 0) { - CpuPause (); - } - DEBUG ((DEBUG_INFO, "%a() done!\n", __FUNCTION__)); -} - -/** - Initialize global data for MP support. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -InitMpGlobalData ( - IN CPU_MP_DATA *CpuMpData - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS Address; - UINTN ApSafeBufferSize; - - SaveCpuMpData (CpuMpData); - - if (CpuMpData->CpuCount == 1) { - // - // If only BSP exists, return - // - return; - } - - // - // Avoid APs access invalid buffer data which allocated by BootServices, - // so we will allocate reserved data for AP loop code. We also need to - // allocate this buffer below 4GB due to APs may be transferred to 32bit - // protected mode on long mode DXE. - // Allocating it in advance since memory services are not available in - // Exit Boot Services callback function. - // - ApSafeBufferSize = CpuMpData->AddressMap.RelocateApLoopFuncSize; - ApSafeBufferSize += CpuMpData->CpuCount * AP_SAFE_STACK_SIZE; - - Address = BASE_4GB - 1; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiReservedMemoryType, - EFI_SIZE_TO_PAGES (ApSafeBufferSize), - &Address - ); - ASSERT_EFI_ERROR (Status); - mReservedApLoopFunc = (VOID *) (UINTN) Address; - ASSERT (mReservedApLoopFunc != NULL); - mReservedTopOfApStack = (UINTN) Address + EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ApSafeBufferSize)); - ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0); - CopyMem ( - mReservedApLoopFunc, - CpuMpData->AddressMap.RelocateApLoopFuncAddress, - CpuMpData->AddressMap.RelocateApLoopFuncSize - ); - - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - CheckApsStatus, - NULL, - &mCheckAllApsEvent - ); - ASSERT_EFI_ERROR (Status); - - // - // Set timer to check all APs status. - // - Status = gBS->SetTimer ( - mCheckAllApsEvent, - TimerPeriodic, - AP_CHECK_INTERVAL - ); - ASSERT_EFI_ERROR (Status); - - Status = gBS->CreateEvent ( - EVT_SIGNAL_EXIT_BOOT_SERVICES, - TPL_CALLBACK, - MpInitChangeApLoopCallback, - NULL, - &mMpInitExitBootServicesEvent - ); - ASSERT_EFI_ERROR (Status); - - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - MpInitChangeApLoopCallback, - NULL, - &gEfiEventLegacyBootGuid, - &mLegacyBootEvent - ); - ASSERT_EFI_ERROR (Status); -} - -/** - This service executes 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. See type - EFI_AP_PROCEDURE. - @param[in] SingleThread If TRUE, then all the enabled APs execute - the function specified by Procedure one by - one, in ascending order of processor handle - number. If FALSE, then all the enabled APs - execute the function specified by Procedure - simultaneously. - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. If it is NULL, then execute in - blocking mode. BSP waits until all APs finish - or TimeoutInMicroSeconds expires. If it's - not NULL, then execute in non-blocking mode. - BSP requests the function specified by - Procedure to be started on all the enabled - APs, and go on executing immediately. If - all return from Procedure, or TimeoutInMicroSeconds - expires, this event is signaled. The BSP - can use the CheckEvent() or WaitForEvent() - services to check the state of event. Type - EFI_EVENT is defined in CreateEvent() in - the Unified Extensible Firmware Interface - Specification. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - APs to return from Procedure, either for - blocking or non-blocking mode. Zero means - infinity. If the timeout expires before - all APs return from Procedure, then Procedure - on the failed APs is terminated. All enabled - APs are available for next function assigned - by MpInitLibStartupAllAPs() or - MPInitLibStartupThisAP(). - If the timeout expires in blocking mode, - BSP returns EFI_TIMEOUT. If the timeout - expires in non-blocking mode, WaitEvent - is signaled with SignalEvent(). - @param[in] ProcedureArgument The parameter passed into Procedure for - all APs. - @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise, - if all APs finish successfully, then its - content is set to NULL. If not all APs - finish before timeout expires, then its - content is set to address of the buffer - holding handle numbers of the failed APs. - The buffer is allocated by MP Initialization - library, and it's the caller's responsibility to - free the buffer with FreePool() service. - In blocking mode, it is ready for consumption - when the call returns. In non-blocking mode, - it is ready when WaitEvent is signaled. The - list of failed CPU is terminated by - END_OF_CPU_LIST. - - @retval EFI_SUCCESS In blocking mode, all APs have finished before - the timeout expired. - @retval EFI_SUCCESS In non-blocking mode, function has been dispatched - to all enabled APs. - @retval EFI_UNSUPPORTED A non-blocking mode request was made after the - UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was - signaled. - @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not - supported. - @retval EFI_DEVICE_ERROR Caller processor is AP. - @retval EFI_NOT_STARTED No enabled APs exist in the system. - @retval EFI_NOT_READY Any enabled APs are busy. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - @retval EFI_TIMEOUT In blocking mode, the timeout expired before - all enabled APs have finished. - @retval EFI_INVALID_PARAMETER Procedure is NULL. - -**/ -EFI_STATUS -EFIAPI -MpInitLibStartupAllAPs ( - IN EFI_AP_PROCEDURE Procedure, - IN BOOLEAN SingleThread, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT UINTN **FailedCpuList OPTIONAL - ) -{ - EFI_STATUS Status; - - // - // Temporarily stop checkAllApsStatus for avoid resource dead-lock. - // - mStopCheckAllApsStatus = TRUE; - - Status = StartupAllAPsWorker ( - Procedure, - SingleThread, - WaitEvent, - TimeoutInMicroseconds, - ProcedureArgument, - FailedCpuList - ); - - // - // Start checkAllApsStatus - // - mStopCheckAllApsStatus = FALSE; - - return Status; -} - -/** - This service lets the caller get one enabled AP to execute a caller-provided - function. - - @param[in] Procedure A pointer to the function to be run on the - designated AP of the system. See type - EFI_AP_PROCEDURE. - @param[in] ProcessorNumber The handle number of the AP. The range is - from 0 to the total number of logical - processors minus 1. The total number of - logical processors can be retrieved by - MpInitLibGetNumberOfProcessors(). - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. If it is NULL, then execute in - blocking mode. BSP waits until this AP finish - or TimeoutInMicroSeconds expires. If it's - not NULL, then execute in non-blocking mode. - BSP requests the function specified by - Procedure to be started on this AP, - and go on executing immediately. If this AP - return from Procedure or TimeoutInMicroSeconds - expires, this event is signaled. The BSP - can use the CheckEvent() or WaitForEvent() - services to check the state of event. Type - EFI_EVENT is defined in CreateEvent() in - the Unified Extensible Firmware Interface - Specification. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - this AP to finish this Procedure, either for - blocking or non-blocking mode. Zero means - infinity. If the timeout expires before - this AP returns from Procedure, then Procedure - on the AP is terminated. The - AP is available for next function assigned - by MpInitLibStartupAllAPs() or - MpInitLibStartupThisAP(). - If the timeout expires in blocking mode, - BSP returns EFI_TIMEOUT. If the timeout - expires in non-blocking mode, WaitEvent - is signaled with SignalEvent(). - @param[in] ProcedureArgument The parameter passed into Procedure on the - specified AP. - @param[out] Finished If NULL, this parameter is ignored. In - blocking mode, this parameter is ignored. - In non-blocking mode, if AP returns from - Procedure before the timeout expires, its - content is set to TRUE. Otherwise, the - value is set to FALSE. The caller can - determine if the AP returned from Procedure - by evaluating this value. - - @retval EFI_SUCCESS In blocking mode, specified AP finished before - the timeout expires. - @retval EFI_SUCCESS In non-blocking mode, the function has been - dispatched to specified AP. - @retval EFI_UNSUPPORTED A non-blocking mode request was made after the - UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was - signaled. - @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not - supported. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_TIMEOUT In blocking mode, the timeout expired before - the specified AP has finished. - @retval EFI_NOT_READY The specified AP is busy. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - @retval EFI_NOT_FOUND The processor with the handle specified by - ProcessorNumber does not exist. - @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. - @retval EFI_INVALID_PARAMETER Procedure is NULL. - -**/ -EFI_STATUS -EFIAPI -MpInitLibStartupThisAP ( - IN EFI_AP_PROCEDURE Procedure, - IN UINTN ProcessorNumber, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT BOOLEAN *Finished OPTIONAL - ) -{ - EFI_STATUS Status; - - // - // temporarily stop checkAllApsStatus for avoid resource dead-lock. - // - mStopCheckAllApsStatus = TRUE; - - Status = StartupThisAPWorker ( - Procedure, - ProcessorNumber, - WaitEvent, - TimeoutInMicroseconds, - ProcedureArgument, - Finished - ); - - mStopCheckAllApsStatus = FALSE; - - return Status; -} - -/** - This service switches the requested AP to be the BSP from that point onward. - This service changes the BSP for all purposes. This call can only be performed - by the current BSP. - - @param[in] ProcessorNumber The handle number of AP that is to become the new - BSP. The range is from 0 to the total number of - logical processors minus 1. The total number of - logical processors can be retrieved by - MpInitLibGetNumberOfProcessors(). - @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an - enabled AP. Otherwise, it will be disabled. - - @retval EFI_SUCCESS BSP successfully switched. - @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to - this service returning. - @retval EFI_UNSUPPORTED Switching the BSP is not supported. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_NOT_FOUND The processor with the handle specified by - ProcessorNumber does not exist. - @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or - a disabled AP. - @retval EFI_NOT_READY The specified AP is busy. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - -**/ -EFI_STATUS -EFIAPI -MpInitLibSwitchBSP ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableOldBSP - ) -{ - EFI_STATUS Status; - EFI_TIMER_ARCH_PROTOCOL *Timer; - UINT64 TimerPeriod; - - TimerPeriod = 0; - // - // Locate Timer Arch Protocol - // - Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &Timer); - if (EFI_ERROR (Status)) { - Timer = NULL; - } - - if (Timer != NULL) { - // - // Save current rate of DXE Timer - // - Timer->GetTimerPeriod (Timer, &TimerPeriod); - // - // Disable DXE Timer and drain pending interrupts - // - Timer->SetTimerPeriod (Timer, 0); - } - - Status = SwitchBSPWorker (ProcessorNumber, EnableOldBSP); - - if (Timer != NULL) { - // - // Enable and restore rate of DXE Timer - // - Timer->SetTimerPeriod (Timer, TimerPeriod); - } - - return Status; -} - -/** - This service lets the caller enable or disable an AP from this point onward. - This service may only be called from the BSP. - - @param[in] ProcessorNumber The handle number of AP. - The range is from 0 to the total number of - logical processors minus 1. The total number of - logical processors can be retrieved by - MpInitLibGetNumberOfProcessors(). - @param[in] EnableAP Specifies the new state for the processor for - enabled, FALSE for disabled. - @param[in] HealthFlag If not NULL, a pointer to a value that specifies - the new health status of the AP. This flag - corresponds to StatusFlag defined in - EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only - the PROCESSOR_HEALTH_STATUS_BIT is used. All other - bits are ignored. If it is NULL, this parameter - is ignored. - - @retval EFI_SUCCESS The specified AP was enabled or disabled successfully. - @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed - prior to this service returning. - @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber - does not exist. - @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - -**/ -EFI_STATUS -EFIAPI -MpInitLibEnableDisableAP ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableAP, - IN UINT32 *HealthFlag OPTIONAL - ) -{ - EFI_STATUS Status; - BOOLEAN TempStopCheckState; - - TempStopCheckState = FALSE; - // - // temporarily stop checkAllAPsStatus for initialize parameters. - // - if (!mStopCheckAllApsStatus) { - mStopCheckAllApsStatus = TRUE; - TempStopCheckState = TRUE; - } - - Status = EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag); - - if (TempStopCheckState) { - mStopCheckAllApsStatus = FALSE; - } - - return Status; -} diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc deleted file mode 100644 index 62762308e2..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc +++ /dev/null @@ -1,43 +0,0 @@ -;------------------------------------------------------------------------------ ; -; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
-; 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. -; -; Module Name: -; -; MpEqu.inc -; -; Abstract: -; -; This is the equates file for Multiple Processor support -; -;------------------------------------------------------------------------------- - -VacantFlag equ 00h -NotVacantFlag equ 0ffh - -CPU_SWITCH_STATE_IDLE equ 0 -CPU_SWITCH_STATE_STORED equ 1 -CPU_SWITCH_STATE_LOADED equ 2 - -LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart) -StackStartAddressLocation equ LockLocation + 04h -StackSizeLocation equ LockLocation + 08h -ApProcedureLocation equ LockLocation + 0Ch -GdtrLocation equ LockLocation + 10h -IdtrLocation equ LockLocation + 16h -BufferStartLocation equ LockLocation + 1Ch -ModeOffsetLocation equ LockLocation + 20h -NumApsExecutingLocation equ LockLocation + 24h -CodeSegmentLocation equ LockLocation + 28h -DataSegmentLocation equ LockLocation + 2Ch -EnableExecuteDisableLocation equ LockLocation + 30h -Cr3Location equ LockLocation + 34h -InitFlagLocation equ LockLocation + 38h -CpuInfoLocation equ LockLocation + 3Ch - diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm deleted file mode 100644 index 52363e6e08..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm +++ /dev/null @@ -1,339 +0,0 @@ -;------------------------------------------------------------------------------ ; -; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
-; 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. -; -; Module Name: -; -; MpFuncs.nasm -; -; Abstract: -; -; This is the assembly code for MP support -; -;------------------------------------------------------------------------------- - -%include "MpEqu.inc" -extern ASM_PFX(InitializeFloatingPointUnits) - -SECTION .text - -;------------------------------------------------------------------------------------- -;RendezvousFunnelProc procedure follows. All APs execute their procedure. This -;procedure serializes all the AP processors through an Init sequence. It must be -;noted that APs arrive here very raw...ie: real mode, no stack. -;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC -;IS IN MACHINE CODE. -;------------------------------------------------------------------------------------- -global ASM_PFX(RendezvousFunnelProc) -ASM_PFX(RendezvousFunnelProc): -RendezvousFunnelProcStart: -; At this point CS = 0x(vv00) and ip= 0x0. -BITS 16 - mov ebp, eax ; save BIST information - - mov ax, cs - mov ds, ax - mov es, ax - mov ss, ax - xor ax, ax - mov fs, ax - mov gs, ax - - mov si, BufferStartLocation - mov ebx, [si] - - mov si, ModeOffsetLocation - mov eax, [si] - mov si, CodeSegmentLocation - mov edx, [si] - mov di, ax - sub di, 02h - mov [di], dx - sub di, 04h - add eax, ebx - mov [di],eax - - mov si, DataSegmentLocation - mov edx, [si] - - mov si, GdtrLocation -o32 lgdt [cs:si] - - mov si, IdtrLocation -o32 lidt [cs:si] - - xor ax, ax - mov ds, ax - - mov eax, cr0 ; Get control register 0 - or eax, 000000003h ; Set PE bit (bit #0) & MP - mov cr0, eax - - jmp 0:strict dword 0 ; far jump to protected mode -BITS 32 -Flat32Start: ; protected mode entry point - mov ds, dx - mov es, dx - mov fs, dx - mov gs, dx - mov ss, dx - - mov esi, ebx - - mov edi, esi - add edi, EnableExecuteDisableLocation - cmp byte [edi], 0 - jz SkipEnableExecuteDisable - - ; - ; Enable IA32 PAE execute disable - ; - - mov ecx, 0xc0000080 - rdmsr - bts eax, 11 - wrmsr - - mov edi, esi - add edi, Cr3Location - mov eax, dword [edi] - mov cr3, eax - - mov eax, cr4 - bts eax, 5 - mov cr4, eax - - mov eax, cr0 - bts eax, 31 - mov cr0, eax - -SkipEnableExecuteDisable: - mov edi, esi - add edi, InitFlagLocation - cmp dword [edi], 1 ; 1 == ApInitConfig - jnz GetApicId - - ; AP init - mov edi, esi - add edi, LockLocation - mov eax, NotVacantFlag - -TestLock: - xchg [edi], eax - cmp eax, NotVacantFlag - jz TestLock - - mov ecx, esi - add ecx, NumApsExecutingLocation - inc dword [ecx] - mov ebx, [ecx] - -Releaselock: - mov eax, VacantFlag - xchg [edi], eax - - mov edi, esi - add edi, StackSizeLocation - mov eax, [edi] - mov ecx, ebx - inc ecx - mul ecx ; EAX = StackSize * (CpuNumber + 1) - mov edi, esi - add edi, StackStartAddressLocation - add eax, [edi] - mov esp, eax - jmp CProcedureInvoke - -GetApicId: - mov eax, 0 - cpuid - cmp eax, 0bh - jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY - - mov eax, 0bh - xor ecx, ecx - cpuid - test ebx, 0ffffh - jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero - - ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX - jmp GetProcessorNumber - -NoX2Apic: - ; Processor is not x2APIC capable, so get 8-bit APIC ID - mov eax, 1 - cpuid - shr ebx, 24 - mov edx, ebx - -GetProcessorNumber: - ; - ; Get processor number for this AP - ; Note that BSP may become an AP due to SwitchBsp() - ; - xor ebx, ebx - lea eax, [esi + CpuInfoLocation] - mov edi, [eax] - -GetNextProcNumber: - cmp [edi], edx ; APIC ID match? - jz ProgramStack - add edi, 20 - inc ebx - jmp GetNextProcNumber - -ProgramStack: - mov esp, [edi + 12] - -CProcedureInvoke: - push ebp ; push BIST data at top of AP stack - xor ebp, ebp ; clear ebp for call stack trace - push ebp - mov ebp, esp - - mov eax, ASM_PFX(InitializeFloatingPointUnits) - call eax ; Call assembly function to initialize FPU per UEFI spec - - push ebx ; Push NumApsExecuting - mov eax, esi - add eax, LockLocation - push eax ; push address of exchange info data buffer - - mov edi, esi - add edi, ApProcedureLocation - mov eax, [edi] - - call eax ; Invoke C function - - jmp $ ; Never reach here -RendezvousFunnelProcEnd: - -;------------------------------------------------------------------------------------- -; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish); -;------------------------------------------------------------------------------------- -global ASM_PFX(AsmRelocateApLoop) -ASM_PFX(AsmRelocateApLoop): -AsmRelocateApLoopStart: - mov eax, esp - mov esp, [eax + 16] ; TopOfApStack - push dword [eax] ; push return address for stack trace - push ebp - mov ebp, esp - mov ebx, [eax + 8] ; ApTargetCState - mov ecx, [eax + 4] ; MwaitSupport - mov eax, [eax + 20] ; CountTofinish - lock dec dword [eax] ; (*CountTofinish)-- - cmp cl, 1 ; Check mwait-monitor support - jnz HltLoop -MwaitLoop: - mov eax, esp - xor ecx, ecx - xor edx, edx - monitor - mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] - shl eax, 4 - mwait - jmp MwaitLoop -HltLoop: - cli - hlt - jmp HltLoop -AsmRelocateApLoopEnd: - -;------------------------------------------------------------------------------------- -; AsmGetAddressMap (&AddressMap); -;------------------------------------------------------------------------------------- -global ASM_PFX(AsmGetAddressMap) -ASM_PFX(AsmGetAddressMap): - pushad - mov ebp,esp - - mov ebx, [ebp + 24h] - mov dword [ebx], RendezvousFunnelProcStart - mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart - mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart - mov dword [ebx + 0Ch], AsmRelocateApLoopStart - mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart - - popad - ret - -;------------------------------------------------------------------------------------- -;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is -;about to become an AP. It switches it'stack with the current AP. -;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); -;------------------------------------------------------------------------------------- -global ASM_PFX(AsmExchangeRole) -ASM_PFX(AsmExchangeRole): - ; DO NOT call other functions in this function, since 2 CPU may use 1 stack - ; at the same time. If 1 CPU try to call a function, stack will be corrupted. - pushad - mov ebp,esp - - ; esi contains MyInfo pointer - mov esi, [ebp + 24h] - - ; edi contains OthersInfo pointer - mov edi, [ebp + 28h] - - ;Store EFLAGS, GDTR and IDTR register to stack - pushfd - mov eax, cr4 - push eax ; push cr4 firstly - mov eax, cr0 - push eax - - sgdt [esi + 8] - sidt [esi + 14] - - ; Store the its StackPointer - mov [esi + 4],esp - - ; update its switch state to STORED - mov byte [esi], CPU_SWITCH_STATE_STORED - -WaitForOtherStored: - ; wait until the other CPU finish storing its state - cmp byte [edi], CPU_SWITCH_STATE_STORED - jz OtherStored - pause - jmp WaitForOtherStored - -OtherStored: - ; Since another CPU already stored its state, load them - ; load GDTR value - lgdt [edi + 8] - - ; load IDTR value - lidt [edi + 14] - - ; load its future StackPointer - mov esp, [edi + 4] - - ; update the other CPU's switch state to LOADED - mov byte [edi], CPU_SWITCH_STATE_LOADED - -WaitForOtherLoaded: - ; wait until the other CPU finish loading new state, - ; otherwise the data in stack may corrupt - cmp byte [esi], CPU_SWITCH_STATE_LOADED - jz OtherLoaded - pause - jmp WaitForOtherLoaded - -OtherLoaded: - ; since the other CPU already get the data it want, leave this procedure - pop eax - mov cr0, eax - pop eax - mov cr4, eax - popfd - - popad - ret diff --git a/UefiCpuPkg/Library/MpInitLib/Microcode.c b/UefiCpuPkg/Library/MpInitLib/Microcode.c deleted file mode 100644 index 982995be7d..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/Microcode.c +++ /dev/null @@ -1,218 +0,0 @@ -/** @file - Implementation of loading microcode on processors. - - Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
- 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 "MpLib.h" - -/** - Get microcode update signature of currently loaded microcode update. - - @return Microcode signature. -**/ -UINT32 -GetCurrentMicrocodeSignature ( - VOID - ) -{ - MSR_IA32_BIOS_SIGN_ID_REGISTER BiosSignIdMsr; - - AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0); - AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL); - BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID); - return BiosSignIdMsr.Bits.MicrocodeUpdateSignature; -} - -/** - Detect whether specified processor can find matching microcode patch and load it. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -MicrocodeDetect ( - IN CPU_MP_DATA *CpuMpData - ) -{ - UINT64 MicrocodePatchAddress; - UINT64 MicrocodePatchRegionSize; - UINT32 ExtendedTableLength; - UINT32 ExtendedTableCount; - CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable; - CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader; - CPU_MICROCODE_HEADER *MicrocodeEntryPoint; - UINTN MicrocodeEnd; - UINTN Index; - UINT8 PlatformId; - CPUID_VERSION_INFO_EAX Eax; - UINT32 CurrentRevision; - UINT32 LatestRevision; - UINTN TotalSize; - UINT32 CheckSum32; - BOOLEAN CorrectMicrocode; - VOID *MicrocodeData; - MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr; - - MicrocodePatchAddress = PcdGet64 (PcdCpuMicrocodePatchAddress); - MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize); - if (MicrocodePatchRegionSize == 0) { - // - // There is no microcode patches - // - return; - } - - CurrentRevision = GetCurrentMicrocodeSignature (); - if (CurrentRevision != 0) { - // - // Skip loading microcode if it has been loaded successfully - // - return; - } - - ExtendedTableLength = 0; - // - // Here data of CPUID leafs have not been collected into context buffer, so - // GetProcessorCpuid() cannot be used here to retrieve sCPUID data. - // - AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL); - - // - // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID - // - PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID); - PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId; - - LatestRevision = 0; - MicrocodeData = NULL; - MicrocodeEnd = (UINTN) (MicrocodePatchAddress + MicrocodePatchRegionSize); - MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress; - do { - // - // Check if the microcode is for the Cpu and the version is newer - // and the update can be processed on the platform - // - CorrectMicrocode = FALSE; - if (MicrocodeEntryPoint->HeaderVersion == 0x1) { - // - // It is the microcode header. It is not the padding data between microcode patches - // because the padding data should not include 0x00000001 and it should be the repeated - // byte format (like 0xXYXYXYXY....). - // - if (MicrocodeEntryPoint->ProcessorSignature.Uint32 == Eax.Uint32 && - MicrocodeEntryPoint->UpdateRevision > LatestRevision && - (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId)) - ) { - if (MicrocodeEntryPoint->DataSize == 0) { - CheckSum32 = CalculateSum32 ((UINT32 *) MicrocodeEntryPoint, 2048); - } else { - CheckSum32 = CalculateSum32 ( - (UINT32 *) MicrocodeEntryPoint, - MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER) - ); - } - if (CheckSum32 == 0) { - CorrectMicrocode = TRUE; - } - } else if ((MicrocodeEntryPoint->DataSize != 0) && - (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) { - ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + - sizeof (CPU_MICROCODE_HEADER)); - if (ExtendedTableLength != 0) { - // - // Extended Table exist, check if the CPU in support list - // - ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint) - + MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER)); - // - // Calculate Extended Checksum - // - if ((ExtendedTableLength % 4) == 0) { - CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength); - if (CheckSum32 == 0) { - // - // Checksum correct - // - ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount; - ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1); - for (Index = 0; Index < ExtendedTableCount; Index ++) { - CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTable, sizeof(CPU_MICROCODE_EXTENDED_TABLE)); - if (CheckSum32 == 0) { - // - // Verify Header - // - if ((ExtendedTable->ProcessorSignature.Uint32 == Eax.Uint32) && - (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) { - // - // Find one - // - CorrectMicrocode = TRUE; - break; - } - } - ExtendedTable ++; - } - } - } - } - } - } else { - // - // It is the padding data between the microcode patches for microcode patches alignment. - // Because the microcode patch is the multiple of 1-KByte, the padding data should not - // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode - // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to - // find the next possible microcode patch header. - // - MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB); - continue; - } - // - // Get the next patch. - // - if (MicrocodeEntryPoint->DataSize == 0) { - TotalSize = 2048; - } else { - TotalSize = MicrocodeEntryPoint->TotalSize; - } - - if (CorrectMicrocode) { - LatestRevision = MicrocodeEntryPoint->UpdateRevision; - MicrocodeData = (VOID *) ((UINTN) MicrocodeEntryPoint + sizeof (CPU_MICROCODE_HEADER)); - } - - MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize); - } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd)); - - if (LatestRevision > CurrentRevision) { - // - // BIOS only authenticate updates that contain a numerically larger revision - // than the currently loaded revision, where Current Signature < New Update - // Revision. A processor with no loaded update is considered to have a - // revision equal to zero. - // - ASSERT (MicrocodeData != NULL); - AsmWriteMsr64 ( - MSR_IA32_BIOS_UPDT_TRIG, - (UINT64) (UINTN) MicrocodeData - ); - // - // Get and check new microcode signature - // - CurrentRevision = GetCurrentMicrocodeSignature (); - if (CurrentRevision != LatestRevision) { - AcquireSpinLock(&CpuMpData->MpLock); - DEBUG ((EFI_D_ERROR, "Updated microcode signature [0x%08x] does not match \ - loaded microcode signature [0x%08x]\n", CurrentRevision, LatestRevision)); - ReleaseSpinLock(&CpuMpData->MpLock); - } - } -} diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c deleted file mode 100644 index 03d6c2d89e..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ /dev/null @@ -1,2126 +0,0 @@ -/** @file - CPU MP Initialize Library common functions. - - Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
- 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 "MpLib.h" - -EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID; - -/** - The function will check if BSP Execute Disable is enabled. - - DxeIpl may have enabled Execute Disable for BSP, APs need to - get the status and sync up the settings. - If BSP's CR0.Paging is not set, BSP execute Disble feature is - not working actually. - - @retval TRUE BSP Execute Disable is enabled. - @retval FALSE BSP Execute Disable is not enabled. -**/ -BOOLEAN -IsBspExecuteDisableEnabled ( - VOID - ) -{ - UINT32 Eax; - CPUID_EXTENDED_CPU_SIG_EDX Edx; - MSR_IA32_EFER_REGISTER EferMsr; - BOOLEAN Enabled; - IA32_CR0 Cr0; - - Enabled = FALSE; - Cr0.UintN = AsmReadCr0 (); - if (Cr0.Bits.PG != 0) { - // - // If CR0 Paging bit is set - // - AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL); - if (Eax >= CPUID_EXTENDED_CPU_SIG) { - AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &Edx.Uint32); - // - // CPUID 0x80000001 - // Bit 20: Execute Disable Bit available. - // - if (Edx.Bits.NX != 0) { - EferMsr.Uint64 = AsmReadMsr64 (MSR_IA32_EFER); - // - // MSR 0xC0000080 - // Bit 11: Execute Disable Bit enable. - // - if (EferMsr.Bits.NXE != 0) { - Enabled = TRUE; - } - } - } - } - - return Enabled; -} - -/** - Worker function for SwitchBSP(). - - Worker function for SwitchBSP(), assigned to the AP which is intended - to become BSP. - - @param[in] Buffer Pointer to CPU MP Data -**/ -VOID -EFIAPI -FutureBSPProc ( - IN VOID *Buffer - ) -{ - CPU_MP_DATA *DataInHob; - - DataInHob = (CPU_MP_DATA *) Buffer; - AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo); -} - -/** - Get the Application Processors state. - - @param[in] CpuData The pointer to CPU_AP_DATA of specified AP - - @return The AP status -**/ -CPU_STATE -GetApState ( - IN CPU_AP_DATA *CpuData - ) -{ - return CpuData->State; -} - -/** - Set the Application Processors state. - - @param[in] CpuData The pointer to CPU_AP_DATA of specified AP - @param[in] State The AP status -**/ -VOID -SetApState ( - IN CPU_AP_DATA *CpuData, - IN CPU_STATE State - ) -{ - AcquireSpinLock (&CpuData->ApLock); - CpuData->State = State; - ReleaseSpinLock (&CpuData->ApLock); -} - -/** - Save BSP's local APIC timer setting. - - @param[in] CpuMpData Pointer to CPU MP Data -**/ -VOID -SaveLocalApicTimerSetting ( - IN CPU_MP_DATA *CpuMpData - ) -{ - // - // Record the current local APIC timer setting of BSP - // - GetApicTimerState ( - &CpuMpData->DivideValue, - &CpuMpData->PeriodicMode, - &CpuMpData->Vector - ); - CpuMpData->CurrentTimerCount = GetApicTimerCurrentCount (); - CpuMpData->TimerInterruptState = GetApicTimerInterruptState (); -} - -/** - Sync local APIC timer setting from BSP to AP. - - @param[in] CpuMpData Pointer to CPU MP Data -**/ -VOID -SyncLocalApicTimerSetting ( - IN CPU_MP_DATA *CpuMpData - ) -{ - // - // Sync local APIC timer setting from BSP to AP - // - InitializeApicTimer ( - CpuMpData->DivideValue, - CpuMpData->CurrentTimerCount, - CpuMpData->PeriodicMode, - CpuMpData->Vector - ); - // - // Disable AP's local APIC timer interrupt - // - DisableApicTimerInterrupt (); -} - -/** - Save the volatile registers required to be restored following INIT IPI. - - @param[out] VolatileRegisters Returns buffer saved the volatile resisters -**/ -VOID -SaveVolatileRegisters ( - OUT CPU_VOLATILE_REGISTERS *VolatileRegisters - ) -{ - CPUID_VERSION_INFO_EDX VersionInfoEdx; - - VolatileRegisters->Cr0 = AsmReadCr0 (); - VolatileRegisters->Cr3 = AsmReadCr3 (); - VolatileRegisters->Cr4 = AsmReadCr4 (); - - AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32); - if (VersionInfoEdx.Bits.DE != 0) { - // - // If processor supports Debugging Extensions feature - // by CPUID.[EAX=01H]:EDX.BIT2 - // - VolatileRegisters->Dr0 = AsmReadDr0 (); - VolatileRegisters->Dr1 = AsmReadDr1 (); - VolatileRegisters->Dr2 = AsmReadDr2 (); - VolatileRegisters->Dr3 = AsmReadDr3 (); - VolatileRegisters->Dr6 = AsmReadDr6 (); - VolatileRegisters->Dr7 = AsmReadDr7 (); - } -} - -/** - Restore the volatile registers following INIT IPI. - - @param[in] VolatileRegisters Pointer to volatile resisters - @param[in] IsRestoreDr TRUE: Restore DRx if supported - FALSE: Do not restore DRx -**/ -VOID -RestoreVolatileRegisters ( - IN CPU_VOLATILE_REGISTERS *VolatileRegisters, - IN BOOLEAN IsRestoreDr - ) -{ - CPUID_VERSION_INFO_EDX VersionInfoEdx; - - AsmWriteCr0 (VolatileRegisters->Cr0); - AsmWriteCr3 (VolatileRegisters->Cr3); - AsmWriteCr4 (VolatileRegisters->Cr4); - - if (IsRestoreDr) { - AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32); - if (VersionInfoEdx.Bits.DE != 0) { - // - // If processor supports Debugging Extensions feature - // by CPUID.[EAX=01H]:EDX.BIT2 - // - AsmWriteDr0 (VolatileRegisters->Dr0); - AsmWriteDr1 (VolatileRegisters->Dr1); - AsmWriteDr2 (VolatileRegisters->Dr2); - AsmWriteDr3 (VolatileRegisters->Dr3); - AsmWriteDr6 (VolatileRegisters->Dr6); - AsmWriteDr7 (VolatileRegisters->Dr7); - } - } -} - -/** - Detect whether Mwait-monitor feature is supported. - - @retval TRUE Mwait-monitor feature is supported. - @retval FALSE Mwait-monitor feature is not supported. -**/ -BOOLEAN -IsMwaitSupport ( - VOID - ) -{ - CPUID_VERSION_INFO_ECX VersionInfoEcx; - - AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL); - return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE; -} - -/** - Get AP loop mode. - - @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes. - - @return The AP loop mode. -**/ -UINT8 -GetApLoopMode ( - OUT UINT32 *MonitorFilterSize - ) -{ - UINT8 ApLoopMode; - CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx; - - ASSERT (MonitorFilterSize != NULL); - - ApLoopMode = PcdGet8 (PcdCpuApLoopMode); - ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop); - if (ApLoopMode == ApInMwaitLoop) { - if (!IsMwaitSupport ()) { - // - // If processor does not support MONITOR/MWAIT feature, - // force AP in Hlt-loop mode - // - ApLoopMode = ApInHltLoop; - } - } - - if (ApLoopMode != ApInMwaitLoop) { - *MonitorFilterSize = sizeof (UINT32); - } else { - // - // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes - // CPUID.[EAX=05H].EDX: C-states supported using MWAIT - // - AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL); - *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize; - } - - return ApLoopMode; -} - -/** - Sort the APIC ID of all processors. - - This function sorts the APIC ID of all processors so that processor number is - assigned in the ascending order of APIC ID which eases MP debugging. - - @param[in] CpuMpData Pointer to PEI CPU MP Data -**/ -VOID -SortApicId ( - IN CPU_MP_DATA *CpuMpData - ) -{ - UINTN Index1; - UINTN Index2; - UINTN Index3; - UINT32 ApicId; - CPU_INFO_IN_HOB CpuInfo; - UINT32 ApCount; - CPU_INFO_IN_HOB *CpuInfoInHob; - - ApCount = CpuMpData->CpuCount - 1; - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - if (ApCount != 0) { - for (Index1 = 0; Index1 < ApCount; Index1++) { - Index3 = Index1; - // - // Sort key is the hardware default APIC ID - // - ApicId = CpuInfoInHob[Index1].ApicId; - for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) { - if (ApicId > CpuInfoInHob[Index2].ApicId) { - Index3 = Index2; - ApicId = CpuInfoInHob[Index2].ApicId; - } - } - if (Index3 != Index1) { - CopyMem (&CpuInfo, &CpuInfoInHob[Index3], sizeof (CPU_INFO_IN_HOB)); - CopyMem ( - &CpuInfoInHob[Index3], - &CpuInfoInHob[Index1], - sizeof (CPU_INFO_IN_HOB) - ); - CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB)); - } - } - - // - // Get the processor number for the BSP - // - ApicId = GetInitialApicId (); - for (Index1 = 0; Index1 < CpuMpData->CpuCount; Index1++) { - if (CpuInfoInHob[Index1].ApicId == ApicId) { - CpuMpData->BspNumber = (UINT32) Index1; - break; - } - } - } -} - -/** - Enable x2APIC mode on APs. - - @param[in, out] Buffer Pointer to private data buffer. -**/ -VOID -EFIAPI -ApFuncEnableX2Apic ( - IN OUT VOID *Buffer - ) -{ - SetApicMode (LOCAL_APIC_MODE_X2APIC); -} - -/** - Do sync on APs. - - @param[in, out] Buffer Pointer to private data buffer. -**/ -VOID -EFIAPI -ApInitializeSync ( - IN OUT VOID *Buffer - ) -{ - CPU_MP_DATA *CpuMpData; - - CpuMpData = (CPU_MP_DATA *) Buffer; - // - // Load microcode on AP - // - MicrocodeDetect (CpuMpData); - // - // Sync BSP's MTRR table to AP - // - MtrrSetAllMtrrs (&CpuMpData->MtrrTable); -} - -/** - Find the current Processor number by APIC ID. - - @param[in] CpuMpData Pointer to PEI CPU MP Data - @param[out] ProcessorNumber Return the pocessor number found - - @retval EFI_SUCCESS ProcessorNumber is found and returned. - @retval EFI_NOT_FOUND ProcessorNumber is not found. -**/ -EFI_STATUS -GetProcessorNumber ( - IN CPU_MP_DATA *CpuMpData, - OUT UINTN *ProcessorNumber - ) -{ - UINTN TotalProcessorNumber; - UINTN Index; - CPU_INFO_IN_HOB *CpuInfoInHob; - - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - - TotalProcessorNumber = CpuMpData->CpuCount; - for (Index = 0; Index < TotalProcessorNumber; Index ++) { - if (CpuInfoInHob[Index].ApicId == GetApicId ()) { - *ProcessorNumber = Index; - return EFI_SUCCESS; - } - } - return EFI_NOT_FOUND; -} - -/** - This function will get CPU count in the system. - - @param[in] CpuMpData Pointer to PEI CPU MP Data - - @return CPU count detected -**/ -UINTN -CollectProcessorCount ( - IN CPU_MP_DATA *CpuMpData - ) -{ - // - // Send 1st broadcast IPI to APs to wakeup APs - // - CpuMpData->InitFlag = ApInitConfig; - CpuMpData->X2ApicEnable = FALSE; - WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL); - CpuMpData->InitFlag = ApInitDone; - ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber)); - // - // Wait for all APs finished the initialization - // - while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { - CpuPause (); - } - - if (CpuMpData->X2ApicEnable) { - DEBUG ((DEBUG_INFO, "Force x2APIC mode!\n")); - // - // Wakeup all APs to enable x2APIC mode - // - WakeUpAP (CpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL); - // - // Wait for all known APs finished - // - while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { - CpuPause (); - } - // - // Enable x2APIC on BSP - // - SetApicMode (LOCAL_APIC_MODE_X2APIC); - } - DEBUG ((DEBUG_INFO, "APIC MODE is %d\n", GetApicMode ())); - // - // Sort BSP/Aps by CPU APIC ID in ascending order - // - SortApicId (CpuMpData); - - DEBUG ((DEBUG_INFO, "MpInitLib: Find %d processors in system.\n", CpuMpData->CpuCount)); - - return CpuMpData->CpuCount; -} - -/** - Initialize CPU AP Data when AP is wakeup at the first time. - - @param[in, out] CpuMpData Pointer to PEI CPU MP Data - @param[in] ProcessorNumber The handle number of processor - @param[in] BistData Processor BIST data - @param[in] ApTopOfStack Top of AP stack - -**/ -VOID -InitializeApData ( - IN OUT CPU_MP_DATA *CpuMpData, - IN UINTN ProcessorNumber, - IN UINT32 BistData, - IN UINT64 ApTopOfStack - ) -{ - CPU_INFO_IN_HOB *CpuInfoInHob; - - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId (); - CpuInfoInHob[ProcessorNumber].ApicId = GetApicId (); - CpuInfoInHob[ProcessorNumber].Health = BistData; - CpuInfoInHob[ProcessorNumber].ApTopOfStack = ApTopOfStack; - - CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE; - CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE; - if (CpuInfoInHob[ProcessorNumber].InitialApicId >= 0xFF) { - // - // Set x2APIC mode if there are any logical processor reporting - // an Initial APIC ID of 255 or greater. - // - AcquireSpinLock(&CpuMpData->MpLock); - CpuMpData->X2ApicEnable = TRUE; - ReleaseSpinLock(&CpuMpData->MpLock); - } - - InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock); - SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle); -} - -/** - This function will be called from AP reset code if BSP uses WakeUpAP. - - @param[in] ExchangeInfo Pointer to the MP exchange info buffer - @param[in] NumApsExecuting Number of current executing AP -**/ -VOID -EFIAPI -ApWakeupFunction ( - IN MP_CPU_EXCHANGE_INFO *ExchangeInfo, - IN UINTN NumApsExecuting - ) -{ - CPU_MP_DATA *CpuMpData; - UINTN ProcessorNumber; - EFI_AP_PROCEDURE Procedure; - VOID *Parameter; - UINT32 BistData; - volatile UINT32 *ApStartupSignalBuffer; - CPU_INFO_IN_HOB *CpuInfoInHob; - UINT64 ApTopOfStack; - - // - // AP finished assembly code and begin to execute C code - // - CpuMpData = ExchangeInfo->CpuMpData; - - // - // AP's local APIC settings will be lost after received INIT IPI - // We need to re-initialize them at here - // - ProgramVirtualWireMode (); - SyncLocalApicTimerSetting (CpuMpData); - - while (TRUE) { - if (CpuMpData->InitFlag == ApInitConfig) { - // - // Add CPU number - // - InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount); - ProcessorNumber = NumApsExecuting; - // - // This is first time AP wakeup, get BIST information from AP stack - // - ApTopOfStack = CpuMpData->Buffer + (ProcessorNumber + 1) * CpuMpData->CpuApStackSize; - BistData = *(UINT32 *) ((UINTN) ApTopOfStack - sizeof (UINTN)); - // - // Do some AP initialize sync - // - ApInitializeSync (CpuMpData); - // - // Sync BSP's Control registers to APs - // - RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE); - InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack); - ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal; - } else { - // - // Execute AP function if AP is ready - // - GetProcessorNumber (CpuMpData, &ProcessorNumber); - // - // Clear AP start-up signal when AP waken up - // - ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal; - InterlockedCompareExchange32 ( - (UINT32 *) ApStartupSignalBuffer, - WAKEUP_AP_SIGNAL, - 0 - ); - if (CpuMpData->ApLoopMode == ApInHltLoop) { - // - // Restore AP's volatile registers saved - // - RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE); - } - - if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) { - Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction; - Parameter = (VOID *) CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument; - if (Procedure != NULL) { - SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy); - // - // Enable source debugging on AP function - // - EnableDebugAgent (); - // - // Invoke AP function here - // - Procedure (Parameter); - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - if (CpuMpData->SwitchBspFlag) { - // - // Re-get the processor number due to BSP/AP maybe exchange in AP function - // - GetProcessorNumber (CpuMpData, &ProcessorNumber); - CpuMpData->CpuData[ProcessorNumber].ApFunction = 0; - CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument = 0; - ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal; - CpuInfoInHob[ProcessorNumber].ApTopOfStack = CpuInfoInHob[CpuMpData->NewBspNumber].ApTopOfStack; - } else { - // - // Re-get the CPU APICID and Initial APICID - // - CpuInfoInHob[ProcessorNumber].ApicId = GetApicId (); - CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId (); - } - } - SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished); - } - } - - // - // AP finished executing C code - // - InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount); - - // - // Place AP is specified loop mode - // - if (CpuMpData->ApLoopMode == ApInHltLoop) { - // - // Save AP volatile registers - // - SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters); - // - // Place AP in HLT-loop - // - while (TRUE) { - DisableInterrupts (); - CpuSleep (); - CpuPause (); - } - } - while (TRUE) { - DisableInterrupts (); - if (CpuMpData->ApLoopMode == ApInMwaitLoop) { - // - // Place AP in MWAIT-loop - // - AsmMonitor ((UINTN) ApStartupSignalBuffer, 0, 0); - if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) { - // - // Check AP start-up signal again. - // If AP start-up signal is not set, place AP into - // the specified C-state - // - AsmMwait (CpuMpData->ApTargetCState << 4, 0); - } - } else if (CpuMpData->ApLoopMode == ApInRunLoop) { - // - // Place AP in Run-loop - // - CpuPause (); - } else { - ASSERT (FALSE); - } - - // - // If AP start-up signal is written, AP is waken up - // otherwise place AP in loop again - // - if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) { - break; - } - } - } -} - -/** - Wait for AP wakeup and write AP start-up signal till AP is waken up. - - @param[in] ApStartupSignalBuffer Pointer to AP wakeup signal -**/ -VOID -WaitApWakeup ( - IN volatile UINT32 *ApStartupSignalBuffer - ) -{ - // - // If AP is waken up, StartupApSignal should be cleared. - // Otherwise, write StartupApSignal again till AP waken up. - // - while (InterlockedCompareExchange32 ( - (UINT32 *) ApStartupSignalBuffer, - WAKEUP_AP_SIGNAL, - WAKEUP_AP_SIGNAL - ) != 0) { - CpuPause (); - } -} - -/** - This function will fill the exchange info structure. - - @param[in] CpuMpData Pointer to CPU MP Data - -**/ -VOID -FillExchangeInfoData ( - IN CPU_MP_DATA *CpuMpData - ) -{ - volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo; - - ExchangeInfo = CpuMpData->MpCpuExchangeInfo; - ExchangeInfo->Lock = 0; - ExchangeInfo->StackStart = CpuMpData->Buffer; - ExchangeInfo->StackSize = CpuMpData->CpuApStackSize; - ExchangeInfo->BufferStart = CpuMpData->WakeupBuffer; - ExchangeInfo->ModeOffset = CpuMpData->AddressMap.ModeEntryOffset; - - ExchangeInfo->CodeSegment = AsmReadCs (); - ExchangeInfo->DataSegment = AsmReadDs (); - - ExchangeInfo->Cr3 = AsmReadCr3 (); - - ExchangeInfo->CFunction = (UINTN) ApWakeupFunction; - ExchangeInfo->NumApsExecuting = 0; - ExchangeInfo->InitFlag = (UINTN) CpuMpData->InitFlag; - ExchangeInfo->CpuInfo = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - ExchangeInfo->CpuMpData = CpuMpData; - - ExchangeInfo->EnableExecuteDisable = IsBspExecuteDisableEnabled (); - - // - // Get the BSP's data of GDT and IDT - // - AsmReadGdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->GdtrProfile); - AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile); -} - -/** - Helper function that waits until the finished AP count reaches the specified - limit, or the specified timeout elapses (whichever comes first). - - @param[in] CpuMpData Pointer to CPU MP Data. - @param[in] FinishedApLimit The number of finished APs to wait for. - @param[in] TimeLimit The number of microseconds to wait for. -**/ -VOID -TimedWaitForApFinish ( - IN CPU_MP_DATA *CpuMpData, - IN UINT32 FinishedApLimit, - IN UINT32 TimeLimit - ); - -/** - This function will be called by BSP to wakeup AP. - - @param[in] CpuMpData Pointer to CPU MP Data - @param[in] Broadcast TRUE: Send broadcast IPI to all APs - FALSE: Send IPI to AP by ApicId - @param[in] ProcessorNumber The handle number of specified processor - @param[in] Procedure The function to be invoked by AP - @param[in] ProcedureArgument The argument to be passed into AP function -**/ -VOID -WakeUpAP ( - IN CPU_MP_DATA *CpuMpData, - IN BOOLEAN Broadcast, - IN UINTN ProcessorNumber, - IN EFI_AP_PROCEDURE Procedure, OPTIONAL - IN VOID *ProcedureArgument OPTIONAL - ) -{ - volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo; - UINTN Index; - CPU_AP_DATA *CpuData; - BOOLEAN ResetVectorRequired; - CPU_INFO_IN_HOB *CpuInfoInHob; - - CpuMpData->FinishedCount = 0; - ResetVectorRequired = FALSE; - - if (CpuMpData->ApLoopMode == ApInHltLoop || - CpuMpData->InitFlag != ApInitDone) { - ResetVectorRequired = TRUE; - AllocateResetVector (CpuMpData); - FillExchangeInfoData (CpuMpData); - SaveLocalApicTimerSetting (CpuMpData); - } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) { - // - // Get AP target C-state each time when waking up AP, - // for it maybe updated by platform again - // - CpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate); - } - - ExchangeInfo = CpuMpData->MpCpuExchangeInfo; - - if (Broadcast) { - for (Index = 0; Index < CpuMpData->CpuCount; Index++) { - if (Index != CpuMpData->BspNumber) { - CpuData = &CpuMpData->CpuData[Index]; - CpuData->ApFunction = (UINTN) Procedure; - CpuData->ApFunctionArgument = (UINTN) ProcedureArgument; - SetApState (CpuData, CpuStateReady); - if (CpuMpData->InitFlag != ApInitConfig) { - *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL; - } - } - } - if (ResetVectorRequired) { - // - // Wakeup all APs - // - SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart); - } - if (CpuMpData->InitFlag == ApInitConfig) { - // - // Wait for all potential APs waken up in one specified period - // - TimedWaitForApFinish ( - CpuMpData, - PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1, - PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds) - ); - } else { - // - // Wait all APs waken up if this is not the 1st broadcast of SIPI - // - for (Index = 0; Index < CpuMpData->CpuCount; Index++) { - CpuData = &CpuMpData->CpuData[Index]; - if (Index != CpuMpData->BspNumber) { - WaitApWakeup (CpuData->StartupApSignal); - } - } - } - } else { - CpuData = &CpuMpData->CpuData[ProcessorNumber]; - CpuData->ApFunction = (UINTN) Procedure; - CpuData->ApFunctionArgument = (UINTN) ProcedureArgument; - SetApState (CpuData, CpuStateReady); - // - // Wakeup specified AP - // - ASSERT (CpuMpData->InitFlag != ApInitConfig); - *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL; - if (ResetVectorRequired) { - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - SendInitSipiSipi ( - CpuInfoInHob[ProcessorNumber].ApicId, - (UINT32) ExchangeInfo->BufferStart - ); - } - // - // Wait specified AP waken up - // - WaitApWakeup (CpuData->StartupApSignal); - } - - if (ResetVectorRequired) { - FreeResetVector (CpuMpData); - } -} - -/** - Calculate timeout value and return the current performance counter value. - - Calculate the number of performance counter ticks required for a timeout. - If TimeoutInMicroseconds is 0, return value is also 0, which is recognized - as infinity. - - @param[in] TimeoutInMicroseconds Timeout value in microseconds. - @param[out] CurrentTime Returns the current value of the performance counter. - - @return Expected time stamp counter for timeout. - If TimeoutInMicroseconds is 0, return value is also 0, which is recognized - as infinity. - -**/ -UINT64 -CalculateTimeout ( - IN UINTN TimeoutInMicroseconds, - OUT UINT64 *CurrentTime - ) -{ - // - // Read the current value of the performance counter - // - *CurrentTime = GetPerformanceCounter (); - - // - // If TimeoutInMicroseconds is 0, return value is also 0, which is recognized - // as infinity. - // - if (TimeoutInMicroseconds == 0) { - return 0; - } - - // - // GetPerformanceCounterProperties () returns the timestamp counter's frequency - // in Hz. So multiply the return value with TimeoutInMicroseconds and then divide - // it by 1,000,000, to get the number of ticks for the timeout value. - // - return DivU64x32 ( - MultU64x64 ( - GetPerformanceCounterProperties (NULL, NULL), - TimeoutInMicroseconds - ), - 1000000 - ); -} - -/** - Checks whether timeout expires. - - Check whether the number of elapsed performance counter ticks required for - a timeout condition has been reached. - If Timeout is zero, which means infinity, return value is always FALSE. - - @param[in, out] PreviousTime On input, the value of the performance counter - when it was last read. - On output, the current value of the performance - counter - @param[in] TotalTime The total amount of elapsed time in performance - counter ticks. - @param[in] Timeout The number of performance counter ticks required - to reach a timeout condition. - - @retval TRUE A timeout condition has been reached. - @retval FALSE A timeout condition has not been reached. - -**/ -BOOLEAN -CheckTimeout ( - IN OUT UINT64 *PreviousTime, - IN UINT64 *TotalTime, - IN UINT64 Timeout - ) -{ - UINT64 Start; - UINT64 End; - UINT64 CurrentTime; - INT64 Delta; - INT64 Cycle; - - if (Timeout == 0) { - return FALSE; - } - GetPerformanceCounterProperties (&Start, &End); - Cycle = End - Start; - if (Cycle < 0) { - Cycle = -Cycle; - } - Cycle++; - CurrentTime = GetPerformanceCounter(); - Delta = (INT64) (CurrentTime - *PreviousTime); - if (Start > End) { - Delta = -Delta; - } - if (Delta < 0) { - Delta += Cycle; - } - *TotalTime += Delta; - *PreviousTime = CurrentTime; - if (*TotalTime > Timeout) { - return TRUE; - } - return FALSE; -} - -/** - Helper function that waits until the finished AP count reaches the specified - limit, or the specified timeout elapses (whichever comes first). - - @param[in] CpuMpData Pointer to CPU MP Data. - @param[in] FinishedApLimit The number of finished APs to wait for. - @param[in] TimeLimit The number of microseconds to wait for. -**/ -VOID -TimedWaitForApFinish ( - IN CPU_MP_DATA *CpuMpData, - IN UINT32 FinishedApLimit, - IN UINT32 TimeLimit - ) -{ - // - // CalculateTimeout() and CheckTimeout() consider a TimeLimit of 0 - // "infinity", so check for (TimeLimit == 0) explicitly. - // - if (TimeLimit == 0) { - return; - } - - CpuMpData->TotalTime = 0; - CpuMpData->ExpectedTime = CalculateTimeout ( - TimeLimit, - &CpuMpData->CurrentTime - ); - while (CpuMpData->FinishedCount < FinishedApLimit && - !CheckTimeout ( - &CpuMpData->CurrentTime, - &CpuMpData->TotalTime, - CpuMpData->ExpectedTime - )) { - CpuPause (); - } - - if (CpuMpData->FinishedCount >= FinishedApLimit) { - DEBUG (( - DEBUG_VERBOSE, - "%a: reached FinishedApLimit=%u in %Lu microseconds\n", - __FUNCTION__, - FinishedApLimit, - DivU64x64Remainder ( - MultU64x32 (CpuMpData->TotalTime, 1000000), - GetPerformanceCounterProperties (NULL, NULL), - NULL - ) - )); - } -} - -/** - Reset an AP to Idle state. - - Any task being executed by the AP will be aborted and the AP - will be waiting for a new task in Wait-For-SIPI state. - - @param[in] ProcessorNumber The handle number of processor. -**/ -VOID -ResetProcessorToIdleState ( - IN UINTN ProcessorNumber - ) -{ - CPU_MP_DATA *CpuMpData; - - CpuMpData = GetCpuMpData (); - - CpuMpData->InitFlag = ApInitReconfig; - WakeUpAP (CpuMpData, FALSE, ProcessorNumber, NULL, NULL); - while (CpuMpData->FinishedCount < 1) { - CpuPause (); - } - CpuMpData->InitFlag = ApInitDone; - - SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle); -} - -/** - Searches for the next waiting AP. - - Search for the next AP that is put in waiting state by single-threaded StartupAllAPs(). - - @param[out] NextProcessorNumber Pointer to the processor number of the next waiting AP. - - @retval EFI_SUCCESS The next waiting AP has been found. - @retval EFI_NOT_FOUND No waiting AP exists. - -**/ -EFI_STATUS -GetNextWaitingProcessorNumber ( - OUT UINTN *NextProcessorNumber - ) -{ - UINTN ProcessorNumber; - CPU_MP_DATA *CpuMpData; - - CpuMpData = GetCpuMpData (); - - for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) { - if (CpuMpData->CpuData[ProcessorNumber].Waiting) { - *NextProcessorNumber = ProcessorNumber; - return EFI_SUCCESS; - } - } - - return EFI_NOT_FOUND; -} - -/** Checks status of specified AP. - - This function checks whether the specified AP has finished the task assigned - by StartupThisAP(), and whether timeout expires. - - @param[in] ProcessorNumber The handle number of processor. - - @retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs(). - @retval EFI_TIMEOUT The timeout expires. - @retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired. -**/ -EFI_STATUS -CheckThisAP ( - IN UINTN ProcessorNumber - ) -{ - CPU_MP_DATA *CpuMpData; - CPU_AP_DATA *CpuData; - - CpuMpData = GetCpuMpData (); - CpuData = &CpuMpData->CpuData[ProcessorNumber]; - - // - // Check the CPU state of AP. If it is CpuStateFinished, then the AP has finished its task. - // Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the - // value of state after setting the it to CpuStateFinished, so BSP can safely make use of its value. - // - // - // If the AP finishes for StartupThisAP(), return EFI_SUCCESS. - // - if (GetApState(CpuData) == CpuStateFinished) { - if (CpuData->Finished != NULL) { - *(CpuData->Finished) = TRUE; - } - SetApState (CpuData, CpuStateIdle); - return EFI_SUCCESS; - } else { - // - // If timeout expires for StartupThisAP(), report timeout. - // - if (CheckTimeout (&CpuData->CurrentTime, &CpuData->TotalTime, CpuData->ExpectedTime)) { - if (CpuData->Finished != NULL) { - *(CpuData->Finished) = FALSE; - } - // - // Reset failed AP to idle state - // - ResetProcessorToIdleState (ProcessorNumber); - - return EFI_TIMEOUT; - } - } - return EFI_NOT_READY; -} - -/** - Checks status of all APs. - - This function checks whether all APs have finished task assigned by StartupAllAPs(), - and whether timeout expires. - - @retval EFI_SUCCESS All APs have finished task assigned by StartupAllAPs(). - @retval EFI_TIMEOUT The timeout expires. - @retval EFI_NOT_READY APs have not finished task and timeout has not expired. -**/ -EFI_STATUS -CheckAllAPs ( - VOID - ) -{ - UINTN ProcessorNumber; - UINTN NextProcessorNumber; - UINTN ListIndex; - EFI_STATUS Status; - CPU_MP_DATA *CpuMpData; - CPU_AP_DATA *CpuData; - - CpuMpData = GetCpuMpData (); - - NextProcessorNumber = 0; - - // - // Go through all APs that are responsible for the StartupAllAPs(). - // - for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) { - if (!CpuMpData->CpuData[ProcessorNumber].Waiting) { - continue; - } - - CpuData = &CpuMpData->CpuData[ProcessorNumber]; - // - // Check the CPU state of AP. If it is CpuStateFinished, then the AP has finished its task. - // Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the - // value of state after setting the it to CpuStateFinished, so BSP can safely make use of its value. - // - if (GetApState(CpuData) == CpuStateFinished) { - CpuMpData->RunningCount ++; - CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE; - SetApState(CpuData, CpuStateIdle); - - // - // If in Single Thread mode, then search for the next waiting AP for execution. - // - if (CpuMpData->SingleThread) { - Status = GetNextWaitingProcessorNumber (&NextProcessorNumber); - - if (!EFI_ERROR (Status)) { - WakeUpAP ( - CpuMpData, - FALSE, - (UINT32) NextProcessorNumber, - CpuMpData->Procedure, - CpuMpData->ProcArguments - ); - } - } - } - } - - // - // If all APs finish, return EFI_SUCCESS. - // - if (CpuMpData->RunningCount == CpuMpData->StartCount) { - return EFI_SUCCESS; - } - - // - // If timeout expires, report timeout. - // - if (CheckTimeout ( - &CpuMpData->CurrentTime, - &CpuMpData->TotalTime, - CpuMpData->ExpectedTime) - ) { - // - // If FailedCpuList is not NULL, record all failed APs in it. - // - if (CpuMpData->FailedCpuList != NULL) { - *CpuMpData->FailedCpuList = - AllocatePool ((CpuMpData->StartCount - CpuMpData->FinishedCount + 1) * sizeof (UINTN)); - ASSERT (*CpuMpData->FailedCpuList != NULL); - } - ListIndex = 0; - - for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) { - // - // Check whether this processor is responsible for StartupAllAPs(). - // - if (CpuMpData->CpuData[ProcessorNumber].Waiting) { - // - // Reset failed APs to idle state - // - ResetProcessorToIdleState (ProcessorNumber); - CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE; - if (CpuMpData->FailedCpuList != NULL) { - (*CpuMpData->FailedCpuList)[ListIndex++] = ProcessorNumber; - } - } - } - if (CpuMpData->FailedCpuList != NULL) { - (*CpuMpData->FailedCpuList)[ListIndex] = END_OF_CPU_LIST; - } - return EFI_TIMEOUT; - } - return EFI_NOT_READY; -} - -/** - MP Initialize Library initialization. - - This service will allocate AP reset vector and wakeup all APs to do APs - initialization. - - This service must be invoked before all other MP Initialize Library - service are invoked. - - @retval EFI_SUCCESS MP initialization succeeds. - @retval Others MP initialization fails. - -**/ -EFI_STATUS -EFIAPI -MpInitLibInitialize ( - VOID - ) -{ - CPU_MP_DATA *OldCpuMpData; - CPU_INFO_IN_HOB *CpuInfoInHob; - UINT32 MaxLogicalProcessorNumber; - UINT32 ApStackSize; - MP_ASSEMBLY_ADDRESS_MAP AddressMap; - UINTN BufferSize; - UINT32 MonitorFilterSize; - VOID *MpBuffer; - UINTN Buffer; - CPU_MP_DATA *CpuMpData; - UINT8 ApLoopMode; - UINT8 *MonitorBuffer; - UINTN Index; - UINTN ApResetVectorSize; - UINTN BackupBufferAddr; - - OldCpuMpData = GetCpuMpDataFromGuidedHob (); - if (OldCpuMpData == NULL) { - MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber); - } else { - MaxLogicalProcessorNumber = OldCpuMpData->CpuCount; - } - ASSERT (MaxLogicalProcessorNumber != 0); - - AsmGetAddressMap (&AddressMap); - ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO); - ApStackSize = PcdGet32(PcdCpuApStackSize); - ApLoopMode = GetApLoopMode (&MonitorFilterSize); - - BufferSize = ApStackSize * MaxLogicalProcessorNumber; - BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber; - BufferSize += sizeof (CPU_MP_DATA); - BufferSize += ApResetVectorSize; - BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber; - MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize)); - ASSERT (MpBuffer != NULL); - ZeroMem (MpBuffer, BufferSize); - Buffer = (UINTN) MpBuffer; - - MonitorBuffer = (UINT8 *) (Buffer + ApStackSize * MaxLogicalProcessorNumber); - BackupBufferAddr = (UINTN) MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber; - CpuMpData = (CPU_MP_DATA *) (BackupBufferAddr + ApResetVectorSize); - CpuMpData->Buffer = Buffer; - CpuMpData->CpuApStackSize = ApStackSize; - CpuMpData->BackupBuffer = BackupBufferAddr; - CpuMpData->BackupBufferSize = ApResetVectorSize; - CpuMpData->SaveRestoreFlag = FALSE; - CpuMpData->WakeupBuffer = (UINTN) -1; - CpuMpData->CpuCount = 1; - CpuMpData->BspNumber = 0; - CpuMpData->WaitEvent = NULL; - CpuMpData->SwitchBspFlag = FALSE; - CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1); - CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber); - InitializeSpinLock(&CpuMpData->MpLock); - // - // Save BSP's Control registers to APs - // - SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters); - // - // Set BSP basic information - // - InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer); - // - // Save assembly code information - // - CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP)); - // - // Finally set AP loop mode - // - CpuMpData->ApLoopMode = ApLoopMode; - DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode)); - // - // Set up APs wakeup signal buffer - // - for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) { - CpuMpData->CpuData[Index].StartupApSignal = - (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index); - } - // - // Load Microcode on BSP - // - MicrocodeDetect (CpuMpData); - // - // Store BSP's MTRR setting - // - MtrrGetAllMtrrs (&CpuMpData->MtrrTable); - - if (OldCpuMpData == NULL) { - if (MaxLogicalProcessorNumber > 1) { - // - // Wakeup all APs and calculate the processor count in system - // - CollectProcessorCount (CpuMpData); - } - } else { - // - // APs have been wakeup before, just get the CPU Information - // from HOB - // - CpuMpData->CpuCount = OldCpuMpData->CpuCount; - CpuMpData->BspNumber = OldCpuMpData->BspNumber; - CpuMpData->InitFlag = ApInitReconfig; - CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob; - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - for (Index = 0; Index < CpuMpData->CpuCount; Index++) { - InitializeSpinLock(&CpuMpData->CpuData[Index].ApLock); - if (CpuInfoInHob[Index].InitialApicId >= 255) { - CpuMpData->X2ApicEnable = TRUE; - } - CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0)? TRUE:FALSE; - CpuMpData->CpuData[Index].ApFunction = 0; - CopyMem ( - &CpuMpData->CpuData[Index].VolatileRegisters, - &CpuMpData->CpuData[0].VolatileRegisters, - sizeof (CPU_VOLATILE_REGISTERS) - ); - } - if (MaxLogicalProcessorNumber > 1) { - // - // Wakeup APs to do some AP initialize sync - // - WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData); - // - // Wait for all APs finished initialization - // - while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { - CpuPause (); - } - CpuMpData->InitFlag = ApInitDone; - for (Index = 0; Index < CpuMpData->CpuCount; Index++) { - SetApState (&CpuMpData->CpuData[Index], CpuStateIdle); - } - } - } - - // - // Initialize global data for MP support - // - InitMpGlobalData (CpuMpData); - - return EFI_SUCCESS; -} - -/** - Gets detailed MP-related information on the requested processor at the - instant this call is made. This service may only be called from the BSP. - - @param[in] ProcessorNumber The handle number of processor. - @param[out] ProcessorInfoBuffer A pointer to the buffer where information for - the requested processor is deposited. - @param[out] HealthData Return processor health data. - - @retval EFI_SUCCESS Processor information was returned. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. - @retval EFI_NOT_FOUND The processor with the handle specified by - ProcessorNumber does not exist in the platform. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - -**/ -EFI_STATUS -EFIAPI -MpInitLibGetProcessorInfo ( - IN UINTN ProcessorNumber, - OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, - OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL - ) -{ - CPU_MP_DATA *CpuMpData; - UINTN CallerNumber; - CPU_INFO_IN_HOB *CpuInfoInHob; - - CpuMpData = GetCpuMpData (); - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - - // - // Check whether caller processor is BSP - // - MpInitLibWhoAmI (&CallerNumber); - if (CallerNumber != CpuMpData->BspNumber) { - return EFI_DEVICE_ERROR; - } - - if (ProcessorInfoBuffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (ProcessorNumber >= CpuMpData->CpuCount) { - return EFI_NOT_FOUND; - } - - ProcessorInfoBuffer->ProcessorId = (UINT64) CpuInfoInHob[ProcessorNumber].ApicId; - ProcessorInfoBuffer->StatusFlag = 0; - if (ProcessorNumber == CpuMpData->BspNumber) { - ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT; - } - if (CpuMpData->CpuData[ProcessorNumber].CpuHealthy) { - ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT; - } - if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) { - ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT; - } else { - ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT; - } - - // - // Get processor location information - // - GetProcessorLocationByApicId ( - CpuInfoInHob[ProcessorNumber].ApicId, - &ProcessorInfoBuffer->Location.Package, - &ProcessorInfoBuffer->Location.Core, - &ProcessorInfoBuffer->Location.Thread - ); - - if (HealthData != NULL) { - HealthData->Uint32 = CpuInfoInHob[ProcessorNumber].Health; - } - - return EFI_SUCCESS; -} - -/** - 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. - @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an - enabled AP. Otherwise, it will be disabled. - - @retval EFI_SUCCESS BSP successfully switched. - @retval others Failed to switch BSP. - -**/ -EFI_STATUS -SwitchBSPWorker ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableOldBSP - ) -{ - CPU_MP_DATA *CpuMpData; - UINTN CallerNumber; - CPU_STATE State; - MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr; - BOOLEAN OldInterruptState; - BOOLEAN OldTimerInterruptState; - - // - // Save and Disable Local APIC timer interrupt - // - OldTimerInterruptState = GetApicTimerInterruptState (); - DisableApicTimerInterrupt (); - // - // Before send both BSP and AP to a procedure to exchange their roles, - // interrupt must be disabled. This is because during the exchange role - // process, 2 CPU may use 1 stack. If interrupt happens, the stack will - // be corrupted, since interrupt return address will be pushed to stack - // by hardware. - // - OldInterruptState = SaveAndDisableInterrupts (); - - // - // Mask LINT0 & LINT1 for the old BSP - // - DisableLvtInterrupts (); - - CpuMpData = GetCpuMpData (); - - // - // Check whether caller processor is BSP - // - MpInitLibWhoAmI (&CallerNumber); - if (CallerNumber != CpuMpData->BspNumber) { - return EFI_SUCCESS; - } - - if (ProcessorNumber >= CpuMpData->CpuCount) { - return EFI_NOT_FOUND; - } - - // - // Check whether specified AP is disabled - // - State = GetApState (&CpuMpData->CpuData[ProcessorNumber]); - if (State == CpuStateDisabled) { - return EFI_INVALID_PARAMETER; - } - - // - // Check whether ProcessorNumber specifies the current BSP - // - if (ProcessorNumber == CpuMpData->BspNumber) { - return EFI_INVALID_PARAMETER; - } - - // - // Check whether specified AP is busy - // - if (State == CpuStateBusy) { - return EFI_NOT_READY; - } - - CpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE; - CpuMpData->APInfo.State = CPU_SWITCH_STATE_IDLE; - CpuMpData->SwitchBspFlag = TRUE; - CpuMpData->NewBspNumber = ProcessorNumber; - - // - // Clear the BSP bit of MSR_IA32_APIC_BASE - // - ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); - ApicBaseMsr.Bits.BSP = 0; - AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); - - // - // Need to wakeUp AP (future BSP). - // - WakeUpAP (CpuMpData, FALSE, ProcessorNumber, FutureBSPProc, CpuMpData); - - AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo); - - // - // Set the BSP bit of MSR_IA32_APIC_BASE on new BSP - // - ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); - ApicBaseMsr.Bits.BSP = 1; - AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); - - // - // Wait for old BSP finished AP task - // - while (GetApState (&CpuMpData->CpuData[CallerNumber]) != CpuStateFinished) { - CpuPause (); - } - - CpuMpData->SwitchBspFlag = FALSE; - // - // Set old BSP enable state - // - if (!EnableOldBSP) { - SetApState (&CpuMpData->CpuData[CallerNumber], CpuStateDisabled); - } else { - SetApState (&CpuMpData->CpuData[CallerNumber], CpuStateIdle); - } - // - // Save new BSP number - // - CpuMpData->BspNumber = (UINT32) ProcessorNumber; - - // - // Restore interrupt state. - // - SetInterruptState (OldInterruptState); - - if (OldTimerInterruptState) { - EnableApicTimerInterrupt (); - } - - return EFI_SUCCESS; -} - -/** - Worker function to let the caller enable or disable an AP from this point onward. - This service may only be called from the BSP. - - @param[in] ProcessorNumber The handle number of AP. - @param[in] EnableAP Specifies the new state for the processor for - enabled, FALSE for disabled. - @param[in] HealthFlag If not NULL, a pointer to a value that specifies - the new health status of the AP. - - @retval EFI_SUCCESS The specified AP was enabled or disabled successfully. - @retval others Failed to Enable/Disable AP. - -**/ -EFI_STATUS -EnableDisableApWorker ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableAP, - IN UINT32 *HealthFlag OPTIONAL - ) -{ - CPU_MP_DATA *CpuMpData; - UINTN CallerNumber; - - CpuMpData = GetCpuMpData (); - - // - // Check whether caller processor is BSP - // - MpInitLibWhoAmI (&CallerNumber); - if (CallerNumber != CpuMpData->BspNumber) { - return EFI_DEVICE_ERROR; - } - - if (ProcessorNumber == CpuMpData->BspNumber) { - return EFI_INVALID_PARAMETER; - } - - if (ProcessorNumber >= CpuMpData->CpuCount) { - return EFI_NOT_FOUND; - } - - if (!EnableAP) { - SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateDisabled); - } else { - SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle); - } - - if (HealthFlag != NULL) { - CpuMpData->CpuData[ProcessorNumber].CpuHealthy = - (BOOLEAN) ((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) != 0); - } - - return EFI_SUCCESS; -} - -/** - This return the handle number for the calling processor. This service may be - called from the BSP and APs. - - @param[out] ProcessorNumber Pointer to the handle number of AP. - The range is from 0 to the total number of - logical processors minus 1. The total number of - logical processors can be retrieved by - MpInitLibGetNumberOfProcessors(). - - @retval EFI_SUCCESS The current processor handle number was returned - in ProcessorNumber. - @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - -**/ -EFI_STATUS -EFIAPI -MpInitLibWhoAmI ( - OUT UINTN *ProcessorNumber - ) -{ - CPU_MP_DATA *CpuMpData; - - if (ProcessorNumber == NULL) { - return EFI_INVALID_PARAMETER; - } - - CpuMpData = GetCpuMpData (); - - return GetProcessorNumber (CpuMpData, ProcessorNumber); -} - -/** - Retrieves the number of logical processor in the platform and the number of - those logical processors that are enabled on this boot. This service may only - be called from the BSP. - - @param[out] NumberOfProcessors 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. - - @retval EFI_SUCCESS The number of logical processors and enabled - logical processors was retrieved. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors - is NULL. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - -**/ -EFI_STATUS -EFIAPI -MpInitLibGetNumberOfProcessors ( - OUT UINTN *NumberOfProcessors, OPTIONAL - OUT UINTN *NumberOfEnabledProcessors OPTIONAL - ) -{ - CPU_MP_DATA *CpuMpData; - UINTN CallerNumber; - UINTN ProcessorNumber; - UINTN EnabledProcessorNumber; - UINTN Index; - - CpuMpData = GetCpuMpData (); - - if ((NumberOfProcessors == NULL) && (NumberOfEnabledProcessors == NULL)) { - return EFI_INVALID_PARAMETER; - } - - // - // Check whether caller processor is BSP - // - MpInitLibWhoAmI (&CallerNumber); - if (CallerNumber != CpuMpData->BspNumber) { - return EFI_DEVICE_ERROR; - } - - ProcessorNumber = CpuMpData->CpuCount; - EnabledProcessorNumber = 0; - for (Index = 0; Index < ProcessorNumber; Index++) { - if (GetApState (&CpuMpData->CpuData[Index]) != CpuStateDisabled) { - EnabledProcessorNumber ++; - } - } - - if (NumberOfProcessors != NULL) { - *NumberOfProcessors = ProcessorNumber; - } - if (NumberOfEnabledProcessors != NULL) { - *NumberOfEnabledProcessors = EnabledProcessorNumber; - } - - return EFI_SUCCESS; -} - - -/** - 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] SingleThread If TRUE, then all the enabled APs execute - the function specified by Procedure one by - one, in ascending order of processor handle - number. If FALSE, then all the enabled APs - execute the function specified by Procedure - simultaneously. - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - APs to return from Procedure, either for - blocking or non-blocking mode. - @param[in] ProcedureArgument The parameter passed into Procedure for - all APs. - @param[out] FailedCpuList If all APs finish successfully, then its - content is set to NULL. If not all APs - finish before timeout expires, then its - content is set to address of the buffer - holding handle numbers of the failed APs. - - @retval EFI_SUCCESS In blocking mode, all APs have finished before - the timeout expired. - @retval EFI_SUCCESS In non-blocking mode, function has been dispatched - to all enabled APs. - @retval others Failed to Startup all APs. - -**/ -EFI_STATUS -StartupAllAPsWorker ( - IN EFI_AP_PROCEDURE Procedure, - IN BOOLEAN SingleThread, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT UINTN **FailedCpuList OPTIONAL - ) -{ - EFI_STATUS Status; - CPU_MP_DATA *CpuMpData; - UINTN ProcessorCount; - UINTN ProcessorNumber; - UINTN CallerNumber; - CPU_AP_DATA *CpuData; - BOOLEAN HasEnabledAp; - CPU_STATE ApState; - - CpuMpData = GetCpuMpData (); - - if (FailedCpuList != NULL) { - *FailedCpuList = NULL; - } - - if (CpuMpData->CpuCount == 1) { - return EFI_NOT_STARTED; - } - - if (Procedure == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check whether caller processor is BSP - // - MpInitLibWhoAmI (&CallerNumber); - if (CallerNumber != CpuMpData->BspNumber) { - return EFI_DEVICE_ERROR; - } - - // - // Update AP state - // - CheckAndUpdateApsStatus (); - - ProcessorCount = CpuMpData->CpuCount; - HasEnabledAp = FALSE; - // - // Check whether all enabled APs are idle. - // If any enabled AP is not idle, return EFI_NOT_READY. - // - for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) { - CpuData = &CpuMpData->CpuData[ProcessorNumber]; - if (ProcessorNumber != CpuMpData->BspNumber) { - ApState = GetApState (CpuData); - if (ApState != CpuStateDisabled) { - HasEnabledAp = TRUE; - if (ApState != CpuStateIdle) { - // - // If any enabled APs are busy, return EFI_NOT_READY. - // - return EFI_NOT_READY; - } - } - } - } - - if (!HasEnabledAp) { - // - // If no enabled AP exists, return EFI_NOT_STARTED. - // - return EFI_NOT_STARTED; - } - - CpuMpData->StartCount = 0; - for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) { - CpuData = &CpuMpData->CpuData[ProcessorNumber]; - CpuData->Waiting = FALSE; - if (ProcessorNumber != CpuMpData->BspNumber) { - if (CpuData->State == CpuStateIdle) { - // - // Mark this processor as responsible for current calling. - // - CpuData->Waiting = TRUE; - CpuMpData->StartCount++; - } - } - } - - CpuMpData->Procedure = Procedure; - CpuMpData->ProcArguments = ProcedureArgument; - CpuMpData->SingleThread = SingleThread; - CpuMpData->FinishedCount = 0; - CpuMpData->RunningCount = 0; - CpuMpData->FailedCpuList = FailedCpuList; - CpuMpData->ExpectedTime = CalculateTimeout ( - TimeoutInMicroseconds, - &CpuMpData->CurrentTime - ); - CpuMpData->TotalTime = 0; - CpuMpData->WaitEvent = WaitEvent; - - if (!SingleThread) { - WakeUpAP (CpuMpData, TRUE, 0, Procedure, ProcedureArgument); - } else { - for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) { - if (ProcessorNumber == CallerNumber) { - continue; - } - if (CpuMpData->CpuData[ProcessorNumber].Waiting) { - WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument); - break; - } - } - } - - Status = EFI_SUCCESS; - if (WaitEvent == NULL) { - do { - Status = CheckAllAPs (); - } while (Status == EFI_NOT_READY); - } - - return Status; -} - -/** - Worker function to let the caller get one enabled AP to execute a caller-provided - function. - - @param[in] Procedure A pointer to the function to be run on - enabled APs of the system. - @param[in] ProcessorNumber The handle number of the AP. - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - APs to return from Procedure, either for - blocking or non-blocking mode. - @param[in] ProcedureArgument The parameter passed into Procedure for - all APs. - @param[out] Finished If AP returns from Procedure before the - timeout expires, its content is set to TRUE. - Otherwise, the value is set to FALSE. - - @retval EFI_SUCCESS In blocking mode, specified AP finished before - the timeout expires. - @retval others Failed to Startup AP. - -**/ -EFI_STATUS -StartupThisAPWorker ( - IN EFI_AP_PROCEDURE Procedure, - IN UINTN ProcessorNumber, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT BOOLEAN *Finished OPTIONAL - ) -{ - EFI_STATUS Status; - CPU_MP_DATA *CpuMpData; - CPU_AP_DATA *CpuData; - UINTN CallerNumber; - - CpuMpData = GetCpuMpData (); - - if (Finished != NULL) { - *Finished = FALSE; - } - - // - // Check whether caller processor is BSP - // - MpInitLibWhoAmI (&CallerNumber); - if (CallerNumber != CpuMpData->BspNumber) { - return EFI_DEVICE_ERROR; - } - - // - // Check whether processor with the handle specified by ProcessorNumber exists - // - if (ProcessorNumber >= CpuMpData->CpuCount) { - return EFI_NOT_FOUND; - } - - // - // Check whether specified processor is BSP - // - if (ProcessorNumber == CpuMpData->BspNumber) { - return EFI_INVALID_PARAMETER; - } - - // - // Check parameter Procedure - // - if (Procedure == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Update AP state - // - CheckAndUpdateApsStatus (); - - // - // Check whether specified AP is disabled - // - if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) { - return EFI_INVALID_PARAMETER; - } - - // - // If WaitEvent is not NULL, execute in non-blocking mode. - // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS. - // CheckAPsStatus() will check completion and timeout periodically. - // - CpuData = &CpuMpData->CpuData[ProcessorNumber]; - CpuData->WaitEvent = WaitEvent; - CpuData->Finished = Finished; - CpuData->ExpectedTime = CalculateTimeout (TimeoutInMicroseconds, &CpuData->CurrentTime); - CpuData->TotalTime = 0; - - WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument); - - // - // If WaitEvent is NULL, execute in blocking mode. - // BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires. - // - Status = EFI_SUCCESS; - if (WaitEvent == NULL) { - do { - Status = CheckThisAP (ProcessorNumber); - } while (Status == EFI_NOT_READY); - } - - return Status; -} - -/** - Get pointer to CPU MP Data structure from GUIDed HOB. - - @return The pointer to CPU MP Data structure. -**/ -CPU_MP_DATA * -GetCpuMpDataFromGuidedHob ( - VOID - ) -{ - EFI_HOB_GUID_TYPE *GuidHob; - VOID *DataInHob; - CPU_MP_DATA *CpuMpData; - - CpuMpData = NULL; - GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid); - if (GuidHob != NULL) { - DataInHob = GET_GUID_HOB_DATA (GuidHob); - CpuMpData = (CPU_MP_DATA *) (*(UINTN *) DataInHob); - } - return CpuMpData; -} - -/** - Get available system memory below 1MB by specified size. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -BackupAndPrepareWakeupBuffer( - IN CPU_MP_DATA *CpuMpData - ) -{ - CopyMem ( - (VOID *) CpuMpData->BackupBuffer, - (VOID *) CpuMpData->WakeupBuffer, - CpuMpData->BackupBufferSize - ); - CopyMem ( - (VOID *) CpuMpData->WakeupBuffer, - (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress, - CpuMpData->AddressMap.RendezvousFunnelSize - ); -} - -/** - Restore wakeup buffer data. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -RestoreWakeupBuffer( - IN CPU_MP_DATA *CpuMpData - ) -{ - CopyMem ( - (VOID *) CpuMpData->WakeupBuffer, - (VOID *) CpuMpData->BackupBuffer, - CpuMpData->BackupBufferSize - ); -} diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h deleted file mode 100644 index 7a272d78ec..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ /dev/null @@ -1,594 +0,0 @@ -/** @file - Common header file for MP Initialize Library. - - Copyright (c) 2016, Intel Corporation. All rights reserved.
- 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. - -**/ - -#ifndef _MP_LIB_H_ -#define _MP_LIB_H_ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P') - -#define CPU_INIT_MP_LIB_HOB_GUID \ - { \ - 0x58eb6a19, 0x3699, 0x4c68, { 0xa8, 0x36, 0xda, 0xcd, 0x8e, 0xdc, 0xad, 0x4a } \ - } - -// -// The MP data for switch BSP -// -#define CPU_SWITCH_STATE_IDLE 0 -#define CPU_SWITCH_STATE_STORED 1 -#define CPU_SWITCH_STATE_LOADED 2 - -// -// CPU exchange information for switch BSP -// -typedef struct { - UINT8 State; // offset 0 - UINTN StackPointer; // offset 4 / 8 - IA32_DESCRIPTOR Gdtr; // offset 8 / 16 - IA32_DESCRIPTOR Idtr; // offset 14 / 26 -} CPU_EXCHANGE_ROLE_INFO; - -// -// AP loop state when APs are in idle state -// It's value is the same with PcdCpuApLoopMode -// -typedef enum { - ApInHltLoop = 1, - ApInMwaitLoop = 2, - ApInRunLoop = 3 -} AP_LOOP_MODE; - -// -// AP initialization state during APs wakeup -// -typedef enum { - ApInitConfig = 1, - ApInitReconfig = 2, - ApInitDone = 3 -} AP_INIT_STATE; - -// -// AP state -// -typedef enum { - CpuStateIdle, - CpuStateReady, - CpuStateBusy, - CpuStateFinished, - CpuStateDisabled -} CPU_STATE; - -// -// CPU volatile registers around INIT-SIPI-SIPI -// -typedef struct { - UINTN Cr0; - UINTN Cr3; - UINTN Cr4; - UINTN Dr0; - UINTN Dr1; - UINTN Dr2; - UINTN Dr3; - UINTN Dr6; - UINTN Dr7; -} CPU_VOLATILE_REGISTERS; - -// -// AP related data -// -typedef struct { - SPIN_LOCK ApLock; - volatile UINT32 *StartupApSignal; - volatile UINTN ApFunction; - volatile UINTN ApFunctionArgument; - BOOLEAN CpuHealthy; - volatile CPU_STATE State; - CPU_VOLATILE_REGISTERS VolatileRegisters; - BOOLEAN Waiting; - BOOLEAN *Finished; - UINT64 ExpectedTime; - UINT64 CurrentTime; - UINT64 TotalTime; - EFI_EVENT WaitEvent; -} CPU_AP_DATA; - -// -// Basic CPU information saved in Guided HOB. -// Because the contents will be shard between PEI and DXE, -// we need to make sure the each fields offset same in different -// architecture. -// -#pragma pack (1) -typedef struct { - UINT32 InitialApicId; - UINT32 ApicId; - UINT32 Health; - UINT64 ApTopOfStack; -} CPU_INFO_IN_HOB; -#pragma pack () - -// -// AP reset code information including code address and size, -// this structure will be shared be C code and assembly code. -// It is natural aligned by design. -// -typedef struct { - UINT8 *RendezvousFunnelAddress; - UINTN ModeEntryOffset; - UINTN RendezvousFunnelSize; - UINT8 *RelocateApLoopFuncAddress; - UINTN RelocateApLoopFuncSize; -} MP_ASSEMBLY_ADDRESS_MAP; - -typedef struct _CPU_MP_DATA CPU_MP_DATA; - -#pragma pack(1) - -// -// MP CPU exchange information for AP reset code -// This structure is required to be packed because fixed field offsets -// into this structure are used in assembly code in this module -// -typedef struct { - UINTN Lock; - UINTN StackStart; - UINTN StackSize; - UINTN CFunction; - IA32_DESCRIPTOR GdtrProfile; - IA32_DESCRIPTOR IdtrProfile; - UINTN BufferStart; - UINTN ModeOffset; - UINTN NumApsExecuting; - UINTN CodeSegment; - UINTN DataSegment; - UINTN EnableExecuteDisable; - UINTN Cr3; - UINTN InitFlag; - CPU_INFO_IN_HOB *CpuInfo; - CPU_MP_DATA *CpuMpData; -} MP_CPU_EXCHANGE_INFO; - -#pragma pack() - -// -// CPU MP Data save in memory -// -struct _CPU_MP_DATA { - UINT64 CpuInfoInHob; - UINT32 CpuCount; - UINT32 BspNumber; - // - // The above fields data will be passed from PEI to DXE - // Please make sure the fields offset same in the different - // architecture. - // - SPIN_LOCK MpLock; - UINTN Buffer; - UINTN CpuApStackSize; - MP_ASSEMBLY_ADDRESS_MAP AddressMap; - UINTN WakeupBuffer; - UINTN BackupBuffer; - UINTN BackupBufferSize; - BOOLEAN SaveRestoreFlag; - - volatile UINT32 StartCount; - volatile UINT32 FinishedCount; - volatile UINT32 RunningCount; - BOOLEAN SingleThread; - EFI_AP_PROCEDURE Procedure; - VOID *ProcArguments; - BOOLEAN *Finished; - UINT64 ExpectedTime; - UINT64 CurrentTime; - UINT64 TotalTime; - EFI_EVENT WaitEvent; - UINTN **FailedCpuList; - - AP_INIT_STATE InitFlag; - BOOLEAN X2ApicEnable; - BOOLEAN SwitchBspFlag; - UINTN NewBspNumber; - CPU_EXCHANGE_ROLE_INFO BSPInfo; - CPU_EXCHANGE_ROLE_INFO APInfo; - MTRR_SETTINGS MtrrTable; - UINT8 ApLoopMode; - UINT8 ApTargetCState; - UINT16 PmCodeSegment; - CPU_AP_DATA *CpuData; - volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo; - - UINT32 CurrentTimerCount; - UINTN DivideValue; - UINT8 Vector; - BOOLEAN PeriodicMode; - BOOLEAN TimerInterruptState; -}; - -extern EFI_GUID mCpuInitMpLibHobGuid; - -/** - Assembly code to place AP into safe loop mode. - - Place AP into targeted C-State if MONITOR is supported, otherwise - place AP into hlt state. - Place AP in protected mode if the current is long mode. Due to AP maybe - wakeup by some hardware event. It could avoid accessing page table that - may not available during booting to OS. - - @param[in] MwaitSupport TRUE indicates MONITOR is supported. - FALSE indicates MONITOR is not supported. - @param[in] ApTargetCState Target C-State value. - @param[in] PmCodeSegment Protected mode code segment value. -**/ -typedef -VOID -(EFIAPI * ASM_RELOCATE_AP_LOOP) ( - IN BOOLEAN MwaitSupport, - IN UINTN ApTargetCState, - IN UINTN PmCodeSegment, - IN UINTN TopOfApStack, - IN UINTN NumberToFinish - ); - -/** - Assembly code to get starting address and size of the rendezvous entry for APs. - Information for fixing a jump instruction in the code is also returned. - - @param[out] AddressMap Output buffer for address map information. -**/ -VOID -EFIAPI -AsmGetAddressMap ( - OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap - ); - -/** - This function is called by both the BSP and the AP which is to become the BSP to - Exchange execution context including stack between them. After return from this - function, the BSP becomes AP and the AP becomes the BSP. - - @param[in] MyInfo Pointer to buffer holding the exchanging information for the executing processor. - @param[in] OthersInfo Pointer to buffer holding the exchanging information for the peer. - -**/ -VOID -EFIAPI -AsmExchangeRole ( - IN CPU_EXCHANGE_ROLE_INFO *MyInfo, - IN CPU_EXCHANGE_ROLE_INFO *OthersInfo - ); - -/** - Get the pointer to CPU MP Data structure. - - @return The pointer to CPU MP Data structure. -**/ -CPU_MP_DATA * -GetCpuMpData ( - VOID - ); - -/** - Save the pointer to CPU MP Data structure. - - @param[in] CpuMpData The pointer to CPU MP Data structure will be saved. -**/ -VOID -SaveCpuMpData ( - IN CPU_MP_DATA *CpuMpData - ); - -/** - Allocate reset vector buffer. - - @param[in, out] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -AllocateResetVector ( - IN OUT CPU_MP_DATA *CpuMpData - ); - -/** - Free AP reset vector buffer. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -FreeResetVector ( - IN CPU_MP_DATA *CpuMpData - ); - -/** - This function will be called by BSP to wakeup AP. - - @param[in] CpuMpData Pointer to CPU MP Data - @param[in] Broadcast TRUE: Send broadcast IPI to all APs - FALSE: Send IPI to AP by ApicId - @param[in] ProcessorNumber The handle number of specified processor - @param[in] Procedure The function to be invoked by AP - @param[in] ProcedureArgument The argument to be passed into AP function -**/ -VOID -WakeUpAP ( - IN CPU_MP_DATA *CpuMpData, - IN BOOLEAN Broadcast, - IN UINTN ProcessorNumber, - IN EFI_AP_PROCEDURE Procedure, OPTIONAL - IN VOID *ProcedureArgument OPTIONAL - ); - -/** - Initialize global data for MP support. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -InitMpGlobalData ( - IN CPU_MP_DATA *CpuMpData - ); - -/** - 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] SingleThread If TRUE, then all the enabled APs execute - the function specified by Procedure one by - one, in ascending order of processor handle - number. If FALSE, then all the enabled APs - execute the function specified by Procedure - simultaneously. - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - APs to return from Procedure, either for - blocking or non-blocking mode. - @param[in] ProcedureArgument The parameter passed into Procedure for - all APs. - @param[out] FailedCpuList If all APs finish successfully, then its - content is set to NULL. If not all APs - finish before timeout expires, then its - content is set to address of the buffer - holding handle numbers of the failed APs. - - @retval EFI_SUCCESS In blocking mode, all APs have finished before - the timeout expired. - @retval EFI_SUCCESS In non-blocking mode, function has been dispatched - to all enabled APs. - @retval others Failed to Startup all APs. - -**/ -EFI_STATUS -StartupAllAPsWorker ( - IN EFI_AP_PROCEDURE Procedure, - IN BOOLEAN SingleThread, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT UINTN **FailedCpuList OPTIONAL - ); - -/** - Worker function to let the caller get one enabled AP to execute a caller-provided - function. - - @param[in] Procedure A pointer to the function to be run on - enabled APs of the system. - @param[in] ProcessorNumber The handle number of the AP. - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - APs to return from Procedure, either for - blocking or non-blocking mode. - @param[in] ProcedureArgument The parameter passed into Procedure for - all APs. - @param[out] Finished If AP returns from Procedure before the - timeout expires, its content is set to TRUE. - Otherwise, the value is set to FALSE. - - @retval EFI_SUCCESS In blocking mode, specified AP finished before - the timeout expires. - @retval others Failed to Startup AP. - -**/ -EFI_STATUS -StartupThisAPWorker ( - IN EFI_AP_PROCEDURE Procedure, - IN UINTN ProcessorNumber, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT BOOLEAN *Finished OPTIONAL - ); - -/** - 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. - @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an - enabled AP. Otherwise, it will be disabled. - - @retval EFI_SUCCESS BSP successfully switched. - @retval others Failed to switch BSP. - -**/ -EFI_STATUS -SwitchBSPWorker ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableOldBSP - ); - -/** - Worker function to let the caller enable or disable an AP from this point onward. - This service may only be called from the BSP. - - @param[in] ProcessorNumber The handle number of AP. - @param[in] EnableAP Specifies the new state for the processor for - enabled, FALSE for disabled. - @param[in] HealthFlag If not NULL, a pointer to a value that specifies - the new health status of the AP. - - @retval EFI_SUCCESS The specified AP was enabled or disabled successfully. - @retval others Failed to Enable/Disable AP. - -**/ -EFI_STATUS -EnableDisableApWorker ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableAP, - IN UINT32 *HealthFlag OPTIONAL - ); - -/** - Get pointer to CPU MP Data structure from GUIDed HOB. - - @return The pointer to CPU MP Data structure. -**/ -CPU_MP_DATA * -GetCpuMpDataFromGuidedHob ( - VOID - ); - -/** Checks status of specified AP. - - This function checks whether the specified AP has finished the task assigned - by StartupThisAP(), and whether timeout expires. - - @param[in] ProcessorNumber The handle number of processor. - - @retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs(). - @retval EFI_TIMEOUT The timeout expires. - @retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired. -**/ -EFI_STATUS -CheckThisAP ( - IN UINTN ProcessorNumber - ); - -/** - Checks status of all APs. - - This function checks whether all APs have finished task assigned by StartupAllAPs(), - and whether timeout expires. - - @retval EFI_SUCCESS All APs have finished task assigned by StartupAllAPs(). - @retval EFI_TIMEOUT The timeout expires. - @retval EFI_NOT_READY APs have not finished task and timeout has not expired. -**/ -EFI_STATUS -CheckAllAPs ( - VOID - ); - -/** - Checks APs status and updates APs status if needed. - -**/ -VOID -CheckAndUpdateApsStatus ( - VOID - ); - -/** - Detect whether specified processor can find matching microcode patch and load it. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -MicrocodeDetect ( - IN CPU_MP_DATA *CpuMpData - ); - -/** - Detect whether Mwait-monitor feature is supported. - - @retval TRUE Mwait-monitor feature is supported. - @retval FALSE Mwait-monitor feature is not supported. -**/ -BOOLEAN -IsMwaitSupport ( - VOID - ); - -/** - Notify function on End Of PEI PPI. - - On S3 boot, this function will restore wakeup buffer data. - On normal boot, this function will flag wakeup buffer to be un-used type. - - @param[in] PeiServices The pointer 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. - - @retval EFI_SUCCESS When everything is OK. -**/ -EFI_STATUS -EFIAPI -CpuMpEndOfPeiCallback ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, - IN VOID *Ppi - ); - -/** - Get available system memory below 1MB by specified size. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -BackupAndPrepareWakeupBuffer( - IN CPU_MP_DATA *CpuMpData - ); - -/** - Restore wakeup buffer data. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -RestoreWakeupBuffer( - IN CPU_MP_DATA *CpuMpData - ); - -/** - Enable Debug Agent to support source debugging on AP function. - -**/ -VOID -EnableDebugAgent ( - VOID - ); - -#endif - diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf deleted file mode 100644 index 0c6873da79..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ /dev/null @@ -1,70 +0,0 @@ -## @file -# MP Initialize Library instance for PEI driver. -# -# Copyright (c) 2016, Intel Corporation. All rights reserved.
-# 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. -# -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = PeiMpInitLib - MODULE_UNI_FILE = PeiMpInitLib.uni - FILE_GUID = B00F6090-7739-4830-B906-E0032D388987 - MODULE_TYPE = PEIM - VERSION_STRING = 1.1 - LIBRARY_CLASS = MpInitLib|PEIM - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 -# - -[Sources.IA32] - Ia32/MpEqu.inc - Ia32/MpFuncs.nasm - -[Sources.X64] - X64/MpEqu.inc - X64/MpFuncs.nasm - -[Sources.common] - PeiMpLib.c - MpLib.c - MpLib.h - Microcode.c - -[Packages] - MdePkg/MdePkg.dec - UefiCpuPkg/UefiCpuPkg.dec - -[LibraryClasses] - BaseLib - LocalApicLib - MemoryAllocationLib - HobLib - PeiServicesLib - MtrrLib - CpuLib - UefiCpuLib - SynchronizationLib - -[Ppis] - gEfiEndOfPeiSignalPpiGuid ## NOTIFY - -[Pcd] - gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES - diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni deleted file mode 100644 index d16f306685..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.uni +++ /dev/null @@ -1,22 +0,0 @@ -// /** @file -// MP Initialize Library instance for PEI driver. -// -// MP Initialize Library instance for PEI driver. -// -// Copyright (c) 2016, Intel Corporation. All rights reserved.
-// -// 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. -// -// **/ - - -#string STR_MODULE_ABSTRACT #language en-US "MP Initialize Library instance for PEI driver." - -#string STR_MODULE_DESCRIPTION #language en-US "MP Initialize Library instance for PEI driver." - diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c deleted file mode 100644 index fb1d48fad8..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c +++ /dev/null @@ -1,624 +0,0 @@ -/** @file - MP initialize support functions for PEI phase. - - Copyright (c) 2016, Intel Corporation. All rights reserved.
- 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 "MpLib.h" -#include -#include - -// -// Global PEI notify function descriptor on EndofPei event -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mMpInitLibNotifyList = { - (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gEfiEndOfPeiSignalPpiGuid, - CpuMpEndOfPeiCallback -}; - - -/** - Enable Debug Agent to support source debugging on AP function. - -**/ -VOID -EnableDebugAgent ( - VOID - ) -{ -} - -/** - Get pointer to CPU MP Data structure. - - @return The pointer to CPU MP Data structure. -**/ -CPU_MP_DATA * -GetCpuMpData ( - VOID - ) -{ - CPU_MP_DATA *CpuMpData; - - CpuMpData = GetCpuMpDataFromGuidedHob (); - ASSERT (CpuMpData != NULL); - return CpuMpData; -} - -/** - Save the pointer to CPU MP Data structure. - - @param[in] CpuMpData The pointer to CPU MP Data structure will be saved. -**/ -VOID -SaveCpuMpData ( - IN CPU_MP_DATA *CpuMpData - ) -{ - UINT64 Data64; - // - // Build location of CPU MP DATA buffer in HOB - // - Data64 = (UINT64) (UINTN) CpuMpData; - BuildGuidDataHob ( - &mCpuInitMpLibHobGuid, - (VOID *) &Data64, - sizeof (UINT64) - ); -} - -/** - Notify function on End Of PEI PPI. - - On S3 boot, this function will restore wakeup buffer data. - On normal boot, this function will flag wakeup buffer to be un-used type. - - @param[in] PeiServices The pointer 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. - - @retval EFI_SUCCESS When everything is OK. -**/ -EFI_STATUS -EFIAPI -CpuMpEndOfPeiCallback ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, - IN VOID *Ppi - ) -{ - EFI_STATUS Status; - EFI_BOOT_MODE BootMode; - CPU_MP_DATA *CpuMpData; - EFI_PEI_HOB_POINTERS Hob; - EFI_HOB_MEMORY_ALLOCATION *MemoryHob; - - DEBUG ((DEBUG_INFO, "PeiMpInitLib: CpuMpEndOfPeiCallback () invoked\n")); - - Status = PeiServicesGetBootMode (&BootMode); - ASSERT_EFI_ERROR (Status); - - CpuMpData = GetCpuMpData (); - if (BootMode != BOOT_ON_S3_RESUME) { - // - // Get the HOB list for processing - // - Hob.Raw = GetHobList (); - // - // Collect memory ranges - // - while (!END_OF_HOB_LIST (Hob)) { - if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { - MemoryHob = Hob.MemoryAllocation; - if (MemoryHob->AllocDescriptor.MemoryBaseAddress == CpuMpData->WakeupBuffer) { - // - // Flag this HOB type to un-used - // - GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED; - break; - } - } - Hob.Raw = GET_NEXT_HOB (Hob); - } - } else { - CpuMpData->SaveRestoreFlag = TRUE; - RestoreWakeupBuffer (CpuMpData); - } - return EFI_SUCCESS; -} - -/** - Check if AP wakeup buffer is overlapped with existing allocated buffer. - - @param[in] WakeupBufferStart AP wakeup buffer start address. - @param[in] WakeupBufferEnd AP wakeup buffer end address. - - @retval TRUE There is overlap. - @retval FALSE There is no overlap. -**/ -BOOLEAN -CheckOverlapWithAllocatedBuffer ( - IN UINTN WakeupBufferStart, - IN UINTN WakeupBufferEnd - ) -{ - EFI_PEI_HOB_POINTERS Hob; - EFI_HOB_MEMORY_ALLOCATION *MemoryHob; - BOOLEAN Overlapped; - UINTN MemoryStart; - UINTN MemoryEnd; - - Overlapped = FALSE; - // - // Get the HOB list for processing - // - Hob.Raw = GetHobList (); - // - // Collect memory ranges - // - while (!END_OF_HOB_LIST (Hob)) { - if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { - MemoryHob = Hob.MemoryAllocation; - MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress; - MemoryEnd = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress + - MemoryHob->AllocDescriptor.MemoryLength); - if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) { - Overlapped = TRUE; - break; - } - } - Hob.Raw = GET_NEXT_HOB (Hob); - } - return Overlapped; -} - -/** - Get available system memory below 1MB by specified size. - - @param[in] WakeupBufferSize Wakeup buffer size required - - @retval other Return wakeup buffer address below 1MB. - @retval -1 Cannot find free memory below 1MB. -**/ -UINTN -GetWakeupBuffer ( - IN UINTN WakeupBufferSize - ) -{ - EFI_PEI_HOB_POINTERS Hob; - UINTN WakeupBufferStart; - UINTN WakeupBufferEnd; - - WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1); - - // - // Get the HOB list for processing - // - Hob.Raw = GetHobList (); - - // - // Collect memory ranges - // - while (!END_OF_HOB_LIST (Hob)) { - if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { - if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) && - (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && - ((Hob.ResourceDescriptor->ResourceAttribute & - (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | - EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | - EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED - )) == 0) - ) { - // - // Need memory under 1MB to be collected here - // - WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength); - if (WakeupBufferEnd > BASE_1MB) { - // - // Wakeup buffer should be under 1MB - // - WakeupBufferEnd = BASE_1MB; - } - while (WakeupBufferEnd > WakeupBufferSize) { - // - // Wakeup buffer should be aligned on 4KB - // - WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1); - if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) { - break; - } - if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) { - // - // If this range is overlapped with existing allocated buffer, skip it - // and find the next range - // - WakeupBufferEnd -= WakeupBufferSize; - continue; - } - DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n", - WakeupBufferStart, WakeupBufferSize)); - // - // Create a memory allocation HOB. - // - BuildMemoryAllocationHob ( - WakeupBufferStart, - WakeupBufferSize, - EfiBootServicesData - ); - return WakeupBufferStart; - } - } - } - // - // Find the next HOB - // - Hob.Raw = GET_NEXT_HOB (Hob); - } - - return (UINTN) -1; -} - -/** - Allocate reset vector buffer. - - @param[in, out] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -AllocateResetVector ( - IN OUT CPU_MP_DATA *CpuMpData - ) -{ - UINTN ApResetVectorSize; - - if (CpuMpData->WakeupBuffer == (UINTN) -1) { - ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize + - sizeof (MP_CPU_EXCHANGE_INFO); - - CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize); - CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) - (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize); - BackupAndPrepareWakeupBuffer (CpuMpData); - } - - if (CpuMpData->SaveRestoreFlag) { - BackupAndPrepareWakeupBuffer (CpuMpData); - } -} - -/** - Free AP reset vector buffer. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -FreeResetVector ( - IN CPU_MP_DATA *CpuMpData - ) -{ - if (CpuMpData->SaveRestoreFlag) { - RestoreWakeupBuffer (CpuMpData); - } -} - -/** - Checks APs status and updates APs status if needed. - -**/ -VOID -CheckAndUpdateApsStatus ( - VOID - ) -{ -} - -/** - Initialize global data for MP support. - - @param[in] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -InitMpGlobalData ( - IN CPU_MP_DATA *CpuMpData - ) -{ - EFI_STATUS Status; - - SaveCpuMpData (CpuMpData); - - if (CpuMpData->CpuCount == 1) { - // - // If only BSP exists, return - // - return; - } - - // - // Register an event for EndOfPei - // - Status = PeiServicesNotifyPpi (&mMpInitLibNotifyList); - ASSERT_EFI_ERROR (Status); -} - -/** - This service executes 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. See type - EFI_AP_PROCEDURE. - @param[in] SingleThread If TRUE, then all the enabled APs execute - the function specified by Procedure one by - one, in ascending order of processor handle - number. If FALSE, then all the enabled APs - execute the function specified by Procedure - simultaneously. - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. If it is NULL, then execute in - blocking mode. BSP waits until all APs finish - or TimeoutInMicroSeconds expires. If it's - not NULL, then execute in non-blocking mode. - BSP requests the function specified by - Procedure to be started on all the enabled - APs, and go on executing immediately. If - all return from Procedure, or TimeoutInMicroSeconds - expires, this event is signaled. The BSP - can use the CheckEvent() or WaitForEvent() - services to check the state of event. Type - EFI_EVENT is defined in CreateEvent() in - the Unified Extensible Firmware Interface - Specification. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - APs to return from Procedure, either for - blocking or non-blocking mode. Zero means - infinity. If the timeout expires before - all APs return from Procedure, then Procedure - on the failed APs is terminated. All enabled - APs are available for next function assigned - by MpInitLibStartupAllAPs() or - MPInitLibStartupThisAP(). - If the timeout expires in blocking mode, - BSP returns EFI_TIMEOUT. If the timeout - expires in non-blocking mode, WaitEvent - is signaled with SignalEvent(). - @param[in] ProcedureArgument The parameter passed into Procedure for - all APs. - @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise, - if all APs finish successfully, then its - content is set to NULL. If not all APs - finish before timeout expires, then its - content is set to address of the buffer - holding handle numbers of the failed APs. - The buffer is allocated by MP Initialization - library, and it's the caller's responsibility to - free the buffer with FreePool() service. - In blocking mode, it is ready for consumption - when the call returns. In non-blocking mode, - it is ready when WaitEvent is signaled. The - list of failed CPU is terminated by - END_OF_CPU_LIST. - - @retval EFI_SUCCESS In blocking mode, all APs have finished before - the timeout expired. - @retval EFI_SUCCESS In non-blocking mode, function has been dispatched - to all enabled APs. - @retval EFI_UNSUPPORTED A non-blocking mode request was made after the - UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was - signaled. - @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not - supported. - @retval EFI_DEVICE_ERROR Caller processor is AP. - @retval EFI_NOT_STARTED No enabled APs exist in the system. - @retval EFI_NOT_READY Any enabled APs are busy. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - @retval EFI_TIMEOUT In blocking mode, the timeout expired before - all enabled APs have finished. - @retval EFI_INVALID_PARAMETER Procedure is NULL. - -**/ -EFI_STATUS -EFIAPI -MpInitLibStartupAllAPs ( - IN EFI_AP_PROCEDURE Procedure, - IN BOOLEAN SingleThread, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT UINTN **FailedCpuList OPTIONAL - ) -{ - if (WaitEvent != NULL) { - return EFI_UNSUPPORTED; - } - - return StartupAllAPsWorker ( - Procedure, - SingleThread, - NULL, - TimeoutInMicroseconds, - ProcedureArgument, - FailedCpuList - ); -} - -/** - This service lets the caller get one enabled AP to execute a caller-provided - function. - - @param[in] Procedure A pointer to the function to be run on the - designated AP of the system. See type - EFI_AP_PROCEDURE. - @param[in] ProcessorNumber The handle number of the AP. The range is - from 0 to the total number of logical - processors minus 1. The total number of - logical processors can be retrieved by - MpInitLibGetNumberOfProcessors(). - @param[in] WaitEvent The event created by the caller with CreateEvent() - service. If it is NULL, then execute in - blocking mode. BSP waits until this AP finish - or TimeoutInMicroSeconds expires. If it's - not NULL, then execute in non-blocking mode. - BSP requests the function specified by - Procedure to be started on this AP, - and go on executing immediately. If this AP - return from Procedure or TimeoutInMicroSeconds - expires, this event is signaled. The BSP - can use the CheckEvent() or WaitForEvent() - services to check the state of event. Type - EFI_EVENT is defined in CreateEvent() in - the Unified Extensible Firmware Interface - Specification. - @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - this AP to finish this Procedure, either for - blocking or non-blocking mode. Zero means - infinity. If the timeout expires before - this AP returns from Procedure, then Procedure - on the AP is terminated. The - AP is available for next function assigned - by MpInitLibStartupAllAPs() or - MpInitLibStartupThisAP(). - If the timeout expires in blocking mode, - BSP returns EFI_TIMEOUT. If the timeout - expires in non-blocking mode, WaitEvent - is signaled with SignalEvent(). - @param[in] ProcedureArgument The parameter passed into Procedure on the - specified AP. - @param[out] Finished If NULL, this parameter is ignored. In - blocking mode, this parameter is ignored. - In non-blocking mode, if AP returns from - Procedure before the timeout expires, its - content is set to TRUE. Otherwise, the - value is set to FALSE. The caller can - determine if the AP returned from Procedure - by evaluating this value. - - @retval EFI_SUCCESS In blocking mode, specified AP finished before - the timeout expires. - @retval EFI_SUCCESS In non-blocking mode, the function has been - dispatched to specified AP. - @retval EFI_UNSUPPORTED A non-blocking mode request was made after the - UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was - signaled. - @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not - supported. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_TIMEOUT In blocking mode, the timeout expired before - the specified AP has finished. - @retval EFI_NOT_READY The specified AP is busy. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - @retval EFI_NOT_FOUND The processor with the handle specified by - ProcessorNumber does not exist. - @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. - @retval EFI_INVALID_PARAMETER Procedure is NULL. - -**/ -EFI_STATUS -EFIAPI -MpInitLibStartupThisAP ( - IN EFI_AP_PROCEDURE Procedure, - IN UINTN ProcessorNumber, - IN EFI_EVENT WaitEvent OPTIONAL, - IN UINTN TimeoutInMicroseconds, - IN VOID *ProcedureArgument OPTIONAL, - OUT BOOLEAN *Finished OPTIONAL - ) -{ - if (WaitEvent != NULL) { - return EFI_UNSUPPORTED; - } - - return StartupThisAPWorker ( - Procedure, - ProcessorNumber, - NULL, - TimeoutInMicroseconds, - ProcedureArgument, - Finished - ); -} - -/** - This service switches the requested AP to be the BSP from that point onward. - This service changes the BSP for all purposes. This call can only be performed - by the current BSP. - - @param[in] ProcessorNumber The handle number of AP that is to become the new - BSP. The range is from 0 to the total number of - logical processors minus 1. The total number of - logical processors can be retrieved by - MpInitLibGetNumberOfProcessors(). - @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an - enabled AP. Otherwise, it will be disabled. - - @retval EFI_SUCCESS BSP successfully switched. - @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to - this service returning. - @retval EFI_UNSUPPORTED Switching the BSP is not supported. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_NOT_FOUND The processor with the handle specified by - ProcessorNumber does not exist. - @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or - a disabled AP. - @retval EFI_NOT_READY The specified AP is busy. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - -**/ -EFI_STATUS -EFIAPI -MpInitLibSwitchBSP ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableOldBSP - ) -{ - return SwitchBSPWorker (ProcessorNumber, EnableOldBSP); -} - -/** - This service lets the caller enable or disable an AP from this point onward. - This service may only be called from the BSP. - - @param[in] ProcessorNumber The handle number of AP. - The range is from 0 to the total number of - logical processors minus 1. The total number of - logical processors can be retrieved by - MpInitLibGetNumberOfProcessors(). - @param[in] EnableAP Specifies the new state for the processor for - enabled, FALSE for disabled. - @param[in] HealthFlag If not NULL, a pointer to a value that specifies - the new health status of the AP. This flag - corresponds to StatusFlag defined in - EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only - the PROCESSOR_HEALTH_STATUS_BIT is used. All other - bits are ignored. If it is NULL, this parameter - is ignored. - - @retval EFI_SUCCESS The specified AP was enabled or disabled successfully. - @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed - prior to this service returning. - @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported. - @retval EFI_DEVICE_ERROR The calling processor is an AP. - @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber - does not exist. - @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP. - @retval EFI_NOT_READY MP Initialize Library is not initialized. - -**/ -EFI_STATUS -EFIAPI -MpInitLibEnableDisableAP ( - IN UINTN ProcessorNumber, - IN BOOLEAN EnableAP, - IN UINT32 *HealthFlag OPTIONAL - ) -{ - return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag); -} - - diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc b/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc deleted file mode 100644 index a63cd23a40..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc +++ /dev/null @@ -1,43 +0,0 @@ -;------------------------------------------------------------------------------ ; -; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
-; 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. -; -; Module Name: -; -; MpEqu.inc -; -; Abstract: -; -; This is the equates file for Multiple Processor support -; -;------------------------------------------------------------------------------- - -VacantFlag equ 00h -NotVacantFlag equ 0ffh - -CPU_SWITCH_STATE_IDLE equ 0 -CPU_SWITCH_STATE_STORED equ 1 -CPU_SWITCH_STATE_LOADED equ 2 - -LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart) -StackStartAddressLocation equ LockLocation + 08h -StackSizeLocation equ LockLocation + 10h -ApProcedureLocation equ LockLocation + 18h -GdtrLocation equ LockLocation + 20h -IdtrLocation equ LockLocation + 2Ah -BufferStartLocation equ LockLocation + 34h -ModeOffsetLocation equ LockLocation + 3Ch -NumApsExecutingLocation equ LockLocation + 44h -CodeSegmentLocation equ LockLocation + 4Ch -DataSegmentLocation equ LockLocation + 54h -EnableExecuteDisableLocation equ LockLocation + 5Ch -Cr3Location equ LockLocation + 64h -InitFlagLocation equ LockLocation + 6Ch -CpuInfoLocation equ LockLocation + 74h - diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm deleted file mode 100644 index fa54d01542..0000000000 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ /dev/null @@ -1,398 +0,0 @@ -;------------------------------------------------------------------------------ ; -; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
-; 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. -; -; Module Name: -; -; MpFuncs.nasm -; -; Abstract: -; -; This is the assembly code for MP support -; -;------------------------------------------------------------------------------- - -%include "MpEqu.inc" -extern ASM_PFX(InitializeFloatingPointUnits) - -DEFAULT REL - -SECTION .text - -;------------------------------------------------------------------------------------- -;RendezvousFunnelProc procedure follows. All APs execute their procedure. This -;procedure serializes all the AP processors through an Init sequence. It must be -;noted that APs arrive here very raw...ie: real mode, no stack. -;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC -;IS IN MACHINE CODE. -;------------------------------------------------------------------------------------- -global ASM_PFX(RendezvousFunnelProc) -ASM_PFX(RendezvousFunnelProc): -RendezvousFunnelProcStart: -; At this point CS = 0x(vv00) and ip= 0x0. -; Save BIST information to ebp firstly - -BITS 16 - mov ebp, eax ; Save BIST information - - mov ax, cs - mov ds, ax - mov es, ax - mov ss, ax - xor ax, ax - mov fs, ax - mov gs, ax - - mov si, BufferStartLocation - mov ebx, [si] - - mov di, ModeOffsetLocation - mov eax, [di] - mov di, CodeSegmentLocation - mov edx, [di] - mov di, ax - sub di, 02h - mov [di],dx ; Patch long mode CS - sub di, 04h - add eax, ebx - mov [di],eax ; Patch address - - mov si, GdtrLocation -o32 lgdt [cs:si] - - mov si, IdtrLocation -o32 lidt [cs:si] - - mov si, EnableExecuteDisableLocation - cmp byte [si], 0 - jz SkipEnableExecuteDisableBit - - ; - ; Enable execute disable bit - ; - mov ecx, 0c0000080h ; EFER MSR number - rdmsr ; Read EFER - bts eax, 11 ; Enable Execute Disable Bit - wrmsr ; Write EFER - -SkipEnableExecuteDisableBit: - - mov di, DataSegmentLocation - mov edi, [di] ; Save long mode DS in edi - - mov si, Cr3Location ; Save CR3 in ecx - mov ecx, [si] - - xor ax, ax - mov ds, ax ; Clear data segment - - mov eax, cr0 ; Get control register 0 - or eax, 000000003h ; Set PE bit (bit #0) & MP - mov cr0, eax - - mov eax, cr4 - bts eax, 5 - mov cr4, eax - - mov cr3, ecx ; Load CR3 - - mov ecx, 0c0000080h ; EFER MSR number - rdmsr ; Read EFER - bts eax, 8 ; Set LME=1 - wrmsr ; Write EFER - - mov eax, cr0 ; Read CR0 - bts eax, 31 ; Set PG=1 - mov cr0, eax ; Write CR0 - - jmp 0:strict dword 0 ; far jump to long mode -BITS 64 -LongModeStart: - mov eax, edi - mov ds, ax - mov es, ax - mov ss, ax - - mov esi, ebx - lea edi, [esi + InitFlagLocation] - cmp qword [edi], 1 ; ApInitConfig - jnz GetApicId - - ; AP init - mov edi, esi - add edi, LockLocation - mov rax, NotVacantFlag - -TestLock: - xchg qword [edi], rax - cmp rax, NotVacantFlag - jz TestLock - - lea ecx, [esi + NumApsExecutingLocation] - inc dword [ecx] - mov ebx, [ecx] - -Releaselock: - mov rax, VacantFlag - xchg qword [edi], rax - ; program stack - mov edi, esi - add edi, StackSizeLocation - mov eax, dword [edi] - mov ecx, ebx - inc ecx - mul ecx ; EAX = StackSize * (CpuNumber + 1) - mov edi, esi - add edi, StackStartAddressLocation - add rax, qword [edi] - mov rsp, rax - jmp CProcedureInvoke - -GetApicId: - mov eax, 0 - cpuid - cmp eax, 0bh - jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY - - mov eax, 0bh - xor ecx, ecx - cpuid - test ebx, 0ffffh - jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero - - ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX - jmp GetProcessorNumber - -NoX2Apic: - ; Processor is not x2APIC capable, so get 8-bit APIC ID - mov eax, 1 - cpuid - shr ebx, 24 - mov edx, ebx - -GetProcessorNumber: - ; - ; Get processor number for this AP - ; Note that BSP may become an AP due to SwitchBsp() - ; - xor ebx, ebx - lea eax, [esi + CpuInfoLocation] - mov edi, [eax] - -GetNextProcNumber: - cmp dword [edi], edx ; APIC ID match? - jz ProgramStack - add edi, 20 - inc ebx - jmp GetNextProcNumber - -ProgramStack: - mov rsp, qword [edi + 12] - -CProcedureInvoke: - push rbp ; Push BIST data at top of AP stack - xor rbp, rbp ; Clear ebp for call stack trace - push rbp - mov rbp, rsp - - mov rax, ASM_PFX(InitializeFloatingPointUnits) - sub rsp, 20h - call rax ; Call assembly function to initialize FPU per UEFI spec - add rsp, 20h - - mov edx, ebx ; edx is NumApsExecuting - mov ecx, esi - add ecx, LockLocation ; rcx is address of exchange info data buffer - - mov edi, esi - add edi, ApProcedureLocation - mov rax, qword [edi] - - sub rsp, 20h - call rax ; Invoke C function - add rsp, 20h - jmp $ ; Should never reach here - -RendezvousFunnelProcEnd: - -;------------------------------------------------------------------------------------- -; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish); -;------------------------------------------------------------------------------------- -global ASM_PFX(AsmRelocateApLoop) -ASM_PFX(AsmRelocateApLoop): -AsmRelocateApLoopStart: - mov rax, [rsp + 40] ; CountTofinish - lock dec dword [rax] ; (*CountTofinish)-- - mov rsp, r9 - push rcx - push rdx - - lea rsi, [PmEntry] ; rsi <- The start address of transition code - - push r8 - push rsi - DB 0x48 - retf -BITS 32 -PmEntry: - mov eax, cr0 - btr eax, 31 ; Clear CR0.PG - mov cr0, eax ; Disable paging and caches - - mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx - mov ecx, 0xc0000080 - rdmsr - and ah, ~ 1 ; Clear LME - wrmsr - mov eax, cr4 - and al, ~ (1 << 5) ; Clear PAE - mov cr4, eax - - pop edx - add esp, 4 - pop ecx, - add esp, 4 - cmp cl, 1 ; Check mwait-monitor support - jnz HltLoop - mov ebx, edx ; Save C-State to ebx -MwaitLoop: - mov eax, esp ; Set Monitor Address - xor ecx, ecx ; ecx = 0 - xor edx, edx ; edx = 0 - monitor - mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] - shl eax, 4 - mwait - jmp MwaitLoop -HltLoop: - cli - hlt - jmp HltLoop -BITS 64 -AsmRelocateApLoopEnd: - -;------------------------------------------------------------------------------------- -; AsmGetAddressMap (&AddressMap); -;------------------------------------------------------------------------------------- -global ASM_PFX(AsmGetAddressMap) -ASM_PFX(AsmGetAddressMap): - mov rax, ASM_PFX(RendezvousFunnelProc) - mov qword [rcx], rax - mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart - mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart - mov rax, ASM_PFX(AsmRelocateApLoop) - mov qword [rcx + 18h], rax - mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart - ret - -;------------------------------------------------------------------------------------- -;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is -;about to become an AP. It switches its stack with the current AP. -;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); -;------------------------------------------------------------------------------------- -global ASM_PFX(AsmExchangeRole) -ASM_PFX(AsmExchangeRole): - ; DO NOT call other functions in this function, since 2 CPU may use 1 stack - ; at the same time. If 1 CPU try to call a function, stack will be corrupted. - - push rax - push rbx - push rcx - push rdx - push rsi - push rdi - push rbp - push r8 - push r9 - push r10 - push r11 - push r12 - push r13 - push r14 - push r15 - - mov rax, cr0 - push rax - - mov rax, cr4 - push rax - - ; rsi contains MyInfo pointer - mov rsi, rcx - - ; rdi contains OthersInfo pointer - mov rdi, rdx - - ;Store EFLAGS, GDTR and IDTR regiter to stack - pushfq - sgdt [rsi + 16] - sidt [rsi + 26] - - ; Store the its StackPointer - mov [rsi + 8], rsp - - ; update its switch state to STORED - mov byte [rsi], CPU_SWITCH_STATE_STORED - -WaitForOtherStored: - ; wait until the other CPU finish storing its state - cmp byte [rdi], CPU_SWITCH_STATE_STORED - jz OtherStored - pause - jmp WaitForOtherStored - -OtherStored: - ; Since another CPU already stored its state, load them - ; load GDTR value - lgdt [rdi + 16] - - ; load IDTR value - lidt [rdi + 26] - - ; load its future StackPointer - mov rsp, [rdi + 8] - - ; update the other CPU's switch state to LOADED - mov byte [rdi], CPU_SWITCH_STATE_LOADED - -WaitForOtherLoaded: - ; wait until the other CPU finish loading new state, - ; otherwise the data in stack may corrupt - cmp byte [rsi], CPU_SWITCH_STATE_LOADED - jz OtherLoaded - pause - jmp WaitForOtherLoaded - -OtherLoaded: - ; since the other CPU already get the data it want, leave this procedure - popfq - - pop rax - mov cr4, rax - - pop rax - mov cr0, rax - - pop r15 - pop r14 - pop r13 - pop r12 - pop r11 - pop r10 - pop r9 - pop r8 - pop rbp - pop rdi - pop rsi - pop rdx - pop rcx - pop rbx - pop rax - - ret -- cgit v1.2.3