]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmulatorPkg/CpuRuntimeDxe/MpService.c
EmulatorPkg/MpService: add enabled processor check for startupThisAP
[mirror_edk2.git] / EmulatorPkg / CpuRuntimeDxe / MpService.c
index b5b1d156c011ccc83d3e4c97c4b0c2126fac4c43..36fa68f3e83bac65dedde4028bb4fd967f3296c7 100644 (file)
@@ -28,7 +28,7 @@
   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
@@ -59,7 +59,7 @@ IsBSP (
   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
@@ -111,8 +111,31 @@ GetNextBlockedNumber (
   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
@@ -374,12 +397,11 @@ CpuMpServicesStartupAllAps (
 {\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
@@ -398,6 +420,24 @@ CpuMpServicesStartupAllAps (
     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
@@ -411,7 +451,6 @@ CpuMpServicesStartupAllAps (
 \r
   Timeout = TimeoutInMicroseconds;\r
 \r
-  ListIndex                   = 0;\r
   ProcessorData               = NULL;\r
 \r
   gMPSystem.FinishCount   = 0;\r
@@ -439,18 +478,14 @@ CpuMpServicesStartupAllAps (
     // 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
@@ -467,7 +502,13 @@ CpuMpServicesStartupAllAps (
         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
@@ -514,11 +555,16 @@ CpuMpServicesStartupAllAps (
         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
@@ -531,13 +577,12 @@ CpuMpServicesStartupAllAps (
       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
@@ -650,8 +695,7 @@ CpuMpServicesStartupThisAP (
   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
@@ -669,9 +713,16 @@ CpuMpServicesStartupThisAP (
     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
@@ -685,33 +736,32 @@ CpuMpServicesStartupThisAP (
   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
@@ -787,9 +837,12 @@ CpuMpServicesSwitchBSP (
   }\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
@@ -859,11 +912,12 @@ CpuMpServicesEnableDisableAP (
     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
@@ -882,8 +936,6 @@ CpuMpServicesEnableDisableAP (
     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
@@ -939,7 +991,7 @@ CpuMpServicesWhoAmI (
 \r
 \r
 \r
-EFI_MP_SERVICES_PROTOCOL  mMpSercicesTemplate = {\r
+EFI_MP_SERVICES_PROTOCOL  mMpServicesTemplate = {\r
   CpuMpServicesGetNumberOfProcessors,\r
   CpuMpServicesGetProcessorInfo,\r
   CpuMpServicesStartupAllAps,\r
@@ -974,13 +1026,12 @@ CpuCheckAllAPsStatus (
   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
@@ -995,33 +1046,31 @@ CpuCheckAllAPsStatus (
     // 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
@@ -1030,13 +1079,14 @@ CpuCheckAllAPsStatus (
     }\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
@@ -1047,12 +1097,12 @@ CpuCheckAllAPsStatus (
         }\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
@@ -1155,17 +1205,13 @@ FillInProcessorInformation (
   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
@@ -1315,35 +1361,33 @@ CpuReadToBootFunction (
 \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
@@ -1357,7 +1401,7 @@ CpuMpServicesInit (
   Handle = NULL;\r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &Handle,\r
-                  &gEfiMpServiceProtocolGuid,   &mMpSercicesTemplate,\r
+                  &gEfiMpServiceProtocolGuid,   &mMpServicesTemplate,\r
                   NULL\r
                   );\r
   return Status;\r