1 /** @file
2 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
3 
4 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
6 
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #ifndef _CPU_PISMMCPUDXESMM_H_
12 #define _CPU_PISMMCPUDXESMM_H_
13 
14 #include <PiSmm.h>
15 
16 #include <Protocol/MpService.h>
17 #include <Protocol/SmmConfiguration.h>
18 #include <Protocol/SmmCpu.h>
19 #include <Protocol/SmmAccess2.h>
20 #include <Protocol/SmmReadyToLock.h>
21 #include <Protocol/SmmCpuService.h>
22 #include <Protocol/SmmMemoryAttribute.h>
23 
24 #include <Guid/AcpiS3Context.h>
25 #include <Guid/MemoryAttributesTable.h>
26 #include <Guid/PiSmmMemoryAttributesTable.h>
27 
28 #include <Library/BaseLib.h>
29 #include <Library/IoLib.h>
30 #include <Library/TimerLib.h>
31 #include <Library/SynchronizationLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/BaseMemoryLib.h>
34 #include <Library/PcdLib.h>
35 #include <Library/MtrrLib.h>
36 #include <Library/SmmCpuPlatformHookLib.h>
37 #include <Library/SmmServicesTableLib.h>
38 #include <Library/MemoryAllocationLib.h>
39 #include <Library/UefiBootServicesTableLib.h>
40 #include <Library/UefiRuntimeServicesTableLib.h>
41 #include <Library/DebugAgentLib.h>
42 #include <Library/UefiLib.h>
43 #include <Library/HobLib.h>
44 #include <Library/LocalApicLib.h>
45 #include <Library/UefiCpuLib.h>
46 #include <Library/CpuExceptionHandlerLib.h>
47 #include <Library/ReportStatusCodeLib.h>
48 #include <Library/SmmCpuFeaturesLib.h>
49 #include <Library/PeCoffGetEntryPointLib.h>
50 #include <Library/RegisterCpuFeaturesLib.h>
51 
52 #include <AcpiCpuData.h>
53 #include <CpuHotPlugData.h>
54 
55 #include <Register/Cpuid.h>
56 #include <Register/Msr.h>
57 
58 #include "CpuService.h"
59 #include "SmmProfile.h"
60 
61 //
62 // CET definition
63 //
64 #define CPUID_CET_SS   BIT7
65 #define CPUID_CET_IBT  BIT20
66 
67 #define CR4_CET_ENABLE  BIT23
68 
69 #define MSR_IA32_S_CET                     0x6A2
70 #define MSR_IA32_PL0_SSP                   0x6A4
71 #define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR  0x6A8
72 
73 typedef union {
74   struct {
75     // enable shadow stacks
76     UINT32  SH_STK_ENP:1;
77     // enable the WRSS{D,Q}W instructions.
78     UINT32  WR_SHSTK_EN:1;
79     // enable tracking of indirect call/jmp targets to be ENDBRANCH instruction.
80     UINT32  ENDBR_EN:1;
81     // enable legacy compatibility treatment for indirect call/jmp tracking.
82     UINT32  LEG_IW_EN:1;
83     // enable use of no-track prefix on indirect call/jmp.
84     UINT32  NO_TRACK_EN:1;
85     // disable suppression of CET indirect branch tracking on legacy compatibility.
86     UINT32  SUPPRESS_DIS:1;
87     UINT32  RSVD:4;
88     // indirect branch tracking is suppressed.
89     // This bit can be written to 1 only if TRACKER is written as IDLE.
90     UINT32  SUPPRESS:1;
91     // Value of the endbranch state machine
92     // Values: IDLE (0), WAIT_FOR_ENDBRANCH(1).
93     UINT32  TRACKER:1;
94     // linear address of a bitmap in memory indicating valid
95     // pages as target of CALL/JMP_indirect that do not land on ENDBRANCH when CET is enabled
96     // and not suppressed. Valid when ENDBR_EN is 1. Must be machine canonical when written on
97     // parts that support 64 bit mode. On parts that do not support 64 bit mode, the bits 63:32 are
98     // reserved and must be 0. This value is extended by 12 bits at the low end to form the base address
99     // (this automatically aligns the address on a 4-Kbyte boundary).
100     UINT32  EB_LEG_BITMAP_BASE_low:12;
101     UINT32  EB_LEG_BITMAP_BASE_high:32;
102   } Bits;
103   UINT64   Uint64;
104 } MSR_IA32_CET;
105 
106 //
107 // MSRs required for configuration of SMM Code Access Check
108 //
109 #define EFI_MSR_SMM_MCA_CAP                    0x17D
110 #define  SMM_CODE_ACCESS_CHK_BIT               BIT58
111 
112 #define  SMM_FEATURE_CONTROL_LOCK_BIT          BIT0
113 #define  SMM_CODE_CHK_EN_BIT                   BIT2
114 
115 ///
116 /// Page Table Entry
117 ///
118 #define IA32_PG_P                   BIT0
119 #define IA32_PG_RW                  BIT1
120 #define IA32_PG_U                   BIT2
121 #define IA32_PG_WT                  BIT3
122 #define IA32_PG_CD                  BIT4
123 #define IA32_PG_A                   BIT5
124 #define IA32_PG_D                   BIT6
125 #define IA32_PG_PS                  BIT7
126 #define IA32_PG_PAT_2M              BIT12
127 #define IA32_PG_PAT_4K              IA32_PG_PS
128 #define IA32_PG_PMNT                BIT62
129 #define IA32_PG_NX                  BIT63
130 
131 #define PAGE_ATTRIBUTE_BITS         (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
132 //
133 // Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
134 // X64 PAE PDPTE does not have such restriction
135 //
136 #define IA32_PAE_PDPTE_ATTRIBUTE_BITS    (IA32_PG_P)
137 
138 #define PAGE_PROGATE_BITS           (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)
139 
140 #define PAGING_4K_MASK  0xFFF
141 #define PAGING_2M_MASK  0x1FFFFF
142 #define PAGING_1G_MASK  0x3FFFFFFF
143 
144 #define PAGING_PAE_INDEX_MASK  0x1FF
145 
146 #define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
147 #define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
148 #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
149 
150 #define SMRR_MAX_ADDRESS       BASE_4GB
151 
152 typedef enum {
153   PageNone,
154   Page4K,
155   Page2M,
156   Page1G,
157 } PAGE_ATTRIBUTE;
158 
159 typedef struct {
160   PAGE_ATTRIBUTE   Attribute;
161   UINT64           Length;
162   UINT64           AddressMask;
163 } PAGE_ATTRIBUTE_TABLE;
164 
165 //
166 // Size of Task-State Segment defined in IA32 Manual
167 //
168 #define TSS_SIZE              104
169 #define EXCEPTION_TSS_SIZE    (TSS_SIZE + 4) // Add 4 bytes SSP
170 #define TSS_X64_IST1_OFFSET   36
171 #define TSS_IA32_CR3_OFFSET   28
172 #define TSS_IA32_ESP_OFFSET   56
173 #define TSS_IA32_SSP_OFFSET   104
174 
175 #define CR0_WP                BIT16
176 
177 //
178 // Code select value
179 //
180 #define PROTECT_MODE_CODE_SEGMENT          0x08
181 #define LONG_MODE_CODE_SEGMENT             0x38
182 
183 //
184 // The size 0x20 must be bigger than
185 // the size of template code of SmmInit. Currently,
186 // the size of SmmInit requires the 0x16 Bytes buffer
187 // at least.
188 //
189 #define BACK_BUF_SIZE  0x20
190 
191 #define EXCEPTION_VECTOR_NUMBER     0x20
192 
193 #define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL
194 
195 typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
196 #define ARRIVAL_EXCEPTION_BLOCKED           0x1
197 #define ARRIVAL_EXCEPTION_DELAYED           0x2
198 #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
199 
200 //
201 // Private structure for the SMM CPU module that is stored in DXE Runtime memory
202 // Contains the SMM Configuration Protocols that is produced.
203 // Contains a mix of DXE and SMM contents.  All the fields must be used properly.
204 //
205 #define SMM_CPU_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('s', 'c', 'p', 'u')
206 
207 typedef struct {
208   UINTN                           Signature;
209 
210   EFI_HANDLE                      SmmCpuHandle;
211 
212   EFI_PROCESSOR_INFORMATION       *ProcessorInfo;
213   SMM_CPU_OPERATION               *Operation;
214   UINTN                           *CpuSaveStateSize;
215   VOID                            **CpuSaveState;
216 
217   EFI_SMM_RESERVED_SMRAM_REGION   SmmReservedSmramRegion[1];
218   EFI_SMM_ENTRY_CONTEXT           SmmCoreEntryContext;
219   EFI_SMM_ENTRY_POINT             SmmCoreEntry;
220 
221   EFI_SMM_CONFIGURATION_PROTOCOL  SmmConfiguration;
222 } SMM_CPU_PRIVATE_DATA;
223 
224 extern SMM_CPU_PRIVATE_DATA  *gSmmCpuPrivate;
225 extern CPU_HOT_PLUG_DATA      mCpuHotPlugData;
226 extern UINTN                  mMaxNumberOfCpus;
227 extern UINTN                  mNumberOfCpus;
228 extern EFI_SMM_CPU_PROTOCOL   mSmmCpu;
229 
230 ///
231 /// The mode of the CPU at the time an SMI occurs
232 ///
233 extern UINT8  mSmmSaveStateRegisterLma;
234 
235 //
236 // SMM CPU Protocol function prototypes.
237 //
238 
239 /**
240   Read information from the CPU save state.
241 
242   @param  This      EFI_SMM_CPU_PROTOCOL instance
243   @param  Width     The number of bytes to read from the CPU save state.
244   @param  Register  Specifies the CPU register to read form the save state.
245   @param  CpuIndex  Specifies the zero-based index of the CPU save state
246   @param  Buffer    Upon return, this holds the CPU register value read from the save state.
247 
248   @retval EFI_SUCCESS   The register was read from Save State
249   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
250   @retval EFI_INVALID_PARAMTER   This or Buffer is NULL.
251 
252 **/
253 EFI_STATUS
254 EFIAPI
255 SmmReadSaveState (
256   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
257   IN UINTN                              Width,
258   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
259   IN UINTN                              CpuIndex,
260   OUT VOID                              *Buffer
261   );
262 
263 /**
264   Write data to the CPU save state.
265 
266   @param  This      EFI_SMM_CPU_PROTOCOL instance
267   @param  Width     The number of bytes to read from the CPU save state.
268   @param  Register  Specifies the CPU register to write to the save state.
269   @param  CpuIndex  Specifies the zero-based index of the CPU save state
270   @param  Buffer    Upon entry, this holds the new CPU register value.
271 
272   @retval EFI_SUCCESS   The register was written from Save State
273   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
274   @retval EFI_INVALID_PARAMTER   ProcessorIndex or Width is not correct
275 
276 **/
277 EFI_STATUS
278 EFIAPI
279 SmmWriteSaveState (
280   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
281   IN UINTN                              Width,
282   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
283   IN UINTN                              CpuIndex,
284   IN CONST VOID                         *Buffer
285   );
286 
287 /**
288 Read a CPU Save State register on the target processor.
289 
290 This function abstracts the differences that whether the CPU Save State register is in the
291 IA32 CPU Save State Map or X64 CPU Save State Map.
292 
293 This function supports reading a CPU Save State register in SMBase relocation handler.
294 
295 @param[in]  CpuIndex       Specifies the zero-based index of the CPU save state.
296 @param[in]  RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
297 @param[in]  Width          The number of bytes to read from the CPU save state.
298 @param[out] Buffer         Upon return, this holds the CPU register value read from the save state.
299 
300 @retval EFI_SUCCESS           The register was read from Save State.
301 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
302 @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
303 
304 **/
305 EFI_STATUS
306 EFIAPI
307 ReadSaveStateRegister (
308   IN UINTN                        CpuIndex,
309   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
310   IN UINTN                        Width,
311   OUT VOID                        *Buffer
312   );
313 
314 /**
315 Write value to a CPU Save State register on the target processor.
316 
317 This function abstracts the differences that whether the CPU Save State register is in the
318 IA32 CPU Save State Map or X64 CPU Save State Map.
319 
320 This function supports writing a CPU Save State register in SMBase relocation handler.
321 
322 @param[in] CpuIndex       Specifies the zero-based index of the CPU save state.
323 @param[in] RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
324 @param[in] Width          The number of bytes to read from the CPU save state.
325 @param[in] Buffer         Upon entry, this holds the new CPU register value.
326 
327 @retval EFI_SUCCESS           The register was written to Save State.
328 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
329 @retval EFI_INVALID_PARAMTER  ProcessorIndex or Width is not correct.
330 
331 **/
332 EFI_STATUS
333 EFIAPI
334 WriteSaveStateRegister (
335   IN UINTN                        CpuIndex,
336   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
337   IN UINTN                        Width,
338   IN CONST VOID                   *Buffer
339   );
340 
341 extern CONST UINT8                  gcSmmInitTemplate[];
342 extern CONST UINT16                 gcSmmInitSize;
343 X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr0;
344 extern UINT32                       mSmmCr0;
345 X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr3;
346 extern UINT32                       mSmmCr4;
347 X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr4;
348 X86_ASSEMBLY_PATCH_LABEL            gPatchSmmInitStack;
349 X86_ASSEMBLY_PATCH_LABEL            mPatchCetSupported;
350 extern BOOLEAN                      mCetSupported;
351 
352 /**
353   Semaphore operation for all processor relocate SMMBase.
354 **/
355 VOID
356 EFIAPI
357 SmmRelocationSemaphoreComplete (
358   VOID
359   );
360 
361 ///
362 /// The type of SMM CPU Information
363 ///
364 typedef struct {
365   SPIN_LOCK                         *Busy;
366   volatile EFI_AP_PROCEDURE         Procedure;
367   volatile VOID                     *Parameter;
368   volatile UINT32                   *Run;
369   volatile BOOLEAN                  *Present;
370 } SMM_CPU_DATA_BLOCK;
371 
372 typedef enum {
373   SmmCpuSyncModeTradition,
374   SmmCpuSyncModeRelaxedAp,
375   SmmCpuSyncModeMax
376 } SMM_CPU_SYNC_MODE;
377 
378 typedef struct {
379   //
380   // Pointer to an array. The array should be located immediately after this structure
381   // so that UC cache-ability can be set together.
382   //
383   SMM_CPU_DATA_BLOCK            *CpuData;
384   volatile UINT32               *Counter;
385   volatile UINT32               BspIndex;
386   volatile BOOLEAN              *InsideSmm;
387   volatile BOOLEAN              *AllCpusInSync;
388   volatile SMM_CPU_SYNC_MODE    EffectiveSyncMode;
389   volatile BOOLEAN              SwitchBsp;
390   volatile BOOLEAN              *CandidateBsp;
391 } SMM_DISPATCHER_MP_SYNC_DATA;
392 
393 #define SMM_PSD_OFFSET              0xfb00
394 
395 ///
396 /// All global semaphores' pointer
397 ///
398 typedef struct {
399   volatile UINT32      *Counter;
400   volatile BOOLEAN     *InsideSmm;
401   volatile BOOLEAN     *AllCpusInSync;
402   SPIN_LOCK            *PFLock;
403   SPIN_LOCK            *CodeAccessCheckLock;
404 } SMM_CPU_SEMAPHORE_GLOBAL;
405 
406 ///
407 /// All semaphores for each processor
408 ///
409 typedef struct {
410   SPIN_LOCK                         *Busy;
411   volatile UINT32                   *Run;
412   volatile BOOLEAN                  *Present;
413 } SMM_CPU_SEMAPHORE_CPU;
414 
415 ///
416 /// All semaphores' information
417 ///
418 typedef struct {
419   SMM_CPU_SEMAPHORE_GLOBAL          SemaphoreGlobal;
420   SMM_CPU_SEMAPHORE_CPU             SemaphoreCpu;
421 } SMM_CPU_SEMAPHORES;
422 
423 extern IA32_DESCRIPTOR                     gcSmiGdtr;
424 extern EFI_PHYSICAL_ADDRESS                mGdtBuffer;
425 extern UINTN                               mGdtBufferSize;
426 extern IA32_DESCRIPTOR                     gcSmiIdtr;
427 extern VOID                                *gcSmiIdtrPtr;
428 extern UINT64                              gPhyMask;
429 extern SMM_DISPATCHER_MP_SYNC_DATA         *mSmmMpSyncData;
430 extern UINTN                               mSmmStackArrayBase;
431 extern UINTN                               mSmmStackArrayEnd;
432 extern UINTN                               mSmmStackSize;
433 extern EFI_SMM_CPU_SERVICE_PROTOCOL        mSmmCpuService;
434 extern IA32_DESCRIPTOR                     gcSmiInitGdtr;
435 extern SMM_CPU_SEMAPHORES                  mSmmCpuSemaphores;
436 extern UINTN                               mSemaphoreSize;
437 extern SPIN_LOCK                           *mPFLock;
438 extern SPIN_LOCK                           *mConfigSmmCodeAccessCheckLock;
439 extern EFI_SMRAM_DESCRIPTOR                *mSmmCpuSmramRanges;
440 extern UINTN                               mSmmCpuSmramRangeCount;
441 extern UINT8                               mPhysicalAddressBits;
442 
443 //
444 // Copy of the PcdPteMemoryEncryptionAddressOrMask
445 //
446 extern UINT64  mAddressEncMask;
447 
448 /**
449   Create 4G PageTable in SMRAM.
450 
451   @param[in]      Is32BitPageTable Whether the page table is 32-bit PAE
452   @return         PageTable Address
453 
454 **/
455 UINT32
456 Gen4GPageTable (
457   IN      BOOLEAN                   Is32BitPageTable
458   );
459 
460 
461 /**
462   Initialize global data for MP synchronization.
463 
464   @param Stacks             Base address of SMI stack buffer for all processors.
465   @param StackSize          Stack size for each processor in SMM.
466   @param ShadowStackSize    Shadow Stack size for each processor in SMM.
467 
468 **/
469 UINT32
470 InitializeMpServiceData (
471   IN VOID        *Stacks,
472   IN UINTN       StackSize,
473   IN UINTN       ShadowStackSize
474   );
475 
476 /**
477   Initialize Timer for SMM AP Sync.
478 
479 **/
480 VOID
481 InitializeSmmTimer (
482   VOID
483   );
484 
485 /**
486   Start Timer for SMM AP Sync.
487 
488 **/
489 UINT64
490 EFIAPI
491 StartSyncTimer (
492   VOID
493   );
494 
495 /**
496   Check if the SMM AP Sync timer is timeout.
497 
498   @param Timer  The start timer from the begin.
499 
500 **/
501 BOOLEAN
502 EFIAPI
503 IsSyncTimerTimeout (
504   IN      UINT64                    Timer
505   );
506 
507 /**
508   Initialize IDT for SMM Stack Guard.
509 
510 **/
511 VOID
512 EFIAPI
513 InitializeIDTSmmStackGuard (
514   VOID
515   );
516 
517 /**
518   Initialize Gdt for all processors.
519 
520   @param[in]   Cr3          CR3 value.
521   @param[out]  GdtStepSize  The step size for GDT table.
522 
523   @return GdtBase for processor 0.
524           GdtBase for processor X is: GdtBase + (GdtStepSize * X)
525 **/
526 VOID *
527 InitGdt (
528   IN  UINTN  Cr3,
529   OUT UINTN  *GdtStepSize
530   );
531 
532 /**
533 
534   Register the SMM Foundation entry point.
535 
536   @param          This              Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
537   @param          SmmEntryPoint     SMM Foundation EntryPoint
538 
539   @retval         EFI_SUCCESS       Successfully to register SMM foundation entry point
540 
541 **/
542 EFI_STATUS
543 EFIAPI
544 RegisterSmmEntry (
545   IN CONST EFI_SMM_CONFIGURATION_PROTOCOL  *This,
546   IN EFI_SMM_ENTRY_POINT                   SmmEntryPoint
547   );
548 
549 /**
550   Create PageTable for SMM use.
551 
552   @return     PageTable Address
553 
554 **/
555 UINT32
556 SmmInitPageTable (
557   VOID
558   );
559 
560 /**
561   Schedule a procedure to run on the specified CPU.
562 
563   @param   Procedure        The address of the procedure to run
564   @param   CpuIndex         Target CPU number
565   @param   ProcArguments    The parameter to pass to the procedure
566 
567   @retval   EFI_INVALID_PARAMETER    CpuNumber not valid
568   @retval   EFI_INVALID_PARAMETER    CpuNumber specifying BSP
569   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
570   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
571   @retval   EFI_SUCCESS - The procedure has been successfully scheduled
572 
573 **/
574 EFI_STATUS
575 EFIAPI
576 SmmStartupThisAp (
577   IN      EFI_AP_PROCEDURE          Procedure,
578   IN      UINTN                     CpuIndex,
579   IN OUT  VOID                      *ProcArguments OPTIONAL
580   );
581 
582 /**
583   Schedule a procedure to run on the specified CPU in a blocking fashion.
584 
585   @param  Procedure                The address of the procedure to run
586   @param  CpuIndex                 Target CPU Index
587   @param  ProcArguments            The parameter to pass to the procedure
588 
589   @retval EFI_INVALID_PARAMETER    CpuNumber not valid
590   @retval EFI_INVALID_PARAMETER    CpuNumber specifying BSP
591   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
592   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
593   @retval EFI_SUCCESS              The procedure has been successfully scheduled
594 
595 **/
596 EFI_STATUS
597 EFIAPI
598 SmmBlockingStartupThisAp (
599   IN      EFI_AP_PROCEDURE          Procedure,
600   IN      UINTN                     CpuIndex,
601   IN OUT  VOID                      *ProcArguments OPTIONAL
602   );
603 
604 /**
605   This function sets the attributes for the memory region specified by BaseAddress and
606   Length from their current attributes to the attributes specified by Attributes.
607 
608   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
609   @param[in]  Length           The size in bytes of the memory region.
610   @param[in]  Attributes       The bit mask of attributes to set for the memory region.
611 
612   @retval EFI_SUCCESS           The attributes were set for the memory region.
613   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
614                                 BaseAddress and Length cannot be modified.
615   @retval EFI_INVALID_PARAMETER Length is zero.
616                                 Attributes specified an illegal combination of attributes that
617                                 cannot be set together.
618   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
619                                 the memory resource range.
620   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
621                                 resource range specified by BaseAddress and Length.
622                                 The bit mask of attributes is not support for the memory resource
623                                 range specified by BaseAddress and Length.
624 
625 **/
626 EFI_STATUS
627 EFIAPI
628 SmmSetMemoryAttributes (
629   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
630   IN  UINT64                                     Length,
631   IN  UINT64                                     Attributes
632   );
633 
634 /**
635   This function clears the attributes for the memory region specified by BaseAddress and
636   Length from their current attributes to the attributes specified by Attributes.
637 
638   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
639   @param[in]  Length           The size in bytes of the memory region.
640   @param[in]  Attributes       The bit mask of attributes to clear for the memory region.
641 
642   @retval EFI_SUCCESS           The attributes were cleared for the memory region.
643   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
644                                 BaseAddress and Length cannot be modified.
645   @retval EFI_INVALID_PARAMETER Length is zero.
646                                 Attributes specified an illegal combination of attributes that
647                                 cannot be set together.
648   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
649                                 the memory resource range.
650   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
651                                 resource range specified by BaseAddress and Length.
652                                 The bit mask of attributes is not support for the memory resource
653                                 range specified by BaseAddress and Length.
654 
655 **/
656 EFI_STATUS
657 EFIAPI
658 SmmClearMemoryAttributes (
659   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
660   IN  UINT64                                     Length,
661   IN  UINT64                                     Attributes
662   );
663 
664 /**
665   Initialize MP synchronization data.
666 
667 **/
668 VOID
669 EFIAPI
670 InitializeMpSyncData (
671   VOID
672   );
673 
674 /**
675 
676   Find out SMRAM information including SMRR base and SMRR size.
677 
678   @param          SmrrBase          SMRR base
679   @param          SmrrSize          SMRR size
680 
681 **/
682 VOID
683 FindSmramInfo (
684   OUT UINT32   *SmrrBase,
685   OUT UINT32   *SmrrSize
686   );
687 
688 /**
689   Relocate SmmBases for each processor.
690 
691   Execute on first boot and all S3 resumes
692 
693 **/
694 VOID
695 EFIAPI
696 SmmRelocateBases (
697   VOID
698   );
699 
700 /**
701   Page Fault handler for SMM use.
702 
703   @param  InterruptType    Defines the type of interrupt or exception that
704                            occurred on the processor.This parameter is processor architecture specific.
705   @param  SystemContext    A pointer to the processor context when
706                            the interrupt occurred on the processor.
707 **/
708 VOID
709 EFIAPI
710 SmiPFHandler (
711   IN EFI_EXCEPTION_TYPE   InterruptType,
712   IN EFI_SYSTEM_CONTEXT   SystemContext
713   );
714 
715 /**
716   Perform the remaining tasks.
717 
718 **/
719 VOID
720 PerformRemainingTasks (
721   VOID
722   );
723 
724 /**
725   Perform the pre tasks.
726 
727 **/
728 VOID
729 PerformPreTasks (
730   VOID
731   );
732 
733 /**
734   Initialize MSR spin lock by MSR index.
735 
736   @param  MsrIndex       MSR index value.
737 
738 **/
739 VOID
740 InitMsrSpinLockByIndex (
741   IN UINT32      MsrIndex
742   );
743 
744 /**
745   Hook return address of SMM Save State so that semaphore code
746   can be executed immediately after AP exits SMM to indicate to
747   the BSP that an AP has exited SMM after SMBASE relocation.
748 
749   @param[in] CpuIndex     The processor index.
750   @param[in] RebasedFlag  A pointer to a flag that is set to TRUE
751                           immediately after AP exits SMM.
752 
753 **/
754 VOID
755 SemaphoreHook (
756   IN UINTN             CpuIndex,
757   IN volatile BOOLEAN  *RebasedFlag
758   );
759 
760 /**
761 Configure SMM Code Access Check feature for all processors.
762 SMM Feature Control MSR will be locked after configuration.
763 **/
764 VOID
765 ConfigSmmCodeAccessCheck (
766   VOID
767   );
768 
769 /**
770   Hook the code executed immediately after an RSM instruction on the currently
771   executing CPU.  The mode of code executed immediately after RSM must be
772   detected, and the appropriate hook must be selected.  Always clear the auto
773   HALT restart flag if it is set.
774 
775   @param[in] CpuIndex                 The processor index for the currently
776                                       executing CPU.
777   @param[in] CpuState                 Pointer to SMRAM Save State Map for the
778                                       currently executing CPU.
779   @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
780                                       32-bit mode from 64-bit SMM.
781   @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
782                                       same mode as SMM.
783 
784   @retval The value of the original instruction pointer before it was hooked.
785 
786 **/
787 UINT64
788 EFIAPI
789 HookReturnFromSmm (
790   IN UINTN              CpuIndex,
791   SMRAM_SAVE_STATE_MAP  *CpuState,
792   UINT64                NewInstructionPointer32,
793   UINT64                NewInstructionPointer
794   );
795 
796 /**
797   Get the size of the SMI Handler in bytes.
798 
799   @retval The size, in bytes, of the SMI Handler.
800 
801 **/
802 UINTN
803 EFIAPI
804 GetSmiHandlerSize (
805   VOID
806   );
807 
808 /**
809   Install the SMI handler for the CPU specified by CpuIndex.  This function
810   is called by the CPU that was elected as monarch during System Management
811   Mode initialization.
812 
813   @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
814                         The value must be between 0 and the NumberOfCpus field
815                         in the System Management System Table (SMST).
816   @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
817   @param[in] SmiStack   The stack to use when an SMI is processed by the
818                         the CPU specified by CpuIndex.
819   @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
820                         processed by the CPU specified by CpuIndex.
821   @param[in] GdtBase    The base address of the GDT to use when an SMI is
822                         processed by the CPU specified by CpuIndex.
823   @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
824                         processed by the CPU specified by CpuIndex.
825   @param[in] IdtBase    The base address of the IDT to use when an SMI is
826                         processed by the CPU specified by CpuIndex.
827   @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
828                         processed by the CPU specified by CpuIndex.
829   @param[in] Cr3        The base address of the page tables to use when an SMI
830                         is processed by the CPU specified by CpuIndex.
831 **/
832 VOID
833 EFIAPI
834 InstallSmiHandler (
835   IN UINTN   CpuIndex,
836   IN UINT32  SmBase,
837   IN VOID    *SmiStack,
838   IN UINTN   StackSize,
839   IN UINTN   GdtBase,
840   IN UINTN   GdtSize,
841   IN UINTN   IdtBase,
842   IN UINTN   IdtSize,
843   IN UINT32  Cr3
844   );
845 
846 /**
847   Search module name by input IP address and output it.
848 
849   @param CallerIpAddress   Caller instruction pointer.
850 
851 **/
852 VOID
853 DumpModuleInfoByIp (
854   IN  UINTN              CallerIpAddress
855   );
856 
857 /**
858   This function sets memory attribute according to MemoryAttributesTable.
859 **/
860 VOID
861 SetMemMapAttributes (
862   VOID
863   );
864 
865 /**
866   This function sets UEFI memory attribute according to UEFI memory map.
867 **/
868 VOID
869 SetUefiMemMapAttributes (
870   VOID
871   );
872 
873 /**
874   Return if the Address is forbidden as SMM communication buffer.
875 
876   @param[in] Address the address to be checked
877 
878   @return TRUE  The address is forbidden as SMM communication buffer.
879   @return FALSE The address is allowed as SMM communication buffer.
880 **/
881 BOOLEAN
882 IsSmmCommBufferForbiddenAddress (
883   IN UINT64  Address
884   );
885 
886 /**
887   This function caches the UEFI memory map information.
888 **/
889 VOID
890 GetUefiMemoryMap (
891   VOID
892   );
893 
894 /**
895   This function sets memory attribute for page table.
896 **/
897 VOID
898 SetPageTableAttributes (
899   VOID
900   );
901 
902 /**
903   Return page table base.
904 
905   @return page table base.
906 **/
907 UINTN
908 GetPageTableBase (
909   VOID
910   );
911 
912 /**
913   This function sets the attributes for the memory region specified by BaseAddress and
914   Length from their current attributes to the attributes specified by Attributes.
915 
916   @param[in]   BaseAddress      The physical address that is the start address of a memory region.
917   @param[in]   Length           The size in bytes of the memory region.
918   @param[in]   Attributes       The bit mask of attributes to set for the memory region.
919   @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.
920 
921   @retval EFI_SUCCESS           The attributes were set for the memory region.
922   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
923                                 BaseAddress and Length cannot be modified.
924   @retval EFI_INVALID_PARAMETER Length is zero.
925                                 Attributes specified an illegal combination of attributes that
926                                 cannot be set together.
927   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
928                                 the memory resource range.
929   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
930                                 resource range specified by BaseAddress and Length.
931                                 The bit mask of attributes is not support for the memory resource
932                                 range specified by BaseAddress and Length.
933 
934 **/
935 EFI_STATUS
936 EFIAPI
937 SmmSetMemoryAttributesEx (
938   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
939   IN  UINT64                                     Length,
940   IN  UINT64                                     Attributes,
941   OUT BOOLEAN                                    *IsSplitted  OPTIONAL
942   );
943 
944 /**
945   This function clears the attributes for the memory region specified by BaseAddress and
946   Length from their current attributes to the attributes specified by Attributes.
947 
948   @param[in]   BaseAddress      The physical address that is the start address of a memory region.
949   @param[in]   Length           The size in bytes of the memory region.
950   @param[in]   Attributes       The bit mask of attributes to clear for the memory region.
951   @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.
952 
953   @retval EFI_SUCCESS           The attributes were cleared for the memory region.
954   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
955                                 BaseAddress and Length cannot be modified.
956   @retval EFI_INVALID_PARAMETER Length is zero.
957                                 Attributes specified an illegal combination of attributes that
958                                 cannot be set together.
959   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
960                                 the memory resource range.
961   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
962                                 resource range specified by BaseAddress and Length.
963                                 The bit mask of attributes is not support for the memory resource
964                                 range specified by BaseAddress and Length.
965 
966 **/
967 EFI_STATUS
968 EFIAPI
969 SmmClearMemoryAttributesEx (
970   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
971   IN  UINT64                                     Length,
972   IN  UINT64                                     Attributes,
973   OUT BOOLEAN                                    *IsSplitted  OPTIONAL
974   );
975 
976 /**
977   This API provides a way to allocate memory for page table.
978 
979   This API can be called more once to allocate memory for page tables.
980 
981   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
982   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
983   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
984   returned.
985 
986   @param  Pages                 The number of 4 KB pages to allocate.
987 
988   @return A pointer to the allocated buffer or NULL if allocation fails.
989 
990 **/
991 VOID *
992 AllocatePageTableMemory (
993   IN UINTN           Pages
994   );
995 
996 /**
997   Allocate pages for code.
998 
999   @param[in]  Pages Number of pages to be allocated.
1000 
1001   @return Allocated memory.
1002 **/
1003 VOID *
1004 AllocateCodePages (
1005   IN UINTN           Pages
1006   );
1007 
1008 /**
1009   Allocate aligned pages for code.
1010 
1011   @param[in]  Pages                 Number of pages to be allocated.
1012   @param[in]  Alignment             The requested alignment of the allocation.
1013                                     Must be a power of two.
1014                                     If Alignment is zero, then byte alignment is used.
1015 
1016   @return Allocated memory.
1017 **/
1018 VOID *
1019 AllocateAlignedCodePages (
1020   IN UINTN            Pages,
1021   IN UINTN            Alignment
1022   );
1023 
1024 
1025 //
1026 // S3 related global variable and function prototype.
1027 //
1028 
1029 extern BOOLEAN                mSmmS3Flag;
1030 
1031 /**
1032   Initialize SMM S3 resume state structure used during S3 Resume.
1033 
1034   @param[in] Cr3    The base address of the page tables to use in SMM.
1035 
1036 **/
1037 VOID
1038 InitSmmS3ResumeState (
1039   IN UINT32  Cr3
1040   );
1041 
1042 /**
1043   Get ACPI CPU data.
1044 
1045 **/
1046 VOID
1047 GetAcpiCpuData (
1048   VOID
1049   );
1050 
1051 /**
1052   Restore SMM Configuration in S3 boot path.
1053 
1054 **/
1055 VOID
1056 RestoreSmmConfigurationInS3 (
1057   VOID
1058   );
1059 
1060 /**
1061   Get ACPI S3 enable flag.
1062 
1063 **/
1064 VOID
1065 GetAcpiS3EnableFlag (
1066   VOID
1067   );
1068 
1069 /**
1070   Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
1071 
1072   @param[in] ApHltLoopCode          The address of the safe hlt-loop function.
1073   @param[in] TopOfStack             A pointer to the new stack to use for the ApHltLoopCode.
1074   @param[in] NumberToFinishAddress  Address of Semaphore of APs finish count.
1075 
1076 **/
1077 VOID
1078 TransferApToSafeState (
1079   IN UINTN  ApHltLoopCode,
1080   IN UINTN  TopOfStack,
1081   IN UINTN  NumberToFinishAddress
1082   );
1083 
1084 /**
1085   Set ShadowStack memory.
1086 
1087   @param[in]  Cr3              The page table base address.
1088   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
1089   @param[in]  Length           The size in bytes of the memory region.
1090 
1091   @retval EFI_SUCCESS           The shadow stack memory is set.
1092 **/
1093 EFI_STATUS
1094 SetShadowStack (
1095   IN  UINTN                                      Cr3,
1096   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
1097   IN  UINT64                                     Length
1098   );
1099 
1100 /**
1101   Set not present memory.
1102 
1103   @param[in]  Cr3              The page table base address.
1104   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
1105   @param[in]  Length           The size in bytes of the memory region.
1106 
1107   @retval EFI_SUCCESS           The not present memory is set.
1108 **/
1109 EFI_STATUS
1110 SetNotPresentPage (
1111   IN  UINTN                                      Cr3,
1112   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
1113   IN  UINT64                                     Length
1114   );
1115 
1116 /**
1117   Initialize the shadow stack related data structure.
1118 
1119   @param CpuIndex     The index of CPU.
1120   @param ShadowStack  The bottom of the shadow stack for this CPU.
1121 **/
1122 VOID
1123 InitShadowStack (
1124   IN UINTN  CpuIndex,
1125   IN VOID   *ShadowStack
1126   );
1127 
1128 /**
1129   This function set given attributes of the memory region specified by
1130   BaseAddress and Length.
1131 
1132   @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1133   @param  BaseAddress       The physical address that is the start address of
1134                             a memory region.
1135   @param  Length            The size in bytes of the memory region.
1136   @param  Attributes        The bit mask of attributes to set for the memory
1137                             region.
1138 
1139   @retval EFI_SUCCESS           The attributes were set for the memory region.
1140   @retval EFI_INVALID_PARAMETER Length is zero.
1141                                 Attributes specified an illegal combination of
1142                                 attributes that cannot be set together.
1143   @retval EFI_UNSUPPORTED       The processor does not support one or more
1144                                 bytes of the memory resource range specified
1145                                 by BaseAddress and Length.
1146                                 The bit mask of attributes is not supported for
1147                                 the memory resource range specified by
1148                                 BaseAddress and Length.
1149 
1150 **/
1151 EFI_STATUS
1152 EFIAPI
1153 EdkiiSmmSetMemoryAttributes (
1154   IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,
1155   IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,
1156   IN  UINT64                                Length,
1157   IN  UINT64                                Attributes
1158   );
1159 
1160 /**
1161   This function clears given attributes of the memory region specified by
1162   BaseAddress and Length.
1163 
1164   @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1165   @param  BaseAddress       The physical address that is the start address of
1166                             a memory region.
1167   @param  Length            The size in bytes of the memory region.
1168   @param  Attributes        The bit mask of attributes to clear for the memory
1169                             region.
1170 
1171   @retval EFI_SUCCESS           The attributes were cleared for the memory region.
1172   @retval EFI_INVALID_PARAMETER Length is zero.
1173                                 Attributes specified an illegal combination of
1174                                 attributes that cannot be cleared together.
1175   @retval EFI_UNSUPPORTED       The processor does not support one or more
1176                                 bytes of the memory resource range specified
1177                                 by BaseAddress and Length.
1178                                 The bit mask of attributes is not supported for
1179                                 the memory resource range specified by
1180                                 BaseAddress and Length.
1181 
1182 **/
1183 EFI_STATUS
1184 EFIAPI
1185 EdkiiSmmClearMemoryAttributes (
1186   IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,
1187   IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,
1188   IN  UINT64                                Length,
1189   IN  UINT64                                Attributes
1190   );
1191 
1192 /**
1193   This function retrieves the attributes of the memory region specified by
1194   BaseAddress and Length. If different attributes are got from different part
1195   of the memory region, EFI_NO_MAPPING will be returned.
1196 
1197   @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1198   @param  BaseAddress       The physical address that is the start address of
1199                             a memory region.
1200   @param  Length            The size in bytes of the memory region.
1201   @param  Attributes        Pointer to attributes returned.
1202 
1203   @retval EFI_SUCCESS           The attributes got for the memory region.
1204   @retval EFI_INVALID_PARAMETER Length is zero.
1205                                 Attributes is NULL.
1206   @retval EFI_NO_MAPPING        Attributes are not consistent cross the memory
1207                                 region.
1208   @retval EFI_UNSUPPORTED       The processor does not support one or more
1209                                 bytes of the memory resource range specified
1210                                 by BaseAddress and Length.
1211 
1212 **/
1213 EFI_STATUS
1214 EFIAPI
1215 EdkiiSmmGetMemoryAttributes (
1216   IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,
1217   IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,
1218   IN  UINT64                                Length,
1219   IN  UINT64                                *Attributes
1220   );
1221 
1222 /**
1223   This function fixes up the address of the global variable or function
1224   referred in SmmInit assembly files to be the absoute address.
1225 **/
1226 VOID
1227 EFIAPI
1228 PiSmmCpuSmmInitFixupAddress (
1229  );
1230 
1231 /**
1232   This function fixes up the address of the global variable or function
1233   referred in SmiEntry assembly files to be the absoute address.
1234 **/
1235 VOID
1236 EFIAPI
1237 PiSmmCpuSmiEntryFixupAddress (
1238  );
1239 
1240 /**
1241   This function reads CR2 register when on-demand paging is enabled
1242   for 64 bit and no action for 32 bit.
1243 
1244   @param[out]  *Cr2  Pointer to variable to hold CR2 register value.
1245 **/
1246 VOID
1247 SaveCr2 (
1248   OUT UINTN  *Cr2
1249   );
1250 
1251 /**
1252   This function writes into CR2 register when on-demand paging is enabled
1253   for 64 bit and no action for 32 bit.
1254 
1255   @param[in]  Cr2  Value to write into CR2 register.
1256 **/
1257 VOID
1258 RestoreCr2 (
1259   IN UINTN  Cr2
1260   );
1261 
1262 #endif
1263