when stack NX has been enabled for BSP.

DxeIpl may have enabled Execute Disable for BSP,
APs need to get the status and sync up the settings,
otherwise EFI_MP_SERVICES_PROTOCOL->StartupAllAPs
may not work.

Got positive comments and test result from Laszlo
for the early draft patch, thanks.

Cc: Laszlo Ersek <ler...@redhat.com>
Cc: Jeff Fan <jeff....@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.z...@intel.com>
---
 UefiCpuPkg/CpuDxe/ApStartup.c | 133 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 132 insertions(+), 1 deletion(-)

diff --git a/UefiCpuPkg/CpuDxe/ApStartup.c b/UefiCpuPkg/CpuDxe/ApStartup.c
index 7613b47..6f617a0 100644
--- a/UefiCpuPkg/CpuDxe/ApStartup.c
+++ b/UefiCpuPkg/CpuDxe/ApStartup.c
@@ -19,6 +19,47 @@
 #pragma pack(1)
 
 typedef struct {
+  UINT8  MoveIa32EferMsrToEcx[5];
+  UINT8  ReadIa32EferMsr[2];
+  UINT8  SetExecuteDisableBitEnableBit[4];
+  UINT8  WriteIa32EferMsr[2];
+
+#if defined (MDE_CPU_IA32)
+  UINT8  MovEaxCr3;
+  UINT32 Cr3Value;
+  UINT8  MovCr3Eax[3];
+
+  UINT8  MoveCr4ToEax[3];
+  UINT8  SetCr4Bit5[4];
+  UINT8  MoveEaxToCr4[3];
+
+  UINT8  MoveCr0ToEax[3];
+  UINT8  SetCr0PagingBit[4];
+  UINT8  MoveEaxToCr0[3];
+#endif
+} ENABLE_EXECUTE_DISABLE_CODE;
+
+ENABLE_EXECUTE_DISABLE_CODE mEnableExecuteDisableCodeTemplate = {
+  { 0xB9, 0x80, 0x00, 0x00, 0xC0 },   // mov ecx, 0xc0000080
+  { 0x0F, 0x32 },                     // rdmsr
+  { 0x0F, 0xBA, 0xE8, 0x0B },         // bts eax, 11
+  { 0x0F, 0x30 },                     // wrmsr
+
+#if defined (MDE_CPU_IA32)
+  0xB8, 0x00000000,                   // mov eax, cr3 value
+  { 0x0F, 0x22, 0xd8 },               // mov cr3, eax
+
+  { 0x0F, 0x20, 0xE0 },               // mov eax, cr4
+  { 0x0F, 0xBA, 0xE8, 0x05 },         // bts eax, 5
+  { 0x0F, 0x22, 0xE0 },               // mov cr4, eax
+
+  { 0x0F, 0x20, 0xC0 },               // mov eax, cr0
+  { 0x0F, 0xBA, 0xE8, 0x1F },         // bts eax, 31
+  { 0x0F, 0x22, 0xC0 },               // mov cr0, eax
+#endif
+};
+
+typedef struct {
   UINT8  JmpToCli[2];
 
   UINT16 GdtLimit;
@@ -52,6 +93,12 @@ typedef struct {
   UINT8  MoveFlatDataSelectorFromAxToGs[2];
   UINT8  MoveFlatDataSelectorFromAxToSs[2];
 
+  //
+  // Code placeholder to enable PAE Execute Disable for IA32
+  // and enable Execute Disable Bit for X64
+  //
+  ENABLE_EXECUTE_DISABLE_CODE EnableExecuteDisable;
+
 #if defined (MDE_CPU_X64)
   //
   // Transition to X64
@@ -207,6 +254,17 @@ STARTUP_CODE mStartupCodeTemplate = {
   { 0x8e, 0xd0 },                     // mov ss, ax
 
 #if defined (MDE_CPU_X64)
+  //
+  // Code placeholder to enable Execute Disable Bit for X64
+  // Default is all NOP - No Operation
+  //
+  {
+    { 0x90, 0x90, 0x90, 0x90, 0x90 },
+    { 0x90, 0x90 },
+    { 0x90, 0x90, 0x90, 0x90 },
+    { 0x90, 0x90 },
+  },
+
   0xB8, 0x00000000,                   // mov eax, cr3 value
   { 0x0F, 0x22, 0xd8 },               // mov cr3, eax
 
@@ -226,7 +284,29 @@ STARTUP_CODE mStartupCodeTemplate = {
   0xEA,                               // FarJmp32LongMode
         OFFSET_OF(STARTUP_CODE, MovEaxOrRaxCpuDxeEntry),
         LINEAR_CODE64_SEL,
-#endif // defined (MDE_CPU_X64)
+#else
+  //
+  // Code placeholder to enable PAE Execute Disable for IA32
+  // Default is all NOP - No Operation
+  //
+  {
+    { 0x90, 0x90, 0x90, 0x90, 0x90 },
+    { 0x90, 0x90 },
+    { 0x90, 0x90, 0x90, 0x90 },
+    { 0x90, 0x90 },
+
+    0x90, 0x90909090,
+    { 0x90, 0x90, 0x90 },
+
+    { 0x90, 0x90, 0x90 },
+    { 0x90, 0x90, 0x90, 0x90 },
+    { 0x90, 0x90, 0x90 },
+
+    { 0x90, 0x90, 0x90 },
+    { 0x90, 0x90, 0x90, 0x90 },
+    { 0x90, 0x90, 0x90 },
+  },
+#endif
 
   //0xeb, 0xfe,       // jmp $
 #if defined (MDE_CPU_X64)
@@ -241,6 +321,48 @@ STARTUP_CODE mStartupCodeTemplate = {
 volatile STARTUP_CODE *StartupCode = NULL;
 
 /**
+  The function will check if BSP Execute Disable is enabled.
+  DxeIpl may have enabled Execute Disable for BSP,
+  APs need to get the status and sync up the settings.
+
+  @retval TRUE      BSP Execute Disable is enabled.
+  @retval FALSE     BSP Execute Disable is not enabled.
+
+**/
+BOOLEAN
+IsBspExecuteDisableEnabled (
+  VOID
+  )
+{
+  UINT32            RegEax;
+  UINT32            RegEdx;
+  UINT64            MsrRegisters;
+  BOOLEAN           Enabled;
+
+  Enabled = FALSE;
+  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+  if (RegEax >= 0x80000001) {
+    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+    //
+    // Cpuid 0x80000001
+    // Bit 20: Execute Disable Bit available.
+    //
+    if ((RegEdx & BIT20) != 0) {
+      MsrRegisters = AsmReadMsr64 (0xC0000080);
+      //
+      // Msr 0xC0000080
+      // Bit 11: Execute Disable Bit enable.
+      //
+      if ((MsrRegisters & BIT11) != 0) {
+        Enabled = TRUE;
+      }
+    }
+  }
+
+  return Enabled;
+}
+
+/**
   Prepares Startup Code for APs.
   This function prepares Startup Code for APs.
 
@@ -280,9 +402,18 @@ PrepareAPStartupCode (
 
   StartupCode->FlatJmpOffset += (UINT32) StartAddress;
 
+  if (IsBspExecuteDisableEnabled ()) {
+    CopyMem (
+      (VOID*) &StartupCode->EnableExecuteDisable,
+      &mEnableExecuteDisableCodeTemplate,
+      sizeof (ENABLE_EXECUTE_DISABLE_CODE)
+      );
+  }
 #if defined (MDE_CPU_X64)
   StartupCode->Cr3Value = (UINT32) AsmReadCr3 ();
   StartupCode->LongJmpOffset += (UINT32) StartAddress;
+#else
+  StartupCode->EnableExecuteDisable.Cr3Value = (UINT32) AsmReadCr3 ();
 #endif
 
   return EFI_SUCCESS;
-- 
1.9.5.msysgit.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to