Home | History | Annotate | Download | only in PiSmmCpuDxeSmm
      1 /** @file
      2 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
      3 
      4 Copyright (c) 2009 - 2015, 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 _CPU_PISMMCPUDXESMM_H_
     16 #define _CPU_PISMMCPUDXESMM_H_
     17 
     18 #include <PiSmm.h>
     19 
     20 #include <Protocol/MpService.h>
     21 #include <Protocol/SmmConfiguration.h>
     22 #include <Protocol/SmmCpu.h>
     23 #include <Protocol/SmmAccess2.h>
     24 #include <Protocol/SmmReadyToLock.h>
     25 #include <Protocol/SmmCpuService.h>
     26 
     27 #include <Guid/AcpiS3Context.h>
     28 
     29 #include <Library/BaseLib.h>
     30 #include <Library/IoLib.h>
     31 #include <Library/TimerLib.h>
     32 #include <Library/SynchronizationLib.h>
     33 #include <Library/DebugLib.h>
     34 #include <Library/BaseMemoryLib.h>
     35 #include <Library/PcdLib.h>
     36 #include <Library/CacheMaintenanceLib.h>
     37 #include <Library/MtrrLib.h>
     38 #include <Library/SmmCpuPlatformHookLib.h>
     39 #include <Library/SmmServicesTableLib.h>
     40 #include <Library/MemoryAllocationLib.h>
     41 #include <Library/UefiBootServicesTableLib.h>
     42 #include <Library/UefiRuntimeServicesTableLib.h>
     43 #include <Library/DebugAgentLib.h>
     44 #include <Library/HobLib.h>
     45 #include <Library/LocalApicLib.h>
     46 #include <Library/UefiCpuLib.h>
     47 #include <Library/CpuExceptionHandlerLib.h>
     48 #include <Library/ReportStatusCodeLib.h>
     49 #include <Library/SmmCpuFeaturesLib.h>
     50 #include <Library/PeCoffGetEntryPointLib.h>
     51 
     52 #include <AcpiCpuData.h>
     53 #include <CpuHotPlugData.h>
     54 
     55 #include <Register/Cpuid.h>
     56 
     57 #include "CpuService.h"
     58 #include "SmmProfile.h"
     59 
     60 //
     61 // MSRs required for configuration of SMM Code Access Check
     62 //
     63 #define EFI_MSR_SMM_MCA_CAP                    0x17D
     64 #define  SMM_CODE_ACCESS_CHK_BIT               BIT58
     65 
     66 #define  SMM_FEATURE_CONTROL_LOCK_BIT          BIT0
     67 #define  SMM_CODE_CHK_EN_BIT                   BIT2
     68 
     69 ///
     70 /// Page Table Entry
     71 ///
     72 #define IA32_PG_P                   BIT0
     73 #define IA32_PG_RW                  BIT1
     74 #define IA32_PG_U                   BIT2
     75 #define IA32_PG_WT                  BIT3
     76 #define IA32_PG_CD                  BIT4
     77 #define IA32_PG_A                   BIT5
     78 #define IA32_PG_D                   BIT6
     79 #define IA32_PG_PS                  BIT7
     80 #define IA32_PG_PAT_2M              BIT12
     81 #define IA32_PG_PAT_4K              IA32_PG_PS
     82 #define IA32_PG_PMNT                BIT62
     83 #define IA32_PG_NX                  BIT63
     84 
     85 #define PAGE_ATTRIBUTE_BITS         (IA32_PG_RW | IA32_PG_P)
     86 //
     87 // Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
     88 // X64 PAE PDPTE does not have such restriction
     89 //
     90 #define IA32_PAE_PDPTE_ATTRIBUTE_BITS    (IA32_PG_P)
     91 
     92 //
     93 // Size of Task-State Segment defined in IA32 Manual
     94 //
     95 #define TSS_SIZE              104
     96 #define TSS_X64_IST1_OFFSET   36
     97 #define TSS_IA32_CR3_OFFSET   28
     98 #define TSS_IA32_ESP_OFFSET   56
     99 
    100 //
    101 // Code select value
    102 //
    103 #define PROTECT_MODE_CODE_SEGMENT          0x08
    104 #define LONG_MODE_CODE_SEGMENT             0x38
    105 
    106 //
    107 // The size 0x20 must be bigger than
    108 // the size of template code of SmmInit. Currently,
    109 // the size of SmmInit requires the 0x16 Bytes buffer
    110 // at least.
    111 //
    112 #define BACK_BUF_SIZE  0x20
    113 
    114 #define EXCEPTION_VECTOR_NUMBER     0x20
    115 
    116 #define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL
    117 
    118 typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
    119 #define ARRIVAL_EXCEPTION_BLOCKED           0x1
    120 #define ARRIVAL_EXCEPTION_DELAYED           0x2
    121 #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
    122 
    123 //
    124 // Private structure for the SMM CPU module that is stored in DXE Runtime memory
    125 // Contains the SMM Configuration Protocols that is produced.
    126 // Contains a mix of DXE and SMM contents.  All the fields must be used properly.
    127 //
    128 #define SMM_CPU_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('s', 'c', 'p', 'u')
    129 
    130 typedef struct {
    131   UINTN                           Signature;
    132 
    133   EFI_HANDLE                      SmmCpuHandle;
    134 
    135   EFI_PROCESSOR_INFORMATION       *ProcessorInfo;
    136   SMM_CPU_OPERATION               *Operation;
    137   UINTN                           *CpuSaveStateSize;
    138   VOID                            **CpuSaveState;
    139 
    140   EFI_SMM_RESERVED_SMRAM_REGION   SmmReservedSmramRegion[1];
    141   EFI_SMM_ENTRY_CONTEXT           SmmCoreEntryContext;
    142   EFI_SMM_ENTRY_POINT             SmmCoreEntry;
    143 
    144   EFI_SMM_CONFIGURATION_PROTOCOL  SmmConfiguration;
    145 } SMM_CPU_PRIVATE_DATA;
    146 
    147 extern SMM_CPU_PRIVATE_DATA  *gSmmCpuPrivate;
    148 extern CPU_HOT_PLUG_DATA      mCpuHotPlugData;
    149 extern UINTN                  mMaxNumberOfCpus;
    150 extern UINTN                  mNumberOfCpus;
    151 extern BOOLEAN                mRestoreSmmConfigurationInS3;
    152 extern EFI_SMM_CPU_PROTOCOL   mSmmCpu;
    153 
    154 ///
    155 /// The mode of the CPU at the time an SMI occurs
    156 ///
    157 extern UINT8  mSmmSaveStateRegisterLma;
    158 
    159 
    160 //
    161 // SMM CPU Protocol function prototypes.
    162 //
    163 
    164 /**
    165   Read information from the CPU save state.
    166 
    167   @param  This      EFI_SMM_CPU_PROTOCOL instance
    168   @param  Width     The number of bytes to read from the CPU save state.
    169   @param  Register  Specifies the CPU register to read form the save state.
    170   @param  CpuIndex  Specifies the zero-based index of the CPU save state
    171   @param  Buffer    Upon return, this holds the CPU register value read from the save state.
    172 
    173   @retval EFI_SUCCESS   The register was read from Save State
    174   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
    175   @retval EFI_INVALID_PARAMTER   This or Buffer is NULL.
    176 
    177 **/
    178 EFI_STATUS
    179 EFIAPI
    180 SmmReadSaveState (
    181   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
    182   IN UINTN                              Width,
    183   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
    184   IN UINTN                              CpuIndex,
    185   OUT VOID                              *Buffer
    186   );
    187 
    188 /**
    189   Write data to the CPU save state.
    190 
    191   @param  This      EFI_SMM_CPU_PROTOCOL instance
    192   @param  Width     The number of bytes to read from the CPU save state.
    193   @param  Register  Specifies the CPU register to write to the save state.
    194   @param  CpuIndex  Specifies the zero-based index of the CPU save state
    195   @param  Buffer    Upon entry, this holds the new CPU register value.
    196 
    197   @retval EFI_SUCCESS   The register was written from Save State
    198   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
    199   @retval EFI_INVALID_PARAMTER   ProcessorIndex or Width is not correct
    200 
    201 **/
    202 EFI_STATUS
    203 EFIAPI
    204 SmmWriteSaveState (
    205   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
    206   IN UINTN                              Width,
    207   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
    208   IN UINTN                              CpuIndex,
    209   IN CONST VOID                         *Buffer
    210   );
    211 
    212 /**
    213 Read a CPU Save State register on the target processor.
    214 
    215 This function abstracts the differences that whether the CPU Save State register is in the
    216 IA32 CPU Save State Map or X64 CPU Save State Map.
    217 
    218 This function supports reading a CPU Save State register in SMBase relocation handler.
    219 
    220 @param[in]  CpuIndex       Specifies the zero-based index of the CPU save state.
    221 @param[in]  RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
    222 @param[in]  Width          The number of bytes to read from the CPU save state.
    223 @param[out] Buffer         Upon return, this holds the CPU register value read from the save state.
    224 
    225 @retval EFI_SUCCESS           The register was read from Save State.
    226 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
    227 @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
    228 
    229 **/
    230 EFI_STATUS
    231 EFIAPI
    232 ReadSaveStateRegister (
    233   IN UINTN                        CpuIndex,
    234   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
    235   IN UINTN                        Width,
    236   OUT VOID                        *Buffer
    237   );
    238 
    239 /**
    240 Write value to a CPU Save State register on the target processor.
    241 
    242 This function abstracts the differences that whether the CPU Save State register is in the
    243 IA32 CPU Save State Map or X64 CPU Save State Map.
    244 
    245 This function supports writing a CPU Save State register in SMBase relocation handler.
    246 
    247 @param[in] CpuIndex       Specifies the zero-based index of the CPU save state.
    248 @param[in] RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
    249 @param[in] Width          The number of bytes to read from the CPU save state.
    250 @param[in] Buffer         Upon entry, this holds the new CPU register value.
    251 
    252 @retval EFI_SUCCESS           The register was written to Save State.
    253 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
    254 @retval EFI_INVALID_PARAMTER  ProcessorIndex or Width is not correct.
    255 
    256 **/
    257 EFI_STATUS
    258 EFIAPI
    259 WriteSaveStateRegister (
    260   IN UINTN                        CpuIndex,
    261   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
    262   IN UINTN                        Width,
    263   IN CONST VOID                   *Buffer
    264   );
    265 
    266 //
    267 //
    268 //
    269 typedef struct {
    270   UINT32                            Offset;
    271   UINT16                            Segment;
    272   UINT16                            Reserved;
    273 } IA32_FAR_ADDRESS;
    274 
    275 extern IA32_FAR_ADDRESS             gSmmJmpAddr;
    276 
    277 extern CONST UINT8                  gcSmmInitTemplate[];
    278 extern CONST UINT16                 gcSmmInitSize;
    279 extern UINT32                       gSmmCr0;
    280 extern UINT32                       gSmmCr3;
    281 extern UINT32                       gSmmCr4;
    282 extern UINTN                        gSmmInitStack;
    283 
    284 /**
    285   Semaphore operation for all processor relocate SMMBase.
    286 **/
    287 VOID
    288 EFIAPI
    289 SmmRelocationSemaphoreComplete (
    290   VOID
    291   );
    292 
    293 ///
    294 /// The type of SMM CPU Information
    295 ///
    296 typedef struct {
    297   SPIN_LOCK                         Busy;
    298   volatile EFI_AP_PROCEDURE         Procedure;
    299   volatile VOID                     *Parameter;
    300   volatile UINT32                   Run;
    301   volatile BOOLEAN                  Present;
    302 } SMM_CPU_DATA_BLOCK;
    303 
    304 typedef enum {
    305   SmmCpuSyncModeTradition,
    306   SmmCpuSyncModeRelaxedAp,
    307   SmmCpuSyncModeMax
    308 } SMM_CPU_SYNC_MODE;
    309 
    310 typedef struct {
    311   //
    312   // Pointer to an array. The array should be located immediately after this structure
    313   // so that UC cache-ability can be set together.
    314   //
    315   SMM_CPU_DATA_BLOCK            *CpuData;
    316   volatile UINT32               Counter;
    317   volatile UINT32               BspIndex;
    318   volatile BOOLEAN              InsideSmm;
    319   volatile BOOLEAN              AllCpusInSync;
    320   volatile SMM_CPU_SYNC_MODE    EffectiveSyncMode;
    321   volatile BOOLEAN              SwitchBsp;
    322   volatile BOOLEAN              *CandidateBsp;
    323 } SMM_DISPATCHER_MP_SYNC_DATA;
    324 
    325 typedef struct {
    326   SPIN_LOCK    SpinLock;
    327   UINT32       MsrIndex;
    328 } MP_MSR_LOCK;
    329 
    330 #define SMM_PSD_OFFSET              0xfb00
    331 
    332 typedef struct {
    333   UINT64                            Signature;              // Offset 0x00
    334   UINT16                            Reserved1;              // Offset 0x08
    335   UINT16                            Reserved2;              // Offset 0x0A
    336   UINT16                            Reserved3;              // Offset 0x0C
    337   UINT16                            SmmCs;                  // Offset 0x0E
    338   UINT16                            SmmDs;                  // Offset 0x10
    339   UINT16                            SmmSs;                  // Offset 0x12
    340   UINT16                            SmmOtherSegment;        // Offset 0x14
    341   UINT16                            Reserved4;              // Offset 0x16
    342   UINT64                            Reserved5;              // Offset 0x18
    343   UINT64                            Reserved6;              // Offset 0x20
    344   UINT64                            Reserved7;              // Offset 0x28
    345   UINT64                            SmmGdtPtr;              // Offset 0x30
    346   UINT32                            SmmGdtSize;             // Offset 0x38
    347   UINT32                            Reserved8;              // Offset 0x3C
    348   UINT64                            Reserved9;              // Offset 0x40
    349   UINT64                            Reserved10;             // Offset 0x48
    350   UINT16                            Reserved11;             // Offset 0x50
    351   UINT16                            Reserved12;             // Offset 0x52
    352   UINT32                            Reserved13;             // Offset 0x54
    353   UINT64                            MtrrBaseMaskPtr;        // Offset 0x58
    354 } PROCESSOR_SMM_DESCRIPTOR;
    355 
    356 extern IA32_DESCRIPTOR                     gcSmiGdtr;
    357 extern IA32_DESCRIPTOR                     gcSmiIdtr;
    358 extern VOID                                *gcSmiIdtrPtr;
    359 extern CONST PROCESSOR_SMM_DESCRIPTOR      gcPsd;
    360 extern UINT64                              gPhyMask;
    361 extern ACPI_CPU_DATA                       mAcpiCpuData;
    362 extern SMM_DISPATCHER_MP_SYNC_DATA         *mSmmMpSyncData;
    363 extern VOID                                *mGdtForAp;
    364 extern VOID                                *mIdtForAp;
    365 extern VOID                                *mMachineCheckHandlerForAp;
    366 extern UINTN                               mSmmStackArrayBase;
    367 extern UINTN                               mSmmStackArrayEnd;
    368 extern UINTN                               mSmmStackSize;
    369 extern EFI_SMM_CPU_SERVICE_PROTOCOL        mSmmCpuService;
    370 extern IA32_DESCRIPTOR                     gcSmiInitGdtr;
    371 
    372 /**
    373   Create 4G PageTable in SMRAM.
    374 
    375   @param          ExtraPages       Additional page numbers besides for 4G memory
    376   @param          Is32BitPageTable Whether the page table is 32-bit PAE
    377   @return         PageTable Address
    378 
    379 **/
    380 UINT32
    381 Gen4GPageTable (
    382   IN      UINTN                     ExtraPages,
    383   IN      BOOLEAN                   Is32BitPageTable
    384   );
    385 
    386 
    387 /**
    388   Initialize global data for MP synchronization.
    389 
    390   @param Stacks       Base address of SMI stack buffer for all processors.
    391   @param StackSize    Stack size for each processor in SMM.
    392 
    393 **/
    394 UINT32
    395 InitializeMpServiceData (
    396   IN VOID        *Stacks,
    397   IN UINTN       StackSize
    398   );
    399 
    400 /**
    401   Initialize Timer for SMM AP Sync.
    402 
    403 **/
    404 VOID
    405 InitializeSmmTimer (
    406   VOID
    407   );
    408 
    409 /**
    410   Start Timer for SMM AP Sync.
    411 
    412 **/
    413 UINT64
    414 EFIAPI
    415 StartSyncTimer (
    416   VOID
    417   );
    418 
    419 /**
    420   Check if the SMM AP Sync timer is timeout.
    421 
    422   @param Timer  The start timer from the begin.
    423 
    424 **/
    425 BOOLEAN
    426 EFIAPI
    427 IsSyncTimerTimeout (
    428   IN      UINT64                    Timer
    429   );
    430 
    431 /**
    432   Initialize IDT for SMM Stack Guard.
    433 
    434 **/
    435 VOID
    436 EFIAPI
    437 InitializeIDTSmmStackGuard (
    438   VOID
    439   );
    440 
    441 /**
    442   Initialize Gdt for all processors.
    443 
    444   @param[in]   Cr3          CR3 value.
    445   @param[out]  GdtStepSize  The step size for GDT table.
    446 
    447   @return GdtBase for processor 0.
    448           GdtBase for processor X is: GdtBase + (GdtStepSize * X)
    449 **/
    450 VOID *
    451 InitGdt (
    452   IN  UINTN  Cr3,
    453   OUT UINTN  *GdtStepSize
    454   );
    455 
    456 /**
    457 
    458   Register the SMM Foundation entry point.
    459 
    460   @param          This              Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
    461   @param          SmmEntryPoint     SMM Foundation EntryPoint
    462 
    463   @retval         EFI_SUCCESS       Successfully to register SMM foundation entry point
    464 
    465 **/
    466 EFI_STATUS
    467 EFIAPI
    468 RegisterSmmEntry (
    469   IN CONST EFI_SMM_CONFIGURATION_PROTOCOL  *This,
    470   IN EFI_SMM_ENTRY_POINT                   SmmEntryPoint
    471   );
    472 
    473 /**
    474   Create PageTable for SMM use.
    475 
    476   @return     PageTable Address
    477 
    478 **/
    479 UINT32
    480 SmmInitPageTable (
    481   VOID
    482   );
    483 
    484 /**
    485   Schedule a procedure to run on the specified CPU.
    486 
    487   @param   Procedure        The address of the procedure to run
    488   @param   CpuIndex         Target CPU number
    489   @param   ProcArguments    The parameter to pass to the procedure
    490 
    491   @retval   EFI_INVALID_PARAMETER    CpuNumber not valid
    492   @retval   EFI_INVALID_PARAMETER    CpuNumber specifying BSP
    493   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
    494   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
    495   @retval   EFI_SUCCESS - The procedure has been successfully scheduled
    496 
    497 **/
    498 EFI_STATUS
    499 EFIAPI
    500 SmmStartupThisAp (
    501   IN      EFI_AP_PROCEDURE          Procedure,
    502   IN      UINTN                     CpuIndex,
    503   IN OUT  VOID                      *ProcArguments OPTIONAL
    504   );
    505 
    506 /**
    507   Schedule a procedure to run on the specified CPU in a blocking fashion.
    508 
    509   @param  Procedure                The address of the procedure to run
    510   @param  CpuIndex                 Target CPU Index
    511   @param  ProcArguments            The parameter to pass to the procedure
    512 
    513   @retval EFI_INVALID_PARAMETER    CpuNumber not valid
    514   @retval EFI_INVALID_PARAMETER    CpuNumber specifying BSP
    515   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
    516   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
    517   @retval EFI_SUCCESS              The procedure has been successfully scheduled
    518 
    519 **/
    520 EFI_STATUS
    521 EFIAPI
    522 SmmBlockingStartupThisAp (
    523   IN      EFI_AP_PROCEDURE          Procedure,
    524   IN      UINTN                     CpuIndex,
    525   IN OUT  VOID                      *ProcArguments OPTIONAL
    526   );
    527 
    528 /**
    529   Initialize MP synchronization data.
    530 
    531 **/
    532 VOID
    533 EFIAPI
    534 InitializeMpSyncData (
    535   VOID
    536   );
    537 
    538 /**
    539 
    540   Find out SMRAM information including SMRR base and SMRR size.
    541 
    542   @param          SmrrBase          SMRR base
    543   @param          SmrrSize          SMRR size
    544 
    545 **/
    546 VOID
    547 FindSmramInfo (
    548   OUT UINT32   *SmrrBase,
    549   OUT UINT32   *SmrrSize
    550   );
    551 
    552 /**
    553   The function is invoked before SMBASE relocation in S3 path to restores CPU status.
    554 
    555   The function is invoked before SMBASE relocation in S3 path. It does first time microcode load
    556   and restores MTRRs for both BSP and APs.
    557 
    558 **/
    559 VOID
    560 EarlyInitializeCpu (
    561   VOID
    562   );
    563 
    564 /**
    565   The function is invoked after SMBASE relocation in S3 path to restores CPU status.
    566 
    567   The function is invoked after SMBASE relocation in S3 path. It restores configuration according to
    568   data saved by normal boot path for both BSP and APs.
    569 
    570 **/
    571 VOID
    572 InitializeCpu (
    573   VOID
    574   );
    575 
    576 /**
    577   Page Fault handler for SMM use.
    578 
    579   @param  InterruptType    Defines the type of interrupt or exception that
    580                            occurred on the processor.This parameter is processor architecture specific.
    581   @param  SystemContext    A pointer to the processor context when
    582                            the interrupt occurred on the processor.
    583 **/
    584 VOID
    585 EFIAPI
    586 SmiPFHandler (
    587     IN EFI_EXCEPTION_TYPE   InterruptType,
    588     IN EFI_SYSTEM_CONTEXT   SystemContext
    589   );
    590 
    591 /**
    592   Perform the remaining tasks.
    593 
    594 **/
    595 VOID
    596 PerformRemainingTasks (
    597   VOID
    598   );
    599 
    600 /**
    601   Perform the pre tasks.
    602 
    603 **/
    604 VOID
    605 PerformPreTasks (
    606   VOID
    607   );
    608 
    609 /**
    610   Initialize MSR spin lock by MSR index.
    611 
    612   @param  MsrIndex       MSR index value.
    613 
    614 **/
    615 VOID
    616 InitMsrSpinLockByIndex (
    617   IN UINT32      MsrIndex
    618   );
    619 
    620 /**
    621   Hook return address of SMM Save State so that semaphore code
    622   can be executed immediately after AP exits SMM to indicate to
    623   the BSP that an AP has exited SMM after SMBASE relocation.
    624 
    625   @param[in] CpuIndex     The processor index.
    626   @param[in] RebasedFlag  A pointer to a flag that is set to TRUE
    627                           immediately after AP exits SMM.
    628 
    629 **/
    630 VOID
    631 SemaphoreHook (
    632   IN UINTN             CpuIndex,
    633   IN volatile BOOLEAN  *RebasedFlag
    634   );
    635 
    636 /**
    637 Configure SMM Code Access Check feature for all processors.
    638 SMM Feature Control MSR will be locked after configuration.
    639 **/
    640 VOID
    641 ConfigSmmCodeAccessCheck (
    642   VOID
    643   );
    644 
    645 /**
    646   Hook the code executed immediately after an RSM instruction on the currently
    647   executing CPU.  The mode of code executed immediately after RSM must be
    648   detected, and the appropriate hook must be selected.  Always clear the auto
    649   HALT restart flag if it is set.
    650 
    651   @param[in] CpuIndex                 The processor index for the currently
    652                                       executing CPU.
    653   @param[in] CpuState                 Pointer to SMRAM Save State Map for the
    654                                       currently executing CPU.
    655   @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
    656                                       32-bit mode from 64-bit SMM.
    657   @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
    658                                       same mode as SMM.
    659 
    660   @retval The value of the original instruction pointer before it was hooked.
    661 
    662 **/
    663 UINT64
    664 EFIAPI
    665 HookReturnFromSmm (
    666   IN UINTN              CpuIndex,
    667   SMRAM_SAVE_STATE_MAP  *CpuState,
    668   UINT64                NewInstructionPointer32,
    669   UINT64                NewInstructionPointer
    670   );
    671 
    672 /**
    673   Get the size of the SMI Handler in bytes.
    674 
    675   @retval The size, in bytes, of the SMI Handler.
    676 
    677 **/
    678 UINTN
    679 EFIAPI
    680 GetSmiHandlerSize (
    681   VOID
    682   );
    683 
    684 /**
    685   Install the SMI handler for the CPU specified by CpuIndex.  This function
    686   is called by the CPU that was elected as monarch during System Management
    687   Mode initialization.
    688 
    689   @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
    690                         The value must be between 0 and the NumberOfCpus field
    691                         in the System Management System Table (SMST).
    692   @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
    693   @param[in] SmiStack   The stack to use when an SMI is processed by the
    694                         the CPU specified by CpuIndex.
    695   @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
    696                         processed by the CPU specified by CpuIndex.
    697   @param[in] GdtBase    The base address of the GDT to use when an SMI is
    698                         processed by the CPU specified by CpuIndex.
    699   @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
    700                         processed by the CPU specified by CpuIndex.
    701   @param[in] IdtBase    The base address of the IDT to use when an SMI is
    702                         processed by the CPU specified by CpuIndex.
    703   @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
    704                         processed by the CPU specified by CpuIndex.
    705   @param[in] Cr3        The base address of the page tables to use when an SMI
    706                         is processed by the CPU specified by CpuIndex.
    707 **/
    708 VOID
    709 EFIAPI
    710 InstallSmiHandler (
    711   IN UINTN   CpuIndex,
    712   IN UINT32  SmBase,
    713   IN VOID    *SmiStack,
    714   IN UINTN   StackSize,
    715   IN UINTN   GdtBase,
    716   IN UINTN   GdtSize,
    717   IN UINTN   IdtBase,
    718   IN UINTN   IdtSize,
    719   IN UINT32  Cr3
    720   );
    721 
    722 /**
    723   Search module name by input IP address and output it.
    724 
    725   @param CallerIpAddress   Caller instruction pointer.
    726 
    727 **/
    728 VOID
    729 DumpModuleInfoByIp (
    730   IN  UINTN              CallerIpAddress
    731   );
    732 
    733 /**
    734   This API provides a way to allocate memory for page table.
    735 
    736   This API can be called more once to allocate memory for page tables.
    737 
    738   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
    739   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
    740   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
    741   returned.
    742 
    743   @param  Pages                 The number of 4 KB pages to allocate.
    744 
    745   @return A pointer to the allocated buffer or NULL if allocation fails.
    746 
    747 **/
    748 VOID *
    749 AllocatePageTableMemory (
    750   IN UINTN           Pages
    751   );
    752 
    753 #endif
    754