]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Cleanup MpService interface. Still needs more testing, but now it is much closer...
authorandrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 17 May 2011 03:48:27 +0000 (03:48 +0000)
committerandrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 17 May 2011 03:48:27 +0000 (03:48 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11669 6f19259b-4bc3-4df7-8a09-765794883524

InOsEmuPkg/CpuRuntimeDxe/CpuDriver.h
InOsEmuPkg/CpuRuntimeDxe/MpService.c
InOsEmuPkg/Unix/UnixX64.dsc

index 43b683014a9ec325c562f7a6bccd8b58f9caa613..3ef251101ffd148e36bb386682124a1700b546e1 100644 (file)
@@ -109,6 +109,10 @@ typedef struct {
   BOOLEAN                     SingleThread;\r
   UINTN                       StartedNumber;\r
   PROCESSOR_DATA_BLOCK        *ProcessorData;\r
+  UINTN                       Timeout;\r
+  UINTN                       *FailedList;\r
+  UINTN                       FailedListIndex;\r
+  BOOLEAN                     TimeoutActive;\r
 } MP_SYSTEM_DATA;\r
 \r
 \r
index f49c55afa08ff69ac4c59726de2d56f4658a1b1e..87b546bc5f5b33b7b37fc7c26cf899a3a456b037 100644 (file)
@@ -402,20 +402,24 @@ CpuMpServicesStartupAllAps (
   \r
   \r
   if (FailedCpuList != NULL) {\r
-    FailledList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));\r
-    SetMemN (FailledList, (gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN), END_OF_CPU_LIST);\r
-    FailedListIndex = 0;\r
-    *FailedCpuList = FailledList;\r
+    gMPSystem.FailedList = AllocatePool ((gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN));\r
+    if (gMPSystem.FailedList == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    SetMemN (gMPSystem.FailedList, (gMPSystem.NumberOfProcessors + 1) * sizeof (UINTN), END_OF_CPU_LIST);\r
+    gMPSystem.FailedListIndex = 0;\r
+    *FailedCpuList = gMPSystem.FailedList;\r
   }\r
 \r
   Timeout = TimeoutInMicroseconds;\r
 \r
   ListIndex                   = 0;\r
-  ProcessorData                     = NULL;\r
+  ProcessorData               = NULL;\r
 \r
-  gMPSystem.FinishCount  = 0;\r
-  gMPSystem.StartCount   = 0;\r
-  APInitialState              = CPU_STATE_READY;\r
+  gMPSystem.FinishCount   = 0;\r
+  gMPSystem.StartCount    = 0;\r
+  gMPSystem.SingleThread  = SingleThread;\r
+  APInitialState          = CPU_STATE_READY;\r
 \r
   for (Number = 0; Number < gMPSystem.NumberOfProcessors; Number++) {\r
     ProcessorData = &gMPSystem.ProcessorData[Number];\r
@@ -425,6 +429,12 @@ CpuMpServicesStartupAllAps (
       continue;\r
     }\r
 \r
+    if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+      // Skip Disabled processors\r
+      gMPSystem.FailedList[gMPSystem.FailedListIndex++] = Number;\r
+      continue;\r
+    }\r
+\r
     //\r
     // Get APs prepared, and put failing APs into FailedCpuList\r
     // if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready\r
@@ -441,18 +451,42 @@ CpuMpServicesStartupAllAps (
       if (SingleThread) {\r
         APInitialState = CPU_STATE_BLOCKED;\r
       }\r
-\r
-    } else if (FailedCpuList != NULL) {\r
-      FailledList[FailedListIndex++] = Number;\r
-      ListIndex++;\r
+    } else {\r
+      return EFI_NOT_READY;\r
     }\r
   }\r
   \r
-  if (FailedCpuList != NULL) {\r
-    if (FailedListIndex == 0) {\r
-      FreePool (*FailedCpuList);\r
-      *FailedCpuList = NULL;\r
+  if (WaitEvent != NULL) {\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
+    \r
+      SetApProcedure (ProcessorData, Procedure, ProcedureArgument);\r
     }\r
+\r
+    //\r
+    // Save data into private data structure, and create timer to poll AP state before exiting\r
+    //\r
+    gMPSystem.Procedure         = Procedure;\r
+    gMPSystem.ProcedureArgument = ProcedureArgument;\r
+    gMPSystem.WaitEvent         = WaitEvent;\r
+    gMPSystem.Timeout           = TimeoutInMicroseconds;\r
+    gMPSystem.TimeoutActive     = (BOOLEAN)(TimeoutInMicroseconds != 0);\r
+    Status = gBS->SetTimer (\r
+                    gMPSystem.CheckAllAPsEvent,\r
+                    TimerPeriodic,\r
+                    gPollInterval\r
+                    );\r
+    return Status;\r
+\r
   }\r
 \r
   while (TRUE) {\r
@@ -463,6 +497,11 @@ CpuMpServicesStartupAllAps (
         continue;\r
       }\r
 \r
+      if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+        // Skip Disabled processors\r
+        continue;\r
+      }\r
+\r
       gThread->MutexLock (ProcessorData->StateLock);\r
       ProcessorState = ProcessorData->State;\r
       gThread->MutexUnlock (ProcessorData->StateLock);\r
@@ -490,29 +529,27 @@ CpuMpServicesStartupAllAps (
     }\r
 \r
     if (gMPSystem.FinishCount == gMPSystem.StartCount) {\r
-      return EFI_SUCCESS;\r
+      Status = EFI_SUCCESS;\r
+      goto Done;\r
     }\r
 \r
     if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
-      //\r
-      // Save data into private data structure, and create timer to poll AP state before exiting\r
-      //\r
-      gMPSystem.Procedure         = Procedure;\r
-      gMPSystem.ProcedureArgument = ProcedureArgument;\r
-      gMPSystem.WaitEvent         = WaitEvent;\r
-\r
-      Status = gBS->SetTimer (\r
-                      gMPSystem.CheckAllAPsEvent,\r
-                      TimerPeriodic,\r
-                      gPollInterval\r
-                      );\r
-      return EFI_TIMEOUT;\r
+      Status = EFI_TIMEOUT;\r
+      goto Done;\r
     }\r
 \r
     gBS->Stall (gPollInterval);\r
     Timeout -= gPollInterval;\r
   }\r
 \r
+Done:\r
+  if (FailedCpuList != NULL) {\r
+    if (gMPSystem.FailedListIndex == 0) {\r
+      FreePool (*FailedCpuList);\r
+      *FailedCpuList = NULL;\r
+    }\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -649,6 +686,18 @@ CpuMpServicesStartupThisAP (
 \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
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  // Blocking\r
   while (TRUE) {\r
     gThread->MutexLock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
     if (gMPSystem.ProcessorData[ProcessorNumber].State == CPU_STATE_FINISHED) {\r
@@ -660,12 +709,6 @@ CpuMpServicesStartupThisAP (
     gThread->MutexUnlock (&gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
 \r
     if ((TimeoutInMicroseconds != 0) && (Timeout < 0)) {\r
-      gMPSystem.WaitEvent = WaitEvent;\r
-      Status = gBS->SetTimer (\r
-                      gMPSystem.ProcessorData[ProcessorNumber].CheckThisAPEvent,\r
-                      TimerPeriodic,\r
-                      gPollInterval\r
-                      );\r
       return EFI_TIMEOUT;\r
     }\r
 \r
@@ -929,7 +972,13 @@ CpuCheckAllAPsStatus (
   PROCESSOR_DATA_BLOCK  *NextData;\r
   EFI_STATUS            Status;\r
   PROCESSOR_STATE       ProcessorState;\r
+  UINTN                 Cpu;\r
+  BOOLEAN               Found;\r
 \r
+  if (gMPSystem.TimeoutActive) {\r
+    gMPSystem.Timeout -= gPollInterval;\r
+  }\r
+  \r
   ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;\r
 \r
   for (ProcessorNumber = 0; ProcessorNumber < gMPSystem.NumberOfProcessors; ProcessorNumber++) {\r
@@ -938,6 +987,11 @@ CpuCheckAllAPsStatus (
       continue;\r
     }\r
 \r
+    if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+      // Skip Disabled processors\r
+      continue;\r
+    }\r
+\r
     // This is an Interrupt Service routine.\r
     // This can grab a lock that is held in a non-interrupt\r
     // context. Meaning deadlock. Which is a bad thing.\r
@@ -977,15 +1031,70 @@ CpuCheckAllAPsStatus (
       break;\r
     }\r
   }\r
+  \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
+         // Skip BSP\r
+          continue;\r
+        }\r
+\r
+        if ((ProcessorData->Info.StatusFlag & PROCESSOR_ENABLED_BIT) == 0) {\r
+          // Skip Disabled processors\r
+          continue;\r
+        }\r
+    \r
+        // Mark the \r
+        Status = gThread->MutexTryLock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+        if (EFI_ERROR(Status)) {\r
+          return;\r
+        }\r
+        ProcessorState = gMPSystem.ProcessorData[ProcessorNumber].State;\r
+        gThread->MutexUnlock (gMPSystem.ProcessorData[ProcessorNumber].StateLock);\r
+    \r
+        if (ProcessorState != CPU_STATE_IDLE) {\r
+          // If we are retrying make sure we don't double count\r
+          for (Cpu = 0, Found = FALSE; Cpu < gMPSystem.NumberOfProcessors; Cpu++) {\r
+            if (gMPSystem.FailedList[Cpu] == END_OF_CPU_LIST) {\r
+              break;\r
+            }\r
+            if (gMPSystem.FailedList[ProcessorNumber] == Cpu) {\r
+              Found = TRUE;\r
+              break;\r
+            }\r
+          }\r
+          if (!Found) {\r
+            gMPSystem.FailedList[gMPSystem.FailedListIndex++] = Cpu;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    // Force terminal exit\r
+    gMPSystem.FinishCount = gMPSystem.StartCount;\r
+  }\r
 \r
-  if (gMPSystem.FinishCount == gMPSystem.StartCount) {\r
-    gBS->SetTimer (\r
-           gMPSystem.CheckAllAPsEvent,\r
-           TimerCancel,\r
-           0\r
-           );\r
-    Status = gBS->SignalEvent (gMPSystem.WaitEvent);\r
+  if (gMPSystem.FinishCount != gMPSystem.StartCount) {\r
+    return;\r
   }\r
+  \r
+  gBS->SetTimer (\r
+         gMPSystem.CheckAllAPsEvent,\r
+         TimerCancel,\r
+         0\r
+         );\r
+\r
+  if (gMPSystem.FailedListIndex == 0) {\r
+    if (gMPSystem.FailedList != NULL) {\r
+      FreePool (gMPSystem.FailedList);\r
+      gMPSystem.FailedList = NULL;\r
+    }\r
+  }\r
+\r
+  Status = gBS->SignalEvent (gMPSystem.WaitEvent);\r
 \r
   return ;\r
 }\r
@@ -1004,8 +1113,8 @@ CpuCheckThisAPStatus (
   ProcessorData = (PROCESSOR_DATA_BLOCK *) Context;\r
 \r
   //\r
-  // rdar://6260979 - This is an Interrupt Service routine.\r
-  // this can grab a lock that is held in a non-interrupt\r
+  // This is an Interrupt Service routine.\r
+  // that can grab a lock that is held in a non-interrupt\r
   // context. Meaning deadlock. Which is a badddd 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
index 3c867ef3fe9a5cea81858d9c7ad11e53ef555d40..dcae0176ff51c3aa18aa0a3350ff1a89772edbd2 100644 (file)
 #define BOOT_IN_RECOVERY_MODE                         0x20\r
   gInOsEmuPkgTokenSpaceGuid.PcdEmuBootMode|0\r
   \r
-  gInOsEmuPkgTokenSpaceGuid.PcdEmuApCount|L"0"\r
+  gInOsEmuPkgTokenSpaceGuid.PcdEmuApCount|L"1"\r
 \r
   gInOsEmuPkgTokenSpaceGuid.PcdEmuPhysicalDisk|L"E:RW;245760;512"\r
   gInOsEmuPkgTokenSpaceGuid.PcdEmuVirtualDisk|L"FW;40960;512"\r