]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/ApStartup.c
MdeModulePkg BaseSerialPortLib16550: Fix typo in SerialPortWrite()
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / ApStartup.c
index 801f7f8611fd77c63730b1f110c8a505ab4981a0..78fb26f9856abc9a468de88d9da1f28b81c7c6a4 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   CPU DXE AP Startup\r
 \r
-  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2008 - 2015, 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
 \r
 #pragma pack(1)\r
 \r
+typedef struct {\r
+  UINT8  MoveIa32EferMsrToEcx[5];\r
+  UINT8  ReadIa32EferMsr[2];\r
+  UINT8  SetExecuteDisableBitEnableBit[4];\r
+  UINT8  WriteIa32EferMsr[2];\r
+\r
+#if defined (MDE_CPU_IA32)\r
+  UINT8  MovEaxCr3;\r
+  UINT32 Cr3Value;\r
+  UINT8  MovCr3Eax[3];\r
+\r
+  UINT8  MoveCr4ToEax[3];\r
+  UINT8  SetCr4Bit5[4];\r
+  UINT8  MoveEaxToCr4[3];\r
+\r
+  UINT8  MoveCr0ToEax[3];\r
+  UINT8  SetCr0PagingBit[4];\r
+  UINT8  MoveEaxToCr0[3];\r
+#endif\r
+} ENABLE_EXECUTE_DISABLE_CODE;\r
+\r
+ENABLE_EXECUTE_DISABLE_CODE mEnableExecuteDisableCodeTemplate = {\r
+  { 0xB9, 0x80, 0x00, 0x00, 0xC0 },   // mov ecx, 0xc0000080\r
+  { 0x0F, 0x32 },                     // rdmsr\r
+  { 0x0F, 0xBA, 0xE8, 0x0B },         // bts eax, 11\r
+  { 0x0F, 0x30 },                     // wrmsr\r
+\r
+#if defined (MDE_CPU_IA32)\r
+  0xB8, 0x00000000,                   // mov eax, cr3 value\r
+  { 0x0F, 0x22, 0xd8 },               // mov cr3, eax\r
+\r
+  { 0x0F, 0x20, 0xE0 },               // mov eax, cr4\r
+  { 0x0F, 0xBA, 0xE8, 0x05 },         // bts eax, 5\r
+  { 0x0F, 0x22, 0xE0 },               // mov cr4, eax\r
+\r
+  { 0x0F, 0x20, 0xC0 },               // mov eax, cr0\r
+  { 0x0F, 0xBA, 0xE8, 0x1F },         // bts eax, 31\r
+  { 0x0F, 0x22, 0xC0 },               // mov cr0, eax\r
+#endif\r
+};\r
+\r
 typedef struct {\r
   UINT8  JmpToCli[2];\r
 \r
@@ -52,6 +93,12 @@ typedef struct {
   UINT8  MoveFlatDataSelectorFromAxToGs[2];\r
   UINT8  MoveFlatDataSelectorFromAxToSs[2];\r
 \r
+  //\r
+  // Code placeholder to enable PAE Execute Disable for IA32\r
+  // and enable Execute Disable Bit for X64\r
+  //\r
+  ENABLE_EXECUTE_DISABLE_CODE EnableExecuteDisable;\r
+\r
 #if defined (MDE_CPU_X64)\r
   //\r
   // Transition to X64\r
@@ -207,6 +254,17 @@ STARTUP_CODE mStartupCodeTemplate = {
   { 0x8e, 0xd0 },                     // mov ss, ax\r
 \r
 #if defined (MDE_CPU_X64)\r
+  //\r
+  // Code placeholder to enable Execute Disable Bit for X64\r
+  // Default is all NOP - No Operation\r
+  //\r
+  {\r
+    { 0x90, 0x90, 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90 },\r
+    { 0x90, 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90 },\r
+  },\r
+\r
   0xB8, 0x00000000,                   // mov eax, cr3 value\r
   { 0x0F, 0x22, 0xd8 },               // mov cr3, eax\r
 \r
@@ -226,7 +284,29 @@ STARTUP_CODE mStartupCodeTemplate = {
   0xEA,                               // FarJmp32LongMode\r
         OFFSET_OF(STARTUP_CODE, MovEaxOrRaxCpuDxeEntry),\r
         LINEAR_CODE64_SEL,\r
-#endif // defined (MDE_CPU_X64)\r
+#else\r
+  //\r
+  // Code placeholder to enable PAE Execute Disable for IA32\r
+  // Default is all NOP - No Operation\r
+  //\r
+  {\r
+    { 0x90, 0x90, 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90 },\r
+    { 0x90, 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90 },\r
+\r
+    0x90, 0x90909090,\r
+    { 0x90, 0x90, 0x90 },\r
+\r
+    { 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90, 0x90 },\r
+\r
+    { 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90, 0x90, 0x90 },\r
+    { 0x90, 0x90, 0x90 },\r
+  },\r
+#endif\r
 \r
   //0xeb, 0xfe,       // jmp $\r
 #if defined (MDE_CPU_X64)\r
@@ -240,6 +320,48 @@ STARTUP_CODE mStartupCodeTemplate = {
 \r
 volatile STARTUP_CODE *StartupCode = NULL;\r
 \r
+/**\r
+  The function will check if BSP Execute Disable is enabled.\r
+  DxeIpl may have enabled Execute Disable for BSP,\r
+  APs need to get the status and sync up the settings.\r
+\r
+  @retval TRUE      BSP Execute Disable is enabled.\r
+  @retval FALSE     BSP Execute Disable is not enabled.\r
+\r
+**/\r
+BOOLEAN\r
+IsBspExecuteDisableEnabled (\r
+  VOID\r
+  )\r
+{\r
+  UINT32            RegEax;\r
+  UINT32            RegEdx;\r
+  UINT64            MsrRegisters;\r
+  BOOLEAN           Enabled;\r
+\r
+  Enabled = FALSE;\r
+  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+  if (RegEax >= 0x80000001) {\r
+    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+    //\r
+    // Cpuid 0x80000001\r
+    // Bit 20: Execute Disable Bit available.\r
+    //\r
+    if ((RegEdx & BIT20) != 0) {\r
+      MsrRegisters = AsmReadMsr64 (0xC0000080);\r
+      //\r
+      // Msr 0xC0000080\r
+      // Bit 11: Execute Disable Bit enable.\r
+      //\r
+      if ((MsrRegisters & BIT11) != 0) {\r
+        Enabled = TRUE;\r
+      }\r
+    }\r
+  }\r
+\r
+  return Enabled;\r
+}\r
+\r
 /**\r
   Prepares Startup Code for APs.\r
   This function prepares Startup Code for APs.\r
@@ -280,9 +402,18 @@ PrepareAPStartupCode (
 \r
   StartupCode->FlatJmpOffset += (UINT32) StartAddress;\r
 \r
+  if (IsBspExecuteDisableEnabled ()) {\r
+    CopyMem (\r
+      (VOID*) &StartupCode->EnableExecuteDisable,\r
+      &mEnableExecuteDisableCodeTemplate,\r
+      sizeof (ENABLE_EXECUTE_DISABLE_CODE)\r
+      );\r
+  }\r
 #if defined (MDE_CPU_X64)\r
   StartupCode->Cr3Value = (UINT32) AsmReadCr3 ();\r
   StartupCode->LongJmpOffset += (UINT32) StartAddress;\r
+#else\r
+  StartupCode->EnableExecuteDisable.Cr3Value = (UINT32) AsmReadCr3 ();\r
 #endif\r
 \r
   return EFI_SUCCESS;\r
@@ -321,10 +452,27 @@ StartApsStackless (
 {\r
   SendInitSipiSipiAllExcludingSelf ((UINT32)(UINTN)(VOID*) StartupCode);\r
   //\r
-  // Wait 100 milliseconds for APs to arrive at the ApEntryPoint routine\r
+  // Wait for APs to arrive at the ApEntryPoint routine\r
   //\r
-  MicroSecondDelay (100 * 1000);\r
+  MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Resets the Application Processor and directs it to jump to the\r
+  specified routine.\r
+\r
+  The processor jumps to this code in flat mode, but the processor's\r
+  stack is not initialized.\r
+\r
+  @param ProcessorId           the AP of ProcessorId was reset\r
+**/\r
+VOID\r
+ResetApStackless (\r
+  IN UINT32 ProcessorId\r
+  )\r
+{\r
+  SendInitSipiSipi (ProcessorId,\r
+                    (UINT32)(UINTN)(VOID*) StartupCode);\r
+}\r