]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
UefiCpuPkg: Replace Opcode with the corresponding instructions.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.h
index f2a91655a33b85bdbf3c69b30252d172c877fe98..26d07c5b5ea0bcb5f7761d3beb14fb1c82533f1a 100644 (file)
@@ -1,14 +1,10 @@
 /** @file\r
 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.\r
 \r
-Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
+Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -23,8 +19,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SmmAccess2.h>\r
 #include <Protocol/SmmReadyToLock.h>\r
 #include <Protocol/SmmCpuService.h>\r
+#include <Protocol/SmmMemoryAttribute.h>\r
+#include <Protocol/MmMp.h>\r
 \r
 #include <Guid/AcpiS3Context.h>\r
+#include <Guid/MemoryAttributesTable.h>\r
+#include <Guid/PiSmmMemoryAttributesTable.h>\r
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/IoLib.h>\r
@@ -33,7 +33,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/DebugLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/PcdLib.h>\r
-#include <Library/CacheMaintenanceLib.h>\r
 #include <Library/MtrrLib.h>\r
 #include <Library/SmmCpuPlatformHookLib.h>\r
 #include <Library/SmmServicesTableLib.h>\r
@@ -41,6 +40,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Library/DebugAgentLib.h>\r
+#include <Library/UefiLib.h>\r
 #include <Library/HobLib.h>\r
 #include <Library/LocalApicLib.h>\r
 #include <Library/UefiCpuLib.h>\r
@@ -48,51 +48,138 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/ReportStatusCodeLib.h>\r
 #include <Library/SmmCpuFeaturesLib.h>\r
 #include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/RegisterCpuFeaturesLib.h>\r
 \r
 #include <AcpiCpuData.h>\r
 #include <CpuHotPlugData.h>\r
 \r
-#include <Register/Cpuid.h>\r
+#include <Register/Intel/Cpuid.h>\r
+#include <Register/Intel/Msr.h>\r
 \r
 #include "CpuService.h"\r
 #include "SmmProfile.h"\r
 \r
+//\r
+// CET definition\r
+//\r
+#define CPUID_CET_SS   BIT7\r
+#define CPUID_CET_IBT  BIT20\r
+\r
+#define CR4_CET_ENABLE  BIT23\r
+\r
+#define MSR_IA32_S_CET                     0x6A2\r
+#define MSR_IA32_PL0_SSP                   0x6A4\r
+#define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR  0x6A8\r
+\r
+typedef union {\r
+  struct {\r
+    // enable shadow stacks\r
+    UINT32    SH_STK_ENP              : 1;\r
+    // enable the WRSS{D,Q}W instructions.\r
+    UINT32    WR_SHSTK_EN             : 1;\r
+    // enable tracking of indirect call/jmp targets to be ENDBRANCH instruction.\r
+    UINT32    ENDBR_EN                : 1;\r
+    // enable legacy compatibility treatment for indirect call/jmp tracking.\r
+    UINT32    LEG_IW_EN               : 1;\r
+    // enable use of no-track prefix on indirect call/jmp.\r
+    UINT32    NO_TRACK_EN             : 1;\r
+    // disable suppression of CET indirect branch tracking on legacy compatibility.\r
+    UINT32    SUPPRESS_DIS            : 1;\r
+    UINT32    RSVD                    : 4;\r
+    // indirect branch tracking is suppressed.\r
+    // This bit can be written to 1 only if TRACKER is written as IDLE.\r
+    UINT32    SUPPRESS                : 1;\r
+    // Value of the endbranch state machine\r
+    // Values: IDLE (0), WAIT_FOR_ENDBRANCH(1).\r
+    UINT32    TRACKER                 : 1;\r
+    // linear address of a bitmap in memory indicating valid\r
+    // pages as target of CALL/JMP_indirect that do not land on ENDBRANCH when CET is enabled\r
+    // and not suppressed. Valid when ENDBR_EN is 1. Must be machine canonical when written on\r
+    // parts that support 64 bit mode. On parts that do not support 64 bit mode, the bits 63:32 are\r
+    // reserved and must be 0. This value is extended by 12 bits at the low end to form the base address\r
+    // (this automatically aligns the address on a 4-Kbyte boundary).\r
+    UINT32    EB_LEG_BITMAP_BASE_low  : 12;\r
+    UINT32    EB_LEG_BITMAP_BASE_high : 32;\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} MSR_IA32_CET;\r
+\r
 //\r
 // MSRs required for configuration of SMM Code Access Check\r
 //\r
-#define EFI_MSR_SMM_MCA_CAP                    0x17D\r
-#define  SMM_CODE_ACCESS_CHK_BIT               BIT58\r
+#define EFI_MSR_SMM_MCA_CAP       0x17D\r
+#define  SMM_CODE_ACCESS_CHK_BIT  BIT58\r
 \r
-#define  SMM_FEATURE_CONTROL_LOCK_BIT          BIT0\r
-#define  SMM_CODE_CHK_EN_BIT                   BIT2\r
+#define  SMM_FEATURE_CONTROL_LOCK_BIT  BIT0\r
+#define  SMM_CODE_CHK_EN_BIT           BIT2\r
 \r
 ///\r
 /// Page Table Entry\r
 ///\r
-#define IA32_PG_P                   BIT0\r
-#define IA32_PG_RW                  BIT1\r
-#define IA32_PG_WT                  BIT3\r
-#define IA32_PG_CD                  BIT4\r
-#define IA32_PG_A                   BIT5\r
-#define IA32_PG_PS                  BIT7\r
-#define IA32_PG_PAT_2M              BIT12\r
-#define IA32_PG_PAT_4K              IA32_PG_PS\r
-#define IA32_PG_PMNT                BIT62\r
-#define IA32_PG_NX                  BIT63\r
+#define IA32_PG_P       BIT0\r
+#define IA32_PG_RW      BIT1\r
+#define IA32_PG_U       BIT2\r
+#define IA32_PG_WT      BIT3\r
+#define IA32_PG_CD      BIT4\r
+#define IA32_PG_A       BIT5\r
+#define IA32_PG_D       BIT6\r
+#define IA32_PG_PS      BIT7\r
+#define IA32_PG_PAT_2M  BIT12\r
+#define IA32_PG_PAT_4K  IA32_PG_PS\r
+#define IA32_PG_PMNT    BIT62\r
+#define IA32_PG_NX      BIT63\r
+\r
+#define PAGE_ATTRIBUTE_BITS  (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)\r
+//\r
+// Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE\r
+// X64 PAE PDPTE does not have such restriction\r
+//\r
+#define IA32_PAE_PDPTE_ATTRIBUTE_BITS  (IA32_PG_P)\r
+\r
+#define PAGE_PROGATE_BITS  (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)\r
+\r
+#define PAGING_4K_MASK  0xFFF\r
+#define PAGING_2M_MASK  0x1FFFFF\r
+#define PAGING_1G_MASK  0x3FFFFFFF\r
+\r
+#define PAGING_PAE_INDEX_MASK  0x1FF\r
+\r
+#define PAGING_4K_ADDRESS_MASK_64  0x000FFFFFFFFFF000ull\r
+#define PAGING_2M_ADDRESS_MASK_64  0x000FFFFFFFE00000ull\r
+#define PAGING_1G_ADDRESS_MASK_64  0x000FFFFFC0000000ull\r
+\r
+#define SMRR_MAX_ADDRESS  BASE_4GB\r
+\r
+typedef enum {\r
+  PageNone,\r
+  Page4K,\r
+  Page2M,\r
+  Page1G,\r
+} PAGE_ATTRIBUTE;\r
+\r
+typedef struct {\r
+  PAGE_ATTRIBUTE    Attribute;\r
+  UINT64            Length;\r
+  UINT64            AddressMask;\r
+} PAGE_ATTRIBUTE_TABLE;\r
 \r
 //\r
 // Size of Task-State Segment defined in IA32 Manual\r
 //\r
-#define TSS_SIZE              104\r
-#define TSS_X64_IST1_OFFSET   36\r
-#define TSS_IA32_CR3_OFFSET   28\r
-#define TSS_IA32_ESP_OFFSET   56\r
+#define TSS_SIZE             104\r
+#define EXCEPTION_TSS_SIZE   (TSS_SIZE + 4)  // Add 4 bytes SSP\r
+#define TSS_X64_IST1_OFFSET  36\r
+#define TSS_IA32_CR3_OFFSET  28\r
+#define TSS_IA32_ESP_OFFSET  56\r
+#define TSS_IA32_SSP_OFFSET  104\r
+\r
+#define CR0_WP  BIT16\r
 \r
 //\r
 // Code select value\r
 //\r
-#define PROTECT_MODE_CODE_SEGMENT          0x08\r
-#define LONG_MODE_CODE_SEGMENT             0x38\r
+#define PROTECT_MODE_CODE_SEGMENT  0x08\r
+#define LONG_MODE_CODE_SEGMENT     0x38\r
 \r
 //\r
 // The size 0x20 must be bigger than\r
@@ -102,14 +189,45 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 #define BACK_BUF_SIZE  0x20\r
 \r
-#define EXCEPTION_VECTOR_NUMBER     0x20\r
+#define EXCEPTION_VECTOR_NUMBER  0x20\r
 \r
-#define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL\r
+#define INVALID_APIC_ID  0xFFFFFFFFFFFFFFFFULL\r
 \r
-typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;\r
-#define ARRIVAL_EXCEPTION_BLOCKED           0x1\r
-#define ARRIVAL_EXCEPTION_DELAYED           0x2\r
-#define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4\r
+typedef UINT32 SMM_CPU_ARRIVAL_EXCEPTIONS;\r
+#define ARRIVAL_EXCEPTION_BLOCKED       0x1\r
+#define ARRIVAL_EXCEPTION_DELAYED       0x2\r
+#define ARRIVAL_EXCEPTION_SMI_DISABLED  0x4\r
+\r
+//\r
+// Wrapper used to convert EFI_AP_PROCEDURE2 and EFI_AP_PROCEDURE.\r
+//\r
+typedef struct {\r
+  EFI_AP_PROCEDURE    Procedure;\r
+  VOID                *ProcedureArgument;\r
+} PROCEDURE_WRAPPER;\r
+\r
+#define PROCEDURE_TOKEN_SIGNATURE  SIGNATURE_32 ('P', 'R', 'T', 'S')\r
+\r
+typedef struct {\r
+  UINTN              Signature;\r
+  LIST_ENTRY         Link;\r
+\r
+  SPIN_LOCK          *SpinLock;\r
+  volatile UINT32    RunningApCount;\r
+} PROCEDURE_TOKEN;\r
+\r
+#define PROCEDURE_TOKEN_FROM_LINK(a)  CR (a, PROCEDURE_TOKEN, Link, PROCEDURE_TOKEN_SIGNATURE)\r
+\r
+#define TOKEN_BUFFER_SIGNATURE  SIGNATURE_32 ('T', 'K', 'B', 'S')\r
+\r
+typedef struct {\r
+  UINTN         Signature;\r
+  LIST_ENTRY    Link;\r
+\r
+  UINT8         *Buffer;\r
+} TOKEN_BUFFER;\r
+\r
+#define TOKEN_BUFFER_FROM_LINK(a)  CR (a, TOKEN_BUFFER, Link, TOKEN_BUFFER_SIGNATURE)\r
 \r
 //\r
 // Private structure for the SMM CPU module that is stored in DXE Runtime memory\r
@@ -119,35 +237,39 @@ typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
 #define SMM_CPU_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('s', 'c', 'p', 'u')\r
 \r
 typedef struct {\r
-  UINTN                           Signature;\r
+  UINTN                             Signature;\r
 \r
-  EFI_HANDLE                      SmmCpuHandle;\r
+  EFI_HANDLE                        SmmCpuHandle;\r
 \r
-  EFI_PROCESSOR_INFORMATION       *ProcessorInfo;\r
-  SMM_CPU_OPERATION               *Operation;\r
-  UINTN                           *CpuSaveStateSize;\r
-  VOID                            **CpuSaveState;\r
+  EFI_PROCESSOR_INFORMATION         *ProcessorInfo;\r
+  SMM_CPU_OPERATION                 *Operation;\r
+  UINTN                             *CpuSaveStateSize;\r
+  VOID                              **CpuSaveState;\r
 \r
-  EFI_SMM_RESERVED_SMRAM_REGION   SmmReservedSmramRegion[1];\r
-  EFI_SMM_ENTRY_CONTEXT           SmmCoreEntryContext;\r
-  EFI_SMM_ENTRY_POINT             SmmCoreEntry;\r
+  EFI_SMM_RESERVED_SMRAM_REGION     SmmReservedSmramRegion[1];\r
+  EFI_SMM_ENTRY_CONTEXT             SmmCoreEntryContext;\r
+  EFI_SMM_ENTRY_POINT               SmmCoreEntry;\r
 \r
-  EFI_SMM_CONFIGURATION_PROTOCOL  SmmConfiguration;\r
+  EFI_SMM_CONFIGURATION_PROTOCOL    SmmConfiguration;\r
+\r
+  PROCEDURE_WRAPPER                 *ApWrapperFunc;\r
+  LIST_ENTRY                        TokenList;\r
+  LIST_ENTRY                        *FirstFreeToken;\r
 } SMM_CPU_PRIVATE_DATA;\r
 \r
 extern SMM_CPU_PRIVATE_DATA  *gSmmCpuPrivate;\r
-extern CPU_HOT_PLUG_DATA      mCpuHotPlugData;\r
-extern UINTN                  mMaxNumberOfCpus;\r
-extern UINTN                  mNumberOfCpus;\r
-extern BOOLEAN                mRestoreSmmConfigurationInS3;\r
-extern EFI_SMM_CPU_PROTOCOL   mSmmCpu;\r
+extern CPU_HOT_PLUG_DATA     mCpuHotPlugData;\r
+extern UINTN                 mMaxNumberOfCpus;\r
+extern UINTN                 mNumberOfCpus;\r
+extern EFI_SMM_CPU_PROTOCOL  mSmmCpu;\r
+extern EFI_MM_MP_PROTOCOL    mSmmMp;\r
+extern UINTN                 mInternalCr3;\r
 \r
 ///\r
 /// The mode of the CPU at the time an SMI occurs\r
 ///\r
 extern UINT8  mSmmSaveStateRegisterLma;\r
 \r
-\r
 //\r
 // SMM CPU Protocol function prototypes.\r
 //\r
@@ -163,17 +285,17 @@ extern UINT8  mSmmSaveStateRegisterLma;
 \r
   @retval EFI_SUCCESS   The register was read from Save State\r
   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor\r
-  @retval EFI_INVALID_PARAMTER   This or Buffer is NULL.\r
+  @retval EFI_INVALID_PARAMETER   This or Buffer is NULL.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 SmmReadSaveState (\r
-  IN CONST EFI_SMM_CPU_PROTOCOL         *This,\r
-  IN UINTN                              Width,\r
-  IN EFI_SMM_SAVE_STATE_REGISTER        Register,\r
-  IN UINTN                              CpuIndex,\r
-  OUT VOID                              *Buffer\r
+  IN CONST EFI_SMM_CPU_PROTOCOL   *This,\r
+  IN UINTN                        Width,\r
+  IN EFI_SMM_SAVE_STATE_REGISTER  Register,\r
+  IN UINTN                        CpuIndex,\r
+  OUT VOID                        *Buffer\r
   );\r
 \r
 /**\r
@@ -187,17 +309,17 @@ SmmReadSaveState (
 \r
   @retval EFI_SUCCESS   The register was written from Save State\r
   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor\r
-  @retval EFI_INVALID_PARAMTER   ProcessorIndex or Width is not correct\r
+  @retval EFI_INVALID_PARAMETER   ProcessorIndex or Width is not correct\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 SmmWriteSaveState (\r
-  IN CONST EFI_SMM_CPU_PROTOCOL         *This,\r
-  IN UINTN                              Width,\r
-  IN EFI_SMM_SAVE_STATE_REGISTER        Register,\r
-  IN UINTN                              CpuIndex,\r
-  IN CONST VOID                         *Buffer\r
+  IN CONST EFI_SMM_CPU_PROTOCOL   *This,\r
+  IN UINTN                        Width,\r
+  IN EFI_SMM_SAVE_STATE_REGISTER  Register,\r
+  IN UINTN                        CpuIndex,\r
+  IN CONST VOID                   *Buffer\r
   );\r
 \r
 /**\r
@@ -215,7 +337,7 @@ This function supports reading a CPU Save State register in SMBase relocation ha
 \r
 @retval EFI_SUCCESS           The register was read from Save State.\r
 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.\r
-@retval EFI_INVALID_PARAMTER  This or Buffer is NULL.\r
+@retval EFI_INVALID_PARAMETER Buffer is NULL, or Width does not meet requirement per Register type.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -242,7 +364,7 @@ This function supports writing a CPU Save State register in SMBase relocation ha
 \r
 @retval EFI_SUCCESS           The register was written to Save State.\r
 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.\r
-@retval EFI_INVALID_PARAMTER  ProcessorIndex or Width is not correct.\r
+@retval EFI_INVALID_PARAMETER  ProcessorIndex or Width is not correct.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -254,23 +376,16 @@ WriteSaveStateRegister (
   IN CONST VOID                   *Buffer\r
   );\r
 \r
-//\r
-//\r
-//\r
-typedef struct {\r
-  UINT32                            Offset;\r
-  UINT16                            Segment;\r
-  UINT16                            Reserved;\r
-} IA32_FAR_ADDRESS;\r
-\r
-extern IA32_FAR_ADDRESS             gSmmJmpAddr;\r
-\r
-extern CONST UINT8                  gcSmmInitTemplate[];\r
-extern CONST UINT16                 gcSmmInitSize;\r
-extern UINT32                       gSmmCr0;\r
-extern UINT32                       gSmmCr3;\r
-extern UINT32                       gSmmCr4;\r
-extern UINTN                        gSmmInitStack;\r
+extern CONST UINT8        gcSmmInitTemplate[];\r
+extern CONST UINT16       gcSmmInitSize;\r
+X86_ASSEMBLY_PATCH_LABEL  gPatchSmmCr0;\r
+extern UINT32             mSmmCr0;\r
+X86_ASSEMBLY_PATCH_LABEL  gPatchSmmCr3;\r
+extern UINT32             mSmmCr4;\r
+X86_ASSEMBLY_PATCH_LABEL  gPatchSmmCr4;\r
+X86_ASSEMBLY_PATCH_LABEL  gPatchSmmInitStack;\r
+X86_ASSEMBLY_PATCH_LABEL  mPatchCetSupported;\r
+extern BOOLEAN            mCetSupported;\r
 \r
 /**\r
   Semaphore operation for all processor relocate SMMBase.\r
@@ -285,11 +400,13 @@ SmmRelocationSemaphoreComplete (
 /// The type of SMM CPU Information\r
 ///\r
 typedef struct {\r
-  SPIN_LOCK                         Busy;\r
-  volatile EFI_AP_PROCEDURE         Procedure;\r
-  volatile VOID                     *Parameter;\r
-  volatile UINT32                   Run;\r
-  volatile BOOLEAN                  Present;\r
+  SPIN_LOCK                     *Busy;\r
+  volatile EFI_AP_PROCEDURE2    Procedure;\r
+  volatile VOID                 *Parameter;\r
+  volatile UINT32               *Run;\r
+  volatile BOOLEAN              *Present;\r
+  PROCEDURE_TOKEN               *Token;\r
+  EFI_STATUS                    *Status;\r
 } SMM_CPU_DATA_BLOCK;\r
 \r
 typedef enum {\r
@@ -304,86 +421,98 @@ typedef struct {
   // so that UC cache-ability can be set together.\r
   //\r
   SMM_CPU_DATA_BLOCK            *CpuData;\r
-  volatile UINT32               Counter;\r
+  volatile UINT32               *Counter;\r
   volatile UINT32               BspIndex;\r
-  volatile BOOLEAN              InsideSmm;\r
-  volatile BOOLEAN              AllCpusInSync;\r
+  volatile BOOLEAN              *InsideSmm;\r
+  volatile BOOLEAN              *AllCpusInSync;\r
   volatile SMM_CPU_SYNC_MODE    EffectiveSyncMode;\r
   volatile BOOLEAN              SwitchBsp;\r
   volatile BOOLEAN              *CandidateBsp;\r
+  EFI_AP_PROCEDURE              StartupProcedure;\r
+  VOID                          *StartupProcArgs;\r
 } SMM_DISPATCHER_MP_SYNC_DATA;\r
 \r
+#define SMM_PSD_OFFSET  0xfb00\r
+\r
+///\r
+/// All global semaphores' pointer\r
+///\r
 typedef struct {\r
-  SPIN_LOCK    SpinLock;\r
-  UINT32       MsrIndex;\r
-} MP_MSR_LOCK;\r
+  volatile UINT32     *Counter;\r
+  volatile BOOLEAN    *InsideSmm;\r
+  volatile BOOLEAN    *AllCpusInSync;\r
+  SPIN_LOCK           *PFLock;\r
+  SPIN_LOCK           *CodeAccessCheckLock;\r
+} SMM_CPU_SEMAPHORE_GLOBAL;\r
 \r
-#define SMM_PSD_OFFSET              0xfb00\r
+///\r
+/// All semaphores for each processor\r
+///\r
+typedef struct {\r
+  SPIN_LOCK           *Busy;\r
+  volatile UINT32     *Run;\r
+  volatile BOOLEAN    *Present;\r
+  SPIN_LOCK           *Token;\r
+} SMM_CPU_SEMAPHORE_CPU;\r
 \r
+///\r
+/// All semaphores' information\r
+///\r
 typedef struct {\r
-  UINT64                            Signature;              // Offset 0x00\r
-  UINT16                            Reserved1;              // Offset 0x08\r
-  UINT16                            Reserved2;              // Offset 0x0A\r
-  UINT16                            Reserved3;              // Offset 0x0C\r
-  UINT16                            SmmCs;                  // Offset 0x0E\r
-  UINT16                            SmmDs;                  // Offset 0x10\r
-  UINT16                            SmmSs;                  // Offset 0x12\r
-  UINT16                            SmmOtherSegment;        // Offset 0x14\r
-  UINT16                            Reserved4;              // Offset 0x16\r
-  UINT64                            Reserved5;              // Offset 0x18\r
-  UINT64                            Reserved6;              // Offset 0x20\r
-  UINT64                            Reserved7;              // Offset 0x28\r
-  UINT64                            SmmGdtPtr;              // Offset 0x30\r
-  UINT32                            SmmGdtSize;             // Offset 0x38\r
-  UINT32                            Reserved8;              // Offset 0x3C\r
-  UINT64                            Reserved9;              // Offset 0x40\r
-  UINT64                            Reserved10;             // Offset 0x48\r
-  UINT16                            Reserved11;             // Offset 0x50\r
-  UINT16                            Reserved12;             // Offset 0x52\r
-  UINT32                            Reserved13;             // Offset 0x54\r
-  UINT64                            MtrrBaseMaskPtr;        // Offset 0x58\r
-} PROCESSOR_SMM_DESCRIPTOR;\r
-\r
-extern IA32_DESCRIPTOR                     gcSmiGdtr;\r
-extern IA32_DESCRIPTOR                     gcSmiIdtr;\r
-extern VOID                                *gcSmiIdtrPtr;\r
-extern CONST PROCESSOR_SMM_DESCRIPTOR      gcPsd;\r
-extern UINT64                              gPhyMask;\r
-extern ACPI_CPU_DATA                       mAcpiCpuData;\r
-extern SMM_DISPATCHER_MP_SYNC_DATA         *mSmmMpSyncData;\r
-extern VOID                                *mGdtForAp;\r
-extern VOID                                *mIdtForAp;\r
-extern VOID                                *mMachineCheckHandlerForAp;\r
-extern UINTN                               mSmmStackArrayBase;\r
-extern UINTN                               mSmmStackArrayEnd;\r
-extern UINTN                               mSmmStackSize;\r
-extern EFI_SMM_CPU_SERVICE_PROTOCOL        mSmmCpuService;\r
-extern IA32_DESCRIPTOR                     gcSmiInitGdtr;\r
+  SMM_CPU_SEMAPHORE_GLOBAL    SemaphoreGlobal;\r
+  SMM_CPU_SEMAPHORE_CPU       SemaphoreCpu;\r
+} SMM_CPU_SEMAPHORES;\r
+\r
+extern IA32_DESCRIPTOR               gcSmiGdtr;\r
+extern EFI_PHYSICAL_ADDRESS          mGdtBuffer;\r
+extern UINTN                         mGdtBufferSize;\r
+extern IA32_DESCRIPTOR               gcSmiIdtr;\r
+extern VOID                          *gcSmiIdtrPtr;\r
+extern UINT64                        gPhyMask;\r
+extern SMM_DISPATCHER_MP_SYNC_DATA   *mSmmMpSyncData;\r
+extern UINTN                         mSmmStackArrayBase;\r
+extern UINTN                         mSmmStackArrayEnd;\r
+extern UINTN                         mSmmStackSize;\r
+extern EFI_SMM_CPU_SERVICE_PROTOCOL  mSmmCpuService;\r
+extern IA32_DESCRIPTOR               gcSmiInitGdtr;\r
+extern SMM_CPU_SEMAPHORES            mSmmCpuSemaphores;\r
+extern UINTN                         mSemaphoreSize;\r
+extern SPIN_LOCK                     *mPFLock;\r
+extern SPIN_LOCK                     *mConfigSmmCodeAccessCheckLock;\r
+extern EFI_SMRAM_DESCRIPTOR          *mSmmCpuSmramRanges;\r
+extern UINTN                         mSmmCpuSmramRangeCount;\r
+extern UINT8                         mPhysicalAddressBits;\r
+\r
+//\r
+// Copy of the PcdPteMemoryEncryptionAddressOrMask\r
+//\r
+extern UINT64  mAddressEncMask;\r
 \r
 /**\r
   Create 4G PageTable in SMRAM.\r
 \r
-  @param          ExtraPages       Additional page numbers besides for 4G memory\r
+  @param[in]      Is32BitPageTable Whether the page table is 32-bit PAE\r
   @return         PageTable Address\r
 \r
 **/\r
 UINT32\r
 Gen4GPageTable (\r
-  IN      UINTN                     ExtraPages\r
+  IN      BOOLEAN  Is32BitPageTable\r
   );\r
 \r
-\r
 /**\r
   Initialize global data for MP synchronization.\r
 \r
-  @param Stacks       Base address of SMI stack buffer for all processors.\r
-  @param StackSize    Stack size for each processor in SMM.\r
+  @param Stacks             Base address of SMI stack buffer for all processors.\r
+  @param StackSize          Stack size for each processor in SMM.\r
+  @param ShadowStackSize    Shadow Stack size for each processor in SMM.\r
 \r
 **/\r
 UINT32\r
 InitializeMpServiceData (\r
-  IN VOID        *Stacks,\r
-  IN UINTN       StackSize\r
+  IN VOID   *Stacks,\r
+  IN UINTN  StackSize,\r
+  IN UINTN  ShadowStackSize\r
   );\r
 \r
 /**\r
@@ -414,7 +543,7 @@ StartSyncTimer (
 BOOLEAN\r
 EFIAPI\r
 IsSyncTimerTimeout (\r
-  IN      UINT64                    Timer\r
+  IN      UINT64  Timer\r
   );\r
 \r
 /**\r
@@ -427,9 +556,23 @@ InitializeIDTSmmStackGuard (
   VOID\r
   );\r
 \r
+/**\r
+  Initialize IDT IST Field.\r
+\r
+  @param[in]  ExceptionType       Exception type.\r
+  @param[in]  Ist                 IST value.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeIdtIst (\r
+  IN EFI_EXCEPTION_TYPE  ExceptionType,\r
+  IN UINT8               Ist\r
+  );\r
+\r
 /**\r
   Initialize Gdt for all processors.\r
-  \r
+\r
   @param[in]   Cr3          CR3 value.\r
   @param[out]  GdtStepSize  The step size for GDT table.\r
 \r
@@ -487,9 +630,9 @@ SmmInitPageTable (
 EFI_STATUS\r
 EFIAPI\r
 SmmStartupThisAp (\r
-  IN      EFI_AP_PROCEDURE          Procedure,\r
-  IN      UINTN                     CpuIndex,\r
-  IN OUT  VOID                      *ProcArguments OPTIONAL\r
+  IN      EFI_AP_PROCEDURE  Procedure,\r
+  IN      UINTN             CpuIndex,\r
+  IN OUT  VOID              *ProcArguments OPTIONAL\r
   );\r
 \r
 /**\r
@@ -509,9 +652,69 @@ SmmStartupThisAp (
 EFI_STATUS\r
 EFIAPI\r
 SmmBlockingStartupThisAp (\r
-  IN      EFI_AP_PROCEDURE          Procedure,\r
-  IN      UINTN                     CpuIndex,\r
-  IN OUT  VOID                      *ProcArguments OPTIONAL\r
+  IN      EFI_AP_PROCEDURE  Procedure,\r
+  IN      UINTN             CpuIndex,\r
+  IN OUT  VOID              *ProcArguments OPTIONAL\r
+  );\r
+\r
+/**\r
+  This function sets the attributes for the memory region specified by BaseAddress and\r
+  Length from their current attributes to the attributes specified by Attributes.\r
+\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
+  @param[in]  Attributes       The bit mask of attributes to set for the memory region.\r
+\r
+  @retval EFI_SUCCESS           The attributes were set for the memory region.\r
+  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by\r
+                                BaseAddress and Length cannot be modified.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of attributes that\r
+                                cannot be set together.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
+                                the memory resource range.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
+                                resource range specified by BaseAddress and Length.\r
+                                The bit mask of attributes is not support for the memory resource\r
+                                range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmSetMemoryAttributes (\r
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  IN  UINT64                Length,\r
+  IN  UINT64                Attributes\r
+  );\r
+\r
+/**\r
+  This function clears the attributes for the memory region specified by BaseAddress and\r
+  Length from their current attributes to the attributes specified by Attributes.\r
+\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
+  @param[in]  Attributes       The bit mask of attributes to clear for the memory region.\r
+\r
+  @retval EFI_SUCCESS           The attributes were cleared for the memory region.\r
+  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by\r
+                                BaseAddress and Length cannot be modified.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of attributes that\r
+                                cannot be set together.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
+                                the memory resource range.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
+                                resource range specified by BaseAddress and Length.\r
+                                The bit mask of attributes is not support for the memory resource\r
+                                range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmClearMemoryAttributes (\r
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  IN  UINT64                Length,\r
+  IN  UINT64                Attributes\r
   );\r
 \r
 /**\r
@@ -534,31 +737,19 @@ InitializeMpSyncData (
 **/\r
 VOID\r
 FindSmramInfo (\r
-  OUT UINT32   *SmrrBase,\r
-  OUT UINT32   *SmrrSize\r
+  OUT UINT32  *SmrrBase,\r
+  OUT UINT32  *SmrrSize\r
   );\r
 \r
 /**\r
-  The function is invoked before SMBASE relocation in S3 path to restores CPU status.\r
+  Relocate SmmBases for each processor.\r
 \r
-  The function is invoked before SMBASE relocation in S3 path. It does first time microcode load\r
-  and restores MTRRs for both BSP and APs.\r
+  Execute on first boot and all S3 resumes\r
 \r
 **/\r
 VOID\r
-EarlyInitializeCpu (\r
-  VOID\r
-  );\r
-\r
-/**\r
-  The function is invoked after SMBASE relocation in S3 path to restores CPU status.\r
-\r
-  The function is invoked after SMBASE relocation in S3 path. It restores configuration according to\r
-  data saved by normal boot path for both BSP and APs.\r
-\r
-**/\r
-VOID\r
-InitializeCpu (\r
+EFIAPI\r
+SmmRelocateBases (\r
   VOID\r
   );\r
 \r
@@ -573,8 +764,8 @@ InitializeCpu (
 VOID\r
 EFIAPI\r
 SmiPFHandler (\r
-    IN EFI_EXCEPTION_TYPE   InterruptType,\r
-    IN EFI_SYSTEM_CONTEXT   SystemContext\r
+  IN EFI_EXCEPTION_TYPE  InterruptType,\r
+  IN EFI_SYSTEM_CONTEXT  SystemContext\r
   );\r
 \r
 /**\r
@@ -603,7 +794,7 @@ PerformPreTasks (
 **/\r
 VOID\r
 InitMsrSpinLockByIndex (\r
-  IN UINT32      MsrIndex\r
+  IN UINT32  MsrIndex\r
   );\r
 \r
 /**\r
@@ -716,7 +907,128 @@ InstallSmiHandler (
 **/\r
 VOID\r
 DumpModuleInfoByIp (\r
-  IN  UINTN              CallerIpAddress\r
+  IN  UINTN  CallerIpAddress\r
+  );\r
+\r
+/**\r
+  This function sets memory attribute according to MemoryAttributesTable.\r
+**/\r
+VOID\r
+SetMemMapAttributes (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function sets UEFI memory attribute according to UEFI memory map.\r
+**/\r
+VOID\r
+SetUefiMemMapAttributes (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Return if the Address is forbidden as SMM communication buffer.\r
+\r
+  @param[in] Address the address to be checked\r
+\r
+  @return TRUE  The address is forbidden as SMM communication buffer.\r
+  @return FALSE The address is allowed as SMM communication buffer.\r
+**/\r
+BOOLEAN\r
+IsSmmCommBufferForbiddenAddress (\r
+  IN UINT64  Address\r
+  );\r
+\r
+/**\r
+  This function caches the UEFI memory map information.\r
+**/\r
+VOID\r
+GetUefiMemoryMap (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function sets memory attribute for page table.\r
+**/\r
+VOID\r
+SetPageTableAttributes (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get page table base address and the depth of the page table.\r
+\r
+  @param[out] Base        Page table base address.\r
+  @param[out] FiveLevels  TRUE means 5 level paging. FALSE means 4 level paging.\r
+**/\r
+VOID\r
+GetPageTable (\r
+  OUT UINTN    *Base,\r
+  OUT BOOLEAN  *FiveLevels OPTIONAL\r
+  );\r
+\r
+/**\r
+  This function sets the attributes for the memory region specified by BaseAddress and\r
+  Length from their current attributes to the attributes specified by Attributes.\r
+\r
+  @param[in]   BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]   Length           The size in bytes of the memory region.\r
+  @param[in]   Attributes       The bit mask of attributes to set for the memory region.\r
+  @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.\r
+\r
+  @retval EFI_SUCCESS           The attributes were set for the memory region.\r
+  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by\r
+                                BaseAddress and Length cannot be modified.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of attributes that\r
+                                cannot be set together.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
+                                the memory resource range.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
+                                resource range specified by BaseAddress and Length.\r
+                                The bit mask of attributes is not support for the memory resource\r
+                                range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmSetMemoryAttributesEx (\r
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  IN  UINT64                Length,\r
+  IN  UINT64                Attributes,\r
+  OUT BOOLEAN               *IsSplitted  OPTIONAL\r
+  );\r
+\r
+/**\r
+  This function clears the attributes for the memory region specified by BaseAddress and\r
+  Length from their current attributes to the attributes specified by Attributes.\r
+\r
+  @param[in]   BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]   Length           The size in bytes of the memory region.\r
+  @param[in]   Attributes       The bit mask of attributes to clear for the memory region.\r
+  @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.\r
+\r
+  @retval EFI_SUCCESS           The attributes were cleared for the memory region.\r
+  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by\r
+                                BaseAddress and Length cannot be modified.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of attributes that\r
+                                cannot be set together.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
+                                the memory resource range.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
+                                resource range specified by BaseAddress and Length.\r
+                                The bit mask of attributes is not support for the memory resource\r
+                                range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmClearMemoryAttributesEx (\r
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  IN  UINT64                Length,\r
+  IN  UINT64                Attributes,\r
+  OUT BOOLEAN               *IsSplitted  OPTIONAL\r
   );\r
 \r
 /**\r
@@ -736,7 +1048,444 @@ DumpModuleInfoByIp (
 **/\r
 VOID *\r
 AllocatePageTableMemory (\r
-  IN UINTN           Pages\r
+  IN UINTN  Pages\r
+  );\r
+\r
+/**\r
+  Allocate pages for code.\r
+\r
+  @param[in]  Pages Number of pages to be allocated.\r
+\r
+  @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateCodePages (\r
+  IN UINTN  Pages\r
+  );\r
+\r
+/**\r
+  Allocate aligned pages for code.\r
+\r
+  @param[in]  Pages                 Number of pages to be allocated.\r
+  @param[in]  Alignment             The requested alignment of the allocation.\r
+                                    Must be a power of two.\r
+                                    If Alignment is zero, then byte alignment is used.\r
+\r
+  @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateAlignedCodePages (\r
+  IN UINTN  Pages,\r
+  IN UINTN  Alignment\r
+  );\r
+\r
+//\r
+// S3 related global variable and function prototype.\r
+//\r
+\r
+extern BOOLEAN  mSmmS3Flag;\r
+\r
+/**\r
+  Initialize SMM S3 resume state structure used during S3 Resume.\r
+\r
+  @param[in] Cr3    The base address of the page tables to use in SMM.\r
+\r
+**/\r
+VOID\r
+InitSmmS3ResumeState (\r
+  IN UINT32  Cr3\r
+  );\r
+\r
+/**\r
+  Get ACPI CPU data.\r
+\r
+**/\r
+VOID\r
+GetAcpiCpuData (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Restore SMM Configuration in S3 boot path.\r
+\r
+**/\r
+VOID\r
+RestoreSmmConfigurationInS3 (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get ACPI S3 enable flag.\r
+\r
+**/\r
+VOID\r
+GetAcpiS3EnableFlag (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.\r
+\r
+  @param[in] ApHltLoopCode          The address of the safe hlt-loop function.\r
+  @param[in] TopOfStack             A pointer to the new stack to use for the ApHltLoopCode.\r
+  @param[in] NumberToFinishAddress  Address of Semaphore of APs finish count.\r
+\r
+**/\r
+VOID\r
+TransferApToSafeState (\r
+  IN UINTN  ApHltLoopCode,\r
+  IN UINTN  TopOfStack,\r
+  IN UINTN  NumberToFinishAddress\r
+  );\r
+\r
+/**\r
+  Set ShadowStack memory.\r
+\r
+  @param[in]  Cr3              The page table base address.\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
+\r
+  @retval EFI_SUCCESS           The shadow stack memory is set.\r
+**/\r
+EFI_STATUS\r
+SetShadowStack (\r
+  IN  UINTN                 Cr3,\r
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  IN  UINT64                Length\r
+  );\r
+\r
+/**\r
+  Set not present memory.\r
+\r
+  @param[in]  Cr3              The page table base address.\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
+\r
+  @retval EFI_SUCCESS           The not present memory is set.\r
+**/\r
+EFI_STATUS\r
+SetNotPresentPage (\r
+  IN  UINTN                 Cr3,\r
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,\r
+  IN  UINT64                Length\r
+  );\r
+\r
+/**\r
+  Initialize the shadow stack related data structure.\r
+\r
+  @param CpuIndex     The index of CPU.\r
+  @param ShadowStack  The bottom of the shadow stack for this CPU.\r
+**/\r
+VOID\r
+InitShadowStack (\r
+  IN UINTN  CpuIndex,\r
+  IN VOID   *ShadowStack\r
+  );\r
+\r
+/**\r
+  This function set given attributes of the memory region specified by\r
+  BaseAddress and Length.\r
+\r
+  @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+  @param  BaseAddress       The physical address that is the start address of\r
+                            a memory region.\r
+  @param  Length            The size in bytes of the memory region.\r
+  @param  Attributes        The bit mask of attributes to set for the memory\r
+                            region.\r
+\r
+  @retval EFI_SUCCESS           The attributes were set for the memory region.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of\r
+                                attributes that cannot be set together.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more\r
+                                bytes of the memory resource range specified\r
+                                by BaseAddress and Length.\r
+                                The bit mask of attributes is not supported for\r
+                                the memory resource range specified by\r
+                                BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmSetMemoryAttributes (\r
+  IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,\r
+  IN  EFI_PHYSICAL_ADDRESS                 BaseAddress,\r
+  IN  UINT64                               Length,\r
+  IN  UINT64                               Attributes\r
+  );\r
+\r
+/**\r
+  This function clears given attributes of the memory region specified by\r
+  BaseAddress and Length.\r
+\r
+  @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+  @param  BaseAddress       The physical address that is the start address of\r
+                            a memory region.\r
+  @param  Length            The size in bytes of the memory region.\r
+  @param  Attributes        The bit mask of attributes to clear for the memory\r
+                            region.\r
+\r
+  @retval EFI_SUCCESS           The attributes were cleared for the memory region.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of\r
+                                attributes that cannot be cleared together.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more\r
+                                bytes of the memory resource range specified\r
+                                by BaseAddress and Length.\r
+                                The bit mask of attributes is not supported for\r
+                                the memory resource range specified by\r
+                                BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmClearMemoryAttributes (\r
+  IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,\r
+  IN  EFI_PHYSICAL_ADDRESS                 BaseAddress,\r
+  IN  UINT64                               Length,\r
+  IN  UINT64                               Attributes\r
+  );\r
+\r
+/**\r
+  This function retrieves the attributes of the memory region specified by\r
+  BaseAddress and Length. If different attributes are got from different part\r
+  of the memory region, EFI_NO_MAPPING will be returned.\r
+\r
+  @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+  @param  BaseAddress       The physical address that is the start address of\r
+                            a memory region.\r
+  @param  Length            The size in bytes of the memory region.\r
+  @param  Attributes        Pointer to attributes returned.\r
+\r
+  @retval EFI_SUCCESS           The attributes got for the memory region.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes is NULL.\r
+  @retval EFI_NO_MAPPING        Attributes are not consistent cross the memory\r
+                                region.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more\r
+                                bytes of the memory resource range specified\r
+                                by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmGetMemoryAttributes (\r
+  IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,\r
+  IN  EFI_PHYSICAL_ADDRESS                 BaseAddress,\r
+  IN  UINT64                               Length,\r
+  IN  UINT64                               *Attributes\r
+  );\r
+\r
+/**\r
+  This function fixes up the address of the global variable or function\r
+  referred in SmmInit assembly files to be the absolute address.\r
+**/\r
+VOID\r
+EFIAPI\r
+PiSmmCpuSmmInitFixupAddress (\r
+  );\r
+\r
+/**\r
+  This function fixes up the address of the global variable or function\r
+  referred in SmiEntry assembly files to be the absolute address.\r
+**/\r
+VOID\r
+EFIAPI\r
+PiSmmCpuSmiEntryFixupAddress (\r
+  );\r
+\r
+/**\r
+  This function reads CR2 register when on-demand paging is enabled\r
+  for 64 bit and no action for 32 bit.\r
+\r
+  @param[out]  *Cr2  Pointer to variable to hold CR2 register value.\r
+**/\r
+VOID\r
+SaveCr2 (\r
+  OUT UINTN  *Cr2\r
+  );\r
+\r
+/**\r
+  This function writes into CR2 register when on-demand paging is enabled\r
+  for 64 bit and no action for 32 bit.\r
+\r
+  @param[in]  Cr2  Value to write into CR2 register.\r
+**/\r
+VOID\r
+RestoreCr2 (\r
+  IN UINTN  Cr2\r
+  );\r
+\r
+/**\r
+  Schedule a procedure to run on the specified CPU.\r
+\r
+  @param[in]       Procedure                The address of the procedure to run\r
+  @param[in]       CpuIndex                 Target CPU Index\r
+  @param[in,out]   ProcArguments            The parameter to pass to the procedure\r
+  @param[in,out]   Token                    This is an optional parameter that allows the caller to execute the\r
+                                            procedure in a blocking or non-blocking fashion. If it is NULL the\r
+                                            call is blocking, and the call will not return until the AP has\r
+                                            completed the procedure. If the token is not NULL, the call will\r
+                                            return immediately. The caller can check whether the procedure has\r
+                                            completed with CheckOnProcedure or WaitForProcedure.\r
+  @param[in]       TimeoutInMicroseconds    Indicates the time limit in microseconds for the APs to finish\r
+                                            execution of Procedure, either for blocking or non-blocking mode.\r
+                                            Zero means infinity. If the timeout expires before all APs return\r
+                                            from Procedure, then Procedure on the failed APs is terminated. If\r
+                                            the timeout expires in blocking mode, the call returns EFI_TIMEOUT.\r
+                                            If the timeout expires in non-blocking mode, the timeout determined\r
+                                            can be through CheckOnProcedure or WaitForProcedure.\r
+                                            Note that timeout support is optional. Whether an implementation\r
+                                            supports this feature can be determined via the Attributes data\r
+                                            member.\r
+  @param[in,out]   CpuStatus                This optional pointer may be used to get the status code returned\r
+                                            by Procedure when it completes execution on the target AP, or with\r
+                                            EFI_TIMEOUT if the Procedure fails to complete within the optional\r
+                                            timeout. The implementation will update this variable with\r
+                                            EFI_NOT_READY prior to starting Procedure on the target AP.\r
+\r
+  @retval EFI_INVALID_PARAMETER    CpuNumber not valid\r
+  @retval EFI_INVALID_PARAMETER    CpuNumber specifying BSP\r
+  @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM\r
+  @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy\r
+  @retval EFI_SUCCESS              The procedure has been successfully scheduled\r
+\r
+**/\r
+EFI_STATUS\r
+InternalSmmStartupThisAp (\r
+  IN      EFI_AP_PROCEDURE2  Procedure,\r
+  IN      UINTN              CpuIndex,\r
+  IN OUT  VOID               *ProcArguments OPTIONAL,\r
+  IN OUT  MM_COMPLETION      *Token,\r
+  IN      UINTN              TimeoutInMicroseconds,\r
+  IN OUT  EFI_STATUS         *CpuStatus\r
+  );\r
+\r
+/**\r
+  Checks whether the input token is the current used token.\r
+\r
+  @param[in]  Token      This parameter describes the token that was passed into DispatchProcedure or\r
+                         BroadcastProcedure.\r
+\r
+  @retval TRUE           The input token is the current used token.\r
+  @retval FALSE          The input token is not the current used token.\r
+**/\r
+BOOLEAN\r
+IsTokenInUse (\r
+  IN SPIN_LOCK  *Token\r
+  );\r
+\r
+/**\r
+  Checks status of specified AP.\r
+\r
+  This function checks whether the specified AP has finished the task assigned\r
+  by StartupThisAP(), and whether timeout expires.\r
+\r
+  @param[in]  Token             This parameter describes the token that was passed into DispatchProcedure or\r
+                                BroadcastProcedure.\r
+\r
+  @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().\r
+  @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.\r
+**/\r
+EFI_STATUS\r
+IsApReady (\r
+  IN SPIN_LOCK  *Token\r
+  );\r
+\r
+/**\r
+  Check whether it is an present AP.\r
+\r
+  @param   CpuIndex      The AP index which calls this function.\r
+\r
+  @retval  TRUE           It's a present AP.\r
+  @retval  TRUE           This is not an AP or it is not present.\r
+\r
+**/\r
+BOOLEAN\r
+IsPresentAp (\r
+  IN UINTN  CpuIndex\r
+  );\r
+\r
+/**\r
+  Worker function to execute a caller provided function on all enabled APs.\r
+\r
+  @param[in]     Procedure               A pointer to the function to be run on\r
+                                         enabled APs of the system.\r
+  @param[in]     TimeoutInMicroseconds   Indicates the time limit in microseconds for\r
+                                         APs to return from Procedure, either for\r
+                                         blocking or non-blocking mode.\r
+  @param[in,out] ProcedureArguments      The parameter passed into Procedure for\r
+                                         all APs.\r
+  @param[in,out] Token                   This is an optional parameter that allows the caller to execute the\r
+                                         procedure in a blocking or non-blocking fashion. If it is NULL the\r
+                                         call is blocking, and the call will not return until the AP has\r
+                                         completed the procedure. If the token is not NULL, the call will\r
+                                         return immediately. The caller can check whether the procedure has\r
+                                         completed with CheckOnProcedure or WaitForProcedure.\r
+  @param[in,out] CPUStatus               This optional pointer may be used to get the status code returned\r
+                                         by Procedure when it completes execution on the target AP, or with\r
+                                         EFI_TIMEOUT if the Procedure fails to complete within the optional\r
+                                         timeout. The implementation will update this variable with\r
+                                         EFI_NOT_READY prior to starting Procedure on the target AP.\r
+\r
+  @retval EFI_SUCCESS             In blocking mode, all APs have finished before\r
+                                  the timeout expired.\r
+  @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched\r
+                                  to all enabled APs.\r
+  @retval others                  Failed to Startup all APs.\r
+\r
+**/\r
+EFI_STATUS\r
+InternalSmmStartupAllAPs (\r
+  IN       EFI_AP_PROCEDURE2  Procedure,\r
+  IN       UINTN              TimeoutInMicroseconds,\r
+  IN OUT   VOID               *ProcedureArguments OPTIONAL,\r
+  IN OUT   MM_COMPLETION      *Token,\r
+  IN OUT   EFI_STATUS         *CPUStatus\r
+  );\r
+\r
+/**\r
+\r
+  Register the SMM Foundation entry point.\r
+\r
+  @param[in]      Procedure            A pointer to the code stream to be run on the designated target AP\r
+                                       of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2\r
+                                       with the related definitions of\r
+                                       EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.\r
+                                       If caller may pass a value of NULL to deregister any existing\r
+                                       startup procedure.\r
+  @param[in,out]  ProcedureArguments   Allows the caller to pass a list of parameters to the code that is\r
+                                       run by the AP. It is an optional common mailbox between APs and\r
+                                       the caller to share information\r
+\r
+  @retval EFI_SUCCESS                  The Procedure has been set successfully.\r
+  @retval EFI_INVALID_PARAMETER        The Procedure is NULL but ProcedureArguments not NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterStartupProcedure (\r
+  IN     EFI_AP_PROCEDURE  Procedure,\r
+  IN OUT VOID              *ProcedureArguments OPTIONAL\r
+  );\r
+\r
+/**\r
+  Allocate buffer for SpinLock and Wrapper function buffer.\r
+\r
+**/\r
+VOID\r
+InitializeDataForMmMp (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Return whether access to non-SMRAM is restricted.\r
+\r
+  @retval TRUE  Access to non-SMRAM is restricted.\r
+  @retval FALSE Access to non-SMRAM is not restricted.\r
+**/\r
+BOOLEAN\r
+IsRestrictedMemoryAccess (\r
+  VOID\r
   );\r
 \r
 #endif\r