1 /** @file
2   Multiple-Processor initialization Library for uniprocessor platforms.
3 
4   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <PiDxe.h>
10 #include <Ppi/SecPlatformInformation.h>
11 #include <Protocol/MpService.h>
12 #include <Library/DebugLib.h>
13 #include <Library/LocalApicLib.h>
14 #include <Library/HobLib.h>
15 
16 /**
17   MP Initialize Library initialization.
18 
19   This service will allocate AP reset vector and wakeup all APs to do APs
20   initialization.
21 
22   This service must be invoked before all other MP Initialize Library
23   service are invoked.
24 
25   @retval  EFI_SUCCESS           MP initialization succeeds.
26   @retval  Others                MP initialization fails.
27 
28 **/
29 EFI_STATUS
30 EFIAPI
MpInitLibInitialize(VOID)31 MpInitLibInitialize (
32   VOID
33   )
34 {
35   //
36   // Enable the local APIC for Virtual Wire Mode.
37   //
38   ProgramVirtualWireMode ();
39 
40   return EFI_SUCCESS;
41 }
42 
43 /**
44   Retrieves the number of logical processor in the platform and the number of
45   those logical processors that are enabled on this boot. This service may only
46   be called from the BSP.
47 
48   @param[out] NumberOfProcessors          Pointer to the total number of logical
49                                           processors in the system, including the BSP
50                                           and disabled APs.
51   @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled logical
52                                           processors that exist in system, including
53                                           the BSP.
54 
55   @retval EFI_SUCCESS             The number of logical processors and enabled
56                                   logical processors was retrieved.
57   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
58   @retval EFI_INVALID_PARAMETER   NumberOfProcessors is NULL and NumberOfEnabledProcessors
59                                   is NULL.
60   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
61 
62 **/
63 EFI_STATUS
64 EFIAPI
MpInitLibGetNumberOfProcessors(OUT UINTN * NumberOfProcessors,OPTIONAL OUT UINTN * NumberOfEnabledProcessors OPTIONAL)65 MpInitLibGetNumberOfProcessors (
66   OUT UINTN                     *NumberOfProcessors,       OPTIONAL
67   OUT UINTN                     *NumberOfEnabledProcessors OPTIONAL
68   )
69 {
70   *NumberOfProcessors        = 1;
71   *NumberOfEnabledProcessors = 1;
72   return EFI_SUCCESS;
73 }
74 
75 /**
76   Gets detailed MP-related information on the requested processor at the
77   instant this call is made. This service may only be called from the BSP.
78 
79   @param[in]  ProcessorNumber       The handle number of processor.
80   @param[out] ProcessorInfoBuffer   A pointer to the buffer where information for
81                                     the requested processor is deposited.
82   @param[out] HealthData            Return processor health data.
83 
84   @retval EFI_SUCCESS             Processor information was returned.
85   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
86   @retval EFI_INVALID_PARAMETER   ProcessorInfoBuffer is NULL.
87   @retval EFI_NOT_FOUND           The processor with the handle specified by
88                                   ProcessorNumber does not exist in the platform.
89   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
90 
91 **/
92 EFI_STATUS
93 EFIAPI
MpInitLibGetProcessorInfo(IN UINTN ProcessorNumber,OUT EFI_PROCESSOR_INFORMATION * ProcessorInfoBuffer,OUT EFI_HEALTH_FLAGS * HealthData OPTIONAL)94 MpInitLibGetProcessorInfo (
95   IN  UINTN                      ProcessorNumber,
96   OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer,
97   OUT EFI_HEALTH_FLAGS           *HealthData  OPTIONAL
98   )
99 {
100   EFI_HOB_GUID_TYPE                    *GuidHob;
101   EFI_SEC_PLATFORM_INFORMATION_RECORD  *SecPlatformInformation;
102 
103   if (ProcessorInfoBuffer == NULL) {
104     return EFI_INVALID_PARAMETER;
105   }
106   if (ProcessorNumber != 0) {
107     return EFI_NOT_FOUND;
108   }
109   ProcessorInfoBuffer->ProcessorId      = 0;
110   ProcessorInfoBuffer->StatusFlag       = PROCESSOR_AS_BSP_BIT  |
111                                           PROCESSOR_ENABLED_BIT |
112                                           PROCESSOR_HEALTH_STATUS_BIT;
113   ProcessorInfoBuffer->Location.Package = 0;
114   ProcessorInfoBuffer->Location.Core    = 0;
115   ProcessorInfoBuffer->Location.Thread  = 0;
116   if (HealthData != NULL) {
117     GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);
118     if (GuidHob != NULL) {
119       SecPlatformInformation = GET_GUID_HOB_DATA (GuidHob);
120       HealthData->Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32;
121     } else {
122       DEBUG ((DEBUG_INFO, "Does not find any HOB stored CPU BIST information!\n"));
123       HealthData->Uint32 = 0;
124     }
125   }
126   return EFI_SUCCESS;
127 }
128 
129 /**
130   This service executes a caller provided function on all enabled APs.
131 
132   @param[in]  Procedure               A pointer to the function to be run on
133                                       enabled APs of the system. See type
134                                       EFI_AP_PROCEDURE.
135   @param[in]  SingleThread            If TRUE, then all the enabled APs execute
136                                       the function specified by Procedure one by
137                                       one, in ascending order of processor handle
138                                       number.  If FALSE, then all the enabled APs
139                                       execute the function specified by Procedure
140                                       simultaneously.
141   @param[in]  WaitEvent               The event created by the caller with CreateEvent()
142                                       service.  If it is NULL, then execute in
143                                       blocking mode. BSP waits until all APs finish
144                                       or TimeoutInMicroSeconds expires.  If it's
145                                       not NULL, then execute in non-blocking mode.
146                                       BSP requests the function specified by
147                                       Procedure to be started on all the enabled
148                                       APs, and go on executing immediately. If
149                                       all return from Procedure, or TimeoutInMicroSeconds
150                                       expires, this event is signaled. The BSP
151                                       can use the CheckEvent() or WaitForEvent()
152                                       services to check the state of event.  Type
153                                       EFI_EVENT is defined in CreateEvent() in
154                                       the Unified Extensible Firmware Interface
155                                       Specification.
156   @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
157                                       APs to return from Procedure, either for
158                                       blocking or non-blocking mode. Zero means
159                                       infinity.  If the timeout expires before
160                                       all APs return from Procedure, then Procedure
161                                       on the failed APs is terminated. All enabled
162                                       APs are available for next function assigned
163                                       by MpInitLibStartupAllAPs() or
164                                       MPInitLibStartupThisAP().
165                                       If the timeout expires in blocking mode,
166                                       BSP returns EFI_TIMEOUT.  If the timeout
167                                       expires in non-blocking mode, WaitEvent
168                                       is signaled with SignalEvent().
169   @param[in]  ProcedureArgument       The parameter passed into Procedure for
170                                       all APs.
171   @param[out] FailedCpuList           If NULL, this parameter is ignored. Otherwise,
172                                       if all APs finish successfully, then its
173                                       content is set to NULL. If not all APs
174                                       finish before timeout expires, then its
175                                       content is set to address of the buffer
176                                       holding handle numbers of the failed APs.
177                                       The buffer is allocated by MP Initialization
178                                       library, and it's the caller's responsibility to
179                                       free the buffer with FreePool() service.
180                                       In blocking mode, it is ready for consumption
181                                       when the call returns. In non-blocking mode,
182                                       it is ready when WaitEvent is signaled.  The
183                                       list of failed CPU is terminated by
184                                       END_OF_CPU_LIST.
185 
186   @retval EFI_SUCCESS             In blocking mode, all APs have finished before
187                                   the timeout expired.
188   @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched
189                                   to all enabled APs.
190   @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
191                                   UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
192                                   signaled.
193   @retval EFI_UNSUPPORTED         WaitEvent is not NULL if non-blocking mode is not
194                                   supported.
195   @retval EFI_DEVICE_ERROR        Caller processor is AP.
196   @retval EFI_NOT_STARTED         No enabled APs exist in the system.
197   @retval EFI_NOT_READY           Any enabled APs are busy.
198   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
199   @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
200                                   all enabled APs have finished.
201   @retval EFI_INVALID_PARAMETER   Procedure is NULL.
202 
203 **/
204 EFI_STATUS
205 EFIAPI
MpInitLibStartupAllAPs(IN EFI_AP_PROCEDURE Procedure,IN BOOLEAN SingleThread,IN EFI_EVENT WaitEvent OPTIONAL,IN UINTN TimeoutInMicroseconds,IN VOID * ProcedureArgument OPTIONAL,OUT UINTN ** FailedCpuList OPTIONAL)206 MpInitLibStartupAllAPs (
207   IN  EFI_AP_PROCEDURE          Procedure,
208   IN  BOOLEAN                   SingleThread,
209   IN  EFI_EVENT                 WaitEvent               OPTIONAL,
210   IN  UINTN                     TimeoutInMicroseconds,
211   IN  VOID                      *ProcedureArgument      OPTIONAL,
212   OUT UINTN                     **FailedCpuList         OPTIONAL
213   )
214 {
215   return EFI_NOT_STARTED;
216 }
217 
218 /**
219   This service lets the caller get one enabled AP to execute a caller-provided
220   function.
221 
222   @param[in]  Procedure               A pointer to the function to be run on the
223                                       designated AP of the system. See type
224                                       EFI_AP_PROCEDURE.
225   @param[in]  ProcessorNumber         The handle number of the AP. The range is
226                                       from 0 to the total number of logical
227                                       processors minus 1. The total number of
228                                       logical processors can be retrieved by
229                                       MpInitLibGetNumberOfProcessors().
230   @param[in]  WaitEvent               The event created by the caller with CreateEvent()
231                                       service.  If it is NULL, then execute in
232                                       blocking mode. BSP waits until this AP finish
233                                       or TimeoutInMicroSeconds expires.  If it's
234                                       not NULL, then execute in non-blocking mode.
235                                       BSP requests the function specified by
236                                       Procedure to be started on this AP,
237                                       and go on executing immediately. If this AP
238                                       return from Procedure or TimeoutInMicroSeconds
239                                       expires, this event is signaled. The BSP
240                                       can use the CheckEvent() or WaitForEvent()
241                                       services to check the state of event.  Type
242                                       EFI_EVENT is defined in CreateEvent() in
243                                       the Unified Extensible Firmware Interface
244                                       Specification.
245   @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
246                                       this AP to finish this Procedure, either for
247                                       blocking or non-blocking mode. Zero means
248                                       infinity.  If the timeout expires before
249                                       this AP returns from Procedure, then Procedure
250                                       on the AP is terminated. The
251                                       AP is available for next function assigned
252                                       by MpInitLibStartupAllAPs() or
253                                       MpInitLibStartupThisAP().
254                                       If the timeout expires in blocking mode,
255                                       BSP returns EFI_TIMEOUT.  If the timeout
256                                       expires in non-blocking mode, WaitEvent
257                                       is signaled with SignalEvent().
258   @param[in]  ProcedureArgument       The parameter passed into Procedure on the
259                                       specified AP.
260   @param[out] Finished                If NULL, this parameter is ignored.  In
261                                       blocking mode, this parameter is ignored.
262                                       In non-blocking mode, if AP returns from
263                                       Procedure before the timeout expires, its
264                                       content is set to TRUE. Otherwise, the
265                                       value is set to FALSE. The caller can
266                                       determine if the AP returned from Procedure
267                                       by evaluating this value.
268 
269   @retval EFI_SUCCESS             In blocking mode, specified AP finished before
270                                   the timeout expires.
271   @retval EFI_SUCCESS             In non-blocking mode, the function has been
272                                   dispatched to specified AP.
273   @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
274                                   UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
275                                   signaled.
276   @retval EFI_UNSUPPORTED         WaitEvent is not NULL if non-blocking mode is not
277                                   supported.
278   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
279   @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
280                                   the specified AP has finished.
281   @retval EFI_NOT_READY           The specified AP is busy.
282   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
283   @retval EFI_NOT_FOUND           The processor with the handle specified by
284                                   ProcessorNumber does not exist.
285   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP or disabled AP.
286   @retval EFI_INVALID_PARAMETER   Procedure is NULL.
287 
288 **/
289 EFI_STATUS
290 EFIAPI
MpInitLibStartupThisAP(IN EFI_AP_PROCEDURE Procedure,IN UINTN ProcessorNumber,IN EFI_EVENT WaitEvent OPTIONAL,IN UINTN TimeoutInMicroseconds,IN VOID * ProcedureArgument OPTIONAL,OUT BOOLEAN * Finished OPTIONAL)291 MpInitLibStartupThisAP (
292   IN  EFI_AP_PROCEDURE          Procedure,
293   IN  UINTN                     ProcessorNumber,
294   IN  EFI_EVENT                 WaitEvent               OPTIONAL,
295   IN  UINTN                     TimeoutInMicroseconds,
296   IN  VOID                      *ProcedureArgument      OPTIONAL,
297   OUT BOOLEAN                   *Finished               OPTIONAL
298   )
299 {
300   return EFI_INVALID_PARAMETER;
301 }
302 
303 /**
304   This service switches the requested AP to be the BSP from that point onward.
305   This service changes the BSP for all purposes. This call can only be performed
306   by the current BSP.
307 
308   @param[in] ProcessorNumber   The handle number of AP that is to become the new
309                                BSP. The range is from 0 to the total number of
310                                logical processors minus 1. The total number of
311                                logical processors can be retrieved by
312                                MpInitLibGetNumberOfProcessors().
313   @param[in] EnableOldBSP      If TRUE, then the old BSP will be listed as an
314                                enabled AP. Otherwise, it will be disabled.
315 
316   @retval EFI_SUCCESS             BSP successfully switched.
317   @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to
318                                   this service returning.
319   @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
320   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
321   @retval EFI_NOT_FOUND           The processor with the handle specified by
322                                   ProcessorNumber does not exist.
323   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or
324                                   a disabled AP.
325   @retval EFI_NOT_READY           The specified AP is busy.
326   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
327 
328 **/
329 EFI_STATUS
330 EFIAPI
MpInitLibSwitchBSP(IN UINTN ProcessorNumber,IN BOOLEAN EnableOldBSP)331 MpInitLibSwitchBSP (
332   IN UINTN                     ProcessorNumber,
333   IN BOOLEAN                   EnableOldBSP
334   )
335 {
336   return EFI_UNSUPPORTED;
337 }
338 
339 /**
340   This service lets the caller enable or disable an AP from this point onward.
341   This service may only be called from the BSP.
342 
343   @param[in] ProcessorNumber   The handle number of AP.
344                                The range is from 0 to the total number of
345                                logical processors minus 1. The total number of
346                                logical processors can be retrieved by
347                                MpInitLibGetNumberOfProcessors().
348   @param[in] EnableAP          Specifies the new state for the processor for
349                                enabled, FALSE for disabled.
350   @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
351                                the new health status of the AP. This flag
352                                corresponds to StatusFlag defined in
353                                EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
354                                the PROCESSOR_HEALTH_STATUS_BIT is used. All other
355                                bits are ignored.  If it is NULL, this parameter
356                                is ignored.
357 
358   @retval EFI_SUCCESS             The specified AP was enabled or disabled successfully.
359   @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be completed
360                                   prior to this service returning.
361   @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
362   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
363   @retval EFI_NOT_FOUND           Processor with the handle specified by ProcessorNumber
364                                   does not exist.
365   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
366   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
367 
368 **/
369 EFI_STATUS
370 EFIAPI
MpInitLibEnableDisableAP(IN UINTN ProcessorNumber,IN BOOLEAN EnableAP,IN UINT32 * HealthFlag OPTIONAL)371 MpInitLibEnableDisableAP (
372   IN  UINTN                     ProcessorNumber,
373   IN  BOOLEAN                   EnableAP,
374   IN  UINT32                    *HealthFlag OPTIONAL
375   )
376 {
377   return EFI_UNSUPPORTED;
378 }
379 
380 /**
381   This return the handle number for the calling processor.  This service may be
382   called from the BSP and APs.
383 
384   @param[out] ProcessorNumber  Pointer to the handle number of AP.
385                                The range is from 0 to the total number of
386                                logical processors minus 1. The total number of
387                                logical processors can be retrieved by
388                                MpInitLibGetNumberOfProcessors().
389 
390   @retval EFI_SUCCESS             The current processor handle number was returned
391                                   in ProcessorNumber.
392   @retval EFI_INVALID_PARAMETER   ProcessorNumber is NULL.
393   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
394 
395 **/
396 EFI_STATUS
397 EFIAPI
MpInitLibWhoAmI(OUT UINTN * ProcessorNumber)398 MpInitLibWhoAmI (
399   OUT UINTN                    *ProcessorNumber
400   )
401 {
402   if (ProcessorNumber == NULL) {
403     return EFI_INVALID_PARAMETER;
404   }
405   *ProcessorNumber = 0;
406   return EFI_SUCCESS;
407 }
408 
409 /**
410   This service executes a caller provided function on all enabled CPUs.
411 
412   @param[in]  Procedure               A pointer to the function to be run on
413                                       enabled APs of the system. See type
414                                       EFI_AP_PROCEDURE.
415   @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
416                                       APs to return from Procedure, either for
417                                       blocking or non-blocking mode. Zero means
418                                       infinity. TimeoutInMicroseconds is ignored
419                                       for BSP.
420   @param[in]  ProcedureArgument       The parameter passed into Procedure for
421                                       all APs.
422 
423   @retval EFI_SUCCESS             CPU have finished the procedure.
424   @retval EFI_INVALID_PARAMETER   Procedure is NULL.
425 
426 **/
427 EFI_STATUS
428 EFIAPI
MpInitLibStartupAllCPUs(IN EFI_AP_PROCEDURE Procedure,IN UINTN TimeoutInMicroseconds,IN VOID * ProcedureArgument OPTIONAL)429 MpInitLibStartupAllCPUs (
430   IN  EFI_AP_PROCEDURE          Procedure,
431   IN  UINTN                     TimeoutInMicroseconds,
432   IN  VOID                      *ProcedureArgument      OPTIONAL
433   )
434 {
435   if (Procedure == NULL) {
436     return EFI_INVALID_PARAMETER;
437   }
438 
439   Procedure (ProcedureArgument);
440 
441   return EFI_SUCCESS;
442 }
443