mirror of https://github.com/acidanthera/audk.git
Cleanup MpService interface. Still needs more testing, but now it is much closer to PI spec.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11669 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
5ec56d19a6
commit
8b6d0c057f
|
@ -109,6 +109,10 @@ typedef struct {
|
||||||
BOOLEAN SingleThread;
|
BOOLEAN SingleThread;
|
||||||
UINTN StartedNumber;
|
UINTN StartedNumber;
|
||||||
PROCESSOR_DATA_BLOCK *ProcessorData;
|
PROCESSOR_DATA_BLOCK *ProcessorData;
|
||||||
|
UINTN Timeout;
|
||||||
|
UINTN *FailedList;
|
||||||
|
UINTN FailedListIndex;
|
||||||
|
BOOLEAN TimeoutActive;
|
||||||
} MP_SYSTEM_DATA;
|
} MP_SYSTEM_DATA;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -402,20 +402,24 @@ CpuMpServicesStartupAllAps (
|
||||||
|
|
||||||
|
|
||||||
if (FailedCpuList != NULL) {
|
if (FailedCpuList != NULL) {
|
||||||
FailledList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));
|
gMPSystem.FailedList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));
|
||||||
SetMemN (FailledList, (gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN), END_OF_CPU_LIST);
|
if (gMPSystem.FailedList == NULL) {
|
||||||
FailedListIndex = 0;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
*FailedCpuList = FailledList;
|
}
|
||||||
|
SetMemN (gMPSystem.FailedList, (gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN), END_OF_CPU_LIST);
|
||||||
|
gMPSystem.FailedListIndex = 0;
|
||||||
|
*FailedCpuList = gMPSystem.FailedList;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timeout = TimeoutInMicroseconds;
|
Timeout = TimeoutInMicroseconds;
|
||||||
|
|
||||||
ListIndex = 0;
|
ListIndex = 0;
|
||||||
ProcessorData = NULL;
|
ProcessorData = NULL;
|
||||||
|
|
||||||
gMPSystem.FinishCount = 0;
|
gMPSystem.FinishCount = 0;
|
||||||
gMPSystem.StartCount = 0;
|
gMPSystem.StartCount = 0;
|
||||||
APInitialState = CPU_STATE_READY;
|
gMPSystem.SingleThread = SingleThread;
|
||||||
|
APInitialState = CPU_STATE_READY;
|
||||||
|
|
||||||
for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {
|
for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {
|
||||||
ProcessorData = &gMPSystem.ProcessorData[Number];
|
ProcessorData = &gMPSystem.ProcessorData[Number];
|
||||||
|
@ -425,6 +429,12 @@ CpuMpServicesStartupAllAps (
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {
|
||||||
|
// Skip Disabled processors
|
||||||
|
gMPSystem.FailedList[gMPSystem.FailedListIndex++] = Number;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get APs prepared, and put failing APs into FailedCpuList
|
// Get APs prepared, and put failing APs into FailedCpuList
|
||||||
// if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
|
// if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
|
||||||
|
@ -441,18 +451,42 @@ CpuMpServicesStartupAllAps (
|
||||||
if (SingleThread) {
|
if (SingleThread) {
|
||||||
APInitialState = CPU_STATE_BLOCKED;
|
APInitialState = CPU_STATE_BLOCKED;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
} else if (FailedCpuList != NULL) {
|
return EFI_NOT_READY;
|
||||||
FailledList[FailedListIndex++] = Number;
|
|
||||||
ListIndex++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FailedCpuList != NULL) {
|
if (WaitEvent != NULL) {
|
||||||
if (FailedListIndex == 0) {
|
for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {
|
||||||
FreePool (*FailedCpuList);
|
ProcessorData = &gMPSystem.ProcessorData[Number];
|
||||||
*FailedCpuList = NULL;
|
if ((ProcessorData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {
|
||||||
|
// Skip BSP
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {
|
||||||
|
// Skip Disabled processors
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetApProcedure (ProcessorData, Procedure, ProcedureArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save data into private data structure, and create timer to poll AP state before exiting
|
||||||
|
//
|
||||||
|
gMPSystem.Procedure = Procedure;
|
||||||
|
gMPSystem.ProcedureArgument = ProcedureArgument;
|
||||||
|
gMPSystem.WaitEvent = WaitEvent;
|
||||||
|
gMPSystem.Timeout = TimeoutInMicroseconds;
|
||||||
|
gMPSystem.TimeoutActive = (BOOLEAN)(TimeoutInMicroseconds != 0);
|
||||||
|
Status = gBS->SetTimer (
|
||||||
|
gMPSystem.CheckAllAPsEvent,
|
||||||
|
TimerPeriodic,
|
||||||
|
gPollInterval
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
@ -463,6 +497,11 @@ CpuMpServicesStartupAllAps (
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {
|
||||||
|
// Skip Disabled processors
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
gThread->MutexLock (ProcessorData->StateLock);
|
gThread->MutexLock (ProcessorData->StateLock);
|
||||||
ProcessorState = ProcessorData->State;
|
ProcessorState = ProcessorData->State;
|
||||||
gThread->MutexUnlock (ProcessorData->StateLock);
|
gThread->MutexUnlock (ProcessorData->StateLock);
|
||||||
|
@ -490,29 +529,27 @@ CpuMpServicesStartupAllAps (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gMPSystem.FinishCount == gMPSystem.StartCount) {
|
if (gMPSystem.FinishCount == gMPSystem.StartCount) {
|
||||||
return EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {
|
if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {
|
||||||
//
|
Status = EFI_TIMEOUT;
|
||||||
// Save data into private data structure, and create timer to poll AP state before exiting
|
goto Done;
|
||||||
//
|
|
||||||
gMPSystem.Procedure = Procedure;
|
|
||||||
gMPSystem.ProcedureArgument = ProcedureArgument;
|
|
||||||
gMPSystem.WaitEvent = WaitEvent;
|
|
||||||
|
|
||||||
Status = gBS->SetTimer (
|
|
||||||
gMPSystem.CheckAllAPsEvent,
|
|
||||||
TimerPeriodic,
|
|
||||||
gPollInterval
|
|
||||||
);
|
|
||||||
return EFI_TIMEOUT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gBS->Stall (gPollInterval);
|
gBS->Stall (gPollInterval);
|
||||||
Timeout -= gPollInterval;
|
Timeout -= gPollInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
if (FailedCpuList != NULL) {
|
||||||
|
if (gMPSystem.FailedListIndex == 0) {
|
||||||
|
FreePool (*FailedCpuList);
|
||||||
|
*FailedCpuList = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,6 +686,18 @@ CpuMpServicesStartupThisAP (
|
||||||
|
|
||||||
SetApProcedure (&gMPSystem.ProcessorData[ProcessorNumber], Procedure, ProcedureArgument);
|
SetApProcedure (&gMPSystem.ProcessorData[ProcessorNumber], Procedure, ProcedureArgument);
|
||||||
|
|
||||||
|
if (WaitEvent != NULL) {
|
||||||
|
// Non Blocking
|
||||||
|
gMPSystem.WaitEvent = WaitEvent;
|
||||||
|
Status = gBS->SetTimer (
|
||||||
|
gMPSystem.ProcessorData[ProcessorNumber].CheckThisAPEvent,
|
||||||
|
TimerPeriodic,
|
||||||
|
gPollInterval
|
||||||
|
);
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocking
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);
|
gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);
|
||||||
if (gMPSystem.ProcessorData[ProcessorNumber].State == CPU_STATE_FINISHED) {
|
if (gMPSystem.ProcessorData[ProcessorNumber].State == CPU_STATE_FINISHED) {
|
||||||
|
@ -660,12 +709,6 @@ CpuMpServicesStartupThisAP (
|
||||||
gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);
|
gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);
|
||||||
|
|
||||||
if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {
|
if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {
|
||||||
gMPSystem.WaitEvent = WaitEvent;
|
|
||||||
Status = gBS->SetTimer (
|
|
||||||
gMPSystem.ProcessorData[ProcessorNumber].CheckThisAPEvent,
|
|
||||||
TimerPeriodic,
|
|
||||||
gPollInterval
|
|
||||||
);
|
|
||||||
return EFI_TIMEOUT;
|
return EFI_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -929,7 +972,13 @@ CpuCheckAllAPsStatus (
|
||||||
PROCESSOR_DATA_BLOCK *NextData;
|
PROCESSOR_DATA_BLOCK *NextData;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
PROCESSOR_STATE ProcessorState;
|
PROCESSOR_STATE ProcessorState;
|
||||||
|
UINTN Cpu;
|
||||||
|
BOOLEAN Found;
|
||||||
|
|
||||||
|
if (gMPSystem.TimeoutActive) {
|
||||||
|
gMPSystem.Timeout -= gPollInterval;
|
||||||
|
}
|
||||||
|
|
||||||
ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;
|
ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;
|
||||||
|
|
||||||
for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {
|
for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {
|
||||||
|
@ -938,6 +987,11 @@ CpuCheckAllAPsStatus (
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {
|
||||||
|
// Skip Disabled processors
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// This is an Interrupt Service routine.
|
// This is an Interrupt Service routine.
|
||||||
// This can grab a lock that is held in a non-interrupt
|
// This can grab a lock that is held in a non-interrupt
|
||||||
// context. Meaning deadlock. Which is a bad thing.
|
// context. Meaning deadlock. Which is a bad thing.
|
||||||
|
@ -977,16 +1031,71 @@ CpuCheckAllAPsStatus (
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gMPSystem.TimeoutActive && gMPSystem.Timeout < 0) {
|
||||||
|
//
|
||||||
|
// Timeout
|
||||||
|
//
|
||||||
|
if (gMPSystem.FailedList != NULL) {
|
||||||
|
for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {
|
||||||
|
if ((ProcessorData[ProcessorNumber].Info.StatusFlag & PROCESSOR_AS_BSP_BIT) == PROCESSOR_AS_BSP_BIT) {
|
||||||
|
// Skip BSP
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (gMPSystem.FinishCount == gMPSystem.StartCount) {
|
if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {
|
||||||
gBS->SetTimer (
|
// Skip Disabled processors
|
||||||
gMPSystem.CheckAllAPsEvent,
|
continue;
|
||||||
TimerCancel,
|
}
|
||||||
0
|
|
||||||
);
|
// Mark the
|
||||||
Status = gBS->SignalEvent (gMPSystem.WaitEvent);
|
Status = gThread->MutexTryLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProcessorState = gMPSystem.ProcessorData[ProcessorNumber].State;
|
||||||
|
gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);
|
||||||
|
|
||||||
|
if (ProcessorState != CPU_STATE_IDLE) {
|
||||||
|
// If we are retrying make sure we don't double count
|
||||||
|
for (Cpu = 0, Found = FALSE; Cpu < gMPSystem.NumberOfProcessors; Cpu++) {
|
||||||
|
if (gMPSystem.FailedList[Cpu] == END_OF_CPU_LIST) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (gMPSystem.FailedList[ProcessorNumber] == Cpu) {
|
||||||
|
Found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Found) {
|
||||||
|
gMPSystem.FailedList[gMPSystem.FailedListIndex++] = Cpu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Force terminal exit
|
||||||
|
gMPSystem.FinishCount = gMPSystem.StartCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gMPSystem.FinishCount != gMPSystem.StartCount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gBS->SetTimer (
|
||||||
|
gMPSystem.CheckAllAPsEvent,
|
||||||
|
TimerCancel,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (gMPSystem.FailedListIndex == 0) {
|
||||||
|
if (gMPSystem.FailedList != NULL) {
|
||||||
|
FreePool (gMPSystem.FailedList);
|
||||||
|
gMPSystem.FailedList = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->SignalEvent (gMPSystem.WaitEvent);
|
||||||
|
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,8 +1113,8 @@ CpuCheckThisAPStatus (
|
||||||
ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;
|
ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;
|
||||||
|
|
||||||
//
|
//
|
||||||
// rdar://6260979 - This is an Interrupt Service routine.
|
// This is an Interrupt Service routine.
|
||||||
// this can grab a lock that is held in a non-interrupt
|
// that can grab a lock that is held in a non-interrupt
|
||||||
// context. Meaning deadlock. Which is a badddd thing.
|
// context. Meaning deadlock. Which is a badddd thing.
|
||||||
// So, try lock it. If we can get it, cool, do our thing.
|
// So, try lock it. If we can get it, cool, do our thing.
|
||||||
// otherwise, just dump out & try again on the next iteration.
|
// otherwise, just dump out & try again on the next iteration.
|
||||||
|
|
|
@ -218,7 +218,7 @@
|
||||||
#define BOOT_IN_RECOVERY_MODE 0x20
|
#define BOOT_IN_RECOVERY_MODE 0x20
|
||||||
gInOsEmuPkgTokenSpaceGuid.PcdEmuBootMode|0
|
gInOsEmuPkgTokenSpaceGuid.PcdEmuBootMode|0
|
||||||
|
|
||||||
gInOsEmuPkgTokenSpaceGuid.PcdEmuApCount|L"0"
|
gInOsEmuPkgTokenSpaceGuid.PcdEmuApCount|L"1"
|
||||||
|
|
||||||
gInOsEmuPkgTokenSpaceGuid.PcdEmuPhysicalDisk|L"E:RW;245760;512"
|
gInOsEmuPkgTokenSpaceGuid.PcdEmuPhysicalDisk|L"E:RW;245760;512"
|
||||||
gInOsEmuPkgTokenSpaceGuid.PcdEmuVirtualDisk|L"FW;40960;512"
|
gInOsEmuPkgTokenSpaceGuid.PcdEmuVirtualDisk|L"FW;40960;512"
|
||||||
|
|
Loading…
Reference in New Issue