]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/MpServicesOnFrameworkMpServicesThunk/MpServicesOnFrameworkMpServicesThunk.c
EdkCompatibilityPkg: Fix typos in comments
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / MpServicesOnFrameworkMpServicesThunk / MpServicesOnFrameworkMpServicesThunk.c
index 4d0918fa78c7af6d90f13c38da5dc836e085bcb7..73c89a10f026e4763d9040d80509fdd06593b34f 100644 (file)
@@ -4,8 +4,8 @@ Produces PI MP Services Protocol on top of Framework MP Services Protocol.
 Intel's Framework MP Services Protocol is replaced by EFI_MP_SERVICES_PROTOCOL in PI 1.1.\r
 This module produces PI MP Services Protocol on top of Framework MP Services Protocol.\r
 \r
-Copyright (c) 2009 - 2010 Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2009 - 2010, 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
 http://opensource.org/licenses/bsd-license.php\r
@@ -22,7 +22,6 @@ EFI_HANDLE                          mHandle = NULL;
 MP_SYSTEM_DATA                      mMPSystemData;\r
 EFI_PHYSICAL_ADDRESS                mStartupVector;\r
 MP_CPU_EXCHANGE_INFO                *mExchangeInfo;\r
-VOID                                *mStackStartAddress;\r
 BOOLEAN                             mStopCheckAPsStatus = FALSE;\r
 UINTN                               mNumberOfProcessors;\r
 EFI_GENERIC_MEMORY_TEST_PROTOCOL    *mGenMemoryTest;\r
@@ -117,7 +116,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 +164,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 +207,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 +274,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 +317,7 @@ StartupAllAPs (
       }\r
     }\r
   }\r
-  \r
+\r
   //\r
   // If no enabled AP exists, return EFI_NOT_STARTED.\r
   //\r
@@ -532,6 +531,12 @@ SwitchBSP (
   CPU_DATA_BLOCK        *CpuData;\r
   UINTN                 CallerNumber;\r
   UINTN                 BspNumber;\r
+  UINTN                 ApicBase;\r
+  UINT32                CurrentTimerValue;\r
+  UINT32                CurrentTimerRegister;\r
+  UINT32                CurrentTimerDivide;\r
+  UINT64                CurrentTscValue;\r
+  BOOLEAN               OldInterruptState;\r
 \r
   //\r
   // Check whether caller processor is BSP\r
@@ -572,6 +577,28 @@ SwitchBSP (
     return EFI_NOT_READY;\r
   }\r
 \r
+  //\r
+  // Save and disable interrupt.\r
+  //\r
+  OldInterruptState = SaveAndDisableInterrupts ();\r
+       \r
+  //\r
+  // Record the current local APIC timer setting of BSP\r
+  //\r
+  ApicBase = (UINTN)AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE, 12, 35) << 12;\r
+  CurrentTimerValue     = MmioRead32 (ApicBase + APIC_REGISTER_TIMER_COUNT);\r
+  CurrentTimerRegister  = MmioRead32 (ApicBase + APIC_REGISTER_LVT_TIMER);\r
+  CurrentTimerDivide    = MmioRead32 (ApicBase + APIC_REGISTER_TIMER_DIVIDE);\r
+  //\r
+  // Set mask bit (BIT 16) of LVT Timer Register to disable its interrupt\r
+  //\r
+  MmioBitFieldWrite32 (ApicBase + APIC_REGISTER_LVT_TIMER, 16, 16, 1);\r
+\r
+  //\r
+  // Record the current TSC value\r
+  //\r
+  CurrentTscValue = AsmReadTsc ();\r
+  \r
   Status = mFrameworkMpService->SwitchBSP (\r
                                   mFrameworkMpService,\r
                                   ProcessorNumber,\r
@@ -579,6 +606,23 @@ SwitchBSP (
                                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // Restore TSC value\r
+  //\r
+  AsmWriteMsr64 (MSR_IA32_TIME_STAMP_COUNTER, CurrentTscValue);\r
+\r
+  //\r
+  // Restore local APIC timer setting to new BSP\r
+  //\r
+  MmioWrite32 (ApicBase + APIC_REGISTER_TIMER_DIVIDE, CurrentTimerDivide);\r
+  MmioWrite32 (ApicBase + APIC_REGISTER_TIMER_INIT_COUNT, CurrentTimerValue);\r
+  MmioWrite32 (ApicBase + APIC_REGISTER_LVT_TIMER, CurrentTimerRegister);\r
+\r
+  //\r
+  // Restore interrupt state.\r
+  //\r
+  SetInterruptState (OldInterruptState);\r
+  \r
   ChangeCpuState (BspNumber, EnableOldBSP);\r
 \r
   return EFI_SUCCESS;\r
@@ -599,7 +643,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 +705,7 @@ EnableDisableAP (
   ASSERT_EFI_ERROR (Status);\r
 \r
   ChangeCpuState (ProcessorNumber, EnableAP);\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -703,7 +747,7 @@ WhoAmI (
 /**\r
   Checks APs' status periodically.\r
 \r
-  This function is triggerred by timer perodically to check the\r
+  This function is triggered by timer periodically to check the\r
   state of APs for StartupAllAPs() and StartupThisAP() executed\r
   in non-blocking mode.\r
 \r
@@ -721,7 +765,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 +897,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 +964,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 +1119,7 @@ GetNextWaitingProcessorNumber (
   return EFI_NOT_FOUND;\r
 }\r
 \r
+\r
 /**\r
   Wrapper function for all procedures assigned to AP.\r
 \r
@@ -1092,6 +1137,17 @@ ApProcWrapper (
   UINTN                 ProcessorNumber;\r
   CPU_DATA_BLOCK        *CpuData;\r
 \r
+  //\r
+  // Program virtual wire mode for AP, since it will be lost after AP wake up\r
+  //\r
+  ProgramVirtualWireMode ();\r
+  DisableLvtInterrupts ();\r
+\r
+  //\r
+  // Initialize Debug Agent to support source level debug on AP code.\r
+  //\r
+  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);\r
+\r
   WhoAmI (&mMpService, &ProcessorNumber);\r
   CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
 \r
@@ -1129,81 +1185,9 @@ ApProcWrapper (
   ReleaseSpinLock (&CpuData->CpuDataLock);\r
 }\r
 \r
-/**\r
-  Sends INIT-SIPI-SIPI to AP.\r
-\r
-  This function sends INIT-SIPI-SIPI to AP, and assign procedure specified by ApFunction.\r
-\r
-  @param  Broadcast   If TRUE, broadcase IPI to all APs; otherwise, send to specified AP.\r
-  @param  ApicID      The Local APIC ID of the specified AP. If Broadcast is TRUE, it is ignored.\r
-  @param  ApFunction  The procedure for AP to work on.\r
-\r
-**/\r
-VOID\r
-SendInitSipiSipi (\r
-  IN BOOLEAN            Broadcast,\r
-  IN UINT32             ApicID,\r
-  IN VOID               *ApFunction\r
-  )\r
-{\r
-  UINTN                 ApicBase;\r
-  UINT32                ICRLow;\r
-  UINT32                ICRHigh;\r
-  \r
-  UINT32                VectorNumber;\r
-  UINT32                DeliveryMode;\r
-\r
-  mExchangeInfo->ApFunction = ApFunction;\r
-  mExchangeInfo->StackStart = mStackStartAddress;\r
-\r
-  if (Broadcast) {\r
-    ICRHigh = 0;\r
-    ICRLow  = BROADCAST_MODE_ALL_EXCLUDING_SELF_BIT | TRIGGER_MODE_LEVEL_BIT | ASSERT_BIT;\r
-  } else {\r
-    ICRHigh = ApicID << 24;\r
-    ICRLow  = SPECIFY_CPU_MODE_BIT | TRIGGER_MODE_LEVEL_BIT | ASSERT_BIT;\r
-  }\r
-\r
-  VectorNumber = 0;\r
-  DeliveryMode = DELIVERY_MODE_INIT;\r
-  ICRLow      |= VectorNumber | (DeliveryMode << 8);\r
-\r
-  ApicBase = 0xfee00000;\r
-\r
-  //\r
-  // Write Interrupt Command Registers to send INIT IPI.\r
-  //\r
-  MmioWrite32 (ApicBase + APIC_REGISTER_ICR_HIGH_OFFSET, ICRHigh);\r
-  MmioWrite32 (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET, ICRLow);\r
-\r
-  MicroSecondDelay (10);\r
-\r
-  VectorNumber = (UINT32) RShiftU64 (mStartupVector, 12);\r
-  DeliveryMode = DELIVERY_MODE_SIPI;\r
-  if (Broadcast) {\r
-    ICRLow = BROADCAST_MODE_ALL_EXCLUDING_SELF_BIT | TRIGGER_MODE_LEVEL_BIT | ASSERT_BIT;\r
-  } else {\r
-    ICRLow = SPECIFY_CPU_MODE_BIT | TRIGGER_MODE_LEVEL_BIT | ASSERT_BIT;\r
-  }\r
-\r
-  ICRLow |= VectorNumber | (DeliveryMode << 8);\r
-\r
-  //\r
-  // Write Interrupt Command Register to send first SIPI IPI.\r
-  //\r
-  MmioWrite32 (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET, ICRLow);\r
-\r
-  MicroSecondDelay (200);\r
-\r
-  //\r
-  // Write Interrupt Command Register to send second SIPI IPI.\r
-  //\r
-  MmioWrite32 (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET, ICRLow);\r
-}\r
-\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
@@ -1237,16 +1221,17 @@ WakeUpAp (
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  mExchangeInfo->ApFunction = (VOID *) (UINTN) ApProcWrapper;\r
+  mExchangeInfo->ProcessorNumber[ProcessorInfoBuffer.ProcessorId] = (UINT32) ProcessorNumber;\r
   SendInitSipiSipi (\r
-    FALSE,\r
     (UINT32) ProcessorInfoBuffer.ProcessorId,\r
-    (VOID *) (UINTN) ApProcWrapper\r
+    (UINT32) (UINTN) mStartupVector\r
     );\r
 }\r
 \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
@@ -1269,10 +1254,11 @@ ResetProcessorToIdleState (
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  mExchangeInfo->ApFunction = NULL;\r
+  mExchangeInfo->ProcessorNumber[ProcessorInfoBuffer.ProcessorId] = (UINT32) ProcessorNumber;\r
   SendInitSipiSipi (\r
-    FALSE,\r
     (UINT32) ProcessorInfoBuffer.ProcessorId,\r
-    NULL\r
+    (UINT32) (UINTN) mStartupVector\r
     );\r
 \r
   CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
@@ -1444,7 +1430,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
@@ -1479,10 +1467,11 @@ PrepareAPStartupVector (
 \r
   ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));\r
 \r
-  mStackStartAddress = AllocatePages (EFI_SIZE_TO_PAGES (MAX_CPU_NUMBER * AP_STACK_SIZE));\r
+  mExchangeInfo->StackStart  = AllocatePages (EFI_SIZE_TO_PAGES (mNumberOfProcessors * AP_STACK_SIZE));\r
   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 +1480,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 +1501,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 +1519,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 +1549,7 @@ GetBspNumber (
                                     &ProcessorContextBuffer\r
                                     );\r
     ASSERT_EFI_ERROR (Status);\r
-    \r
+\r
     if (ProcessorContextBuffer.Designation == EfiCpuBSP) {\r
       break;\r
     }\r
@@ -1568,9 +1562,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
@@ -1583,14 +1577,12 @@ InitializeMpServicesProtocol (
 {\r
   EFI_STATUS Status;\r
 \r
-  PrepareMemoryForConfiguration ();\r
-\r
   //\r
   // 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
@@ -1606,6 +1598,8 @@ InitializeMpServicesProtocol (
   ASSERT_EFI_ERROR (Status);\r
   ASSERT (mNumberOfProcessors < MAX_CPU_NUMBER);\r
 \r
+  PrepareMemoryForConfiguration ();\r
+\r
   //\r
   // Create timer event to check AP state for non-blocking execution.\r
   //\r