DxeMpLib.c revision ed66e0e3f48db7a97ca82b8b630b0cf83b1283fb
1/** @file
2  MP initialize support functions for DXE phase.
3
4  Copyright (c) 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 "MpLib.h"
16
17#include <Library/UefiLib.h>
18#include <Library/UefiBootServicesTableLib.h>
19
20#define  AP_CHECK_INTERVAL     (EFI_TIMER_PERIOD_MILLISECONDS (100))
21
22CPU_MP_DATA      *mCpuMpData = NULL;
23EFI_EVENT        mCheckAllApsEvent = NULL;
24volatile BOOLEAN mStopCheckAllApsStatus = TRUE;
25
26
27/**
28  Get the pointer to CPU MP Data structure.
29
30  @return  The pointer to CPU MP Data structure.
31**/
32CPU_MP_DATA *
33GetCpuMpData (
34  VOID
35  )
36{
37  ASSERT (mCpuMpData != NULL);
38  return mCpuMpData;
39}
40
41/**
42  Save the pointer to CPU MP Data structure.
43
44  @param[in] CpuMpData  The pointer to CPU MP Data structure will be saved.
45**/
46VOID
47SaveCpuMpData (
48  IN CPU_MP_DATA   *CpuMpData
49  )
50{
51  mCpuMpData = CpuMpData;
52}
53
54/**
55  Allocate reset vector buffer.
56
57  @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.
58**/
59VOID
60AllocateResetVector (
61  IN OUT CPU_MP_DATA          *CpuMpData
62  )
63{
64  EFI_STATUS            Status;
65  UINTN                 ApResetVectorSize;
66  EFI_PHYSICAL_ADDRESS  StartAddress;
67
68  ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
69                      sizeof (MP_CPU_EXCHANGE_INFO);
70
71  StartAddress = BASE_1MB;
72  Status = gBS->AllocatePages (
73                  AllocateMaxAddress,
74                  EfiACPIMemoryNVS,
75                  EFI_SIZE_TO_PAGES (ApResetVectorSize),
76                  &StartAddress
77                  );
78  ASSERT_EFI_ERROR (Status);
79
80  CpuMpData->WakeupBuffer      = (UINTN) StartAddress;
81  CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)
82                  (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);
83  //
84  // copy AP reset code in it
85  //
86  CopyMem (
87    (VOID *) CpuMpData->WakeupBuffer,
88    (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,
89    CpuMpData->AddressMap.RendezvousFunnelSize
90    );
91}
92
93/**
94  Free AP reset vector buffer.
95
96  @param[in]  CpuMpData  The pointer to CPU MP Data structure.
97**/
98VOID
99FreeResetVector (
100  IN CPU_MP_DATA              *CpuMpData
101  )
102{
103  EFI_STATUS            Status;
104  UINTN                 ApResetVectorSize;
105  ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
106                      sizeof (MP_CPU_EXCHANGE_INFO);
107  Status = gBS->FreePages(
108             (EFI_PHYSICAL_ADDRESS)CpuMpData->WakeupBuffer,
109             EFI_SIZE_TO_PAGES (ApResetVectorSize)
110             );
111  ASSERT_EFI_ERROR (Status);
112}
113
114/**
115  Checks APs status and updates APs status if needed.
116
117**/
118VOID
119CheckAndUpdateApsStatus (
120  VOID
121  )
122{
123}
124
125/**
126  Checks APs' status periodically.
127
128  This function is triggerred by timer perodically to check the
129  state of APs for StartupAllAPs() and StartupThisAP() executed
130  in non-blocking mode.
131
132  @param[in]  Event    Event triggered.
133  @param[in]  Context  Parameter passed with the event.
134
135**/
136VOID
137EFIAPI
138CheckApsStatus (
139  IN  EFI_EVENT                           Event,
140  IN  VOID                                *Context
141  )
142{
143  //
144  // If CheckApsStatus() is not stopped, otherwise return immediately.
145  //
146  if (!mStopCheckAllApsStatus) {
147    CheckAndUpdateApsStatus ();
148  }
149}
150
151/**
152  Initialize global data for MP support.
153
154  @param[in] CpuMpData  The pointer to CPU MP Data structure.
155**/
156VOID
157InitMpGlobalData (
158  IN CPU_MP_DATA               *CpuMpData
159  )
160{
161  EFI_STATUS     Status;
162
163  SaveCpuMpData (CpuMpData);
164
165  Status = gBS->CreateEvent (
166                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
167                  TPL_NOTIFY,
168                  CheckApsStatus,
169                  NULL,
170                  &mCheckAllApsEvent
171                  );
172  ASSERT_EFI_ERROR (Status);
173
174  //
175  // Set timer to check all APs status.
176  //
177  Status = gBS->SetTimer (
178                  mCheckAllApsEvent,
179                  TimerPeriodic,
180                  AP_CHECK_INTERVAL
181                  );
182  ASSERT_EFI_ERROR (Status);
183}
184
185/**
186  This service executes a caller provided function on all enabled APs.
187
188  @param[in]  Procedure               A pointer to the function to be run on
189                                      enabled APs of the system. See type
190                                      EFI_AP_PROCEDURE.
191  @param[in]  SingleThread            If TRUE, then all the enabled APs execute
192                                      the function specified by Procedure one by
193                                      one, in ascending order of processor handle
194                                      number.  If FALSE, then all the enabled APs
195                                      execute the function specified by Procedure
196                                      simultaneously.
197  @param[in]  WaitEvent               The event created by the caller with CreateEvent()
198                                      service.  If it is NULL, then execute in
199                                      blocking mode. BSP waits until all APs finish
200                                      or TimeoutInMicroSeconds expires.  If it's
201                                      not NULL, then execute in non-blocking mode.
202                                      BSP requests the function specified by
203                                      Procedure to be started on all the enabled
204                                      APs, and go on executing immediately. If
205                                      all return from Procedure, or TimeoutInMicroSeconds
206                                      expires, this event is signaled. The BSP
207                                      can use the CheckEvent() or WaitForEvent()
208                                      services to check the state of event.  Type
209                                      EFI_EVENT is defined in CreateEvent() in
210                                      the Unified Extensible Firmware Interface
211                                      Specification.
212  @param[in]  TimeoutInMicrosecsond   Indicates the time limit in microseconds for
213                                      APs to return from Procedure, either for
214                                      blocking or non-blocking mode. Zero means
215                                      infinity.  If the timeout expires before
216                                      all APs return from Procedure, then Procedure
217                                      on the failed APs is terminated. All enabled
218                                      APs are available for next function assigned
219                                      by MpInitLibStartupAllAPs() or
220                                      MPInitLibStartupThisAP().
221                                      If the timeout expires in blocking mode,
222                                      BSP returns EFI_TIMEOUT.  If the timeout
223                                      expires in non-blocking mode, WaitEvent
224                                      is signaled with SignalEvent().
225  @param[in]  ProcedureArgument       The parameter passed into Procedure for
226                                      all APs.
227  @param[out] FailedCpuList           If NULL, this parameter is ignored. Otherwise,
228                                      if all APs finish successfully, then its
229                                      content is set to NULL. If not all APs
230                                      finish before timeout expires, then its
231                                      content is set to address of the buffer
232                                      holding handle numbers of the failed APs.
233                                      The buffer is allocated by MP Initialization
234                                      library, and it's the caller's responsibility to
235                                      free the buffer with FreePool() service.
236                                      In blocking mode, it is ready for consumption
237                                      when the call returns. In non-blocking mode,
238                                      it is ready when WaitEvent is signaled.  The
239                                      list of failed CPU is terminated by
240                                      END_OF_CPU_LIST.
241
242  @retval EFI_SUCCESS             In blocking mode, all APs have finished before
243                                  the timeout expired.
244  @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched
245                                  to all enabled APs.
246  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
247                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
248                                  signaled.
249  @retval EFI_UNSUPPORTED         WaitEvent is not NULL if non-blocking mode is not
250                                  supported.
251  @retval EFI_DEVICE_ERROR        Caller processor is AP.
252  @retval EFI_NOT_STARTED         No enabled APs exist in the system.
253  @retval EFI_NOT_READY           Any enabled APs are busy.
254  @retval EFI_NOT_READY           MP Initialize Library is not initialized.
255  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
256                                  all enabled APs have finished.
257  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
258
259**/
260EFI_STATUS
261EFIAPI
262MpInitLibStartupAllAPs (
263  IN  EFI_AP_PROCEDURE          Procedure,
264  IN  BOOLEAN                   SingleThread,
265  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
266  IN  UINTN                     TimeoutInMicroseconds,
267  IN  VOID                      *ProcedureArgument      OPTIONAL,
268  OUT UINTN                     **FailedCpuList         OPTIONAL
269  )
270{
271  return EFI_UNSUPPORTED;
272}
273
274/**
275  This service lets the caller get one enabled AP to execute a caller-provided
276  function.
277
278  @param[in]  Procedure               A pointer to the function to be run on the
279                                      designated AP of the system. See type
280                                      EFI_AP_PROCEDURE.
281  @param[in]  ProcessorNumber         The handle number of the AP. The range is
282                                      from 0 to the total number of logical
283                                      processors minus 1. The total number of
284                                      logical processors can be retrieved by
285                                      MpInitLibGetNumberOfProcessors().
286  @param[in]  WaitEvent               The event created by the caller with CreateEvent()
287                                      service.  If it is NULL, then execute in
288                                      blocking mode. BSP waits until this AP finish
289                                      or TimeoutInMicroSeconds expires.  If it's
290                                      not NULL, then execute in non-blocking mode.
291                                      BSP requests the function specified by
292                                      Procedure to be started on this AP,
293                                      and go on executing immediately. If this AP
294                                      return from Procedure or TimeoutInMicroSeconds
295                                      expires, this event is signaled. The BSP
296                                      can use the CheckEvent() or WaitForEvent()
297                                      services to check the state of event.  Type
298                                      EFI_EVENT is defined in CreateEvent() in
299                                      the Unified Extensible Firmware Interface
300                                      Specification.
301  @param[in]  TimeoutInMicrosecsond   Indicates the time limit in microseconds for
302                                      this AP to finish this Procedure, either for
303                                      blocking or non-blocking mode. Zero means
304                                      infinity.  If the timeout expires before
305                                      this AP returns from Procedure, then Procedure
306                                      on the AP is terminated. The
307                                      AP is available for next function assigned
308                                      by MpInitLibStartupAllAPs() or
309                                      MpInitLibStartupThisAP().
310                                      If the timeout expires in blocking mode,
311                                      BSP returns EFI_TIMEOUT.  If the timeout
312                                      expires in non-blocking mode, WaitEvent
313                                      is signaled with SignalEvent().
314  @param[in]  ProcedureArgument       The parameter passed into Procedure on the
315                                      specified AP.
316  @param[out] Finished                If NULL, this parameter is ignored.  In
317                                      blocking mode, this parameter is ignored.
318                                      In non-blocking mode, if AP returns from
319                                      Procedure before the timeout expires, its
320                                      content is set to TRUE. Otherwise, the
321                                      value is set to FALSE. The caller can
322                                      determine if the AP returned from Procedure
323                                      by evaluating this value.
324
325  @retval EFI_SUCCESS             In blocking mode, specified AP finished before
326                                  the timeout expires.
327  @retval EFI_SUCCESS             In non-blocking mode, the function has been
328                                  dispatched to specified AP.
329  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
330                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
331                                  signaled.
332  @retval EFI_UNSUPPORTED         WaitEvent is not NULL if non-blocking mode is not
333                                  supported.
334  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
335  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
336                                  the specified AP has finished.
337  @retval EFI_NOT_READY           The specified AP is busy.
338  @retval EFI_NOT_READY           MP Initialize Library is not initialized.
339  @retval EFI_NOT_FOUND           The processor with the handle specified by
340                                  ProcessorNumber does not exist.
341  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP or disabled AP.
342  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
343
344**/
345EFI_STATUS
346EFIAPI
347MpInitLibStartupThisAP (
348  IN  EFI_AP_PROCEDURE          Procedure,
349  IN  UINTN                     ProcessorNumber,
350  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
351  IN  UINTN                     TimeoutInMicroseconds,
352  IN  VOID                      *ProcedureArgument      OPTIONAL,
353  OUT BOOLEAN                   *Finished               OPTIONAL
354  )
355{
356  return EFI_UNSUPPORTED;
357}
358
359/**
360  This service switches the requested AP to be the BSP from that point onward.
361  This service changes the BSP for all purposes. This call can only be performed
362  by the current BSP.
363
364  @param[in] ProcessorNumber   The handle number of AP that is to become the new
365                               BSP. The range is from 0 to the total number of
366                               logical processors minus 1. The total number of
367                               logical processors can be retrieved by
368                               MpInitLibGetNumberOfProcessors().
369  @param[in] EnableOldBSP      If TRUE, then the old BSP will be listed as an
370                               enabled AP. Otherwise, it will be disabled.
371
372  @retval EFI_SUCCESS             BSP successfully switched.
373  @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to
374                                  this service returning.
375  @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
376  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
377  @retval EFI_NOT_FOUND           The processor with the handle specified by
378                                  ProcessorNumber does not exist.
379  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or
380                                  a disabled AP.
381  @retval EFI_NOT_READY           The specified AP is busy.
382  @retval EFI_NOT_READY           MP Initialize Library is not initialized.
383
384**/
385EFI_STATUS
386EFIAPI
387MpInitLibSwitchBSP (
388  IN UINTN                     ProcessorNumber,
389  IN BOOLEAN                   EnableOldBSP
390  )
391{
392  return EFI_UNSUPPORTED;
393}
394
395/**
396  This service lets the caller enable or disable an AP from this point onward.
397  This service may only be called from the BSP.
398
399  @param[in] ProcessorNumber   The handle number of AP.
400                               The range is from 0 to the total number of
401                               logical processors minus 1. The total number of
402                               logical processors can be retrieved by
403                               MpInitLibGetNumberOfProcessors().
404  @param[in] EnableAP          Specifies the new state for the processor for
405                               enabled, FALSE for disabled.
406  @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
407                               the new health status of the AP. This flag
408                               corresponds to StatusFlag defined in
409                               EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
410                               the PROCESSOR_HEALTH_STATUS_BIT is used. All other
411                               bits are ignored.  If it is NULL, this parameter
412                               is ignored.
413
414  @retval EFI_SUCCESS             The specified AP was enabled or disabled successfully.
415  @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be completed
416                                  prior to this service returning.
417  @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
418  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
419  @retval EFI_NOT_FOUND           Processor with the handle specified by ProcessorNumber
420                                  does not exist.
421  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
422  @retval EFI_NOT_READY           MP Initialize Library is not initialized.
423
424**/
425EFI_STATUS
426EFIAPI
427MpInitLibEnableDisableAP (
428  IN  UINTN                     ProcessorNumber,
429  IN  BOOLEAN                   EnableAP,
430  IN  UINT32                    *HealthFlag OPTIONAL
431  )
432{
433  return EFI_UNSUPPORTED;
434}
435