]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: Make sure AP uses correct StartupApSignal
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
index 61b14c98438e85544ed63700923144f0b41d18e5..742f0c1f5e7b5b7b89e000e3c2695ae5ccbcf096 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   CPU MP Initialize Library common functions.\r
 \r
-  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2018, 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
@@ -195,6 +195,10 @@ SaveVolatileRegisters (
     VolatileRegisters->Dr6 = AsmReadDr6 ();\r
     VolatileRegisters->Dr7 = AsmReadDr7 ();\r
   }\r
+\r
+  AsmReadGdtr (&VolatileRegisters->Gdtr);\r
+  AsmReadIdtr (&VolatileRegisters->Idtr);\r
+  VolatileRegisters->Tr = AsmReadTr ();\r
 }\r
 \r
 /**\r
@@ -211,6 +215,7 @@ RestoreVolatileRegisters (
   )\r
 {\r
   CPUID_VERSION_INFO_EDX        VersionInfoEdx;\r
+  IA32_TSS_DESCRIPTOR           *Tss;\r
 \r
   AsmWriteCr0 (VolatileRegisters->Cr0);\r
   AsmWriteCr3 (VolatileRegisters->Cr3);\r
@@ -231,6 +236,18 @@ RestoreVolatileRegisters (
       AsmWriteDr7 (VolatileRegisters->Dr7);\r
     }\r
   }\r
+\r
+  AsmWriteGdtr (&VolatileRegisters->Gdtr);\r
+  AsmWriteIdtr (&VolatileRegisters->Idtr);\r
+  if (VolatileRegisters->Tr != 0 &&\r
+      VolatileRegisters->Tr < VolatileRegisters->Gdtr.Limit) {\r
+    Tss = (IA32_TSS_DESCRIPTOR *)(VolatileRegisters->Gdtr.Base +\r
+                                  VolatileRegisters->Tr);\r
+    if (Tss->Bits.P == 1) {\r
+      Tss->Bits.Type &= 0xD;  // 1101 - Clear busy bit just in case\r
+      AsmWriteTr (VolatileRegisters->Tr);\r
+    }\r
+  }\r
 }\r
 \r
 /**\r
@@ -313,6 +330,7 @@ SortApicId (
   CPU_INFO_IN_HOB   CpuInfo;\r
   UINT32            ApCount;\r
   CPU_INFO_IN_HOB   *CpuInfoInHob;\r
+  volatile UINT32   *StartupApSignal;\r
 \r
   ApCount = CpuMpData->CpuCount - 1;\r
   CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;\r
@@ -337,6 +355,14 @@ SortApicId (
           sizeof (CPU_INFO_IN_HOB)\r
           );\r
         CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB));\r
+\r
+        //\r
+        // Also exchange the StartupApSignal.\r
+        //\r
+        StartupApSignal = CpuMpData->CpuData[Index3].StartupApSignal;\r
+        CpuMpData->CpuData[Index3].StartupApSignal =\r
+          CpuMpData->CpuData[Index1].StartupApSignal;\r
+        CpuMpData->CpuData[Index1].StartupApSignal = StartupApSignal;\r
       }\r
     }\r
 \r
@@ -565,6 +591,10 @@ ApWakeupFunction (
   // We need to re-initialize them at here\r
   //\r
   ProgramVirtualWireMode ();\r
+  //\r
+  // Mask the LINT0 and LINT1 so that AP doesn't enter the system timer interrupt handler.\r
+  //\r
+  DisableLvtInterrupts ();\r
   SyncLocalApicTimerSetting (CpuMpData);\r
 \r
   CurrentApicMode = GetApicMode ();\r
@@ -751,6 +781,8 @@ FillExchangeInfoData (
   )\r
 {\r
   volatile MP_CPU_EXCHANGE_INFO    *ExchangeInfo;\r
+  UINTN                            Size;\r
+  IA32_SEGMENT_DESCRIPTOR          *Selector;\r
 \r
   ExchangeInfo                  = CpuMpData->MpCpuExchangeInfo;\r
   ExchangeInfo->Lock            = 0;\r
@@ -780,6 +812,45 @@ FillExchangeInfoData (
   //\r
   AsmReadGdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->GdtrProfile);\r
   AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);\r
+\r
+  //\r
+  // Find a 32-bit code segment\r
+  //\r
+  Selector = (IA32_SEGMENT_DESCRIPTOR *)ExchangeInfo->GdtrProfile.Base;\r
+  Size = ExchangeInfo->GdtrProfile.Limit + 1;\r
+  while (Size > 0) {\r
+    if (Selector->Bits.L == 0 && Selector->Bits.Type >= 8) {\r
+      ExchangeInfo->ModeTransitionSegment =\r
+        (UINT16)((UINTN)Selector - ExchangeInfo->GdtrProfile.Base);\r
+      break;\r
+    }\r
+    Selector += 1;\r
+    Size -= sizeof (IA32_SEGMENT_DESCRIPTOR);\r
+  }\r
+\r
+  //\r
+  // Copy all 32-bit code and 64-bit code into memory with type of\r
+  // EfiBootServicesCode to avoid page fault if NX memory protection is enabled.\r
+  //\r
+  if (CpuMpData->WakeupBufferHigh != 0) {\r
+    Size = CpuMpData->AddressMap.RendezvousFunnelSize -\r
+           CpuMpData->AddressMap.ModeTransitionOffset;\r
+    CopyMem (\r
+      (VOID *)CpuMpData->WakeupBufferHigh,\r
+      CpuMpData->AddressMap.RendezvousFunnelAddress +\r
+      CpuMpData->AddressMap.ModeTransitionOffset,\r
+      Size\r
+      );\r
+\r
+    ExchangeInfo->ModeTransitionMemory = (UINT32)CpuMpData->WakeupBufferHigh;\r
+    ExchangeInfo->ModeHighMemory = (UINT32)CpuMpData->WakeupBufferHigh +\r
+                                   (UINT32)ExchangeInfo->ModeOffset -\r
+                                   (UINT32)CpuMpData->AddressMap.ModeTransitionOffset;\r
+    ExchangeInfo->ModeHighSegment = (UINT16)ExchangeInfo->CodeSegment;\r
+  } else {\r
+    ExchangeInfo->ModeTransitionMemory = (UINT32)\r
+      (ExchangeInfo->BufferStart + CpuMpData->AddressMap.ModeTransitionOffset);\r
+  }\r
 }\r
 \r
 /**\r
@@ -855,6 +926,10 @@ AllocateResetVector (
     CpuMpData->WakeupBuffer      = GetWakeupBuffer (ApResetVectorSize);\r
     CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)\r
                     (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);\r
+    CpuMpData->WakeupBufferHigh  = GetModeTransitionBuffer (\r
+                                    CpuMpData->AddressMap.RendezvousFunnelSize -\r
+                                    CpuMpData->AddressMap.ModeTransitionOffset\r
+                                    );\r
   }\r
   BackupAndPrepareWakeupBuffer (CpuMpData);\r
 }\r
@@ -1481,7 +1556,7 @@ MpInitLibInitialize (
   //\r
   // Set BSP basic information\r
   //\r
-  InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer);\r
+  InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer + ApStackSize);\r
   //\r
   // Save assembly code information\r
   //\r
@@ -1750,6 +1825,7 @@ SwitchBSPWorker (
   ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
   ApicBaseMsr.Bits.BSP = 1;\r
   AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);\r
+  ProgramVirtualWireMode ();\r
 \r
   //\r
   // Wait for old BSP finished AP task\r