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
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
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
);\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
/**\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
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
UINTN ProcessorNumber;\r
CPU_DATA_BLOCK *CpuData;\r
\r
- ProgramVirtualWireMode (FALSE);\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
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
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
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
\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
{\r
EFI_STATUS Status;\r
\r
- PrepareMemoryForConfiguration ();\r
-\r
//\r
// Locates Framework version MP Services Protocol\r
//\r
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