Home | History | Annotate | Download | only in CpuMpPei
      1 /** @file
      2   CPU PEI Module installs CPU Multiple Processor PPI.
      3 
      4   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "CpuMpPei.h"
     16 
     17 //
     18 // CPU MP PPI to be installed
     19 //
     20 EFI_PEI_MP_SERVICES_PPI                mMpServicesPpi = {
     21   PeiGetNumberOfProcessors,
     22   PeiGetProcessorInfo,
     23   PeiStartupAllAPs,
     24   PeiStartupThisAP,
     25   PeiSwitchBSP,
     26   PeiEnableDisableAP,
     27   PeiWhoAmI,
     28 };
     29 
     30 EFI_PEI_PPI_DESCRIPTOR           mPeiCpuMpPpiDesc = {
     31   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     32   &gEfiPeiMpServicesPpiGuid,
     33   &mMpServicesPpi
     34 };
     35 
     36 /**
     37   This service retrieves the number of logical processor in the platform
     38   and the number of those logical processors that are enabled on this boot.
     39   This service may only be called from the BSP.
     40 
     41   This function is used to retrieve the following information:
     42     - The number of logical processors that are present in the system.
     43     - The number of enabled logical processors in the system at the instant
     44       this call is made.
     45 
     46   Because MP Service Ppi provides services to enable and disable processors
     47   dynamically, the number of enabled logical processors may vary during the
     48   course of a boot session.
     49 
     50   If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
     51   If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
     52   EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
     53   is returned in NumberOfProcessors, the number of currently enabled processor
     54   is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
     55 
     56   @param[in]  PeiServices         An indirect pointer to the PEI Services Table
     57                                   published by the PEI Foundation.
     58   @param[in]  This                Pointer to this instance of the PPI.
     59   @param[out] NumberOfProcessors  Pointer to the total number of logical processors in
     60                                   the system, including the BSP and disabled APs.
     61   @param[out] NumberOfEnabledProcessors
     62                                   Number of processors in the system that are enabled.
     63 
     64   @retval EFI_SUCCESS             The number of logical processors and enabled
     65                                   logical processors was retrieved.
     66   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
     67   @retval EFI_INVALID_PARAMETER   NumberOfProcessors is NULL.
     68                                   NumberOfEnabledProcessors is NULL.
     69 **/
     70 EFI_STATUS
     71 EFIAPI
     72 PeiGetNumberOfProcessors (
     73   IN  CONST EFI_PEI_SERVICES    **PeiServices,
     74   IN  EFI_PEI_MP_SERVICES_PPI   *This,
     75   OUT UINTN                     *NumberOfProcessors,
     76   OUT UINTN                     *NumberOfEnabledProcessors
     77   )
     78 {
     79   if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {
     80     return EFI_INVALID_PARAMETER;
     81   }
     82 
     83   return MpInitLibGetNumberOfProcessors (
     84            NumberOfProcessors,
     85            NumberOfEnabledProcessors
     86            );
     87 }
     88 
     89 /**
     90   Gets detailed MP-related information on the requested processor at the
     91   instant this call is made. This service may only be called from the BSP.
     92 
     93   This service retrieves detailed MP-related information about any processor
     94   on the platform. Note the following:
     95     - The processor information may change during the course of a boot session.
     96     - The information presented here is entirely MP related.
     97 
     98   Information regarding the number of caches and their sizes, frequency of operation,
     99   slot numbers is all considered platform-related information and is not provided
    100   by this service.
    101 
    102   @param[in]  PeiServices         An indirect pointer to the PEI Services Table
    103                                   published by the PEI Foundation.
    104   @param[in]  This                Pointer to this instance of the PPI.
    105   @param[in]  ProcessorNumber     Pointer to the total number of logical processors in
    106                                   the system, including the BSP and disabled APs.
    107   @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
    108 
    109   @retval EFI_SUCCESS             Processor information was returned.
    110   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
    111   @retval EFI_INVALID_PARAMETER   ProcessorInfoBuffer is NULL.
    112   @retval EFI_NOT_FOUND           The processor with the handle specified by
    113                                   ProcessorNumber does not exist in the platform.
    114 **/
    115 EFI_STATUS
    116 EFIAPI
    117 PeiGetProcessorInfo (
    118   IN  CONST EFI_PEI_SERVICES     **PeiServices,
    119   IN  EFI_PEI_MP_SERVICES_PPI    *This,
    120   IN  UINTN                      ProcessorNumber,
    121   OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
    122   )
    123 {
    124   return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL);
    125 }
    126 
    127 /**
    128   This service executes a caller provided function on all enabled APs. APs can
    129   run either simultaneously or one at a time in sequence. This service supports
    130   both blocking requests only. This service may only
    131   be called from the BSP.
    132 
    133   This function is used to dispatch all the enabled APs to the function specified
    134   by Procedure.  If any enabled AP is busy, then EFI_NOT_READY is returned
    135   immediately and Procedure is not started on any AP.
    136 
    137   If SingleThread is TRUE, all the enabled APs execute the function specified by
    138   Procedure one by one, in ascending order of processor handle number. Otherwise,
    139   all the enabled APs execute the function specified by Procedure simultaneously.
    140 
    141   If the timeout specified by TimeoutInMicroSeconds expires before all APs return
    142   from Procedure, then Procedure on the failed APs is terminated. All enabled APs
    143   are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
    144   and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its
    145   content points to the list of processor handle numbers in which Procedure was
    146   terminated.
    147 
    148   Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
    149   to make sure that the nature of the code that is executed on the BSP and the
    150   dispatched APs is well controlled. The MP Services Ppi does not guarantee
    151   that the Procedure function is MP-safe. Hence, the tasks that can be run in
    152   parallel are limited to certain independent tasks and well-controlled exclusive
    153   code. PEI services and Ppis may not be called by APs unless otherwise
    154   specified.
    155 
    156   In blocking execution mode, BSP waits until all APs finish or
    157   TimeoutInMicroSeconds expires.
    158 
    159   @param[in] PeiServices          An indirect pointer to the PEI Services Table
    160                                   published by the PEI Foundation.
    161   @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
    162   @param[in] Procedure            A pointer to the function to be run on enabled APs of
    163                                   the system.
    164   @param[in] SingleThread         If TRUE, then all the enabled APs execute the function
    165                                   specified by Procedure one by one, in ascending order
    166                                   of processor handle number. If FALSE, then all the
    167                                   enabled APs execute the function specified by Procedure
    168                                   simultaneously.
    169   @param[in] TimeoutInMicroSeconds
    170                                   Indicates the time limit in microseconds for APs to
    171                                   return from Procedure, for blocking mode only. Zero
    172                                   means infinity. If the timeout expires before all APs
    173                                   return from Procedure, then Procedure on the failed APs
    174                                   is terminated. All enabled APs are available for next
    175                                   function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
    176                                   or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
    177                                   timeout expires in blocking mode, BSP returns
    178                                   EFI_TIMEOUT.
    179   @param[in] ProcedureArgument    The parameter passed into Procedure for all APs.
    180 
    181   @retval EFI_SUCCESS             In blocking mode, all APs have finished before the
    182                                   timeout expired.
    183   @retval EFI_DEVICE_ERROR        Caller processor is AP.
    184   @retval EFI_NOT_STARTED         No enabled APs exist in the system.
    185   @retval EFI_NOT_READY           Any enabled APs are busy.
    186   @retval EFI_TIMEOUT             In blocking mode, the timeout expired before all
    187                                   enabled APs have finished.
    188   @retval EFI_INVALID_PARAMETER   Procedure is NULL.
    189 **/
    190 EFI_STATUS
    191 EFIAPI
    192 PeiStartupAllAPs (
    193   IN  CONST EFI_PEI_SERVICES    **PeiServices,
    194   IN  EFI_PEI_MP_SERVICES_PPI   *This,
    195   IN  EFI_AP_PROCEDURE          Procedure,
    196   IN  BOOLEAN                   SingleThread,
    197   IN  UINTN                     TimeoutInMicroSeconds,
    198   IN  VOID                      *ProcedureArgument      OPTIONAL
    199   )
    200 {
    201   return MpInitLibStartupAllAPs (
    202            Procedure,
    203            SingleThread,
    204            NULL,
    205            TimeoutInMicroSeconds,
    206            ProcedureArgument,
    207            NULL
    208            );
    209 }
    210 
    211 /**
    212   This service lets the caller get one enabled AP to execute a caller-provided
    213   function. The caller can request the BSP to wait for the completion
    214   of the AP. This service may only be called from the BSP.
    215 
    216   This function is used to dispatch one enabled AP to the function specified by
    217   Procedure passing in the argument specified by ProcedureArgument.
    218   The execution is in blocking mode. The BSP waits until the AP finishes or
    219   TimeoutInMicroSecondss expires.
    220 
    221   If the timeout specified by TimeoutInMicroseconds expires before the AP returns
    222   from Procedure, then execution of Procedure by the AP is terminated. The AP is
    223   available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and
    224   EFI_PEI_MP_SERVICES_PPI.StartupThisAP().
    225 
    226   @param[in] PeiServices          An indirect pointer to the PEI Services Table
    227                                   published by the PEI Foundation.
    228   @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
    229   @param[in] Procedure            A pointer to the function to be run on enabled APs of
    230                                   the system.
    231   @param[in] ProcessorNumber      The handle number of the AP. The range is from 0 to the
    232                                   total number of logical processors minus 1. The total
    233                                   number of logical processors can be retrieved by
    234                                   EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
    235   @param[in] TimeoutInMicroseconds
    236                                   Indicates the time limit in microseconds for APs to
    237                                   return from Procedure, for blocking mode only. Zero
    238                                   means infinity. If the timeout expires before all APs
    239                                   return from Procedure, then Procedure on the failed APs
    240                                   is terminated. All enabled APs are available for next
    241                                   function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
    242                                   or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
    243                                   timeout expires in blocking mode, BSP returns
    244                                   EFI_TIMEOUT.
    245   @param[in] ProcedureArgument    The parameter passed into Procedure for all APs.
    246 
    247   @retval EFI_SUCCESS             In blocking mode, specified AP finished before the
    248                                   timeout expires.
    249   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
    250   @retval EFI_TIMEOUT             In blocking mode, the timeout expired before the
    251                                   specified AP has finished.
    252   @retval EFI_NOT_FOUND           The processor with the handle specified by
    253                                   ProcessorNumber does not exist.
    254   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP or disabled AP.
    255   @retval EFI_INVALID_PARAMETER   Procedure is NULL.
    256 **/
    257 EFI_STATUS
    258 EFIAPI
    259 PeiStartupThisAP (
    260   IN  CONST EFI_PEI_SERVICES    **PeiServices,
    261   IN  EFI_PEI_MP_SERVICES_PPI   *This,
    262   IN  EFI_AP_PROCEDURE          Procedure,
    263   IN  UINTN                     ProcessorNumber,
    264   IN  UINTN                     TimeoutInMicroseconds,
    265   IN  VOID                      *ProcedureArgument      OPTIONAL
    266   )
    267 {
    268   return MpInitLibStartupThisAP (
    269            Procedure,
    270            ProcessorNumber,
    271            NULL,
    272            TimeoutInMicroseconds,
    273            ProcedureArgument,
    274            NULL
    275            );
    276 }
    277 
    278 /**
    279   This service switches the requested AP to be the BSP from that point onward.
    280   This service changes the BSP for all purposes.   This call can only be performed
    281   by the current BSP.
    282 
    283   This service switches the requested AP to be the BSP from that point onward.
    284   This service changes the BSP for all purposes. The new BSP can take over the
    285   execution of the old BSP and continue seamlessly from where the old one left
    286   off.
    287 
    288   If the BSP cannot be switched prior to the return from this service, then
    289   EFI_UNSUPPORTED must be returned.
    290 
    291   @param[in] PeiServices          An indirect pointer to the PEI Services Table
    292                                   published by the PEI Foundation.
    293   @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
    294   @param[in] ProcessorNumber      The handle number of the AP. The range is from 0 to the
    295                                   total number of logical processors minus 1. The total
    296                                   number of logical processors can be retrieved by
    297                                   EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
    298   @param[in] EnableOldBSP         If TRUE, then the old BSP will be listed as an enabled
    299                                   AP. Otherwise, it will be disabled.
    300 
    301   @retval EFI_SUCCESS             BSP successfully switched.
    302   @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to this
    303                                   service returning.
    304   @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
    305   @retval EFI_SUCCESS             The calling processor is an AP.
    306   @retval EFI_NOT_FOUND           The processor with the handle specified by
    307                                   ProcessorNumber does not exist.
    308   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or a disabled
    309                                   AP.
    310   @retval EFI_NOT_READY           The specified AP is busy.
    311 **/
    312 EFI_STATUS
    313 EFIAPI
    314 PeiSwitchBSP (
    315   IN  CONST EFI_PEI_SERVICES   **PeiServices,
    316   IN  EFI_PEI_MP_SERVICES_PPI  *This,
    317   IN  UINTN                    ProcessorNumber,
    318   IN  BOOLEAN                  EnableOldBSP
    319   )
    320 {
    321   return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP);
    322 }
    323 
    324 /**
    325   This service lets the caller enable or disable an AP from this point onward.
    326   This service may only be called from the BSP.
    327 
    328   This service allows the caller enable or disable an AP from this point onward.
    329   The caller can optionally specify the health status of the AP by Health. If
    330   an AP is being disabled, then the state of the disabled AP is implementation
    331   dependent. If an AP is enabled, then the implementation must guarantee that a
    332   complete initialization sequence is performed on the AP, so the AP is in a state
    333   that is compatible with an MP operating system.
    334 
    335   If the enable or disable AP operation cannot be completed prior to the return
    336   from this service, then EFI_UNSUPPORTED must be returned.
    337 
    338   @param[in] PeiServices          An indirect pointer to the PEI Services Table
    339                                   published by the PEI Foundation.
    340   @param[in] This                 A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
    341   @param[in] ProcessorNumber      The handle number of the AP. The range is from 0 to the
    342                                   total number of logical processors minus 1. The total
    343                                   number of logical processors can be retrieved by
    344                                   EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
    345   @param[in] EnableAP             Specifies the new state for the processor for enabled,
    346                                   FALSE for disabled.
    347   @param[in] HealthFlag           If not NULL, a pointer to a value that specifies the
    348                                   new health status of the AP. This flag corresponds to
    349                                   StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo().
    350                                   Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other
    351                                   bits are ignored. If it is NULL, this parameter is
    352                                   ignored.
    353 
    354   @retval EFI_SUCCESS             The specified AP was enabled or disabled successfully.
    355   @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be completed prior
    356                                   to this service returning.
    357   @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
    358   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
    359   @retval EFI_NOT_FOUND           Processor with the handle specified by ProcessorNumber
    360                                   does not exist.
    361   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
    362 **/
    363 EFI_STATUS
    364 EFIAPI
    365 PeiEnableDisableAP (
    366   IN  CONST EFI_PEI_SERVICES    **PeiServices,
    367   IN  EFI_PEI_MP_SERVICES_PPI   *This,
    368   IN  UINTN                     ProcessorNumber,
    369   IN  BOOLEAN                   EnableAP,
    370   IN  UINT32                    *HealthFlag OPTIONAL
    371   )
    372 {
    373   return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);
    374 }
    375 
    376 /**
    377   This return the handle number for the calling processor.  This service may be
    378   called from the BSP and APs.
    379 
    380   This service returns the processor handle number for the calling processor.
    381   The returned value is in the range from 0 to the total number of logical
    382   processors minus 1. The total number of logical processors can be retrieved
    383   with EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). This service may be
    384   called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
    385   is returned. Otherwise, the current processors handle number is returned in
    386   ProcessorNumber, and EFI_SUCCESS is returned.
    387 
    388   @param[in]  PeiServices         An indirect pointer to the PEI Services Table
    389                                   published by the PEI Foundation.
    390   @param[in]  This                A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
    391   @param[out] ProcessorNumber     The handle number of the AP. The range is from 0 to the
    392                                   total number of logical processors minus 1. The total
    393                                   number of logical processors can be retrieved by
    394                                   EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
    395 
    396   @retval EFI_SUCCESS             The current processor handle number was returned in
    397                                   ProcessorNumber.
    398   @retval EFI_INVALID_PARAMETER   ProcessorNumber is NULL.
    399 **/
    400 EFI_STATUS
    401 EFIAPI
    402 PeiWhoAmI (
    403   IN  CONST EFI_PEI_SERVICES   **PeiServices,
    404   IN  EFI_PEI_MP_SERVICES_PPI  *This,
    405   OUT UINTN                    *ProcessorNumber
    406   )
    407 {
    408   return MpInitLibWhoAmI (ProcessorNumber);
    409 }
    410 
    411 /**
    412   The Entry point of the MP CPU PEIM.
    413 
    414   This function will wakeup APs and collect CPU AP count and install the
    415   Mp Service Ppi.
    416 
    417   @param  FileHandle    Handle of the file being invoked.
    418   @param  PeiServices   Describes the list of possible PEI Services.
    419 
    420   @retval EFI_SUCCESS   MpServicePpi is installed successfully.
    421 
    422 **/
    423 EFI_STATUS
    424 EFIAPI
    425 CpuMpPeimInit (
    426   IN       EFI_PEI_FILE_HANDLE  FileHandle,
    427   IN CONST EFI_PEI_SERVICES     **PeiServices
    428   )
    429 {
    430   EFI_STATUS           Status;
    431   EFI_VECTOR_HANDOFF_INFO         *VectorInfo;
    432   EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
    433 
    434   //
    435   // Get Vector Hand-off Info PPI
    436   //
    437   VectorInfo = NULL;
    438   Status = PeiServicesLocatePpi (
    439              &gEfiVectorHandoffInfoPpiGuid,
    440              0,
    441              NULL,
    442              (VOID **)&VectorHandoffInfoPpi
    443              );
    444   if (Status == EFI_SUCCESS) {
    445     VectorInfo = VectorHandoffInfoPpi->Info;
    446   }
    447   Status = InitializeCpuExceptionHandlers (VectorInfo);
    448   ASSERT_EFI_ERROR (Status);
    449 
    450   //
    451   // Wakeup APs to do initialization
    452   //
    453   Status = MpInitLibInitialize ();
    454   ASSERT_EFI_ERROR (Status);
    455 
    456   //
    457   // Update and publish CPU BIST information
    458   //
    459   CollectBistDataFromPpi (PeiServices);
    460 
    461   //
    462   // Install CPU MP PPI
    463   //
    464   Status = PeiServicesInstallPpi(&mPeiCpuMpPpiDesc);
    465   ASSERT_EFI_ERROR (Status);
    466 
    467   return Status;
    468 }
    469