X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMpInitLib%2FMpLib.h;h=5f50e79744cb506bedb834b36b440d39b646feef;hb=88bd06616617ef2569f093f7b51893c11ad78e26;hp=84bd8721982caf6b55206cfd1ebaa9651b5d62d5;hpb=03a1a925159f7b16bfe67f43482e9924e8dbfa41;p=mirror_edk2.git diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 84bd872198..5f50e79744 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -1,14 +1,8 @@ /** @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. + Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -17,10 +11,10 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -35,6 +29,44 @@ #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 + +// +// Default maximum number of entries to store the microcode patches information +// +#define DEFAULT_MAX_MICROCODE_PATCH_NUM 8 + +// +// Data structure for microcode patch information +// +typedef struct { + UINTN Address; + UINTN Size; + UINTN AlignedSize; +} MICROCODE_PATCH_INFO; + +// +// 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 @@ -57,6 +89,10 @@ typedef enum { // // AP state // +// The state transitions for an AP when it process a procedure are: +// Idle ----> Ready ----> Busy ----> Idle +// [BSP] [AP] [AP] +// typedef enum { CpuStateIdle, CpuStateReady, @@ -65,6 +101,24 @@ typedef enum { 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; + IA32_DESCRIPTOR Gdtr; + IA32_DESCRIPTOR Idtr; + UINT16 Tr; +} CPU_VOLATILE_REGISTERS; + // // AP related data // @@ -73,17 +127,18 @@ typedef struct { volatile UINT32 *StartupApSignal; volatile UINTN ApFunction; volatile UINTN ApFunctionArgument; - UINT32 InitialApicId; - UINT32 ApicId; - UINT32 Health; BOOLEAN CpuHealthy; volatile CPU_STATE State; + CPU_VOLATILE_REGISTERS VolatileRegisters; BOOLEAN Waiting; BOOLEAN *Finished; UINT64 ExpectedTime; UINT64 CurrentTime; UINT64 TotalTime; EFI_EVENT WaitEvent; + UINT32 ProcessorSignature; + UINT8 PlatformId; + UINT64 MicrocodeEntryAddr; } CPU_AP_DATA; // @@ -92,11 +147,14 @@ typedef struct { // 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, @@ -109,6 +167,7 @@ typedef struct { UINTN RendezvousFunnelSize; UINT8 *RelocateApLoopFuncAddress; UINTN RelocateApLoopFuncSize; + UINTN ModeTransitionOffset; } MP_ASSEMBLY_ADDRESS_MAP; typedef struct _CPU_MP_DATA CPU_MP_DATA; @@ -129,12 +188,24 @@ typedef struct { IA32_DESCRIPTOR IdtrProfile; UINTN BufferStart; UINTN ModeOffset; - UINTN NumApsExecuting; + UINTN ApIndex; UINTN CodeSegment; UINTN DataSegment; UINTN EnableExecuteDisable; UINTN Cr3; + UINTN InitFlag; + CPU_INFO_IN_HOB *CpuInfo; + UINTN NumApsExecuting; CPU_MP_DATA *CpuMpData; + UINTN InitializeFloatingPointUnitsAddress; + UINT32 ModeTransitionMemory; + UINT16 ModeTransitionSegment; + UINT32 ModeHighMemory; + UINT16 ModeHighSegment; + // + // Enable5LevelPaging indicates whether 5-level paging is enabled in long mode. + // + BOOLEAN Enable5LevelPaging; } MP_CPU_EXCHANGE_INFO; #pragma pack() @@ -146,6 +217,8 @@ struct _CPU_MP_DATA { UINT64 CpuInfoInHob; UINT32 CpuCount; UINT32 BspNumber; + UINT64 MicrocodePatchAddress; + UINT64 MicrocodePatchRegionSize; // // The above fields data will be passed from PEI to DXE // Please make sure the fields offset same in the different @@ -156,13 +229,12 @@ struct _CPU_MP_DATA { UINTN CpuApStackSize; MP_ASSEMBLY_ADDRESS_MAP AddressMap; UINTN WakeupBuffer; + UINTN WakeupBufferHigh; UINTN BackupBuffer; UINTN BackupBufferSize; - BOOLEAN EndOfPeiFlag; - volatile UINT32 StartCount; volatile UINT32 FinishedCount; - volatile UINT32 RunningCount; + UINT32 RunningCount; BOOLEAN SingleThread; EFI_AP_PROCEDURE Procedure; VOID *ProcArguments; @@ -174,14 +246,40 @@ struct _CPU_MP_DATA { 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; + + UINT32 ProcessorSignature; + UINT32 ProcessorFlags; + UINT64 MicrocodeDataAddress; + UINT32 MicrocodeRevision; + + // + // Whether need to use Init-Sipi-Sipi to wake up the APs. + // Two cases need to set this value to TRUE. One is in HLT + // loop mode, the other is resume from S3 which loop mode + // will be hardcode change to HLT mode by PiSmmCpuDxeSmm + // driver. + // + BOOLEAN WakeUpByInitSipiSipi; }; + +extern EFI_GUID mCpuInitMpLibHobGuid; + /** Assembly code to place AP into safe loop mode. @@ -201,7 +299,9 @@ VOID (EFIAPI * ASM_RELOCATE_AP_LOOP) ( IN BOOLEAN MwaitSupport, IN UINTN ApTargetCState, - IN UINTN PmCodeSegment + IN UINTN PmCodeSegment, + IN UINTN TopOfApStack, + IN UINTN NumberToFinish ); /** @@ -216,5 +316,326 @@ 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 + ); + + +/** + 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 + ); + +/** + Get available EfiBootServicesCode memory below 4GB by specified size. + + This buffer is required to safely transfer AP from real address mode to + protected mode or long mode, due to the fact that the buffer returned by + GetWakeupBuffer() may be marked as non-executable. + + @param[in] BufferSize Wakeup transition buffer size. + + @retval other Return wakeup transition buffer address below 4GB. + @retval 0 Cannot find free memory below 4GB. +**/ +UINTN +GetModeTransitionBuffer ( + IN UINTN BufferSize + ); + +/** + 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 + @param[in] WakeUpDisabledAps Whether need to wake up disabled APs in broadcast mode. +**/ +VOID +WakeUpAP ( + IN CPU_MP_DATA *CpuMpData, + IN BOOLEAN Broadcast, + IN UINTN ProcessorNumber, + IN EFI_AP_PROCEDURE Procedure, OPTIONAL + IN VOID *ProcedureArgument, OPTIONAL + IN BOOLEAN WakeUpDisabledAps 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] ExcludeBsp Whether let BSP also trig this task. + @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 +StartupAllCPUsWorker ( + IN EFI_AP_PROCEDURE Procedure, + IN BOOLEAN SingleThread, + IN BOOLEAN ExcludeBsp, + 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. + @param[in] ProcessorNumber The handle number of the processor. The range is + from 0 to the total number of logical processors + minus 1. +**/ +VOID +MicrocodeDetect ( + IN CPU_MP_DATA *CpuMpData, + IN UINTN ProcessorNumber + ); + +/** + Load the required microcode patches data into memory. + + @param[in, out] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +LoadMicrocodePatch ( + IN OUT 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 + ); + +/** + Enable Debug Agent to support source debugging on AP function. + +**/ +VOID +EnableDebugAgent ( + VOID + ); + +/** + 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 + ); + #endif