]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
ad43bd33f5f820c0c00192c33b22966ce678f5d7
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / PeiMpLib.c
1 /** @file
2 MP initialize support functions for PEI phase.
3
4 Copyright (c) 2016 - 2017, 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 /**
18 Enable Debug Agent to support source debugging on AP function.
19
20 **/
21 VOID
22 EnableDebugAgent (
23 VOID
24 )
25 {
26 }
27
28 /**
29 Get pointer to CPU MP Data structure.
30
31 @return The pointer to CPU MP Data structure.
32 **/
33 CPU_MP_DATA *
34 GetCpuMpData (
35 VOID
36 )
37 {
38 CPU_MP_DATA *CpuMpData;
39
40 CpuMpData = GetCpuMpDataFromGuidedHob ();
41 ASSERT (CpuMpData != NULL);
42 return CpuMpData;
43 }
44
45 /**
46 Save the pointer to CPU MP Data structure.
47
48 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
49 **/
50 VOID
51 SaveCpuMpData (
52 IN CPU_MP_DATA *CpuMpData
53 )
54 {
55 UINT64 Data64;
56 //
57 // Build location of CPU MP DATA buffer in HOB
58 //
59 Data64 = (UINT64) (UINTN) CpuMpData;
60 BuildGuidDataHob (
61 &mCpuInitMpLibHobGuid,
62 (VOID *) &Data64,
63 sizeof (UINT64)
64 );
65 }
66
67 /**
68 Check if AP wakeup buffer is overlapped with existing allocated buffer.
69
70 @param[in] WakeupBufferStart AP wakeup buffer start address.
71 @param[in] WakeupBufferEnd AP wakeup buffer end address.
72
73 @retval TRUE There is overlap.
74 @retval FALSE There is no overlap.
75 **/
76 BOOLEAN
77 CheckOverlapWithAllocatedBuffer (
78 IN UINTN WakeupBufferStart,
79 IN UINTN WakeupBufferEnd
80 )
81 {
82 EFI_PEI_HOB_POINTERS Hob;
83 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
84 BOOLEAN Overlapped;
85 UINTN MemoryStart;
86 UINTN MemoryEnd;
87
88 Overlapped = FALSE;
89 //
90 // Get the HOB list for processing
91 //
92 Hob.Raw = GetHobList ();
93 //
94 // Collect memory ranges
95 //
96 while (!END_OF_HOB_LIST (Hob)) {
97 if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
98 MemoryHob = Hob.MemoryAllocation;
99 MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress;
100 MemoryEnd = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress +
101 MemoryHob->AllocDescriptor.MemoryLength);
102 if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {
103 Overlapped = TRUE;
104 break;
105 }
106 }
107 Hob.Raw = GET_NEXT_HOB (Hob);
108 }
109 return Overlapped;
110 }
111
112 /**
113 Get available system memory below 1MB by specified size.
114
115 @param[in] WakeupBufferSize Wakeup buffer size required
116
117 @retval other Return wakeup buffer address below 1MB.
118 @retval -1 Cannot find free memory below 1MB.
119 **/
120 UINTN
121 GetWakeupBuffer (
122 IN UINTN WakeupBufferSize
123 )
124 {
125 EFI_PEI_HOB_POINTERS Hob;
126 UINTN WakeupBufferStart;
127 UINTN WakeupBufferEnd;
128
129 WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);
130
131 //
132 // Get the HOB list for processing
133 //
134 Hob.Raw = GetHobList ();
135
136 //
137 // Collect memory ranges
138 //
139 while (!END_OF_HOB_LIST (Hob)) {
140 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
141 if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&
142 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
143 ((Hob.ResourceDescriptor->ResourceAttribute &
144 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |
145 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |
146 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
147 )) == 0)
148 ) {
149 //
150 // Need memory under 1MB to be collected here
151 //
152 WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);
153 if (WakeupBufferEnd > BASE_1MB) {
154 //
155 // Wakeup buffer should be under 1MB
156 //
157 WakeupBufferEnd = BASE_1MB;
158 }
159 while (WakeupBufferEnd > WakeupBufferSize) {
160 //
161 // Wakeup buffer should be aligned on 4KB
162 //
163 WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);
164 if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {
165 break;
166 }
167 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {
168 //
169 // If this range is overlapped with existing allocated buffer, skip it
170 // and find the next range
171 //
172 WakeupBufferEnd -= WakeupBufferSize;
173 continue;
174 }
175 DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
176 WakeupBufferStart, WakeupBufferSize));
177 return WakeupBufferStart;
178 }
179 }
180 }
181 //
182 // Find the next HOB
183 //
184 Hob.Raw = GET_NEXT_HOB (Hob);
185 }
186
187 return (UINTN) -1;
188 }
189
190 /**
191 Get available EfiBootServicesCode memory below 4GB by specified size.
192
193 This buffer is required to safely transfer AP from real address mode to
194 protected mode or long mode, due to the fact that the buffer returned by
195 GetWakeupBuffer() may be marked as non-executable.
196
197 @param[in] BufferSize Wakeup transition buffer size.
198
199 @retval other Return wakeup transition buffer address below 4GB.
200 @retval 0 Cannot find free memory below 4GB.
201 **/
202 UINTN
203 GetModeTransitionBuffer (
204 IN UINTN BufferSize
205 )
206 {
207 //
208 // PEI phase doesn't need to do such transition. So simply return 0.
209 //
210 return 0;
211 }
212
213 /**
214 Checks APs status and updates APs status if needed.
215
216 **/
217 VOID
218 CheckAndUpdateApsStatus (
219 VOID
220 )
221 {
222 }
223
224 /**
225 Initialize global data for MP support.
226
227 @param[in] CpuMpData The pointer to CPU MP Data structure.
228 **/
229 VOID
230 InitMpGlobalData (
231 IN CPU_MP_DATA *CpuMpData
232 )
233 {
234 SaveCpuMpData (CpuMpData);
235 }
236
237 /**
238 This service executes a caller provided function on all enabled APs.
239
240 @param[in] Procedure A pointer to the function to be run on
241 enabled APs of the system. See type
242 EFI_AP_PROCEDURE.
243 @param[in] SingleThread If TRUE, then all the enabled APs execute
244 the function specified by Procedure one by
245 one, in ascending order of processor handle
246 number. If FALSE, then all the enabled APs
247 execute the function specified by Procedure
248 simultaneously.
249 @param[in] WaitEvent The event created by the caller with CreateEvent()
250 service. If it is NULL, then execute in
251 blocking mode. BSP waits until all APs finish
252 or TimeoutInMicroSeconds expires. If it's
253 not NULL, then execute in non-blocking mode.
254 BSP requests the function specified by
255 Procedure to be started on all the enabled
256 APs, and go on executing immediately. If
257 all return from Procedure, or TimeoutInMicroSeconds
258 expires, this event is signaled. The BSP
259 can use the CheckEvent() or WaitForEvent()
260 services to check the state of event. Type
261 EFI_EVENT is defined in CreateEvent() in
262 the Unified Extensible Firmware Interface
263 Specification.
264 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
265 APs to return from Procedure, either for
266 blocking or non-blocking mode. Zero means
267 infinity. If the timeout expires before
268 all APs return from Procedure, then Procedure
269 on the failed APs is terminated. All enabled
270 APs are available for next function assigned
271 by MpInitLibStartupAllAPs() or
272 MPInitLibStartupThisAP().
273 If the timeout expires in blocking mode,
274 BSP returns EFI_TIMEOUT. If the timeout
275 expires in non-blocking mode, WaitEvent
276 is signaled with SignalEvent().
277 @param[in] ProcedureArgument The parameter passed into Procedure for
278 all APs.
279 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
280 if all APs finish successfully, then its
281 content is set to NULL. If not all APs
282 finish before timeout expires, then its
283 content is set to address of the buffer
284 holding handle numbers of the failed APs.
285 The buffer is allocated by MP Initialization
286 library, and it's the caller's responsibility to
287 free the buffer with FreePool() service.
288 In blocking mode, it is ready for consumption
289 when the call returns. In non-blocking mode,
290 it is ready when WaitEvent is signaled. The
291 list of failed CPU is terminated by
292 END_OF_CPU_LIST.
293
294 @retval EFI_SUCCESS In blocking mode, all APs have finished before
295 the timeout expired.
296 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
297 to all enabled APs.
298 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
299 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
300 signaled.
301 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
302 supported.
303 @retval EFI_DEVICE_ERROR Caller processor is AP.
304 @retval EFI_NOT_STARTED No enabled APs exist in the system.
305 @retval EFI_NOT_READY Any enabled APs are busy.
306 @retval EFI_NOT_READY MP Initialize Library is not initialized.
307 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
308 all enabled APs have finished.
309 @retval EFI_INVALID_PARAMETER Procedure is NULL.
310
311 **/
312 EFI_STATUS
313 EFIAPI
314 MpInitLibStartupAllAPs (
315 IN EFI_AP_PROCEDURE Procedure,
316 IN BOOLEAN SingleThread,
317 IN EFI_EVENT WaitEvent OPTIONAL,
318 IN UINTN TimeoutInMicroseconds,
319 IN VOID *ProcedureArgument OPTIONAL,
320 OUT UINTN **FailedCpuList OPTIONAL
321 )
322 {
323 if (WaitEvent != NULL) {
324 return EFI_UNSUPPORTED;
325 }
326
327 return StartupAllAPsWorker (
328 Procedure,
329 SingleThread,
330 NULL,
331 TimeoutInMicroseconds,
332 ProcedureArgument,
333 FailedCpuList
334 );
335 }
336
337 /**
338 This service lets the caller get one enabled AP to execute a caller-provided
339 function.
340
341 @param[in] Procedure A pointer to the function to be run on the
342 designated AP of the system. See type
343 EFI_AP_PROCEDURE.
344 @param[in] ProcessorNumber The handle number of the AP. The range is
345 from 0 to the total number of logical
346 processors minus 1. The total number of
347 logical processors can be retrieved by
348 MpInitLibGetNumberOfProcessors().
349 @param[in] WaitEvent The event created by the caller with CreateEvent()
350 service. If it is NULL, then execute in
351 blocking mode. BSP waits until this AP finish
352 or TimeoutInMicroSeconds expires. If it's
353 not NULL, then execute in non-blocking mode.
354 BSP requests the function specified by
355 Procedure to be started on this AP,
356 and go on executing immediately. If this AP
357 return from Procedure or TimeoutInMicroSeconds
358 expires, this event is signaled. The BSP
359 can use the CheckEvent() or WaitForEvent()
360 services to check the state of event. Type
361 EFI_EVENT is defined in CreateEvent() in
362 the Unified Extensible Firmware Interface
363 Specification.
364 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
365 this AP to finish this Procedure, either for
366 blocking or non-blocking mode. Zero means
367 infinity. If the timeout expires before
368 this AP returns from Procedure, then Procedure
369 on the AP is terminated. The
370 AP is available for next function assigned
371 by MpInitLibStartupAllAPs() or
372 MpInitLibStartupThisAP().
373 If the timeout expires in blocking mode,
374 BSP returns EFI_TIMEOUT. If the timeout
375 expires in non-blocking mode, WaitEvent
376 is signaled with SignalEvent().
377 @param[in] ProcedureArgument The parameter passed into Procedure on the
378 specified AP.
379 @param[out] Finished If NULL, this parameter is ignored. In
380 blocking mode, this parameter is ignored.
381 In non-blocking mode, if AP returns from
382 Procedure before the timeout expires, its
383 content is set to TRUE. Otherwise, the
384 value is set to FALSE. The caller can
385 determine if the AP returned from Procedure
386 by evaluating this value.
387
388 @retval EFI_SUCCESS In blocking mode, specified AP finished before
389 the timeout expires.
390 @retval EFI_SUCCESS In non-blocking mode, the function has been
391 dispatched to specified AP.
392 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
393 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
394 signaled.
395 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
396 supported.
397 @retval EFI_DEVICE_ERROR The calling processor is an AP.
398 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
399 the specified AP has finished.
400 @retval EFI_NOT_READY The specified AP is busy.
401 @retval EFI_NOT_READY MP Initialize Library is not initialized.
402 @retval EFI_NOT_FOUND The processor with the handle specified by
403 ProcessorNumber does not exist.
404 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
405 @retval EFI_INVALID_PARAMETER Procedure is NULL.
406
407 **/
408 EFI_STATUS
409 EFIAPI
410 MpInitLibStartupThisAP (
411 IN EFI_AP_PROCEDURE Procedure,
412 IN UINTN ProcessorNumber,
413 IN EFI_EVENT WaitEvent OPTIONAL,
414 IN UINTN TimeoutInMicroseconds,
415 IN VOID *ProcedureArgument OPTIONAL,
416 OUT BOOLEAN *Finished OPTIONAL
417 )
418 {
419 if (WaitEvent != NULL) {
420 return EFI_UNSUPPORTED;
421 }
422
423 return StartupThisAPWorker (
424 Procedure,
425 ProcessorNumber,
426 NULL,
427 TimeoutInMicroseconds,
428 ProcedureArgument,
429 Finished
430 );
431 }
432
433 /**
434 This service switches the requested AP to be the BSP from that point onward.
435 This service changes the BSP for all purposes. This call can only be performed
436 by the current BSP.
437
438 @param[in] ProcessorNumber The handle number of AP that is to become the new
439 BSP. The range is from 0 to the total number of
440 logical processors minus 1. The total number of
441 logical processors can be retrieved by
442 MpInitLibGetNumberOfProcessors().
443 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
444 enabled AP. Otherwise, it will be disabled.
445
446 @retval EFI_SUCCESS BSP successfully switched.
447 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
448 this service returning.
449 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
450 @retval EFI_DEVICE_ERROR The calling processor is an AP.
451 @retval EFI_NOT_FOUND The processor with the handle specified by
452 ProcessorNumber does not exist.
453 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
454 a disabled AP.
455 @retval EFI_NOT_READY The specified AP is busy.
456 @retval EFI_NOT_READY MP Initialize Library is not initialized.
457
458 **/
459 EFI_STATUS
460 EFIAPI
461 MpInitLibSwitchBSP (
462 IN UINTN ProcessorNumber,
463 IN BOOLEAN EnableOldBSP
464 )
465 {
466 return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);
467 }
468
469 /**
470 This service lets the caller enable or disable an AP from this point onward.
471 This service may only be called from the BSP.
472
473 @param[in] ProcessorNumber The handle number of AP.
474 The range is from 0 to the total number of
475 logical processors minus 1. The total number of
476 logical processors can be retrieved by
477 MpInitLibGetNumberOfProcessors().
478 @param[in] EnableAP Specifies the new state for the processor for
479 enabled, FALSE for disabled.
480 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
481 the new health status of the AP. This flag
482 corresponds to StatusFlag defined in
483 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
484 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
485 bits are ignored. If it is NULL, this parameter
486 is ignored.
487
488 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
489 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
490 prior to this service returning.
491 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
492 @retval EFI_DEVICE_ERROR The calling processor is an AP.
493 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
494 does not exist.
495 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
496 @retval EFI_NOT_READY MP Initialize Library is not initialized.
497
498 **/
499 EFI_STATUS
500 EFIAPI
501 MpInitLibEnableDisableAP (
502 IN UINTN ProcessorNumber,
503 IN BOOLEAN EnableAP,
504 IN UINT32 *HealthFlag OPTIONAL
505 )
506 {
507 return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
508 }
509
510