/** @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
\r
#include <Guid/AcpiS3Context.h>\r
+#include <Guid/MemoryAttributesTable.h>\r
#include <Guid/PiSmmMemoryAttributesTable.h>\r
\r
#include <Library/BaseLib.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
#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 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
// 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
extern UINT8 mSmmSaveStateRegisterLma;\r
\r
-\r
//\r
// SMM CPU Protocol function prototypes.\r
//\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
volatile BOOLEAN *CandidateBsp;\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
///\r
volatile BOOLEAN *AllCpusInSync;\r
SPIN_LOCK *PFLock;\r
SPIN_LOCK *CodeAccessCheckLock;\r
- SPIN_LOCK *MemoryMappedLock;\r
} SMM_CPU_SEMAPHORE_GLOBAL;\r
\r
///\r
volatile BOOLEAN *Present;\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 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
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
OUT UINTN *GdtStepSize\r
);\r
\r
-/**\r
- This function sets GDT/IDT buffer to be RO and XP.\r
-**/\r
-VOID\r
-PatchGdtIdtMap (\r
- VOID\r
- );\r
-\r
/**\r
\r
Register the SMM Foundation entry point.\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
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
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 absoute 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 absoute 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
#endif\r