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