/** @file\r
Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.\r
\r
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
\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
-\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 <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
// 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
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
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
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
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