APs to help test system memory in parallel with other device initialization.\r
Diagnostics applications may also use this protocol for multi-processor.\r
\r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
Portitions Copyright (c) 2011, Apple Inc. All rights reserved.\r
This program and the accompanying materials are licensed and made available under\r
the terms and conditions of the BSD License that accompanies this distribution.\r
EFI_STATUS Status;\r
UINTN ProcessorNumber;\r
\r
- Status = CpuMpServicesWhoAmI (&mMpSercicesTemplate, &ProcessorNumber);\r
+ Status = CpuMpServicesWhoAmI (&mMpServicesTemplate, &ProcessorNumber);\r
if (EFI_ERROR (Status)) {\r
return FALSE;\r
}\r
return EFI_NOT_FOUND;\r
}\r
\r
+/**\r
+ * Calculated and stalled the interval time by BSP to check whether\r
+ * the APs have finished.\r
+ *\r
+ * @param[in] Timeout The time limit in microseconds for\r
+ * APs to return from Procedure.\r
+ *\r
+ * @retval StallTime Time of execution stall.\r
+**/\r
+UINTN\r
+CalculateAndStallInterval (\r
+ IN UINTN Timeout\r
+ )\r
+{\r
+ UINTN StallTime;\r
\r
+ if (Timeout < gPollInterval && Timeout != 0) {\r
+ StallTime = Timeout;\r
+ } else {\r
+ StallTime = gPollInterval;\r
+ }\r
+ gBS->Stall (StallTime);\r
\r
+ return StallTime;\r
+}\r
\r
/**\r
This service retrieves the number of logical processor in the platform\r
{\r
EFI_STATUS Status;\r
PROCESSOR_DATA_BLOCK *ProcessorData;\r
- UINTN ListIndex;\r
UINTN Number;\r
UINTN NextNumber;\r
PROCESSOR_STATE APInitialState;\r
PROCESSOR_STATE ProcessorState;\r
- INTN Timeout;\r
+ UINTN Timeout;\r
\r
\r
if (!IsBSP ()) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {\r
+ ProcessorData = &gMPSystem.ProcessorData[Number];\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+ // Skip BSP\r
+ continue;\r
+ }\r
+\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+ // Skip Disabled processors\r
+ continue;\r
+ }\r
+ gThread->MutexLock(ProcessorData->StateLock);\r
+ if (ProcessorData->State != CPU_STATE_IDLE) {\r
+ gThread->MutexUnlock (ProcessorData->StateLock);\r
+ return EFI_NOT_READY;\r
+ }\r
+ gThread->MutexUnlock(ProcessorData->StateLock);\r
+ }\r
\r
if (FailedCpuList != NULL) {\r
gMPSystem.FailedList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));\r
\r
Timeout = TimeoutInMicroseconds;\r
\r
- ListIndex = 0;\r
ProcessorData = NULL;\r
\r
gMPSystem.FinishCount = 0;\r
// state 1 by 1, until the previous 1 finished its task\r
// if not "SingleThread", all APs are put to ready state from the beginning\r
//\r
- if (ProcessorData->State == CPU_STATE_IDLE) {\r
- gMPSystem.StartCount++;\r
-\r
- gThread->MutexLock (&ProcessorData->StateLock);\r
- ProcessorData->State = APInitialState;\r
- gThread->MutexUnlock (&ProcessorData->StateLock);\r
+ gThread->MutexLock(ProcessorData->StateLock);\r
+ ASSERT (ProcessorData->State == CPU_STATE_IDLE);\r
+ ProcessorData->State = APInitialState;\r
+ gThread->MutexUnlock (ProcessorData->StateLock);\r
\r
- if (SingleThread) {\r
- APInitialState = CPU_STATE_BLOCKED;\r
- }\r
- } else {\r
- return EFI_NOT_READY;\r
+ gMPSystem.StartCount++;\r
+ if (SingleThread) {\r
+ APInitialState = CPU_STATE_BLOCKED;\r
}\r
}\r
\r
continue;\r
}\r
\r
- SetApProcedure (ProcessorData, Procedure, ProcedureArgument);\r
+ gThread->MutexLock (ProcessorData->StateLock);\r
+ ProcessorState = ProcessorData->State;\r
+ gThread->MutexUnlock (ProcessorData->StateLock);\r
+\r
+ if (ProcessorState == CPU_STATE_READY) {\r
+ SetApProcedure (ProcessorData, Procedure, ProcedureArgument);\r
+ }\r
}\r
\r
//\r
if (SingleThread) {\r
Status = GetNextBlockedNumber (&NextNumber);\r
if (!EFI_ERROR (Status)) {\r
+ gThread->MutexLock (gMPSystem.ProcessorData[NextNumber].StateLock);\r
gMPSystem.ProcessorData[NextNumber].State = CPU_STATE_READY;\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[NextNumber].StateLock);\r
}\r
}\r
\r
+ gThread->MutexLock (ProcessorData->StateLock);\r
ProcessorData->State = CPU_STATE_IDLE;\r
+ gThread->MutexUnlock (ProcessorData->StateLock);\r
+\r
break;\r
\r
default:\r
goto Done;\r
}\r
\r
- if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
+ if ((TimeoutInMicroseconds != 0) && (Timeout == 0)) {\r
Status = EFI_TIMEOUT;\r
goto Done;\r
}\r
\r
- gBS->Stall (gPollInterval);\r
- Timeout -= gPollInterval;\r
+ Timeout -= CalculateAndStallInterval (Timeout);\r
}\r
\r
Done:\r
OUT BOOLEAN *Finished OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
- INTN Timeout;\r
+ UINTN Timeout;\r
\r
if (!IsBSP ()) {\r
return EFI_DEVICE_ERROR;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ if ((gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ gThread->MutexLock(gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
if (gMPSystem.ProcessorData[ProcessorNumber].State != CPU_STATE_IDLE) {\r
+ gThread->MutexUnlock(gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
return EFI_NOT_READY;\r
}\r
+ gThread->MutexUnlock(gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
\r
if ((WaitEvent != NULL) && gReadToBoot) {\r
return EFI_UNSUPPORTED;\r
SetApProcedure (&gMPSystem.ProcessorData[ProcessorNumber], Procedure, ProcedureArgument);\r
\r
if (WaitEvent != NULL) {\r
- // Non Blocking\r
- gMPSystem.WaitEvent = WaitEvent;\r
- Status = gBS->SetTimer (\r
- gMPSystem.ProcessorData[ProcessorNumber].CheckThisAPEvent,\r
- TimerPeriodic,\r
- gPollInterval\r
- );\r
+ // Non Blocking\r
+ gMPSystem.WaitEvent = WaitEvent;\r
+ gBS->SetTimer (\r
+ gMPSystem.ProcessorData[ProcessorNumber].CheckThisAPEvent,\r
+ TimerPeriodic,\r
+ gPollInterval\r
+ );\r
return EFI_SUCCESS;\r
}\r
\r
// Blocking\r
while (TRUE) {\r
- gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ gThread->MutexLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
if (gMPSystem.ProcessorData[ProcessorNumber].State == CPU_STATE_FINISHED) {\r
gMPSystem.ProcessorData[ProcessorNumber].State = CPU_STATE_IDLE;\r
- gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
break;\r
}\r
\r
- gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
\r
- if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
+ if ((TimeoutInMicroseconds != 0) && (Timeout == 0)) {\r
return EFI_TIMEOUT;\r
}\r
\r
- gBS->Stall (gPollInterval);\r
- Timeout -= gPollInterval;\r
+ Timeout -= CalculateAndStallInterval (Timeout);\r
}\r
\r
return EFI_SUCCESS;\r
}\r
ASSERT (Index != gMPSystem.NumberOfProcessors);\r
\r
+ gThread->MutexLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
if (gMPSystem.ProcessorData[ProcessorNumber].State != CPU_STATE_IDLE) {\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
return EFI_NOT_READY;\r
}\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
\r
// Skip for now as we need switch a bunch of stack stuff around and it's complex\r
// May not be worth it?\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ gThread->MutexLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
if (gMPSystem.ProcessorData[ProcessorNumber].State != CPU_STATE_IDLE) {\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
return EFI_UNSUPPORTED;\r
}\r
-\r
- gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
\r
if (EnableAP) {\r
if ((gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0 ) {\r
gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag |= (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT);\r
}\r
\r
- gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
-\r
return EFI_SUCCESS;\r
}\r
\r
\r
\r
\r
-EFI_MP_SERVICES_PROTOCOL mMpSercicesTemplate = {\r
+EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = {\r
CpuMpServicesGetNumberOfProcessors,\r
CpuMpServicesGetProcessorInfo,\r
CpuMpServicesStartupAllAps,\r
BOOLEAN Found;\r
\r
if (gMPSystem.TimeoutActive) {\r
- gMPSystem.Timeout -= gPollInterval;\r
+ gMPSystem.Timeout -= CalculateAndStallInterval (gMPSystem.Timeout);\r
}\r
\r
- ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;\r
-\r
for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {\r
- if ((ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+ ProcessorData = &gMPSystem.ProcessorData[ProcessorNumber];\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
// Skip BSP\r
continue;\r
}\r
// context. Meaning deadlock. Which is a bad thing.\r
// So, try lock it. If we can get it, cool, do our thing.\r
// otherwise, just dump out & try again on the next iteration.\r
- Status = gThread->MutexTryLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ Status = gThread->MutexTryLock (ProcessorData->StateLock);\r
if (EFI_ERROR(Status)) {\r
return;\r
}\r
- ProcessorState = gMPSystem.ProcessorData[ProcessorNumber].State;\r
- gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ ProcessorState = ProcessorData->State;\r
+ gThread->MutexUnlock (ProcessorData->StateLock);\r
\r
switch (ProcessorState) {\r
- case CPU_STATE_READY:\r
- SetApProcedure (ProcessorData, gMPSystem.Procedure, gMPSystem.ProcedureArgument);\r
- break;\r
-\r
case CPU_STATE_FINISHED:\r
if (gMPSystem.SingleThread) {\r
Status = GetNextBlockedNumber (&NextNumber);\r
if (!EFI_ERROR (Status)) {\r
NextData = &gMPSystem.ProcessorData[NextNumber];\r
\r
- gThread->MutexLock (&NextData->ProcedureLock);\r
+ gThread->MutexLock (NextData->StateLock);\r
NextData->State = CPU_STATE_READY;\r
- gThread->MutexUnlock (&NextData->ProcedureLock);\r
+ gThread->MutexUnlock (NextData->StateLock);\r
\r
SetApProcedure (NextData, gMPSystem.Procedure, gMPSystem.ProcedureArgument);\r
}\r
}\r
\r
- gMPSystem.ProcessorData[ProcessorNumber].State = CPU_STATE_IDLE;\r
+ gThread->MutexLock (ProcessorData->StateLock);\r
+ ProcessorData->State = CPU_STATE_IDLE;\r
+ gThread->MutexUnlock (ProcessorData->StateLock);\r
gMPSystem.FinishCount++;\r
break;\r
\r
}\r
}\r
\r
- if (gMPSystem.TimeoutActive && gMPSystem.Timeout < 0) {\r
+ if (gMPSystem.TimeoutActive && gMPSystem.Timeout == 0) {\r
//\r
// Timeout\r
//\r
if (gMPSystem.FailedList != NULL) {\r
for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {\r
- if ((ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
+ ProcessorData = &gMPSystem.ProcessorData[ProcessorNumber];\r
+ if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {\r
// Skip BSP\r
continue;\r
}\r
}\r
\r
// Mark the\r
- Status = gThread->MutexTryLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ Status = gThread->MutexTryLock (ProcessorData->StateLock);\r
if (EFI_ERROR(Status)) {\r
return;\r
}\r
- ProcessorState = gMPSystem.ProcessorData[ProcessorNumber].State;\r
- gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+ ProcessorState = ProcessorData->State;\r
+ gThread->MutexUnlock (ProcessorData->StateLock);\r
\r
if (ProcessorState != CPU_STATE_IDLE) {\r
// If we are retrying make sure we don't double count\r
IN UINTN ProcessorNumber\r
)\r
{\r
- PROCESSOR_DATA_BLOCK *ProcessorData;\r
-\r
- ProcessorData = &gMPSystem.ProcessorData[ProcessorNumber];\r
-\r
gMPSystem.ProcessorData[ProcessorNumber].Info.ProcessorId = gThread->Self ();\r
gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;\r
if (BSP) {\r
gMPSystem.ProcessorData[ProcessorNumber].Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;\r
}\r
\r
- gMPSystem.ProcessorData[ProcessorNumber].Info.Location.Package = ProcessorNumber;\r
+ gMPSystem.ProcessorData[ProcessorNumber].Info.Location.Package = (UINT32) ProcessorNumber;\r
gMPSystem.ProcessorData[ProcessorNumber].Info.Location.Core = 0;\r
gMPSystem.ProcessorData[ProcessorNumber].Info.Location.Thread = 0;\r
gMPSystem.ProcessorData[ProcessorNumber].State = BSP ? CPU_STATE_BUSY : CPU_STATE_IDLE;\r
\r
EFI_STATUS\r
CpuMpServicesInit (\r
- VOID\r
+ OUT UINTN *MaxCpus\r
)\r
{\r
EFI_STATUS Status;\r
EFI_HANDLE Handle;\r
EMU_IO_THUNK_PROTOCOL *IoThunk;\r
- UINTN MaxCpus;\r
-\r
- MaxCpus = 1; // BSP\r
\r
+ *MaxCpus = 1; // BSP\r
IoThunk = GetIoThunkInstance (&gEmuThreadThunkProtocolGuid, 0);\r
if (IoThunk != NULL) {\r
Status = IoThunk->Open (IoThunk);\r
if (!EFI_ERROR (Status)) {\r
if (IoThunk->ConfigString != NULL) {\r
- MaxCpus += StrDecimalToUintn (IoThunk->ConfigString);\r
+ *MaxCpus += StrDecimalToUintn (IoThunk->ConfigString);\r
gThread = IoThunk->Interface;\r
}\r
}\r
}\r
\r
- if (MaxCpus == 1) {\r
+ if (*MaxCpus == 1) {\r
// We are not MP so nothing to do\r
return EFI_SUCCESS;\r
}\r
\r
- gPollInterval = PcdGet64 (PcdEmuMpServicesPollingInterval);\r
+ gPollInterval = (UINTN) PcdGet64 (PcdEmuMpServicesPollingInterval);\r
\r
- Status = InitializeMpSystemData (MaxCpus);\r
+ Status = InitializeMpSystemData (*MaxCpus);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
Handle = NULL;\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&Handle,\r
- &gEfiMpServiceProtocolGuid, &mMpSercicesTemplate,\r
+ &gEfiMpServiceProtocolGuid, &mMpServicesTemplate,\r
NULL\r
);\r
return Status;\r