]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.c
index 8c9fa14b5b3e21b2bfc9cc631768541e9fc84a72..80dbf152b066c239a6341cdb4476a27f46e86bd8 100644 (file)
@@ -1,7 +1,7 @@
 /** @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
@@ -94,6 +94,9 @@ UINTN mSmmStackArrayBase;
 UINTN mSmmStackArrayEnd;\r
 UINTN mSmmStackSize;\r
 \r
+UINTN mSmmShadowStackSize;\r
+BOOLEAN mCetSupported = TRUE;\r
+\r
 UINTN mMaxNumberOfCpus = 1;\r
 UINTN mNumberOfCpus = 1;\r
 \r
@@ -420,7 +423,7 @@ SmmRelocateBases (
   PatchInstructionX86 (gPatchSmmCr0, mSmmCr0, 4);\r
   PatchInstructionX86 (gPatchSmmCr3, AsmReadCr3 (), 4);\r
   mSmmCr4 = (UINT32)AsmReadCr4 ();\r
-  PatchInstructionX86 (gPatchSmmCr4, mSmmCr4, 4);\r
+  PatchInstructionX86 (gPatchSmmCr4, mSmmCr4 & (~CR4_CET_ENABLE), 4);\r
 \r
   //\r
   // Patch GDTR for SMM base relocation\r
@@ -550,6 +553,8 @@ PiCpuSmmEntry (
   UINT8                      *Stacks;\r
   VOID                       *Registration;\r
   UINT32                     RegEax;\r
+  UINT32                     RegEbx;\r
+  UINT32                     RegEcx;\r
   UINT32                     RegEdx;\r
   UINTN                      FamilyId;\r
   UINTN                      ModelId;\r
@@ -726,6 +731,32 @@ PiCpuSmmEntry (
     }\r
   }\r
 \r
+  DEBUG ((DEBUG_INFO, "PcdControlFlowEnforcementPropertyMask = %d\n", PcdGet32 (PcdControlFlowEnforcementPropertyMask)));\r
+  if (PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) {\r
+    AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
+    if (RegEax > CPUID_EXTENDED_FUNCTION) {\r
+      AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, &RegEdx);\r
+      DEBUG ((DEBUG_INFO, "CPUID[7/0] ECX - 0x%08x\n", RegEcx));\r
+      DEBUG ((DEBUG_INFO, "  CET_SS  - 0x%08x\n", RegEcx & CPUID_CET_SS));\r
+      DEBUG ((DEBUG_INFO, "  CET_IBT - 0x%08x\n", RegEdx & CPUID_CET_IBT));\r
+      if ((RegEcx & CPUID_CET_SS) == 0) {\r
+        mCetSupported = FALSE;\r
+        PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
+      }\r
+      if (mCetSupported) {\r
+        AsmCpuidEx (CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF, NULL, &RegEbx, &RegEcx, NULL);\r
+        DEBUG ((DEBUG_INFO, "CPUID[D/1] EBX - 0x%08x, ECX - 0x%08x\n", RegEbx, RegEcx));\r
+        AsmCpuidEx (CPUID_EXTENDED_STATE, 11, &RegEax, NULL, &RegEcx, NULL);\r
+        DEBUG ((DEBUG_INFO, "CPUID[D/11] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));\r
+        AsmCpuidEx(CPUID_EXTENDED_STATE, 12, &RegEax, NULL, &RegEcx, NULL);\r
+        DEBUG ((DEBUG_INFO, "CPUID[D/12] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));\r
+      }\r
+    }\r
+  } else {\r
+    mCetSupported = FALSE;\r
+    PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
+  }\r
+\r
   //\r
   // Compute tile size of buffer required to hold the CPU SMRAM Save State Map, extra CPU\r
   // specific context start starts at SMBASE + SMM_PSD_OFFSET, and the SMI entry point.\r
@@ -828,6 +859,7 @@ PiCpuSmmEntry (
   //\r
   // Allocate SMI stacks for all processors.\r
   //\r
+  mSmmStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)));\r
   if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
     //\r
     // 2 more pages is allocated for each processor.\r
@@ -839,15 +871,39 @@ PiCpuSmmEntry (
     // |                                           |     |                                           |\r
     // |<-------------- Processor 0 -------------->|     |<-------------- Processor n -------------->|\r
     //\r
-    mSmmStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)) + 2);\r
-    Stacks = (UINT8 *) AllocatePages (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)) + 2));\r
-    ASSERT (Stacks != NULL);\r
-    mSmmStackArrayBase = (UINTN)Stacks;\r
-    mSmmStackArrayEnd = mSmmStackArrayBase + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * mSmmStackSize - 1;\r
-  } else {\r
-    mSmmStackSize = PcdGet32 (PcdCpuSmmStackSize);\r
-    Stacks = (UINT8 *) AllocatePages (EFI_SIZE_TO_PAGES (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * mSmmStackSize));\r
-    ASSERT (Stacks != NULL);\r
+    mSmmStackSize += EFI_PAGES_TO_SIZE (2);\r
+  }\r
+\r
+  mSmmShadowStackSize = 0;\r
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {\r
+    //\r
+    // Append Shadow Stack after normal stack\r
+    //\r
+    // |= Stacks\r
+    // +--------------------------------------------------+---------------------------------------------------------------+\r
+    // | Known Good Stack | Guard Page |    SMM Stack     | Known Good Shadow Stack | Guard Page |    SMM Shadow Stack    |\r
+    // +--------------------------------------------------+---------------------------------------------------------------+\r
+    // |                               |PcdCpuSmmStackSize|                                      |PcdCpuSmmShadowStackSize|\r
+    // |<---------------- mSmmStackSize ----------------->|<--------------------- mSmmShadowStackSize ------------------->|\r
+    // |                                                                                                                  |\r
+    // |<-------------------------------------------- Processor N ------------------------------------------------------->|\r
+    //\r
+    mSmmShadowStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmShadowStackSize)));\r
+    if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
+      mSmmShadowStackSize += EFI_PAGES_TO_SIZE (2);\r
+    }\r
+  }\r
+\r
+  Stacks = (UINT8 *) AllocatePages (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * (EFI_SIZE_TO_PAGES (mSmmStackSize + mSmmShadowStackSize)));\r
+  ASSERT (Stacks != NULL);\r
+  mSmmStackArrayBase = (UINTN)Stacks;\r
+  mSmmStackArrayEnd = mSmmStackArrayBase + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * (mSmmStackSize + mSmmShadowStackSize) - 1;\r
+\r
+  DEBUG ((DEBUG_INFO, "Stacks                   - 0x%x\n", Stacks));\r
+  DEBUG ((DEBUG_INFO, "mSmmStackSize            - 0x%x\n", mSmmStackSize));\r
+  DEBUG ((DEBUG_INFO, "PcdCpuSmmStackGuard      - 0x%x\n", FeaturePcdGet (PcdCpuSmmStackGuard)));\r
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {\r
+    DEBUG ((DEBUG_INFO, "mSmmShadowStackSize      - 0x%x\n", mSmmShadowStackSize));\r
   }\r
 \r
   //\r
@@ -887,7 +943,24 @@ PiCpuSmmEntry (
   //\r
   // Initialize MP globals\r
   //\r
-  Cr3 = InitializeMpServiceData (Stacks, mSmmStackSize);\r
+  Cr3 = InitializeMpServiceData (Stacks, mSmmStackSize, mSmmShadowStackSize);\r
+\r
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {\r
+    for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {\r
+      SetShadowStack (\r
+        Cr3,\r
+        (EFI_PHYSICAL_ADDRESS)(UINTN)Stacks + mSmmStackSize + (mSmmStackSize + mSmmShadowStackSize) * Index,\r
+        mSmmShadowStackSize\r
+        );\r
+      if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
+        SetNotPresentPage (\r
+          Cr3,\r
+          (EFI_PHYSICAL_ADDRESS)(UINTN)Stacks + mSmmStackSize + EFI_PAGES_TO_SIZE(1) + (mSmmStackSize + mSmmShadowStackSize) * Index,\r
+          EFI_PAGES_TO_SIZE(1)\r
+          );\r
+      }\r
+    }\r
+  }\r
 \r
   //\r
   // Fill in SMM Reserved Regions\r