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