/** @file\r
Common header file for MP Initialize Library.\r
\r
- Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
#include <PiPei.h>\r
\r
-#include <Register/Cpuid.h>\r
-#include <Register/Msr.h>\r
-#include <Register/LocalApic.h>\r
-#include <Register/Microcode.h>\r
+#include <Register/Intel/Cpuid.h>\r
+#include <Register/Intel/Msr.h>\r
+#include <Register/Intel/LocalApic.h>\r
+#include <Register/Intel/Microcode.h>\r
\r
#include <Library/MpInitLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/MtrrLib.h>\r
#include <Library/HobLib.h>\r
\r
+#include <Guid/MicrocodePatchHob.h>\r
+\r
+#include <IndustryStandard/FirmwareInterfaceTable.h>\r
+\r
+\r
#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')\r
\r
#define CPU_INIT_MP_LIB_HOB_GUID \\r
#define CPU_SWITCH_STATE_STORED 1\r
#define CPU_SWITCH_STATE_LOADED 2\r
\r
+//\r
+// Default maximum number of entries to store the microcode patches information\r
+//\r
+#define DEFAULT_MAX_MICROCODE_PATCH_NUM 8\r
+\r
+//\r
+// Data structure for microcode patch information\r
+//\r
+typedef struct {\r
+ UINTN Address;\r
+ UINTN Size;\r
+} MICROCODE_PATCH_INFO;\r
+\r
//\r
// CPU exchange information for switch BSP\r
//\r
//\r
// AP state\r
//\r
+// The state transitions for an AP when it process a procedure are:\r
+// Idle ----> Ready ----> Busy ----> Idle\r
+// [BSP] [AP] [AP]\r
+//\r
typedef enum {\r
CpuStateIdle,\r
CpuStateReady,\r
UINTN Dr3;\r
UINTN Dr6;\r
UINTN Dr7;\r
+ IA32_DESCRIPTOR Gdtr;\r
+ IA32_DESCRIPTOR Idtr;\r
+ UINT16 Tr;\r
} CPU_VOLATILE_REGISTERS;\r
\r
//\r
volatile UINT32 *StartupApSignal;\r
volatile UINTN ApFunction;\r
volatile UINTN ApFunctionArgument;\r
- UINT32 InitialApicId;\r
- UINT32 ApicId;\r
- UINT32 Health;\r
BOOLEAN CpuHealthy;\r
volatile CPU_STATE State;\r
CPU_VOLATILE_REGISTERS VolatileRegisters;\r
UINT64 CurrentTime;\r
UINT64 TotalTime;\r
EFI_EVENT WaitEvent;\r
+ UINT32 ProcessorSignature;\r
+ UINT8 PlatformId;\r
+ UINT64 MicrocodeEntryAddr;\r
} CPU_AP_DATA;\r
\r
//\r
// we need to make sure the each fields offset same in different\r
// architecture.\r
//\r
+#pragma pack (1)\r
typedef struct {\r
UINT32 InitialApicId;\r
UINT32 ApicId;\r
UINT32 Health;\r
+ UINT64 ApTopOfStack;\r
} CPU_INFO_IN_HOB;\r
+#pragma pack ()\r
\r
//\r
// AP reset code information including code address and size,\r
UINTN RendezvousFunnelSize;\r
UINT8 *RelocateApLoopFuncAddress;\r
UINTN RelocateApLoopFuncSize;\r
+ UINTN ModeTransitionOffset;\r
} MP_ASSEMBLY_ADDRESS_MAP;\r
\r
typedef struct _CPU_MP_DATA CPU_MP_DATA;\r
IA32_DESCRIPTOR IdtrProfile;\r
UINTN BufferStart;\r
UINTN ModeOffset;\r
- UINTN NumApsExecuting;\r
+ UINTN ApIndex;\r
UINTN CodeSegment;\r
UINTN DataSegment;\r
UINTN EnableExecuteDisable;\r
UINTN Cr3;\r
+ UINTN InitFlag;\r
+ CPU_INFO_IN_HOB *CpuInfo;\r
+ UINTN NumApsExecuting;\r
CPU_MP_DATA *CpuMpData;\r
+ UINTN InitializeFloatingPointUnitsAddress;\r
+ UINT32 ModeTransitionMemory;\r
+ UINT16 ModeTransitionSegment;\r
+ UINT32 ModeHighMemory;\r
+ UINT16 ModeHighSegment;\r
+ //\r
+ // Enable5LevelPaging indicates whether 5-level paging is enabled in long mode.\r
+ //\r
+ BOOLEAN Enable5LevelPaging;\r
} MP_CPU_EXCHANGE_INFO;\r
\r
#pragma pack()\r
UINTN CpuApStackSize;\r
MP_ASSEMBLY_ADDRESS_MAP AddressMap;\r
UINTN WakeupBuffer;\r
+ UINTN WakeupBufferHigh;\r
UINTN BackupBuffer;\r
UINTN BackupBufferSize;\r
- BOOLEAN EndOfPeiFlag;\r
\r
- volatile UINT32 StartCount;\r
volatile UINT32 FinishedCount;\r
- volatile UINT32 RunningCount;\r
+ UINT32 RunningCount;\r
BOOLEAN SingleThread;\r
EFI_AP_PROCEDURE Procedure;\r
VOID *ProcArguments;\r
UINTN **FailedCpuList;\r
\r
AP_INIT_STATE InitFlag;\r
- BOOLEAN X2ApicEnable;\r
BOOLEAN SwitchBspFlag;\r
+ UINTN NewBspNumber;\r
CPU_EXCHANGE_ROLE_INFO BSPInfo;\r
CPU_EXCHANGE_ROLE_INFO APInfo;\r
MTRR_SETTINGS MtrrTable;\r
UINT16 PmCodeSegment;\r
CPU_AP_DATA *CpuData;\r
volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;\r
+\r
+ UINT32 CurrentTimerCount;\r
+ UINTN DivideValue;\r
+ UINT8 Vector;\r
+ BOOLEAN PeriodicMode;\r
+ BOOLEAN TimerInterruptState;\r
+ UINT64 MicrocodePatchAddress;\r
+ UINT64 MicrocodePatchRegionSize;\r
+\r
+ //\r
+ // Whether need to use Init-Sipi-Sipi to wake up the APs.\r
+ // Two cases need to set this value to TRUE. One is in HLT\r
+ // loop mode, the other is resume from S3 which loop mode\r
+ // will be hardcode change to HLT mode by PiSmmCpuDxeSmm\r
+ // driver.\r
+ //\r
+ BOOLEAN WakeUpByInitSipiSipi;\r
};\r
\r
extern EFI_GUID mCpuInitMpLibHobGuid;\r
(EFIAPI * ASM_RELOCATE_AP_LOOP) (\r
IN BOOLEAN MwaitSupport,\r
IN UINTN ApTargetCState,\r
- IN UINTN PmCodeSegment\r
+ IN UINTN PmCodeSegment,\r
+ IN UINTN TopOfApStack,\r
+ IN UINTN NumberToFinish\r
);\r
\r
/**\r
IN CPU_MP_DATA *CpuMpData\r
);\r
\r
+\r
/**\r
- Allocate reset vector buffer.\r
+ Get available system memory below 1MB by specified size.\r
+\r
+ @param[in] WakeupBufferSize Wakeup buffer size required\r
\r
- @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+ @retval other Return wakeup buffer address below 1MB.\r
+ @retval -1 Cannot find free memory below 1MB.\r
**/\r
-VOID\r
-AllocateResetVector (\r
- IN OUT CPU_MP_DATA *CpuMpData\r
+UINTN\r
+GetWakeupBuffer (\r
+ IN UINTN WakeupBufferSize\r
);\r
\r
/**\r
- Free AP reset vector buffer.\r
+ Get available EfiBootServicesCode memory below 4GB by specified size.\r
+\r
+ This buffer is required to safely transfer AP from real address mode to\r
+ protected mode or long mode, due to the fact that the buffer returned by\r
+ GetWakeupBuffer() may be marked as non-executable.\r
\r
- @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+ @param[in] BufferSize Wakeup transition buffer size.\r
+\r
+ @retval other Return wakeup transition buffer address below 4GB.\r
+ @retval 0 Cannot find free memory below 4GB.\r
**/\r
-VOID\r
-FreeResetVector (\r
- IN CPU_MP_DATA *CpuMpData\r
+UINTN\r
+GetModeTransitionBuffer (\r
+ IN UINTN BufferSize\r
);\r
\r
/**\r
@param[in] ProcessorNumber The handle number of specified processor\r
@param[in] Procedure The function to be invoked by AP\r
@param[in] ProcedureArgument The argument to be passed into AP function\r
+ @param[in] WakeUpDisabledAps Whether need to wake up disabled APs in broadcast mode.\r
**/\r
VOID\r
WakeUpAP (\r
IN BOOLEAN Broadcast,\r
IN UINTN ProcessorNumber,\r
IN EFI_AP_PROCEDURE Procedure, OPTIONAL\r
- IN VOID *ProcedureArgument OPTIONAL\r
+ IN VOID *ProcedureArgument, OPTIONAL\r
+ IN BOOLEAN WakeUpDisabledAps OPTIONAL\r
);\r
\r
/**\r
IN CPU_MP_DATA *CpuMpData\r
);\r
\r
+/**\r
+ Worker function to execute a caller provided function on all enabled APs.\r
+\r
+ @param[in] Procedure A pointer to the function to be run on\r
+ enabled APs of the system.\r
+ @param[in] SingleThread If TRUE, then all the enabled APs execute\r
+ the function specified by Procedure one by\r
+ one, in ascending order of processor handle\r
+ number. If FALSE, then all the enabled APs\r
+ execute the function specified by Procedure\r
+ simultaneously.\r
+ @param[in] ExcludeBsp Whether let BSP also trig this task.\r
+ @param[in] WaitEvent The event created by the caller with CreateEvent()\r
+ service.\r
+ @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
+ APs to return from Procedure, either for\r
+ blocking or non-blocking mode.\r
+ @param[in] ProcedureArgument The parameter passed into Procedure for\r
+ all APs.\r
+ @param[out] FailedCpuList If all APs finish successfully, then its\r
+ content is set to NULL. If not all APs\r
+ finish before timeout expires, then its\r
+ content is set to address of the buffer\r
+ holding handle numbers of the failed APs.\r
+\r
+ @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
+ the timeout expired.\r
+ @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
+ to all enabled APs.\r
+ @retval others Failed to Startup all APs.\r
+\r
+**/\r
+EFI_STATUS\r
+StartupAllCPUsWorker (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN BOOLEAN SingleThread,\r
+ IN BOOLEAN ExcludeBsp,\r
+ IN EFI_EVENT WaitEvent OPTIONAL,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN VOID *ProcedureArgument OPTIONAL,\r
+ OUT UINTN **FailedCpuList OPTIONAL\r
+ );\r
+\r
+/**\r
+ Worker function to let the caller get one enabled AP to execute a caller-provided\r
+ function.\r
+\r
+ @param[in] Procedure A pointer to the function to be run on\r
+ enabled APs of the system.\r
+ @param[in] ProcessorNumber The handle number of the AP.\r
+ @param[in] WaitEvent The event created by the caller with CreateEvent()\r
+ service.\r
+ @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
+ APs to return from Procedure, either for\r
+ blocking or non-blocking mode.\r
+ @param[in] ProcedureArgument The parameter passed into Procedure for\r
+ all APs.\r
+ @param[out] Finished If AP returns from Procedure before the\r
+ timeout expires, its content is set to TRUE.\r
+ Otherwise, the value is set to FALSE.\r
+\r
+ @retval EFI_SUCCESS In blocking mode, specified AP finished before\r
+ the timeout expires.\r
+ @retval others Failed to Startup AP.\r
+\r
+**/\r
+EFI_STATUS\r
+StartupThisAPWorker (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN UINTN ProcessorNumber,\r
+ IN EFI_EVENT WaitEvent OPTIONAL,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN VOID *ProcedureArgument OPTIONAL,\r
+ OUT BOOLEAN *Finished OPTIONAL\r
+ );\r
+\r
/**\r
Worker function to switch the requested AP to be the BSP from that point onward.\r
\r
enabled AP. Otherwise, it will be disabled.\r
\r
@retval EFI_SUCCESS BSP successfully switched.\r
- @retval others Failed to switch BSP. \r
+ @retval others Failed to switch BSP.\r
\r
**/\r
EFI_STATUS\r
/**\r
Detect whether specified processor can find matching microcode patch and load it.\r
\r
- @param[in] PeiCpuMpData Pointer to PEI CPU MP Data\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+ @param[in] ProcessorNumber The handle number of the processor. The range is\r
+ from 0 to the total number of logical processors\r
+ minus 1.\r
**/\r
VOID\r
MicrocodeDetect (\r
- IN CPU_MP_DATA *CpuMpData\r
+ IN CPU_MP_DATA *CpuMpData,\r
+ IN UINTN ProcessorNumber\r
+ );\r
+\r
+/**\r
+ Shadow the required microcode patches data into memory.\r
+\r
+ @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+ShadowMicrocodeUpdatePatch (\r
+ IN OUT CPU_MP_DATA *CpuMpData\r
+ );\r
+\r
+/**\r
+ Get the cached microcode patch base address and size from the microcode patch\r
+ information cache HOB.\r
+\r
+ @param[out] Address Base address of the microcode patches data.\r
+ It will be updated if the microcode patch\r
+ information cache HOB is found.\r
+ @param[out] RegionSize Size of the microcode patches data.\r
+ It will be updated if the microcode patch\r
+ information cache HOB is found.\r
+\r
+ @retval TRUE The microcode patch information cache HOB is found.\r
+ @retval FALSE The microcode patch information cache HOB is not found.\r
+\r
+**/\r
+BOOLEAN\r
+GetMicrocodePatchInfoFromHob (\r
+ UINT64 *Address,\r
+ UINT64 *RegionSize\r
);\r
\r
/**\r
- Notify function on End Of PEI PPI.\r
+ Detect whether Mwait-monitor feature is supported.\r
\r
- On S3 boot, this function will restore wakeup buffer data.\r
- On normal boot, this function will flag wakeup buffer to be un-used type.\r
+ @retval TRUE Mwait-monitor feature is supported.\r
+ @retval FALSE Mwait-monitor feature is not supported.\r
+**/\r
+BOOLEAN\r
+IsMwaitSupport (\r
+ VOID\r
+ );\r
\r
- @param[in] PeiServices The pointer to the PEI Services Table.\r
- @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
- @param[in] Ppi Address of the PPI that was installed.\r
+/**\r
+ Enable Debug Agent to support source debugging on AP function.\r
\r
- @retval EFI_SUCCESS When everything is OK.\r
+**/\r
+VOID\r
+EnableDebugAgent (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Find the current Processor number by APIC ID.\r
+\r
+ @param[in] CpuMpData Pointer to PEI CPU MP Data\r
+ @param[out] ProcessorNumber Return the pocessor number found\r
+\r
+ @retval EFI_SUCCESS ProcessorNumber is found and returned.\r
+ @retval EFI_NOT_FOUND ProcessorNumber is not found.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-CpuMpEndOfPeiCallback (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
- IN VOID *Ppi\r
+GetProcessorNumber (\r
+ IN CPU_MP_DATA *CpuMpData,\r
+ OUT UINTN *ProcessorNumber\r
);\r
\r
#endif\r