Home | History | Annotate | Download | only in MpInitLib
      1 /** @file
      2   Common header file for MP Initialize Library.
      3 
      4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #ifndef _MP_LIB_H_
     16 #define _MP_LIB_H_
     17 
     18 #include <PiPei.h>
     19 
     20 #include <Register/Cpuid.h>
     21 #include <Register/Msr.h>
     22 #include <Register/LocalApic.h>
     23 #include <Register/Microcode.h>
     24 
     25 #include <Library/MpInitLib.h>
     26 #include <Library/BaseLib.h>
     27 #include <Library/BaseMemoryLib.h>
     28 #include <Library/MemoryAllocationLib.h>
     29 #include <Library/DebugLib.h>
     30 #include <Library/LocalApicLib.h>
     31 #include <Library/CpuLib.h>
     32 #include <Library/UefiCpuLib.h>
     33 #include <Library/TimerLib.h>
     34 #include <Library/SynchronizationLib.h>
     35 #include <Library/MtrrLib.h>
     36 #include <Library/HobLib.h>
     37 
     38 #define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
     39 
     40 #define CPU_INIT_MP_LIB_HOB_GUID \
     41   { \
     42     0x58eb6a19, 0x3699, 0x4c68, { 0xa8, 0x36, 0xda, 0xcd, 0x8e, 0xdc, 0xad, 0x4a } \
     43   }
     44 
     45 //
     46 //  The MP data for switch BSP
     47 //
     48 #define CPU_SWITCH_STATE_IDLE   0
     49 #define CPU_SWITCH_STATE_STORED 1
     50 #define CPU_SWITCH_STATE_LOADED 2
     51 
     52 //
     53 // CPU exchange information for switch BSP
     54 //
     55 typedef struct {
     56   UINT8             State;        // offset 0
     57   UINTN             StackPointer; // offset 4 / 8
     58   IA32_DESCRIPTOR   Gdtr;         // offset 8 / 16
     59   IA32_DESCRIPTOR   Idtr;         // offset 14 / 26
     60 } CPU_EXCHANGE_ROLE_INFO;
     61 
     62 //
     63 // AP loop state when APs are in idle state
     64 // It's value is the same with PcdCpuApLoopMode
     65 //
     66 typedef enum {
     67   ApInHltLoop   = 1,
     68   ApInMwaitLoop = 2,
     69   ApInRunLoop   = 3
     70 } AP_LOOP_MODE;
     71 
     72 //
     73 // AP initialization state during APs wakeup
     74 //
     75 typedef enum {
     76   ApInitConfig   = 1,
     77   ApInitReconfig = 2,
     78   ApInitDone     = 3
     79 } AP_INIT_STATE;
     80 
     81 //
     82 // AP state
     83 //
     84 typedef enum {
     85   CpuStateIdle,
     86   CpuStateReady,
     87   CpuStateBusy,
     88   CpuStateFinished,
     89   CpuStateDisabled
     90 } CPU_STATE;
     91 
     92 //
     93 // CPU volatile registers around INIT-SIPI-SIPI
     94 //
     95 typedef struct {
     96   UINTN                          Cr0;
     97   UINTN                          Cr3;
     98   UINTN                          Cr4;
     99   UINTN                          Dr0;
    100   UINTN                          Dr1;
    101   UINTN                          Dr2;
    102   UINTN                          Dr3;
    103   UINTN                          Dr6;
    104   UINTN                          Dr7;
    105 } CPU_VOLATILE_REGISTERS;
    106 
    107 //
    108 // AP related data
    109 //
    110 typedef struct {
    111   SPIN_LOCK                      ApLock;
    112   volatile UINT32                *StartupApSignal;
    113   volatile UINTN                 ApFunction;
    114   volatile UINTN                 ApFunctionArgument;
    115   BOOLEAN                        CpuHealthy;
    116   volatile CPU_STATE             State;
    117   CPU_VOLATILE_REGISTERS         VolatileRegisters;
    118   BOOLEAN                        Waiting;
    119   BOOLEAN                        *Finished;
    120   UINT64                         ExpectedTime;
    121   UINT64                         CurrentTime;
    122   UINT64                         TotalTime;
    123   EFI_EVENT                      WaitEvent;
    124 } CPU_AP_DATA;
    125 
    126 //
    127 // Basic CPU information saved in Guided HOB.
    128 // Because the contents will be shard between PEI and DXE,
    129 // we need to make sure the each fields offset same in different
    130 // architecture.
    131 //
    132 #pragma pack (1)
    133 typedef struct {
    134   UINT32                         InitialApicId;
    135   UINT32                         ApicId;
    136   UINT32                         Health;
    137   UINT64                         ApTopOfStack;
    138 } CPU_INFO_IN_HOB;
    139 #pragma pack ()
    140 
    141 //
    142 // AP reset code information including code address and size,
    143 // this structure will be shared be C code and assembly code.
    144 // It is natural aligned by design.
    145 //
    146 typedef struct {
    147   UINT8             *RendezvousFunnelAddress;
    148   UINTN             ModeEntryOffset;
    149   UINTN             RendezvousFunnelSize;
    150   UINT8             *RelocateApLoopFuncAddress;
    151   UINTN             RelocateApLoopFuncSize;
    152 } MP_ASSEMBLY_ADDRESS_MAP;
    153 
    154 typedef struct _CPU_MP_DATA  CPU_MP_DATA;
    155 
    156 #pragma pack(1)
    157 
    158 //
    159 // MP CPU exchange information for AP reset code
    160 // This structure is required to be packed because fixed field offsets
    161 // into this structure are used in assembly code in this module
    162 //
    163 typedef struct {
    164   UINTN                 Lock;
    165   UINTN                 StackStart;
    166   UINTN                 StackSize;
    167   UINTN                 CFunction;
    168   IA32_DESCRIPTOR       GdtrProfile;
    169   IA32_DESCRIPTOR       IdtrProfile;
    170   UINTN                 BufferStart;
    171   UINTN                 ModeOffset;
    172   UINTN                 NumApsExecuting;
    173   UINTN                 CodeSegment;
    174   UINTN                 DataSegment;
    175   UINTN                 EnableExecuteDisable;
    176   UINTN                 Cr3;
    177   UINTN                 InitFlag;
    178   CPU_INFO_IN_HOB       *CpuInfo;
    179   CPU_MP_DATA           *CpuMpData;
    180 } MP_CPU_EXCHANGE_INFO;
    181 
    182 #pragma pack()
    183 
    184 //
    185 // CPU MP Data save in memory
    186 //
    187 struct _CPU_MP_DATA {
    188   UINT64                         CpuInfoInHob;
    189   UINT32                         CpuCount;
    190   UINT32                         BspNumber;
    191   //
    192   // The above fields data will be passed from PEI to DXE
    193   // Please make sure the fields offset same in the different
    194   // architecture.
    195   //
    196   SPIN_LOCK                      MpLock;
    197   UINTN                          Buffer;
    198   UINTN                          CpuApStackSize;
    199   MP_ASSEMBLY_ADDRESS_MAP        AddressMap;
    200   UINTN                          WakeupBuffer;
    201   UINTN                          BackupBuffer;
    202   UINTN                          BackupBufferSize;
    203   BOOLEAN                        SaveRestoreFlag;
    204 
    205   volatile UINT32                StartCount;
    206   volatile UINT32                FinishedCount;
    207   volatile UINT32                RunningCount;
    208   BOOLEAN                        SingleThread;
    209   EFI_AP_PROCEDURE               Procedure;
    210   VOID                           *ProcArguments;
    211   BOOLEAN                        *Finished;
    212   UINT64                         ExpectedTime;
    213   UINT64                         CurrentTime;
    214   UINT64                         TotalTime;
    215   EFI_EVENT                      WaitEvent;
    216   UINTN                          **FailedCpuList;
    217 
    218   AP_INIT_STATE                  InitFlag;
    219   BOOLEAN                        X2ApicEnable;
    220   BOOLEAN                        SwitchBspFlag;
    221   UINTN                          NewBspNumber;
    222   CPU_EXCHANGE_ROLE_INFO         BSPInfo;
    223   CPU_EXCHANGE_ROLE_INFO         APInfo;
    224   MTRR_SETTINGS                  MtrrTable;
    225   UINT8                          ApLoopMode;
    226   UINT8                          ApTargetCState;
    227   UINT16                         PmCodeSegment;
    228   CPU_AP_DATA                    *CpuData;
    229   volatile MP_CPU_EXCHANGE_INFO  *MpCpuExchangeInfo;
    230 
    231   UINT32                         CurrentTimerCount;
    232   UINTN                          DivideValue;
    233   UINT8                          Vector;
    234   BOOLEAN                        PeriodicMode;
    235   BOOLEAN                        TimerInterruptState;
    236 };
    237 
    238 extern EFI_GUID mCpuInitMpLibHobGuid;
    239 
    240 /**
    241   Assembly code to place AP into safe loop mode.
    242 
    243   Place AP into targeted C-State if MONITOR is supported, otherwise
    244   place AP into hlt state.
    245   Place AP in protected mode if the current is long mode. Due to AP maybe
    246   wakeup by some hardware event. It could avoid accessing page table that
    247   may not available during booting to OS.
    248 
    249   @param[in] MwaitSupport    TRUE indicates MONITOR is supported.
    250                              FALSE indicates MONITOR is not supported.
    251   @param[in] ApTargetCState  Target C-State value.
    252   @param[in] PmCodeSegment   Protected mode code segment value.
    253 **/
    254 typedef
    255 VOID
    256 (EFIAPI * ASM_RELOCATE_AP_LOOP) (
    257   IN BOOLEAN                 MwaitSupport,
    258   IN UINTN                   ApTargetCState,
    259   IN UINTN                   PmCodeSegment,
    260   IN UINTN                   TopOfApStack,
    261   IN UINTN                   NumberToFinish
    262   );
    263 
    264 /**
    265   Assembly code to get starting address and size of the rendezvous entry for APs.
    266   Information for fixing a jump instruction in the code is also returned.
    267 
    268   @param[out] AddressMap  Output buffer for address map information.
    269 **/
    270 VOID
    271 EFIAPI
    272 AsmGetAddressMap (
    273   OUT MP_ASSEMBLY_ADDRESS_MAP    *AddressMap
    274   );
    275 
    276 /**
    277   This function is called by both the BSP and the AP which is to become the BSP to
    278   Exchange execution context including stack between them. After return from this
    279   function, the BSP becomes AP and the AP becomes the BSP.
    280 
    281   @param[in] MyInfo      Pointer to buffer holding the exchanging information for the executing processor.
    282   @param[in] OthersInfo  Pointer to buffer holding the exchanging information for the peer.
    283 
    284 **/
    285 VOID
    286 EFIAPI
    287 AsmExchangeRole (
    288   IN CPU_EXCHANGE_ROLE_INFO    *MyInfo,
    289   IN CPU_EXCHANGE_ROLE_INFO    *OthersInfo
    290   );
    291 
    292 /**
    293   Get the pointer to CPU MP Data structure.
    294 
    295   @return  The pointer to CPU MP Data structure.
    296 **/
    297 CPU_MP_DATA *
    298 GetCpuMpData (
    299   VOID
    300   );
    301 
    302 /**
    303   Save the pointer to CPU MP Data structure.
    304 
    305   @param[in] CpuMpData  The pointer to CPU MP Data structure will be saved.
    306 **/
    307 VOID
    308 SaveCpuMpData (
    309   IN CPU_MP_DATA   *CpuMpData
    310   );
    311 
    312 /**
    313   Allocate reset vector buffer.
    314 
    315   @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.
    316 **/
    317 VOID
    318 AllocateResetVector (
    319   IN OUT CPU_MP_DATA          *CpuMpData
    320   );
    321 
    322 /**
    323   Free AP reset vector buffer.
    324 
    325   @param[in]  CpuMpData  The pointer to CPU MP Data structure.
    326 **/
    327 VOID
    328 FreeResetVector (
    329   IN CPU_MP_DATA              *CpuMpData
    330   );
    331 
    332 /**
    333   This function will be called by BSP to wakeup AP.
    334 
    335   @param[in] CpuMpData          Pointer to CPU MP Data
    336   @param[in] Broadcast          TRUE:  Send broadcast IPI to all APs
    337                                 FALSE: Send IPI to AP by ApicId
    338   @param[in] ProcessorNumber    The handle number of specified processor
    339   @param[in] Procedure          The function to be invoked by AP
    340   @param[in] ProcedureArgument  The argument to be passed into AP function
    341 **/
    342 VOID
    343 WakeUpAP (
    344   IN CPU_MP_DATA               *CpuMpData,
    345   IN BOOLEAN                   Broadcast,
    346   IN UINTN                     ProcessorNumber,
    347   IN EFI_AP_PROCEDURE          Procedure,              OPTIONAL
    348   IN VOID                      *ProcedureArgument      OPTIONAL
    349   );
    350 
    351 /**
    352   Initialize global data for MP support.
    353 
    354   @param[in] CpuMpData  The pointer to CPU MP Data structure.
    355 **/
    356 VOID
    357 InitMpGlobalData (
    358   IN CPU_MP_DATA               *CpuMpData
    359   );
    360 
    361 /**
    362   Worker function to execute a caller provided function on all enabled APs.
    363 
    364   @param[in]  Procedure               A pointer to the function to be run on
    365                                       enabled APs of the system.
    366   @param[in]  SingleThread            If TRUE, then all the enabled APs execute
    367                                       the function specified by Procedure one by
    368                                       one, in ascending order of processor handle
    369                                       number.  If FALSE, then all the enabled APs
    370                                       execute the function specified by Procedure
    371                                       simultaneously.
    372   @param[in]  WaitEvent               The event created by the caller with CreateEvent()
    373                                       service.
    374   @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
    375                                       APs to return from Procedure, either for
    376                                       blocking or non-blocking mode.
    377   @param[in]  ProcedureArgument       The parameter passed into Procedure for
    378                                       all APs.
    379   @param[out] FailedCpuList           If all APs finish successfully, then its
    380                                       content is set to NULL. If not all APs
    381                                       finish before timeout expires, then its
    382                                       content is set to address of the buffer
    383                                       holding handle numbers of the failed APs.
    384 
    385   @retval EFI_SUCCESS             In blocking mode, all APs have finished before
    386                                   the timeout expired.
    387   @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched
    388                                   to all enabled APs.
    389   @retval others                  Failed to Startup all APs.
    390 
    391 **/
    392 EFI_STATUS
    393 StartupAllAPsWorker (
    394   IN  EFI_AP_PROCEDURE          Procedure,
    395   IN  BOOLEAN                   SingleThread,
    396   IN  EFI_EVENT                 WaitEvent               OPTIONAL,
    397   IN  UINTN                     TimeoutInMicroseconds,
    398   IN  VOID                      *ProcedureArgument      OPTIONAL,
    399   OUT UINTN                     **FailedCpuList         OPTIONAL
    400   );
    401 
    402 /**
    403   Worker function to let the caller get one enabled AP to execute a caller-provided
    404   function.
    405 
    406   @param[in]  Procedure               A pointer to the function to be run on
    407                                       enabled APs of the system.
    408   @param[in]  ProcessorNumber         The handle number of the AP.
    409   @param[in]  WaitEvent               The event created by the caller with CreateEvent()
    410                                       service.
    411   @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
    412                                       APs to return from Procedure, either for
    413                                       blocking or non-blocking mode.
    414   @param[in]  ProcedureArgument       The parameter passed into Procedure for
    415                                       all APs.
    416   @param[out] Finished                If AP returns from Procedure before the
    417                                       timeout expires, its content is set to TRUE.
    418                                       Otherwise, the value is set to FALSE.
    419 
    420   @retval EFI_SUCCESS             In blocking mode, specified AP finished before
    421                                   the timeout expires.
    422   @retval others                  Failed to Startup AP.
    423 
    424 **/
    425 EFI_STATUS
    426 StartupThisAPWorker (
    427   IN  EFI_AP_PROCEDURE          Procedure,
    428   IN  UINTN                     ProcessorNumber,
    429   IN  EFI_EVENT                 WaitEvent               OPTIONAL,
    430   IN  UINTN                     TimeoutInMicroseconds,
    431   IN  VOID                      *ProcedureArgument      OPTIONAL,
    432   OUT BOOLEAN                   *Finished               OPTIONAL
    433   );
    434 
    435 /**
    436   Worker function to switch the requested AP to be the BSP from that point onward.
    437 
    438   @param[in] ProcessorNumber   The handle number of AP that is to become the new BSP.
    439   @param[in] EnableOldBSP      If TRUE, then the old BSP will be listed as an
    440                                enabled AP. Otherwise, it will be disabled.
    441 
    442   @retval EFI_SUCCESS          BSP successfully switched.
    443   @retval others               Failed to switch BSP.
    444 
    445 **/
    446 EFI_STATUS
    447 SwitchBSPWorker (
    448   IN UINTN                     ProcessorNumber,
    449   IN BOOLEAN                   EnableOldBSP
    450   );
    451 
    452 /**
    453   Worker function to let the caller enable or disable an AP from this point onward.
    454   This service may only be called from the BSP.
    455 
    456   @param[in] ProcessorNumber   The handle number of AP.
    457   @param[in] EnableAP          Specifies the new state for the processor for
    458                                enabled, FALSE for disabled.
    459   @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
    460                                the new health status of the AP.
    461 
    462   @retval EFI_SUCCESS          The specified AP was enabled or disabled successfully.
    463   @retval others               Failed to Enable/Disable AP.
    464 
    465 **/
    466 EFI_STATUS
    467 EnableDisableApWorker (
    468   IN  UINTN                     ProcessorNumber,
    469   IN  BOOLEAN                   EnableAP,
    470   IN  UINT32                    *HealthFlag OPTIONAL
    471   );
    472 
    473 /**
    474   Get pointer to CPU MP Data structure from GUIDed HOB.
    475 
    476   @return  The pointer to CPU MP Data structure.
    477 **/
    478 CPU_MP_DATA *
    479 GetCpuMpDataFromGuidedHob (
    480   VOID
    481   );
    482 
    483 /** Checks status of specified AP.
    484 
    485   This function checks whether the specified AP has finished the task assigned
    486   by StartupThisAP(), and whether timeout expires.
    487 
    488   @param[in]  ProcessorNumber       The handle number of processor.
    489 
    490   @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().
    491   @retval EFI_TIMEOUT           The timeout expires.
    492   @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.
    493 **/
    494 EFI_STATUS
    495 CheckThisAP (
    496   IN UINTN        ProcessorNumber
    497   );
    498 
    499 /**
    500   Checks status of all APs.
    501 
    502   This function checks whether all APs have finished task assigned by StartupAllAPs(),
    503   and whether timeout expires.
    504 
    505   @retval EFI_SUCCESS           All APs have finished task assigned by StartupAllAPs().
    506   @retval EFI_TIMEOUT           The timeout expires.
    507   @retval EFI_NOT_READY         APs have not finished task and timeout has not expired.
    508 **/
    509 EFI_STATUS
    510 CheckAllAPs (
    511   VOID
    512   );
    513 
    514 /**
    515   Checks APs status and updates APs status if needed.
    516 
    517 **/
    518 VOID
    519 CheckAndUpdateApsStatus (
    520   VOID
    521   );
    522 
    523 /**
    524   Detect whether specified processor can find matching microcode patch and load it.
    525 
    526   @param[in]  CpuMpData  The pointer to CPU MP Data structure.
    527 **/
    528 VOID
    529 MicrocodeDetect (
    530   IN CPU_MP_DATA             *CpuMpData
    531   );
    532 
    533 /**
    534   Detect whether Mwait-monitor feature is supported.
    535 
    536   @retval TRUE    Mwait-monitor feature is supported.
    537   @retval FALSE   Mwait-monitor feature is not supported.
    538 **/
    539 BOOLEAN
    540 IsMwaitSupport (
    541   VOID
    542   );
    543 
    544 /**
    545   Notify function on End Of PEI PPI.
    546 
    547   On S3 boot, this function will restore wakeup buffer data.
    548   On normal boot, this function will flag wakeup buffer to be un-used type.
    549 
    550   @param[in]  PeiServices        The pointer to the PEI Services Table.
    551   @param[in]  NotifyDescriptor   Address of the notification descriptor data structure.
    552   @param[in]  Ppi                Address of the PPI that was installed.
    553 
    554   @retval EFI_SUCCESS        When everything is OK.
    555 **/
    556 EFI_STATUS
    557 EFIAPI
    558 CpuMpEndOfPeiCallback (
    559   IN EFI_PEI_SERVICES             **PeiServices,
    560   IN EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDescriptor,
    561   IN VOID                         *Ppi
    562   );
    563 
    564 /**
    565   Get available system memory below 1MB by specified size.
    566 
    567   @param[in]  CpuMpData  The pointer to CPU MP Data structure.
    568 **/
    569 VOID
    570 BackupAndPrepareWakeupBuffer(
    571   IN CPU_MP_DATA              *CpuMpData
    572   );
    573 
    574 /**
    575   Restore wakeup buffer data.
    576 
    577   @param[in]  CpuMpData  The pointer to CPU MP Data structure.
    578 **/
    579 VOID
    580 RestoreWakeupBuffer(
    581   IN CPU_MP_DATA              *CpuMpData
    582   );
    583 
    584 /**
    585   Enable Debug Agent to support source debugging on AP function.
    586 
    587 **/
    588 VOID
    589 EnableDebugAgent (
    590   VOID
    591   );
    592 
    593 #endif
    594 
    595