}\r
\r
/**\r
+ Allocate reset vector buffer.\r
+\r
+ @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+AllocateResetVector (\r
+ IN OUT CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ApResetVectorSize;\r
+ EFI_PHYSICAL_ADDRESS StartAddress;\r
+\r
+ ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +\r
+ sizeof (MP_CPU_EXCHANGE_INFO);\r
+\r
+ StartAddress = BASE_1MB;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (ApResetVectorSize),\r
+ &StartAddress\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ CpuMpData->WakeupBuffer = (UINTN) StartAddress;\r
+ CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)\r
+ (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);\r
+ //\r
+ // copy AP reset code in it\r
+ //\r
+ CopyMem (\r
+ (VOID *) CpuMpData->WakeupBuffer,\r
+ (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,\r
+ CpuMpData->AddressMap.RendezvousFunnelSize\r
+ );\r
+}\r
+\r
+/**\r
+ Free AP reset vector buffer.\r
+\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+FreeResetVector (\r
+ IN CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ApResetVectorSize;\r
+ ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +\r
+ sizeof (MP_CPU_EXCHANGE_INFO);\r
+ Status = gBS->FreePages(\r
+ (EFI_PHYSICAL_ADDRESS)CpuMpData->WakeupBuffer,\r
+ EFI_SIZE_TO_PAGES (ApResetVectorSize)\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
/**\r
Checks APs status and updates APs status if needed.\r
\r
CheckAndUpdateApsStatus ();\r
}\r
}\r
+\r
/**\r
Initialize global data for MP support.\r
\r
IN BOOLEAN EnableOldBSP\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ EFI_STATUS Status;\r
+ BOOLEAN OldInterruptState;\r
+\r
+ //\r
+ // Before send both BSP and AP to a procedure to exchange their roles,\r
+ // interrupt must be disabled. This is because during the exchange role\r
+ // process, 2 CPU may use 1 stack. If interrupt happens, the stack will\r
+ // be corrupted, since interrupt return address will be pushed to stack\r
+ // by hardware.\r
+ //\r
+ OldInterruptState = SaveAndDisableInterrupts ();\r
+\r
+ //\r
+ // Mask LINT0 & LINT1 for the old BSP\r
+ //\r
+ DisableLvtInterrupts ();\r
+\r
+ Status = SwitchBSPWorker (ProcessorNumber, EnableOldBSP);\r
+\r
+ //\r
+ // Restore interrupt state.\r
+ //\r
+ SetInterruptState (OldInterruptState);\r
+\r
+ return Status;\r
}\r
\r
/**\r
IN UINT32 *HealthFlag OPTIONAL\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ EFI_STATUS Status;\r
+ BOOLEAN TempStopCheckState;\r
+\r
+ TempStopCheckState = FALSE;\r
+ //\r
+ // temporarily stop checkAllAPsStatus for initialize parameters.\r
+ //\r
+ if (!mStopCheckAllApsStatus) {\r
+ mStopCheckAllApsStatus = TRUE;\r
+ TempStopCheckState = TRUE;\r
+ }\r
+\r
+ Status = EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);\r
+\r
+ if (TempStopCheckState) {\r
+ mStopCheckAllApsStatus = FALSE;\r
+ }\r
+\r
+ return Status;\r
}\r