]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/MpServicesOnFrameworkMpServicesThunk/MpServicesOnFrameworkMpServicesThunk.c
1.Restore BSP IDT table to AP when AP wakeup.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / MpServicesOnFrameworkMpServicesThunk / MpServicesOnFrameworkMpServicesThunk.c
index 4097b9e87ac80592f561fa36c4fa63f93107aa7a..3ff503758d84916819d7a347ea6ed4dfd1778e59 100644 (file)
@@ -117,7 +117,7 @@ GetNumberOfProcessors (
   @retval EFI_SUCCESS           Processor information successfully returned.\r
   @retval EFI_DEVICE_ERROR      Caller processor is AP.\r
   @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL\r
-  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist. \r
+  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -165,7 +165,7 @@ GetProcessorInfo (
   ASSERT_EFI_ERROR (Status);\r
 \r
   ProcessorInfoBuffer->ProcessorId = (UINT64) ProcessorContextBuffer.ApicID;\r
-  \r
+\r
   //\r
   // Get Status Flag of specified processor\r
   //\r
@@ -208,7 +208,7 @@ GetProcessorInfo (
   @param  FailedCpuList         The list of processor numbers that fail to finish the function before\r
                                 TimeoutInMicrosecsond expires.\r
 \r
-  @retval EFI_SUCCESS           In blocking mode, all APs have finished before the timeout expired. \r
+  @retval EFI_SUCCESS           In blocking mode, all APs have finished before the timeout expired.\r
   @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to all enabled APs.\r
   @retval EFI_DEVICE_ERROR      Caller processor is AP.\r
   @retval EFI_NOT_STARTED       No enabled AP exists in the system.\r
@@ -275,7 +275,7 @@ StartupAllAPs (
           mStopCheckAPsStatus = FALSE;\r
           return EFI_NOT_READY;\r
         } else {\r
-          //     \r
+          //\r
           // Mark this processor as responsible for current calling.\r
           //\r
           mMPSystemData.CpuList[ProcessorNumber] = TRUE;\r
@@ -318,7 +318,7 @@ StartupAllAPs (
       }\r
     }\r
   }\r
-  \r
+\r
   //\r
   // If no enabled AP exists, return EFI_NOT_STARTED.\r
   //\r
@@ -599,7 +599,7 @@ SwitchBSP (
   @retval EFI_DEVICE_ERROR       Caller processor is AP.\r
   @retval EFI_NOT_FOUND          Processor with the handle specified by ProcessorNumber does not exist.\r
   @retval EFI_INVALID_PARAMETERS ProcessorNumber specifies the BSP.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -661,7 +661,7 @@ EnableDisableAP (
   ASSERT_EFI_ERROR (Status);\r
 \r
   ChangeCpuState (ProcessorNumber, EnableAP);\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -721,7 +721,7 @@ CheckAPsStatus (
   UINTN           ProcessorNumber;\r
   CPU_DATA_BLOCK  *CpuData;\r
   EFI_STATUS      Status;\r
-  \r
+\r
   //\r
   // If CheckAPsStatus() is stopped, then return immediately.\r
   //\r
@@ -853,7 +853,7 @@ CheckAllAPs (
       ASSERT (*mMPSystemData.FailedCpuList != NULL);\r
     }\r
     ListIndex = 0;\r
\r
+\r
     for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
       //\r
       // Check whether this processor is responsible for StartupAllAPs().\r
@@ -920,7 +920,7 @@ CheckThisAP (
     AcquireSpinLock (&CpuData->CpuDataLock);\r
     CpuData->State = CpuStateIdle;\r
     ReleaseSpinLock (&CpuData->CpuDataLock);\r
-    \r
+\r
     if (CpuData->Finished != NULL) {\r
       *(CpuData->Finished) = TRUE;\r
     }\r
@@ -1075,6 +1075,71 @@ GetNextWaitingProcessorNumber (
   return EFI_NOT_FOUND;\r
 }\r
 \r
+/**\r
+  Programs Local APIC registers for virtual wire mode.\r
+\r
+  This function programs Local APIC registers for virtual wire mode.\r
+\r
+  @param  Bsp  Indicates whether the programmed processor is going to be BSP\r
+\r
+**/\r
+VOID\r
+ProgramVirtualWireMode (\r
+  BOOLEAN                       Bsp\r
+  )\r
+{\r
+  UINTN                 ApicBase;\r
+  UINT32                Value;\r
+\r
+  ApicBase = (UINTN)AsmMsrBitFieldRead64 (27, 12, 35) << 12;\r
+\r
+  //\r
+  // Program the Spurious Vector entry\r
+  // Set bit 8 (APIC Software Enable/Disable) to enable local APIC,\r
+  // and set Spurious Vector as 0x0F.\r
+  //\r
+  MmioBitFieldWrite32 (ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET, 0, 9, 0x10F);\r
+\r
+  //\r
+  // Program the LINT0 vector entry as ExtInt\r
+  // Set bits 8..10 to 7 as ExtInt Delivery Mode,\r
+  // and clear bits for Delivery Status, Interrupt Input Pin Polarity, Remote IRR,\r
+  // Trigger Mode, and Mask\r
+  //\r
+  if (!Bsp) {\r
+    DisableInterrupts ();\r
+  }\r
+  Value = MmioRead32 (ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET);\r
+  Value = BitFieldWrite32 (Value, 8, 10, 7);\r
+  Value = BitFieldWrite32 (Value, 12, 16, 0);\r
+  if (!Bsp) {\r
+    //\r
+    // For APs, LINT0 is masked\r
+    //\r
+    Value = BitFieldWrite32 (Value, 16, 16, 1);\r
+  }\r
+  MmioWrite32 (ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET, Value);\r
+\r
+  //\r
+  // Program the LINT1 vector entry as NMI\r
+  // Set bits 8..10 to 4 as NMI Delivery Mode,\r
+  // and clear bits for Delivery Status, Interrupt Input Pin Polarity, Remote IRR,\r
+  // Trigger Mode.\r
+  // For BSP clear Mask bit, and for AP set mask bit.\r
+  //\r
+  Value = MmioRead32 (ApicBase + APIC_REGISTER_LINT1_VECTOR_OFFSET);\r
+  Value = BitFieldWrite32 (Value, 8, 10, 4);\r
+  Value = BitFieldWrite32 (Value, 12, 16, 0);\r
+  if (!Bsp) {\r
+    //\r
+    // For APs, LINT1 is masked\r
+    //\r
+    Value = BitFieldWrite32 (Value, 16, 16, 1);\r
+  }\r
+  MmioWrite32 (ApicBase + APIC_REGISTER_LINT1_VECTOR_OFFSET, Value);\r
+}\r
+\r
+\r
 /**\r
   Wrapper function for all procedures assigned to AP.\r
 \r
@@ -1092,6 +1157,8 @@ ApProcWrapper (
   UINTN                 ProcessorNumber;\r
   CPU_DATA_BLOCK        *CpuData;\r
 \r
+  ProgramVirtualWireMode (FALSE);\r
+\r
   WhoAmI (&mMpService, &ProcessorNumber);\r
   CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
 \r
@@ -1149,7 +1216,7 @@ SendInitSipiSipi (
   UINTN                 ApicBase;\r
   UINT32                ICRLow;\r
   UINT32                ICRHigh;\r
-  \r
+\r
   UINT32                VectorNumber;\r
   UINT32                DeliveryMode;\r
 \r
@@ -1203,7 +1270,7 @@ SendInitSipiSipi (
 \r
 /**\r
   Function to wake up a specified AP and assign procedure to it.\r
-  \r
+\r
   @param  ProcessorNumber  Handle number of the specified processor.\r
   @param  Procedure        Procedure to assign.\r
   @param  ProcArguments    Argument for Procedure.\r
@@ -1246,7 +1313,7 @@ WakeUpAp (
 \r
 /**\r
   Terminate AP's task and set it to idle state.\r
-  \r
+\r
   This function terminates AP's task due to timeout by sending INIT-SIPI,\r
   and sends it to idle state.\r
 \r
@@ -1444,7 +1511,9 @@ PrepareAPStartupVector (
 {\r
   MP_ASSEMBLY_ADDRESS_MAP   AddressMap;\r
   IA32_DESCRIPTOR           GdtrForBSP;\r
+  IA32_DESCRIPTOR           IdtrForBSP;\r
   EFI_PHYSICAL_ADDRESS      GdtForAP;\r
+  EFI_PHYSICAL_ADDRESS      IdtForAP;\r
   EFI_STATUS                Status;\r
 \r
   //\r
@@ -1483,6 +1552,7 @@ PrepareAPStartupVector (
   mExchangeInfo->StackSize  = AP_STACK_SIZE;\r
 \r
   AsmReadGdtr (&GdtrForBSP);\r
+  AsmReadIdtr (&IdtrForBSP);\r
 \r
   //\r
   // Allocate memory under 4G to hold GDT for APs\r
@@ -1491,15 +1561,20 @@ PrepareAPStartupVector (
   Status   = gBS->AllocatePages (\r
                     AllocateMaxAddress,\r
                     EfiBootServicesData,\r
-                    EFI_SIZE_TO_PAGES (GdtrForBSP.Limit + 1),\r
+                    EFI_SIZE_TO_PAGES ((GdtrForBSP.Limit + 1) + (IdtrForBSP.Limit + 1)),\r
                     &GdtForAP\r
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  IdtForAP = (UINTN) GdtForAP + GdtrForBSP.Limit + 1;\r
+\r
   CopyMem ((VOID *) (UINTN) GdtForAP, (VOID *) GdtrForBSP.Base, GdtrForBSP.Limit + 1);\r
+  CopyMem ((VOID *) (UINTN) IdtForAP, (VOID *) IdtrForBSP.Base, IdtrForBSP.Limit + 1);\r
 \r
   mExchangeInfo->GdtrProfile.Base  = (UINTN) GdtForAP;\r
   mExchangeInfo->GdtrProfile.Limit = GdtrForBSP.Limit;\r
+  mExchangeInfo->IdtrProfile.Base  = (UINTN) IdtForAP;\r
+  mExchangeInfo->IdtrProfile.Limit = IdtrForBSP.Limit;\r
 \r
   mExchangeInfo->BufferStart = (UINT32) mStartupVector;\r
   mExchangeInfo->Cr3         = (UINT32) (AsmReadCr3 ());\r
@@ -1507,7 +1582,7 @@ PrepareAPStartupVector (
 \r
 /**\r
   Prepares memory region for processor configuration.\r
-  \r
+\r
   This function prepares memory region for processor configuration.\r
 \r
 **/\r
@@ -1525,13 +1600,13 @@ PrepareMemoryForConfiguration (
   for (Index = 0; Index < MAX_CPU_NUMBER; Index++) {\r
     InitializeSpinLock (&mMPSystemData.CpuData[Index].CpuDataLock);\r
   }\r
-  \r
+\r
   PrepareAPStartupVector ();\r
 }\r
 \r
 /**\r
   Gets the processor number of BSP.\r
-  \r
+\r
   @return  The processor number of BSP.\r
 \r
 **/\r
@@ -1555,7 +1630,7 @@ GetBspNumber (
                                     &ProcessorContextBuffer\r
                                     );\r
     ASSERT_EFI_ERROR (Status);\r
-    \r
+\r
     if (ProcessorContextBuffer.Designation == EfiCpuBSP) {\r
       break;\r
     }\r
@@ -1568,9 +1643,9 @@ GetBspNumber (
 /**\r
   Entrypoint of MP Services Protocol thunk driver.\r
 \r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
   @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
+\r
   @retval EFI_SUCCESS       The entry point is executed successfully.\r
 \r
 **/\r
@@ -1589,8 +1664,8 @@ InitializeMpServicesProtocol (
   // Locates Framework version MP Services Protocol\r
   //\r
   Status = gBS->LocateProtocol (\r
-                  &gFrameworkEfiMpServiceProtocolGuid, \r
-                  NULL, \r
+                  &gFrameworkEfiMpServiceProtocolGuid,\r
+                  NULL,\r
                   (VOID **) &mFrameworkMpService\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r