/** @file\r
Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.\r
\r
-Copyright (c) 2009 - 2016, 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 - 2019, 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
#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
#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
#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
#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/Msr.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 IA32_PG_PMNT BIT62\r
#define IA32_PG_NX BIT63\r
\r
-#define PAGE_ATTRIBUTE_BITS (IA32_PG_RW | IA32_PG_P)\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 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
#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
+ BOOLEAN Used;\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
// Contains the SMM Configuration Protocols that is produced.\r
EFI_SMM_ENTRY_POINT SmmCoreEntry;\r
\r
EFI_SMM_CONFIGURATION_PROTOCOL SmmConfiguration;\r
+\r
+ PROCEDURE_WRAPPER *ApWrapperFunc;\r
+ LIST_ENTRY TokenList;\r
} SMM_CPU_PRIVATE_DATA;\r
\r
extern SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate;\r
extern UINTN mMaxNumberOfCpus;\r
extern UINTN mNumberOfCpus;\r
extern EFI_SMM_CPU_PROTOCOL mSmmCpu;\r
+extern EFI_MM_MP_PROTOCOL mSmmMp;\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
\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
\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
\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
\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
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
+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
///\r
typedef struct {\r
SPIN_LOCK *Busy;\r
- volatile EFI_AP_PROCEDURE Procedure;\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
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 MSR_SPIN_LOCK_INIT_NUM 15\r
-\r
-typedef struct {\r
- SPIN_LOCK *SpinLock;\r
- UINT32 MsrIndex;\r
-} MP_MSR_LOCK;\r
-\r
#define SMM_PSD_OFFSET 0xfb00\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
-\r
///\r
/// All global semaphores' pointer\r
///\r
volatile BOOLEAN *AllCpusInSync;\r
SPIN_LOCK *PFLock;\r
SPIN_LOCK *CodeAccessCheckLock;\r
- SPIN_LOCK *MemoryMappedLock;\r
} SMM_CPU_SEMAPHORE_GLOBAL;\r
\r
///\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 MSRs semaphores' pointer and counter\r
-///\r
-typedef struct {\r
- SPIN_LOCK *Msr;\r
- UINTN AvailableCounter;\r
-} SMM_CPU_SEMAPHORE_MSR;\r
-\r
///\r
/// All semaphores' information\r
///\r
typedef struct {\r
SMM_CPU_SEMAPHORE_GLOBAL SemaphoreGlobal;\r
SMM_CPU_SEMAPHORE_CPU SemaphoreCpu;\r
- SMM_CPU_SEMAPHORE_MSR SemaphoreMsr;\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 CONST PROCESSOR_SMM_DESCRIPTOR gcPsd;\r
extern UINT64 gPhyMask;\r
extern SMM_DISPATCHER_MP_SYNC_DATA *mSmmMpSyncData;\r
extern UINTN mSmmStackArrayBase;\r
extern UINTN mSemaphoreSize;\r
extern SPIN_LOCK *mPFLock;\r
extern SPIN_LOCK *mConfigSmmCodeAccessCheckLock;\r
-extern SPIN_LOCK *mMemoryMappedLock;\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 Is32BitPageTable Whether the page table is 32-bit PAE\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
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 UINTN StackSize,\r
+ IN UINTN ShadowStackSize\r
);\r
\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
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
Initialize MP synchronization data.\r
\r
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
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
+ Return page table base.\r
+\r
+ @return page table base.\r
+**/\r
+UINTN\r
+GetPageTableBase (\r
+ VOID\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
This API provides a way to allocate memory for page table.\r
\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
//\r
// S3 related global variable and function prototype.\r
/**\r
Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.\r
\r
- @param[in] ApHltLoopCode The 32-bit 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] 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 UINT32 ApHltLoopCode,\r
- IN UINT32 TopOfStack\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