VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.c@ 106411

最後變更 在這個檔案從106411是 105670,由 vboxsync 提交於 6 月 前

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 30.5 KB
 
1/** @file
2 CPU PEI Module installs CPU Multiple Processor PPI.
3
4 Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "CpuMpPei.h"
10
11extern EDKII_PEI_MP_SERVICES2_PPI mMpServices2Ppi;
12
13//
14// CPU MP PPI to be installed
15//
16EFI_PEI_MP_SERVICES_PPI mMpServicesPpi = {
17 PeiGetNumberOfProcessors,
18 PeiGetProcessorInfo,
19 PeiStartupAllAPs,
20 PeiStartupThisAP,
21 PeiSwitchBSP,
22 PeiEnableDisableAP,
23 PeiWhoAmI,
24};
25
26EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiList[] = {
27 {
28 EFI_PEI_PPI_DESCRIPTOR_PPI,
29 &gEdkiiPeiMpServices2PpiGuid,
30 &mMpServices2Ppi
31 },
32 {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
34 &gEfiPeiMpServicesPpiGuid,
35 &mMpServicesPpi
36 }
37};
38
39/**
40 This service retrieves the number of logical processor in the platform
41 and the number of those logical processors that are enabled on this boot.
42 This service may only be called from the BSP.
43
44 This function is used to retrieve the following information:
45 - The number of logical processors that are present in the system.
46 - The number of enabled logical processors in the system at the instant
47 this call is made.
48
49 Because MP Service Ppi provides services to enable and disable processors
50 dynamically, the number of enabled logical processors may vary during the
51 course of a boot session.
52
53 If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
54 If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
55 EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
56 is returned in NumberOfProcessors, the number of currently enabled processor
57 is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
58
59 @param[in] PeiServices An indirect pointer to the PEI Services Table
60 published by the PEI Foundation.
61 @param[in] This Pointer to this instance of the PPI.
62 @param[out] NumberOfProcessors Pointer to the total number of logical processors in
63 the system, including the BSP and disabled APs.
64 @param[out] NumberOfEnabledProcessors
65 Number of processors in the system that are enabled.
66
67 @retval EFI_SUCCESS The number of logical processors and enabled
68 logical processors was retrieved.
69 @retval EFI_DEVICE_ERROR The calling processor is an AP.
70 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
71 NumberOfEnabledProcessors is NULL.
72**/
73EFI_STATUS
74EFIAPI
75PeiGetNumberOfProcessors (
76 IN CONST EFI_PEI_SERVICES **PeiServices,
77 IN EFI_PEI_MP_SERVICES_PPI *This,
78 OUT UINTN *NumberOfProcessors,
79 OUT UINTN *NumberOfEnabledProcessors
80 )
81{
82 if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {
83 return EFI_INVALID_PARAMETER;
84 }
85
86 return MpInitLibGetNumberOfProcessors (
87 NumberOfProcessors,
88 NumberOfEnabledProcessors
89 );
90}
91
92/**
93 Gets detailed MP-related information on the requested processor at the
94 instant this call is made. This service may only be called from the BSP.
95
96 This service retrieves detailed MP-related information about any processor
97 on the platform. Note the following:
98 - The processor information may change during the course of a boot session.
99 - The information presented here is entirely MP related.
100
101 Information regarding the number of caches and their sizes, frequency of operation,
102 slot numbers is all considered platform-related information and is not provided
103 by this service.
104
105 @param[in] PeiServices An indirect pointer to the PEI Services Table
106 published by the PEI Foundation.
107 @param[in] This Pointer to this instance of the PPI.
108 @param[in] ProcessorNumber Pointer to the total number of logical processors in
109 the system, including the BSP and disabled APs.
110 @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
111
112 @retval EFI_SUCCESS Processor information was returned.
113 @retval EFI_DEVICE_ERROR The calling processor is an AP.
114 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
115 @retval EFI_NOT_FOUND The processor with the handle specified by
116 ProcessorNumber does not exist in the platform.
117**/
118EFI_STATUS
119EFIAPI
120PeiGetProcessorInfo (
121 IN CONST EFI_PEI_SERVICES **PeiServices,
122 IN EFI_PEI_MP_SERVICES_PPI *This,
123 IN UINTN ProcessorNumber,
124 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
125 )
126{
127 return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL);
128}
129
130/**
131 This service executes a caller provided function on all enabled APs. APs can
132 run either simultaneously or one at a time in sequence. This service supports
133 both blocking requests only. This service may only
134 be called from the BSP.
135
136 This function is used to dispatch all the enabled APs to the function specified
137 by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
138 immediately and Procedure is not started on any AP.
139
140 If SingleThread is TRUE, all the enabled APs execute the function specified by
141 Procedure one by one, in ascending order of processor handle number. Otherwise,
142 all the enabled APs execute the function specified by Procedure simultaneously.
143
144 If the timeout specified by TimeoutInMicroSeconds expires before all APs return
145 from Procedure, then Procedure on the failed APs is terminated. All enabled APs
146 are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
147 and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its
148 content points to the list of processor handle numbers in which Procedure was
149 terminated.
150
151 Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
152 to make sure that the nature of the code that is executed on the BSP and the
153 dispatched APs is well controlled. The MP Services Ppi does not guarantee
154 that the Procedure function is MP-safe. Hence, the tasks that can be run in
155 parallel are limited to certain independent tasks and well-controlled exclusive
156 code. PEI services and Ppis may not be called by APs unless otherwise
157 specified.
158
159 In blocking execution mode, BSP waits until all APs finish or
160 TimeoutInMicroSeconds expires.
161
162 @param[in] PeiServices An indirect pointer to the PEI Services Table
163 published by the PEI Foundation.
164 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
165 @param[in] Procedure A pointer to the function to be run on enabled APs of
166 the system.
167 @param[in] SingleThread If TRUE, then all the enabled APs execute the function
168 specified by Procedure one by one, in ascending order
169 of processor handle number. If FALSE, then all the
170 enabled APs execute the function specified by Procedure
171 simultaneously.
172 @param[in] TimeoutInMicroSeconds
173 Indicates the time limit in microseconds for APs to
174 return from Procedure, for blocking mode only. Zero
175 means infinity. If the timeout expires before all APs
176 return from Procedure, then Procedure on the failed APs
177 is terminated. All enabled APs are available for next
178 function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
179 or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
180 timeout expires in blocking mode, BSP returns
181 EFI_TIMEOUT.
182 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
183
184 @retval EFI_SUCCESS In blocking mode, all APs have finished before the
185 timeout expired.
186 @retval EFI_DEVICE_ERROR Caller processor is AP.
187 @retval EFI_NOT_STARTED No enabled APs exist in the system.
188 @retval EFI_NOT_READY Any enabled APs are busy.
189 @retval EFI_TIMEOUT In blocking mode, the timeout expired before all
190 enabled APs have finished.
191 @retval EFI_INVALID_PARAMETER Procedure is NULL.
192**/
193EFI_STATUS
194EFIAPI
195PeiStartupAllAPs (
196 IN CONST EFI_PEI_SERVICES **PeiServices,
197 IN EFI_PEI_MP_SERVICES_PPI *This,
198 IN EFI_AP_PROCEDURE Procedure,
199 IN BOOLEAN SingleThread,
200 IN UINTN TimeoutInMicroSeconds,
201 IN VOID *ProcedureArgument OPTIONAL
202 )
203{
204 return MpInitLibStartupAllAPs (
205 Procedure,
206 SingleThread,
207 NULL,
208 TimeoutInMicroSeconds,
209 ProcedureArgument,
210 NULL
211 );
212}
213
214/**
215 This service lets the caller get one enabled AP to execute a caller-provided
216 function. The caller can request the BSP to wait for the completion
217 of the AP. This service may only be called from the BSP.
218
219 This function is used to dispatch one enabled AP to the function specified by
220 Procedure passing in the argument specified by ProcedureArgument.
221 The execution is in blocking mode. The BSP waits until the AP finishes or
222 TimeoutInMicroSecondss expires.
223
224 If the timeout specified by TimeoutInMicroseconds expires before the AP returns
225 from Procedure, then execution of Procedure by the AP is terminated. The AP is
226 available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and
227 EFI_PEI_MP_SERVICES_PPI.StartupThisAP().
228
229 @param[in] PeiServices An indirect pointer to the PEI Services Table
230 published by the PEI Foundation.
231 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
232 @param[in] Procedure A pointer to the function to be run on enabled APs of
233 the system.
234 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
235 total number of logical processors minus 1. The total
236 number of logical processors can be retrieved by
237 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
238 @param[in] TimeoutInMicroseconds
239 Indicates the time limit in microseconds for APs to
240 return from Procedure, for blocking mode only. Zero
241 means infinity. If the timeout expires before all APs
242 return from Procedure, then Procedure on the failed APs
243 is terminated. All enabled APs are available for next
244 function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
245 or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
246 timeout expires in blocking mode, BSP returns
247 EFI_TIMEOUT.
248 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
249
250 @retval EFI_SUCCESS In blocking mode, specified AP finished before the
251 timeout expires.
252 @retval EFI_DEVICE_ERROR The calling processor is an AP.
253 @retval EFI_TIMEOUT In blocking mode, the timeout expired before the
254 specified AP has finished.
255 @retval EFI_NOT_FOUND The processor with the handle specified by
256 ProcessorNumber does not exist.
257 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
258 @retval EFI_INVALID_PARAMETER Procedure is NULL.
259**/
260EFI_STATUS
261EFIAPI
262PeiStartupThisAP (
263 IN CONST EFI_PEI_SERVICES **PeiServices,
264 IN EFI_PEI_MP_SERVICES_PPI *This,
265 IN EFI_AP_PROCEDURE Procedure,
266 IN UINTN ProcessorNumber,
267 IN UINTN TimeoutInMicroseconds,
268 IN VOID *ProcedureArgument OPTIONAL
269 )
270{
271 return MpInitLibStartupThisAP (
272 Procedure,
273 ProcessorNumber,
274 NULL,
275 TimeoutInMicroseconds,
276 ProcedureArgument,
277 NULL
278 );
279}
280
281/**
282 This service switches the requested AP to be the BSP from that point onward.
283 This service changes the BSP for all purposes. This call can only be performed
284 by the current BSP.
285
286 This service switches the requested AP to be the BSP from that point onward.
287 This service changes the BSP for all purposes. The new BSP can take over the
288 execution of the old BSP and continue seamlessly from where the old one left
289 off.
290
291 If the BSP cannot be switched prior to the return from this service, then
292 EFI_UNSUPPORTED must be returned.
293
294 @param[in] PeiServices An indirect pointer to the PEI Services Table
295 published by the PEI Foundation.
296 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
297 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
298 total number of logical processors minus 1. The total
299 number of logical processors can be retrieved by
300 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
301 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled
302 AP. Otherwise, it will be disabled.
303
304 @retval EFI_SUCCESS BSP successfully switched.
305 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this
306 service returning.
307 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
308 @retval EFI_DEVICE_ERROR The calling processor is an AP.
309 @retval EFI_NOT_FOUND The processor with the handle specified by
310 ProcessorNumber does not exist.
311 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled
312 AP.
313 @retval EFI_NOT_READY The specified AP is busy.
314**/
315EFI_STATUS
316EFIAPI
317PeiSwitchBSP (
318 IN CONST EFI_PEI_SERVICES **PeiServices,
319 IN EFI_PEI_MP_SERVICES_PPI *This,
320 IN UINTN ProcessorNumber,
321 IN BOOLEAN EnableOldBSP
322 )
323{
324 return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP);
325}
326
327/**
328 This service lets the caller enable or disable an AP from this point onward.
329 This service may only be called from the BSP.
330
331 This service allows the caller enable or disable an AP from this point onward.
332 The caller can optionally specify the health status of the AP by Health. If
333 an AP is being disabled, then the state of the disabled AP is implementation
334 dependent. If an AP is enabled, then the implementation must guarantee that a
335 complete initialization sequence is performed on the AP, so the AP is in a state
336 that is compatible with an MP operating system.
337
338 If the enable or disable AP operation cannot be completed prior to the return
339 from this service, then EFI_UNSUPPORTED must be returned.
340
341 @param[in] PeiServices An indirect pointer to the PEI Services Table
342 published by the PEI Foundation.
343 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
344 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
345 total number of logical processors minus 1. The total
346 number of logical processors can be retrieved by
347 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
348 @param[in] EnableAP Specifies the new state for the processor for enabled,
349 FALSE for disabled.
350 @param[in] HealthFlag If not NULL, a pointer to a value that specifies the
351 new health status of the AP. This flag corresponds to
352 StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo().
353 Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other
354 bits are ignored. If it is NULL, this parameter is
355 ignored.
356
357 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
358 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed prior
359 to this service returning.
360 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
361 @retval EFI_DEVICE_ERROR The calling processor is an AP.
362 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
363 does not exist.
364 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
365**/
366EFI_STATUS
367EFIAPI
368PeiEnableDisableAP (
369 IN CONST EFI_PEI_SERVICES **PeiServices,
370 IN EFI_PEI_MP_SERVICES_PPI *This,
371 IN UINTN ProcessorNumber,
372 IN BOOLEAN EnableAP,
373 IN UINT32 *HealthFlag OPTIONAL
374 )
375{
376 return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);
377}
378
379/**
380 This return the handle number for the calling processor. This service may be
381 called from the BSP and APs.
382
383 This service returns the processor handle number for the calling processor.
384 The returned value is in the range from 0 to the total number of logical
385 processors minus 1. The total number of logical processors can be retrieved
386 with EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). This service may be
387 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
388 is returned. Otherwise, the current processors handle number is returned in
389 ProcessorNumber, and EFI_SUCCESS is returned.
390
391 @param[in] PeiServices An indirect pointer to the PEI Services Table
392 published by the PEI Foundation.
393 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
394 @param[out] ProcessorNumber The handle number of the AP. The range is from 0 to the
395 total number of logical processors minus 1. The total
396 number of logical processors can be retrieved by
397 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
398
399 @retval EFI_SUCCESS The current processor handle number was returned in
400 ProcessorNumber.
401 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
402**/
403EFI_STATUS
404EFIAPI
405PeiWhoAmI (
406 IN CONST EFI_PEI_SERVICES **PeiServices,
407 IN EFI_PEI_MP_SERVICES_PPI *This,
408 OUT UINTN *ProcessorNumber
409 )
410{
411 return MpInitLibWhoAmI (ProcessorNumber);
412}
413
414//
415// Structure for InitializeSeparateExceptionStacks
416//
417typedef struct {
418 VOID *Buffer;
419 UINTN BufferSize;
420 EFI_STATUS Status;
421} EXCEPTION_STACK_SWITCH_CONTEXT;
422
423/**
424 Initializes CPU exceptions handlers for the sake of stack switch requirement.
425
426 This function is a wrapper of InitializeSeparateExceptionStacks. It's mainly
427 for the sake of AP's init because of EFI_AP_PROCEDURE API requirement.
428
429 @param[in,out] Buffer The pointer to private data buffer.
430
431**/
432VOID
433EFIAPI
434InitializeExceptionStackSwitchHandlers (
435 IN OUT VOID *Buffer
436 )
437{
438 EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData;
439 UINTN Index;
440
441 MpInitLibWhoAmI (&Index);
442 SwitchStackData = (EXCEPTION_STACK_SWITCH_CONTEXT *)Buffer;
443
444 //
445 // This function may be called twice for each Cpu. Only run InitializeSeparateExceptionStacks
446 // if this is the first call or the first call failed because of size too small.
447 //
448 if ((SwitchStackData[Index].Status == EFI_NOT_STARTED) || (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL)) {
449 SwitchStackData[Index].Status = InitializeSeparateExceptionStacks (SwitchStackData[Index].Buffer, &SwitchStackData[Index].BufferSize);
450 }
451}
452
453/**
454 Initializes MP exceptions handlers for the sake of stack switch requirement.
455
456 This function will allocate required resources required to setup stack switch
457 and pass them through SwitchStackData to each logic processor.
458
459**/
460VOID
461InitializeMpExceptionStackSwitchHandlers (
462 VOID
463 )
464{
465 UINTN Index;
466 UINTN NumberOfProcessors;
467 EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData;
468 UINTN BufferSize;
469 EFI_STATUS Status;
470 UINT8 *Buffer;
471
472 if (!PcdGetBool (PcdCpuStackGuard)) {
473 return;
474 }
475
476 Status = MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL);
477 ASSERT_EFI_ERROR (Status);
478
479 if (EFI_ERROR (Status)) {
480 NumberOfProcessors = 1;
481 }
482
483 SwitchStackData = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT)));
484 ASSERT (SwitchStackData != NULL);
485 ZeroMem (SwitchStackData, NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT));
486 for (Index = 0; Index < NumberOfProcessors; ++Index) {
487 //
488 // Because the procedure may runs multiple times, use the status EFI_NOT_STARTED
489 // to indicate the procedure haven't been run yet.
490 //
491 SwitchStackData[Index].Status = EFI_NOT_STARTED;
492 }
493
494 Status = MpInitLibStartupAllCPUs (
495 InitializeExceptionStackSwitchHandlers,
496 0,
497 SwitchStackData
498 );
499 ASSERT_EFI_ERROR (Status);
500
501 BufferSize = 0;
502 for (Index = 0; Index < NumberOfProcessors; ++Index) {
503 if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {
504 ASSERT (SwitchStackData[Index].BufferSize != 0);
505 BufferSize += SwitchStackData[Index].BufferSize;
506 } else {
507 ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);
508 ASSERT (SwitchStackData[Index].BufferSize == 0);
509 }
510 }
511
512 if (BufferSize != 0) {
513 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
514 ASSERT (Buffer != NULL);
515 BufferSize = 0;
516 for (Index = 0; Index < NumberOfProcessors; ++Index) {
517 if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {
518 SwitchStackData[Index].Buffer = (VOID *)(&Buffer[BufferSize]);
519 BufferSize += SwitchStackData[Index].BufferSize;
520 DEBUG ((
521 DEBUG_INFO,
522 "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlers: 0x%lX with size 0x%lX\n",
523 (UINT64)(UINTN)Index,
524 (UINT64)(UINTN)SwitchStackData[Index].Buffer,
525 (UINT64)(UINTN)SwitchStackData[Index].BufferSize
526 ));
527 }
528 }
529
530 Status = MpInitLibStartupAllCPUs (
531 InitializeExceptionStackSwitchHandlers,
532 0,
533 SwitchStackData
534 );
535 ASSERT_EFI_ERROR (Status);
536 for (Index = 0; Index < NumberOfProcessors; ++Index) {
537 ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);
538 }
539 }
540
541 FreePages (SwitchStackData, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT)));
542}
543
544/**
545 Get CPU core type.
546
547 @param[in, out] Buffer Argument of the procedure.
548**/
549VOID
550EFIAPI
551GetProcessorCoreType (
552 IN OUT VOID *Buffer
553 )
554{
555 EFI_STATUS Status;
556 UINT8 *CoreTypes;
557 CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX NativeModelIdAndCoreTypeEax;
558 UINTN ProcessorIndex;
559
560 Status = MpInitLibWhoAmI (&ProcessorIndex);
561 ASSERT_EFI_ERROR (Status);
562
563 CoreTypes = (UINT8 *)Buffer;
564 AsmCpuidEx (CPUID_HYBRID_INFORMATION, CPUID_HYBRID_INFORMATION_MAIN_LEAF, &NativeModelIdAndCoreTypeEax.Uint32, NULL, NULL, NULL);
565 CoreTypes[ProcessorIndex] = (UINT8)NativeModelIdAndCoreTypeEax.Bits.CoreType;
566}
567
568/**
569 Create gMpInformation2HobGuid.
570**/
571VOID
572BuildMpInformationHob (
573 VOID
574 )
575{
576 EFI_STATUS Status;
577 UINTN ProcessorIndex;
578 UINTN NumberOfProcessors;
579 UINTN NumberOfEnabledProcessors;
580 UINTN NumberOfProcessorsInHob;
581 UINTN MaxProcessorsPerHob;
582 MP_INFORMATION2_HOB_DATA *MpInformation2HobData;
583 MP_INFORMATION2_ENTRY *MpInformation2Entry;
584 UINTN Index;
585 UINT8 *CoreTypes;
586 UINT32 CpuidMaxInput;
587 UINTN CoreTypePages;
588
589 ProcessorIndex = 0;
590 MpInformation2HobData = NULL;
591 MpInformation2Entry = NULL;
592 CoreTypes = NULL;
593 CoreTypePages = 0;
594
595 Status = MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors);
596 ASSERT_EFI_ERROR (Status);
597
598 //
599 // Get Processors CoreType
600 //
601 AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);
602 if (CpuidMaxInput >= CPUID_HYBRID_INFORMATION) {
603 CoreTypePages = EFI_SIZE_TO_PAGES (sizeof (UINT8) * NumberOfProcessors);
604 CoreTypes = AllocatePages (CoreTypePages);
605 ASSERT (CoreTypes != NULL);
606
607 Status = MpInitLibStartupAllCPUs (
608 GetProcessorCoreType,
609 0,
610 (VOID *)CoreTypes
611 );
612 ASSERT_EFI_ERROR (Status);
613 }
614
615 MaxProcessorsPerHob = ((MAX_UINT16 & ~7) - sizeof (EFI_HOB_GUID_TYPE) - sizeof (MP_INFORMATION2_HOB_DATA)) / sizeof (MP_INFORMATION2_ENTRY);
616 NumberOfProcessorsInHob = MaxProcessorsPerHob;
617
618 //
619 // Create MP_INFORMATION2_HOB. when the max HobLength 0xFFF8 is not enough, there
620 // will be a MP_INFORMATION2_HOB series in the HOB list.
621 // In the HOB list, there is a gMpInformation2HobGuid with 0 value NumberOfProcessors
622 // fields to indicate it's the last MP_INFORMATION2_HOB.
623 //
624 while (NumberOfProcessorsInHob != 0) {
625 NumberOfProcessorsInHob = MIN (NumberOfProcessors - ProcessorIndex, MaxProcessorsPerHob);
626 MpInformation2HobData = BuildGuidHob (
627 &gMpInformation2HobGuid,
628 sizeof (MP_INFORMATION2_HOB_DATA) + sizeof (MP_INFORMATION2_ENTRY) * NumberOfProcessorsInHob
629 );
630 ASSERT (MpInformation2HobData != NULL);
631
632 MpInformation2HobData->Version = MP_INFORMATION2_HOB_REVISION;
633 MpInformation2HobData->ProcessorIndex = ProcessorIndex;
634 MpInformation2HobData->NumberOfProcessors = (UINT16)NumberOfProcessorsInHob;
635 MpInformation2HobData->EntrySize = sizeof (MP_INFORMATION2_ENTRY);
636
637 DEBUG ((DEBUG_INFO, "Creating MpInformation2 HOB...\n"));
638
639 for (Index = 0; Index < NumberOfProcessorsInHob; Index++) {
640 MpInformation2Entry = &MpInformation2HobData->Entry[Index];
641 Status = MpInitLibGetProcessorInfo (
642 (Index + ProcessorIndex) | CPU_V2_EXTENDED_TOPOLOGY,
643 &MpInformation2Entry->ProcessorInfo,
644 NULL
645 );
646 ASSERT_EFI_ERROR (Status);
647
648 MpInformation2Entry->CoreType = (CoreTypes != NULL) ? CoreTypes[Index + ProcessorIndex] : 0;
649
650 DEBUG ((
651 DEBUG_INFO,
652 " Processor[%04d]: ProcessorId = 0x%lx, StatusFlag = 0x%x, CoreType = 0x%x\n",
653 Index + ProcessorIndex,
654 MpInformation2Entry->ProcessorInfo.ProcessorId,
655 MpInformation2Entry->ProcessorInfo.StatusFlag,
656 MpInformation2Entry->CoreType
657 ));
658 DEBUG ((
659 DEBUG_INFO,
660 " Location = Package:%d Core:%d Thread:%d\n",
661 MpInformation2Entry->ProcessorInfo.Location.Package,
662 MpInformation2Entry->ProcessorInfo.Location.Core,
663 MpInformation2Entry->ProcessorInfo.Location.Thread
664 ));
665 DEBUG ((
666 DEBUG_INFO,
667 " Location2 = Package:%d Die:%d Tile:%d Module:%d Core:%d Thread:%d\n",
668 MpInformation2Entry->ProcessorInfo.ExtendedInformation.Location2.Package,
669 MpInformation2Entry->ProcessorInfo.ExtendedInformation.Location2.Die,
670 MpInformation2Entry->ProcessorInfo.ExtendedInformation.Location2.Tile,
671 MpInformation2Entry->ProcessorInfo.ExtendedInformation.Location2.Module,
672 MpInformation2Entry->ProcessorInfo.ExtendedInformation.Location2.Core,
673 MpInformation2Entry->ProcessorInfo.ExtendedInformation.Location2.Thread
674 ));
675 }
676
677 ProcessorIndex += NumberOfProcessorsInHob;
678 }
679
680 if (CoreTypes != NULL) {
681 FreePages (CoreTypes, CoreTypePages);
682 }
683}
684
685/**
686 Initializes MP and exceptions handlers.
687
688 @param PeiServices The pointer to the PEI Services Table.
689
690 @retval EFI_SUCCESS MP was successfully initialized.
691 @retval others Error occurred in MP initialization.
692
693**/
694EFI_STATUS
695InitializeCpuMpWorker (
696 IN CONST EFI_PEI_SERVICES **PeiServices
697 )
698{
699 EFI_STATUS Status;
700 EFI_VECTOR_HANDOFF_INFO *VectorInfo;
701 EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
702
703 //
704 // Get Vector Hand-off Info PPI
705 //
706 VectorInfo = NULL;
707 Status = PeiServicesLocatePpi (
708 &gEfiVectorHandoffInfoPpiGuid,
709 0,
710 NULL,
711 (VOID **)&VectorHandoffInfoPpi
712 );
713 if (Status == EFI_SUCCESS) {
714 VectorInfo = VectorHandoffInfoPpi->Info;
715 }
716
717 //
718 // Initialize default handlers
719 //
720 Status = InitializeCpuExceptionHandlers (VectorInfo);
721 if (EFI_ERROR (Status)) {
722 return Status;
723 }
724
725 Status = MpInitLibInitialize ();
726 if (EFI_ERROR (Status)) {
727 return Status;
728 }
729
730 //
731 // Special initialization for the sake of Stack Guard
732 //
733 InitializeMpExceptionStackSwitchHandlers ();
734
735 //
736 // Update and publish CPU BIST information
737 //
738 CollectBistDataFromPpi (PeiServices);
739
740 //
741 // Install CPU MP PPI
742 //
743 Status = PeiServicesInstallPpi (mPeiCpuMpPpiList);
744 ASSERT_EFI_ERROR (Status);
745
746 //
747 // Create gMpInformation2HobGuid
748 //
749 BuildMpInformationHob ();
750
751 return Status;
752}
753
754/**
755 The Entry point of the MP CPU PEIM.
756
757 This function will wakeup APs and collect CPU AP count and install the
758 Mp Service Ppi.
759
760 @param FileHandle Handle of the file being invoked.
761 @param PeiServices Describes the list of possible PEI Services.
762
763 @retval EFI_SUCCESS MpServicePpi is installed successfully.
764
765**/
766EFI_STATUS
767EFIAPI
768CpuMpPeimInit (
769 IN EFI_PEI_FILE_HANDLE FileHandle,
770 IN CONST EFI_PEI_SERVICES **PeiServices
771 )
772{
773 EFI_STATUS Status;
774
775 //
776 // For the sake of special initialization needing to be done right after
777 // memory discovery.
778 //
779 Status = PeiServicesNotifyPpi (&mPostMemNotifyList[0]);
780 ASSERT_EFI_ERROR (Status);
781
782 return Status;
783}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette