Revision: 18008
          http://sourceforge.net/p/edk2/code/18008
Author:   vanjeff
Date:     2015-07-15 03:43:12 +0000 (Wed, 15 Jul 2015)
Log Message:
-----------
UefiCpuPkg/CpuMpPei: Implementation of PeiStartupAllAPs ()

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <[email protected]>
Reviewed-by: Feng Tian <[email protected]>
Reviewed-by: Jiewen Yao <[email protected]>

Modified Paths:
--------------
    trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.c
    trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.h
    trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.c
    trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.h

Modified: trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.c
===================================================================
--- trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.c   2015-07-15 03:42:45 UTC (rev 
18007)
+++ trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.c   2015-07-15 03:43:12 UTC (rev 
18008)
@@ -133,6 +133,8 @@
   )
 {
   PEI_CPU_MP_DATA            *PeiCpuMpData;
+  UINTN                      ProcessorNumber;
+  EFI_AP_PROCEDURE           Procedure;
   UINTN                      BistData;
 
   PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
@@ -148,6 +150,18 @@
     //
     MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
     MicrocodeDetect ();
+  } else {
+    //
+    // Execute AP function if AP is not disabled
+    //
+    GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
+    if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
+        (PeiCpuMpData->ApFunction != 0)) {
+      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
+      Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
+      Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
+      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
+    }
   }
 
   //

Modified: trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.h
===================================================================
--- trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.h   2015-07-15 03:42:45 UTC (rev 
18007)
+++ trunk/edk2/UefiCpuPkg/CpuMpPei/CpuMpPei.h   2015-07-15 03:43:12 UTC (rev 
18008)
@@ -154,6 +154,25 @@
 
 
 /**
+  This function will be called by BSP to wakeup AP.
+
+  @param PeiCpuMpData       Pointer to PEI CPU MP Data
+  @param Broadcast          TRUE:  Send broadcast IPI to all APs
+                            FALSE: Send IPI to AP by ApicId
+  @param ApicId             Apic ID for the processor to be waked
+  @param Procedure          The function to be invoked by AP
+  @param ProcedureArgument  The argument to be passed into AP function
+**/
+VOID
+WakeUpAP (
+  IN PEI_CPU_MP_DATA           *PeiCpuMpData,
+  IN BOOLEAN                   Broadcast,
+  IN UINT32                    ApicId,
+  IN EFI_AP_PROCEDURE          Procedure,              OPTIONAL
+  IN VOID                      *ProcedureArgument      OPTIONAL
+  );
+
+/**
   Get CPU MP Data pointer from the Guided HOB.
 
   @return  Pointer to Pointer to PEI CPU MP Data
@@ -164,6 +183,21 @@
   );
 
 /**
+  Find the current Processor number by APIC ID.
+
+  @param PeiCpuMpData        Pointer to PEI CPU MP Data
+  @param ProcessorNumber     Return the pocessor number found
+
+  @retval EFI_SUCCESS        ProcessorNumber is found and returned.
+  @retval EFI_NOT_FOUND      ProcessorNumber is not found.
+**/
+EFI_STATUS
+GetProcessorNumber (
+  IN PEI_CPU_MP_DATA         *PeiCpuMpData,
+  OUT UINTN                  *ProcessorNumber
+  );
+
+/**
   Collects BIST data from PPI.
 
   This function collects BIST data from Sec Platform Information2 PPI

Modified: trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.c
===================================================================
--- trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.c      2015-07-15 03:42:45 UTC 
(rev 18007)
+++ trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.c      2015-07-15 03:43:12 UTC 
(rev 18008)
@@ -315,6 +315,189 @@
 }
 
 /**
+  This service executes a caller provided function on all enabled APs. APs can
+  run either simultaneously or one at a time in sequence. This service supports
+  both blocking requests only. This service may only
+  be called from the BSP.
+
+  This function is used to dispatch all the enabled APs to the function 
specified
+  by Procedure.  If any enabled AP is busy, then EFI_NOT_READY is returned
+  immediately and Procedure is not started on any AP.
+
+  If SingleThread is TRUE, all the enabled APs execute the function specified 
by
+  Procedure one by one, in ascending order of processor handle number. 
Otherwise,
+  all the enabled APs execute the function specified by Procedure 
simultaneously.
+
+  If the timeout specified by TimeoutInMicroSeconds expires before all APs 
return
+  from Procedure, then Procedure on the failed APs is terminated. All enabled 
APs
+  are always available for further calls to 
EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
+  and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, 
its
+  content points to the list of processor handle numbers in which Procedure was
+  terminated.
+
+  Note: It is the responsibility of the consumer of the 
EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
+  to make sure that the nature of the code that is executed on the BSP and the
+  dispatched APs is well controlled. The MP Services Ppi does not guarantee
+  that the Procedure function is MP-safe. Hence, the tasks that can be run in
+  parallel are limited to certain independent tasks and well-controlled 
exclusive
+  code. PEI services and Ppis may not be called by APs unless otherwise
+  specified.
+
+  In blocking execution mode, BSP waits until all APs finish or
+  TimeoutInMicroSeconds expires.
+
+  @param[in] PeiServices          An indirect pointer to the PEI Services Table
+                                  published by the PEI Foundation.
+  @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI 
instance.
+  @param[in] Procedure            A pointer to the function to be run on 
enabled APs of
+                                  the system.
+  @param[in] SingleThread         If TRUE, then all the enabled APs execute 
the function
+                                  specified by Procedure one by one, in 
ascending order
+                                  of processor handle number. If FALSE, then 
all the
+                                  enabled APs execute the function specified 
by Procedure
+                                  simultaneously.
+  @param[in] TimeoutInMicroSeconds
+                                  Indicates the time limit in microseconds for 
APs to
+                                  return from Procedure, for blocking mode 
only. Zero
+                                  means infinity. If the timeout expires 
before all APs
+                                  return from Procedure, then Procedure on the 
failed APs
+                                  is terminated. All enabled APs are available 
for next
+                                  function assigned by 
EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
+                                  or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). 
If the
+                                  timeout expires in blocking mode, BSP returns
+                                  EFI_TIMEOUT.
+  @param[in] ProcedureArgument    The parameter passed into Procedure for all 
APs.
+
+  @retval EFI_SUCCESS             In blocking mode, all APs have finished 
before the
+                                  timeout expired.
+  @retval EFI_DEVICE_ERROR        Caller processor is AP.
+  @retval EFI_NOT_STARTED         No enabled APs exist in the system.
+  @retval EFI_NOT_READY           Any enabled APs are busy.
+  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before 
all
+                                  enabled APs have finished.
+  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
+**/
+EFI_STATUS
+EFIAPI
+PeiStartupAllAPs (
+  IN  CONST EFI_PEI_SERVICES    **PeiServices,
+  IN  EFI_PEI_MP_SERVICES_PPI   *This,
+  IN  EFI_AP_PROCEDURE          Procedure,
+  IN  BOOLEAN                   SingleThread,
+  IN  UINTN                     TimeoutInMicroSeconds,
+  IN  VOID                      *ProcedureArgument      OPTIONAL
+  )
+{
+  PEI_CPU_MP_DATA         *PeiCpuMpData;
+  UINTN                   ProcessorNumber;
+  UINTN                   Index;
+  UINTN                   CallerNumber;
+  BOOLEAN                 HasEnabledAp;
+  BOOLEAN                 HasEnabledIdleAp;
+  volatile UINT32         *FinishedCount;
+  EFI_STATUS              Status;
+  UINTN                   WaitCountIndex;
+  UINTN                   WaitCountNumber;
+
+  PeiCpuMpData = GetMpHobData ();
+  if (PeiCpuMpData == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check whether caller processor is BSP
+  //
+  PeiWhoAmI (PeiServices, This, &CallerNumber);
+  if (CallerNumber != PeiCpuMpData->BspNumber) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  ProcessorNumber = PeiCpuMpData->CpuCount;
+
+  HasEnabledAp     = FALSE;
+  HasEnabledIdleAp = FALSE;
+  for (Index = 0; Index < ProcessorNumber; Index ++) {
+    if (Index == CallerNumber) {
+      //
+      // Skip BSP
+      //
+      continue;
+    }
+    if (PeiCpuMpData->CpuData[Index].State != CpuStateDisabled) {
+      HasEnabledAp = TRUE;
+      if (PeiCpuMpData->CpuData[Index].State != CpuStateBusy) {
+        HasEnabledIdleAp = TRUE;
+      }
+    }
+  }
+  if (!HasEnabledAp) {
+    //
+    // If no enabled AP exists, return EFI_NOT_STARTED.
+    //
+    return EFI_NOT_STARTED;
+  }
+  if (!HasEnabledIdleAp) {
+    //
+    // If any enabled APs are busy, return EFI_NOT_READY.
+    //
+    return EFI_NOT_READY;
+  }
+
+  WaitCountNumber = TimeoutInMicroSeconds / CPU_CHECK_AP_INTERVAL + 1;
+  WaitCountIndex = 0;
+  FinishedCount = &PeiCpuMpData->FinishedCount;
+  if (!SingleThread) {
+    WakeUpAP (PeiCpuMpData, TRUE, 0, Procedure, ProcedureArgument);
+    //
+    // Wait to finish
+    //
+    if (TimeoutInMicroSeconds == 0) {
+      while (*FinishedCount < ProcessorNumber - 1) {
+        CpuPause ();
+      }
+      Status = EFI_SUCCESS;
+    } else {
+      Status = EFI_TIMEOUT;
+      for (WaitCountIndex = 0; WaitCountIndex < WaitCountNumber; 
WaitCountIndex++) {
+        MicroSecondDelay (CPU_CHECK_AP_INTERVAL);
+        if (*FinishedCount >= ProcessorNumber - 1) {
+          Status = EFI_SUCCESS;
+          break;
+        }
+      }
+    }
+  } else {
+    Status = EFI_SUCCESS;
+    for (Index = 0; Index < ProcessorNumber; Index++) {
+      if (Index == CallerNumber) {
+        continue;
+      }
+      WakeUpAP (PeiCpuMpData, FALSE, PeiCpuMpData->CpuData[Index].ApicId, 
Procedure, ProcedureArgument);
+      //
+      // Wait to finish
+      //
+      if (TimeoutInMicroSeconds == 0) {
+        while (*FinishedCount < 1) {
+          CpuPause ();
+        }
+      } else {
+        for (WaitCountIndex = 0; WaitCountIndex < WaitCountNumber; 
WaitCountIndex++) {
+          MicroSecondDelay (CPU_CHECK_AP_INTERVAL);
+          if (*FinishedCount >= 1) {
+            break;
+          }
+        }
+        if (WaitCountIndex == WaitCountNumber) {
+          Status = EFI_TIMEOUT;
+        }
+      }
+    }
+  }
+
+  return Status;
+}
+
+/**
   This return the handle number for the calling processor.  This service may be
   called from the BSP and APs.
 

Modified: trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.h
===================================================================
--- trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.h      2015-07-15 03:42:45 UTC 
(rev 18007)
+++ trunk/edk2/UefiCpuPkg/CpuMpPei/PeiMpServices.h      2015-07-15 03:43:12 UTC 
(rev 18008)
@@ -17,6 +17,9 @@
 
 #include "CpuMpPei.h"
 
+
+#define CPU_CHECK_AP_INTERVAL             0x100     // 100 microseconds
+
 /**
   This service retrieves the number of logical processor in the platform
   and the number of those logical processors that are enabled on this boot.
@@ -95,7 +98,81 @@
   OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
   );
 
+/**
+  This service executes a caller provided function on all enabled APs. APs can
+  run either simultaneously or one at a time in sequence. This service supports
+  both blocking requests only. This service may only
+  be called from the BSP.
 
+  This function is used to dispatch all the enabled APs to the function 
specified
+  by Procedure.  If any enabled AP is busy, then EFI_NOT_READY is returned
+  immediately and Procedure is not started on any AP.
+
+  If SingleThread is TRUE, all the enabled APs execute the function specified 
by
+  Procedure one by one, in ascending order of processor handle number. 
Otherwise,
+  all the enabled APs execute the function specified by Procedure 
simultaneously.
+
+  If the timeout specified by TimeoutInMicroSeconds expires before all APs 
return
+  from Procedure, then Procedure on the failed APs is terminated. All enabled 
APs
+  are always available for further calls to 
EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
+  and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, 
its
+  content points to the list of processor handle numbers in which Procedure was
+  terminated.
+
+  Note: It is the responsibility of the consumer of the 
EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
+  to make sure that the nature of the code that is executed on the BSP and the
+  dispatched APs is well controlled. The MP Services Ppi does not guarantee
+  that the Procedure function is MP-safe. Hence, the tasks that can be run in
+  parallel are limited to certain independent tasks and well-controlled 
exclusive
+  code. PEI services and Ppis may not be called by APs unless otherwise
+  specified.
+
+  In blocking execution mode, BSP waits until all APs finish or
+  TimeoutInMicroSeconds expires.
+
+  @param[in] PeiServices          An indirect pointer to the PEI Services Table
+                                  published by the PEI Foundation.
+  @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI 
instance.
+  @param[in] Procedure            A pointer to the function to be run on 
enabled APs of
+                                  the system.
+  @param[in] SingleThread         If TRUE, then all the enabled APs execute 
the function
+                                  specified by Procedure one by one, in 
ascending order
+                                  of processor handle number. If FALSE, then 
all the
+                                  enabled APs execute the function specified 
by Procedure
+                                  simultaneously.
+  @param[in] TimeoutInMicroSeconds
+                                  Indicates the time limit in microseconds for 
APs to
+                                  return from Procedure, for blocking mode 
only. Zero
+                                  means infinity. If the timeout expires 
before all APs
+                                  return from Procedure, then Procedure on the 
failed APs
+                                  is terminated. All enabled APs are available 
for next
+                                  function assigned by 
EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
+                                  or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). 
If the
+                                  timeout expires in blocking mode, BSP returns
+                                  EFI_TIMEOUT.
+  @param[in] ProcedureArgument    The parameter passed into Procedure for all 
APs.
+
+  @retval EFI_SUCCESS             In blocking mode, all APs have finished 
before the
+                                  timeout expired.
+  @retval EFI_DEVICE_ERROR        Caller processor is AP.
+  @retval EFI_NOT_STARTED         No enabled APs exist in the system.
+  @retval EFI_NOT_READY           Any enabled APs are busy.
+  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before 
all
+                                  enabled APs have finished.
+  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
+**/
+EFI_STATUS
+EFIAPI
+PeiStartupAllAPs (
+  IN  CONST EFI_PEI_SERVICES    **PeiServices,
+  IN  EFI_PEI_MP_SERVICES_PPI   *This,
+  IN  EFI_AP_PROCEDURE          Procedure,
+  IN  BOOLEAN                   SingleThread,
+  IN  UINTN                     TimeoutInMicroSeconds,
+  IN  VOID                      *ProcedureArgument      OPTIONAL
+  );
+
+
 /**
   This return the handle number for the calling processor.  This service may be
   called from the BSP and APs.


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to