TianoCore EDK2 master
Loading...
Searching...
No Matches
MpLib.c
Go to the documentation of this file.
1
10#include "MpLib.h"
11
12#include <Library/BaseLib.h>
14
15#define INVALID_APIC_ID 0xFFFFFFFF
16
17EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
18
26CPU_STATE
28 IN CPU_AP_DATA *CpuData
29 )
30{
31 return CpuData->State;
32}
33
40VOID
42 IN CPU_AP_DATA *CpuData,
43 IN CPU_STATE State
44 )
45{
46 AcquireSpinLock (&CpuData->ApLock);
47 CpuData->State = State;
48 ReleaseSpinLock (&CpuData->ApLock);
49}
50
56UINT32
58 VOID
59 )
60{
61 UINTN CpuNum;
62
63 CpuNum = CsrRead (LOONGARCH_CSR_CPUID);
64
65 return CpuNum & 0x3ff;
66}
67
79 IN CPU_MP_DATA *CpuMpData,
80 OUT UINTN *ProcessorNumber
81 )
82{
83 UINTN TotalProcessorNumber;
84 UINTN Index;
85 CPU_INFO_IN_HOB *CpuInfoInHob;
86
87 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
88
89 TotalProcessorNumber = CpuMpData->CpuCount;
90 for (Index = 0; Index < TotalProcessorNumber; Index++) {
91 if (CpuInfoInHob[Index].ApicId == GetApicId ()) {
92 *ProcessorNumber = Index;
93 return EFI_SUCCESS;
94 }
95 }
96
97 return EFI_NOT_FOUND;
98}
99
108VOID
110 IN CPU_MP_DATA *CpuMpData
111 )
112{
113 UINTN Index1;
114 UINTN Index2;
115 UINTN Index3;
116 UINT32 ApicId;
117 CPU_INFO_IN_HOB CpuInfo;
118 UINT32 ApCount;
119 CPU_INFO_IN_HOB *CpuInfoInHob;
120 volatile UINT32 *StartupApSignal;
121
122 ApCount = CpuMpData->CpuCount - 1;
123 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
124 if (ApCount != 0) {
125 Index2 = 0;
126 for (Index1 = (PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1); Index1 > 0; Index1--) {
127 if (CpuInfoInHob[Index1].ApicId != INVALID_APIC_ID) {
128 if (Index1 == ApCount) {
129 break;
130 } else {
131 for ( ; Index2 <= ApCount; Index2++) {
132 if (CpuInfoInHob[Index2].ApicId == INVALID_APIC_ID) {
133 CopyMem (CpuInfoInHob + Index2, CpuInfoInHob + Index1, sizeof (CPU_INFO_IN_HOB));
134 CopyMem (CpuMpData->CpuData + Index2, CpuMpData->CpuData + Index1, sizeof (CPU_AP_DATA));
135 CpuInfoInHob[Index1].ApicId = INVALID_APIC_ID;
136 break;
137 }
138 }
139 }
140 } else {
141 continue;
142 }
143 }
144
145 for (Index1 = 0; Index1 < ApCount; Index1++) {
146 Index3 = Index1;
147 //
148 // Sort key is the hardware default APIC ID
149 //
150 ApicId = CpuInfoInHob[Index1].ApicId;
151 for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) {
152 if (ApicId > CpuInfoInHob[Index2].ApicId) {
153 Index3 = Index2;
154 ApicId = CpuInfoInHob[Index2].ApicId;
155 }
156 }
157
158 if (Index3 != Index1) {
159 CopyMem (&CpuInfo, &CpuInfoInHob[Index3], sizeof (CPU_INFO_IN_HOB));
160 CopyMem (
161 &CpuInfoInHob[Index3],
162 &CpuInfoInHob[Index1],
163 sizeof (CPU_INFO_IN_HOB)
164 );
165 CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB));
166
167 //
168 // Also exchange the StartupApSignal.
169 //
170 StartupApSignal = CpuMpData->CpuData[Index3].StartupApSignal;
171 CpuMpData->CpuData[Index3].StartupApSignal =
172 CpuMpData->CpuData[Index1].StartupApSignal;
173 CpuMpData->CpuData[Index1].StartupApSignal = StartupApSignal;
174 }
175 }
176
177 //
178 // Get the processor number for the BSP
179 //
180 ApicId = GetApicId ();
181 for (Index1 = 0; Index1 < CpuMpData->CpuCount; Index1++) {
182 if (CpuInfoInHob[Index1].ApicId == ApicId) {
183 CpuMpData->BspNumber = (UINT32)Index1;
184 break;
185 }
186 }
187 }
188}
189
197 VOID
198 )
199{
200 EFI_HOB_GUID_TYPE *GuidHob;
201 VOID *DataInHob;
202 PROCESSOR_RESOURCE_DATA *ResourceData;
203
204 ResourceData = NULL;
205 GuidHob = GetFirstGuidHob (&gProcessorResourceHobGuid);
206 if (GuidHob != NULL) {
207 DataInHob = GET_GUID_HOB_DATA (GuidHob);
208 ResourceData = (PROCESSOR_RESOURCE_DATA *)(*(UINTN *)DataInHob);
209 }
210
211 return ResourceData;
212}
213
221UINTN
223 IN CPU_MP_DATA *CpuMpData
224 )
225{
226 PROCESSOR_RESOURCE_DATA *ProcessorResourceData;
227 CPU_INFO_IN_HOB *CpuInfoInHob;
228 UINTN Index;
229
230 ProcessorResourceData = NULL;
231
232 //
233 // Set the default loop mode for APs.
234 //
235 CpuMpData->ApLoopMode = ApInRunLoop;
236
237 //
238 // Beacuse LoongArch does not have SIPI now, the APIC ID must be obtained before
239 // calling IPI to wake up the APs. If NULL is obtained, NODE0 Core0 Mailbox0 is used
240 // as the first broadcast method to wake up all APs, and all of APs will read NODE0
241 // Core0 Mailbox0 in an infinit loop.
242 //
243 ProcessorResourceData = GetProcessorResourceDataFromGuidedHob ();
244
245 if (ProcessorResourceData != NULL) {
246 CpuMpData->ApLoopMode = ApInHltLoop;
247 CpuMpData->CpuCount = ProcessorResourceData->NumberOfProcessor;
248 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)(CpuMpData->CpuInfoInHob);
249
250 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
251 CpuInfoInHob[Index].ApicId = ProcessorResourceData->ApicId[Index];
252 }
253 }
254
255 //
256 // Send 1st broadcast IPI to APs to wakeup APs
257 //
258 CpuMpData->InitFlag = ApInitConfig;
259 WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, FALSE);
260 CpuMpData->InitFlag = ApInitDone;
261
262 //
263 // When InitFlag == ApInitConfig, WakeUpAP () guarantees all APs are checked in.
264 // FinishedCount is the number of check-in APs.
265 //
266 CpuMpData->CpuCount = CpuMpData->FinishedCount + 1;
267 ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
268
269 //
270 // Wait for all APs finished the initialization
271 //
272 while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
273 CpuPause ();
274 }
275
276 //
277 // Sort BSP/Aps by CPU APIC ID in ascending order
278 //
279 SortApicId (CpuMpData);
280
281 DEBUG ((DEBUG_INFO, "MpInitLib: Find %d processors in system.\n", CpuMpData->CpuCount));
282
283 return CpuMpData->CpuCount;
284}
285
294VOID
296 IN OUT CPU_MP_DATA *CpuMpData,
297 IN UINTN ProcessorNumber,
298 IN UINT32 BistData
299 )
300{
301 CPU_INFO_IN_HOB *CpuInfoInHob;
302
303 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)(CpuMpData->CpuInfoInHob);
304
305 CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();
306 CpuInfoInHob[ProcessorNumber].Health = BistData;
307
308 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
309 CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;
310
311 InitializeSpinLock (&CpuMpData->CpuData[ProcessorNumber].ApLock);
312 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
313}
314
324VOID
325EFIAPI
327 IN UINTN ApIndex,
328 IN MP_CPU_EXCHANGE_INFO *ExchangeInfo
329 )
330{
331 CPU_MP_DATA *CpuMpData;
332 UINTN ProcessorNumber;
333 volatile UINT32 *ApStartupSignalBuffer;
334 EFI_AP_PROCEDURE Procedure;
335 VOID *Parameter;
336
337 CpuMpData = ExchangeInfo->CpuMpData;
338
339 while (TRUE) {
340 if (CpuMpData->InitFlag == ApInitConfig) {
341 ProcessorNumber = ApIndex;
342 //
343 // If the AP can running to here, then the BIST must be zero.
344 //
345 InitializeApData (CpuMpData, ProcessorNumber, 0);
346 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
347 } else {
348 //
349 // Execute AP function if AP is ready
350 //
351 GetProcessorNumber (CpuMpData, &ProcessorNumber);
352
353 //
354 // Clear AP start-up signal when AP waken up
355 //
356 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
358 (UINT32 *)ApStartupSignalBuffer,
359 WAKEUP_AP_SIGNAL,
360 0
361 );
362
363 //
364 // Invoke AP function here
365 //
366 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {
367 Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;
368 Parameter = (VOID *)CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument;
369 if (Procedure != NULL) {
370 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);
371 Procedure (Parameter);
372 }
373
374 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);
375 }
376 }
377
378 //
379 // Updates the finished count
380 //
381 InterlockedIncrement ((UINT32 *)&CpuMpData->FinishedCount);
382
383 while (TRUE) {
384 //
385 // Clean per-core mail box registers.
386 //
387 IoCsrWrite64 (LOONGARCH_IOCSR_MBUF0, 0x0);
388 IoCsrWrite64 (LOONGARCH_IOCSR_MBUF1, 0x0);
389 IoCsrWrite64 (LOONGARCH_IOCSR_MBUF2, 0x0);
390 IoCsrWrite64 (LOONGARCH_IOCSR_MBUF3, 0x0);
391
392 //
393 // Enable IPI interrupt and global interrupt
394 //
395 EnableLocalInterrupts (BIT12);
396 IoCsrWrite32 (LOONGARCH_IOCSR_IPI_EN, 0xFFFFFFFFU);
398
399 //
400 // Ap entry HLT mode
401 //
402 CpuSleep ();
403
404 //
405 // Disable global interrupts when wake up
406 //
408
409 //
410 // Update CpuMpData
411 //
412 if (CpuMpData != ExchangeInfo->CpuMpData) {
413 CpuMpData = ExchangeInfo->CpuMpData;
414 GetProcessorNumber (CpuMpData, &ProcessorNumber);
415 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
416 }
417
418 //
419 // Break out of the loop if wake up signal is not NULL.
420 //
421 if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {
422 break;
423 }
424 }
425 }
426}
427
443UINT64
445 IN UINTN TimeoutInMicroseconds,
446 OUT UINT64 *CurrentTime
447 )
448{
449 UINT64 TimeoutInSeconds;
450 UINT64 TimestampCounterFreq;
451
452 //
453 // Read the current value of the performance counter
454 //
455 *CurrentTime = GetPerformanceCounter ();
456
457 //
458 // If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
459 // as infinity.
460 //
461 if (TimeoutInMicroseconds == 0) {
462 return 0;
463 }
464
465 //
466 // GetPerformanceCounterProperties () returns the timestamp counter's frequency
467 // in Hz.
468 //
469 TimestampCounterFreq = GetPerformanceCounterProperties (NULL, NULL);
470
471 //
472 // Check the potential overflow before calculate the number of ticks for the timeout value.
473 //
474 if (DivU64x64Remainder (MAX_UINT64, TimeoutInMicroseconds, NULL) < TimestampCounterFreq) {
475 //
476 // Convert microseconds into seconds if direct multiplication overflows
477 //
478 TimeoutInSeconds = DivU64x32 (TimeoutInMicroseconds, 1000000);
479 //
480 // Assertion if the final tick count exceeds MAX_UINT64
481 //
482 ASSERT (DivU64x64Remainder (MAX_UINT64, TimeoutInSeconds, NULL) >= TimestampCounterFreq);
483 return MultU64x64 (TimestampCounterFreq, TimeoutInSeconds);
484 } else {
485 //
486 // No overflow case, multiply the return value with TimeoutInMicroseconds and then divide
487 // it by 1,000,000, to get the number of ticks for the timeout value.
488 //
489 return DivU64x32 (
490 MultU64x64 (
491 TimestampCounterFreq,
492 TimeoutInMicroseconds
493 ),
494 1000000
495 );
496 }
497}
498
519BOOLEAN
521 IN OUT UINT64 *PreviousTime,
522 IN UINT64 *TotalTime,
523 IN UINT64 Timeout
524 )
525{
526 UINT64 Start;
527 UINT64 End;
528 UINT64 CurrentTime;
529 INT64 Delta;
530 INT64 Cycle;
531
532 if (Timeout == 0) {
533 return FALSE;
534 }
535
536 GetPerformanceCounterProperties (&Start, &End);
537 Cycle = End - Start;
538 if (Cycle < 0) {
539 Cycle = -Cycle;
540 }
541
542 Cycle++;
543 CurrentTime = GetPerformanceCounter ();
544 Delta = (INT64)(CurrentTime - *PreviousTime);
545 if (Start > End) {
546 Delta = -Delta;
547 }
548
549 if (Delta < 0) {
550 Delta += Cycle;
551 }
552
553 *TotalTime += Delta;
554 *PreviousTime = CurrentTime;
555 if (*TotalTime > Timeout) {
556 return TRUE;
557 }
558
559 return FALSE;
560}
561
570VOID
572 IN CPU_MP_DATA *CpuMpData,
573 IN UINT32 FinishedApLimit,
574 IN UINT32 TimeLimit
575 )
576{
577 //
578 // CalculateTimeout() and CheckTimeout() consider a TimeLimit of 0
579 // "infinity", so check for (TimeLimit == 0) explicitly.
580 //
581 if (TimeLimit == 0) {
582 return;
583 }
584
585 CpuMpData->TotalTime = 0;
586 CpuMpData->ExpectedTime = CalculateTimeout (
587 TimeLimit,
588 &CpuMpData->CurrentTime
589 );
590 while (CpuMpData->FinishedCount < FinishedApLimit &&
591 !CheckTimeout (
592 &CpuMpData->CurrentTime,
593 &CpuMpData->TotalTime,
594 CpuMpData->ExpectedTime
595 ))
596 {
597 CpuPause ();
598 }
599
600 if (CpuMpData->FinishedCount >= FinishedApLimit) {
601 DEBUG ((
602 DEBUG_VERBOSE,
603 "%a: reached FinishedApLimit=%u in %Lu microseconds\n",
604 __func__,
605 FinishedApLimit,
607 MultU64x32 (CpuMpData->TotalTime, 1000000),
609 NULL
610 )
611 ));
612 }
613}
614
620VOID
622 IN volatile UINT32 *ApStartupSignalBuffer
623 )
624{
625 //
626 // If AP is waken up, StartupApSignal should be cleared.
627 // Otherwise, write StartupApSignal again till AP waken up.
628 //
630 (UINT32 *)ApStartupSignalBuffer,
631 WAKEUP_AP_SIGNAL,
632 WAKEUP_AP_SIGNAL
633 ) != 0)
634 {
635 CpuPause ();
636 }
637}
638
645VOID
647 IN CPU_MP_DATA *CpuMpData
648 )
649{
650 volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
651
652 if (!CpuMpData->MpCpuExchangeInfo) {
653 CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *)AllocatePool (sizeof (MP_CPU_EXCHANGE_INFO));
654 }
655
656 ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
657 ExchangeInfo->CpuMpData = CpuMpData;
658}
659
671VOID
673 IN CPU_MP_DATA *CpuMpData,
674 IN BOOLEAN Broadcast,
675 IN UINTN ProcessorNumber,
676 IN EFI_AP_PROCEDURE Procedure OPTIONAL,
677 IN VOID *ProcedureArgument OPTIONAL,
678 IN BOOLEAN WakeUpDisabledAps
679 )
680{
681 volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
682 UINTN Index;
683 CPU_AP_DATA *CpuData;
684 CPU_INFO_IN_HOB *CpuInfoInHob;
685
686 CpuMpData->FinishedCount = 0;
687
688 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
689
690 if (CpuMpData->InitFlag != ApInitDone) {
691 FillExchangeInfoData (CpuMpData);
692 }
693
694 ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
695 //
696 // If InitFlag is ApInitConfig, broadcasts all APs to initize themselves.
697 //
698 if (CpuMpData->InitFlag == ApInitConfig) {
699 DEBUG ((DEBUG_INFO, "%a: func 0x%llx, ExchangeInfo 0x%llx\n", __func__, ApWakeupFunction, (UINTN)ExchangeInfo));
700 if (CpuMpData->ApLoopMode == ApInHltLoop) {
701 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
702 if (Index != CpuMpData->BspNumber) {
703 IoCsrWrite64 (
704 LOONGARCH_IOCSR_MBUF_SEND,
705 (IOCSR_MBUF_SEND_BLOCKING |
706 (IOCSR_MBUF_SEND_BOX_HI (0x3) << IOCSR_MBUF_SEND_BOX_SHIFT) |
707 (CpuInfoInHob[Index].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
708 ((UINTN)(ExchangeInfo) & IOCSR_MBUF_SEND_H32_MASK))
709 );
710 IoCsrWrite64 (
711 LOONGARCH_IOCSR_MBUF_SEND,
712 (IOCSR_MBUF_SEND_BLOCKING |
713 (IOCSR_MBUF_SEND_BOX_LO (0x3) << IOCSR_MBUF_SEND_BOX_SHIFT) |
714 (CpuInfoInHob[Index].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
715 ((UINTN)ExchangeInfo) << IOCSR_MBUF_SEND_BUF_SHIFT)
716 );
717
718 IoCsrWrite64 (
719 LOONGARCH_IOCSR_MBUF_SEND,
720 (IOCSR_MBUF_SEND_BLOCKING |
721 (IOCSR_MBUF_SEND_BOX_HI (0x0) << IOCSR_MBUF_SEND_BOX_SHIFT) |
722 (CpuInfoInHob[Index].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
723 ((UINTN)(ApWakeupFunction) & IOCSR_MBUF_SEND_H32_MASK))
724 );
725 IoCsrWrite64 (
726 LOONGARCH_IOCSR_MBUF_SEND,
727 (IOCSR_MBUF_SEND_BLOCKING |
728 (IOCSR_MBUF_SEND_BOX_LO (0x0) << IOCSR_MBUF_SEND_BOX_SHIFT) |
729 (CpuInfoInHob[Index].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
730 ((UINTN)ApWakeupFunction) << IOCSR_MBUF_SEND_BUF_SHIFT)
731 );
732
733 //
734 // Send IPI 4 interrupt to wake up APs.
735 //
736 IoCsrWrite64 (
737 LOONGARCH_IOCSR_IPI_SEND,
738 (IOCSR_MBUF_SEND_BLOCKING |
739 (CpuInfoInHob[Index].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
740 0x2 // Bit 2
741 )
742 );
743 }
744 }
745 } else {
746 IoCsrWrite64 (LOONGARCH_IOCSR_MBUF3, (UINTN)ExchangeInfo);
747 IoCsrWrite64 (LOONGARCH_IOCSR_MBUF0, (UINTN)ApWakeupFunction);
748 }
749
751 CpuMpData,
752 PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1,
753 PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)
754 );
755 } else {
756 if (Broadcast) {
757 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
758 if (Index != CpuMpData->BspNumber) {
759 CpuData = &CpuMpData->CpuData[Index];
760 if ((GetApState (CpuData) == CpuStateDisabled) && !WakeUpDisabledAps) {
761 continue;
762 }
763
764 CpuData->ApFunction = (UINTN)Procedure;
765 CpuData->ApFunctionArgument = (UINTN)ProcedureArgument;
766 SetApState (CpuData, CpuStateReady);
767 *(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
768
769 //
770 // Send IPI 4 interrupt to wake up APs.
771 //
772 IoCsrWrite64 (
773 LOONGARCH_IOCSR_IPI_SEND,
774 (IOCSR_MBUF_SEND_BLOCKING |
775 (CpuInfoInHob[Index].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
776 0x2 // Bit 2
777 )
778 );
779 }
780 }
781
782 //
783 // Wait all APs waken up.
784 //
785 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
786 CpuData = &CpuMpData->CpuData[Index];
787 if (Index != CpuMpData->BspNumber) {
788 WaitApWakeup (CpuData->StartupApSignal);
789 }
790 }
791 } else {
792 CpuData = &CpuMpData->CpuData[ProcessorNumber];
793 CpuData->ApFunction = (UINTN)Procedure;
794 CpuData->ApFunctionArgument = (UINTN)ProcedureArgument;
795 SetApState (CpuData, CpuStateReady);
796 //
797 // Wakeup specified AP
798 //
799 *(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
800
801 //
802 // Send IPI 4 interrupt to wake up APs.
803 //
804 IoCsrWrite64 (
805 LOONGARCH_IOCSR_IPI_SEND,
806 (IOCSR_MBUF_SEND_BLOCKING |
807 (CpuInfoInHob[ProcessorNumber].ApicId << IOCSR_MBUF_SEND_CPU_SHIFT) |
808 0x2 // Bit 2
809 )
810 );
811
812 //
813 // Wait specified AP waken up
814 //
815 WaitApWakeup (CpuData->StartupApSignal);
816 }
817 }
818}
819
833 OUT UINTN *NextProcessorNumber
834 )
835{
836 UINTN ProcessorNumber;
837 CPU_MP_DATA *CpuMpData;
838
839 CpuMpData = GetCpuMpData ();
840
841 for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
842 if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
843 *NextProcessorNumber = ProcessorNumber;
844 return EFI_SUCCESS;
845 }
846 }
847
848 return EFI_NOT_FOUND;
849}
850
864 IN UINTN ProcessorNumber
865 )
866{
867 CPU_MP_DATA *CpuMpData;
868 CPU_AP_DATA *CpuData;
869
870 CpuMpData = GetCpuMpData ();
871 CpuData = &CpuMpData->CpuData[ProcessorNumber];
872
873 //
874 // If the AP finishes for StartupThisAP(), return EFI_SUCCESS.
875 //
876 if (GetApState (CpuData) == CpuStateFinished) {
877 if (CpuData->Finished != NULL) {
878 *(CpuData->Finished) = TRUE;
879 }
880
881 SetApState (CpuData, CpuStateIdle);
882 return EFI_SUCCESS;
883 } else {
884 //
885 // If timeout expires for StartupThisAP(), report timeout.
886 //
887 if (CheckTimeout (&CpuData->CurrentTime, &CpuData->TotalTime, CpuData->ExpectedTime)) {
888 if (CpuData->Finished != NULL) {
889 *(CpuData->Finished) = FALSE;
890 }
891
892 return EFI_TIMEOUT;
893 }
894 }
895
896 return EFI_NOT_READY;
897}
898
911 VOID
912 )
913{
914 UINTN ProcessorNumber;
915 UINTN NextProcessorNumber;
916 EFI_STATUS Status;
917 CPU_MP_DATA *CpuMpData;
918 CPU_AP_DATA *CpuData;
919
920 CpuMpData = GetCpuMpData ();
921
922 NextProcessorNumber = 0;
923
924 //
925 // Go through all APs that are responsible for the StartupAllAPs().
926 //
927 for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
928 if (!CpuMpData->CpuData[ProcessorNumber].Waiting) {
929 continue;
930 }
931
932 CpuData = &CpuMpData->CpuData[ProcessorNumber];
933 //
934 // Check the CPU state of AP. If it is CpuStateIdle, then the AP has finished its task.
935 // Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the
936 // value of state after setting the it to CpuStateIdle, so BSP can safely make use of its value.
937 //
938 if (GetApState (CpuData) == CpuStateFinished) {
939 CpuMpData->RunningCount--;
940 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
941 SetApState (CpuData, CpuStateIdle);
942
943 //
944 // If in Single Thread mode, then search for the next waiting AP for execution.
945 //
946 if (CpuMpData->SingleThread) {
947 Status = GetNextWaitingProcessorNumber (&NextProcessorNumber);
948
949 if (!EFI_ERROR (Status)) {
950 WakeUpAP (
951 CpuMpData,
952 FALSE,
953 (UINT32)NextProcessorNumber,
954 CpuMpData->Procedure,
955 CpuMpData->ProcArguments,
956 TRUE
957 );
958 }
959 }
960 }
961 }
962
963 //
964 // If all APs finish, return EFI_SUCCESS.
965 //
966 if (CpuMpData->RunningCount == 0) {
967 return EFI_SUCCESS;
968 }
969
970 //
971 // If timeout expires, report timeout.
972 //
973 if (CheckTimeout (
974 &CpuMpData->CurrentTime,
975 &CpuMpData->TotalTime,
976 CpuMpData->ExpectedTime
977 )
978 )
979 {
980 return EFI_TIMEOUT;
981 }
982
983 return EFI_NOT_READY;
984}
985
1020 IN EFI_AP_PROCEDURE Procedure,
1021 IN BOOLEAN SingleThread,
1022 IN BOOLEAN ExcludeBsp,
1023 IN EFI_EVENT WaitEvent OPTIONAL,
1024 IN UINTN TimeoutInMicroseconds,
1025 IN VOID *ProcedureArgument OPTIONAL,
1026 OUT UINTN **FailedCpuList OPTIONAL
1027 )
1028{
1029 EFI_STATUS Status;
1030 CPU_MP_DATA *CpuMpData;
1031 UINTN ProcessorCount;
1032 UINTN ProcessorNumber;
1033 UINTN CallerNumber;
1034 CPU_AP_DATA *CpuData;
1035 BOOLEAN HasEnabledAp;
1036 CPU_STATE ApState;
1037
1038 CpuMpData = GetCpuMpData ();
1039
1040 if (FailedCpuList != NULL) {
1041 *FailedCpuList = NULL;
1042 }
1043
1044 if ((CpuMpData->CpuCount == 1) && ExcludeBsp) {
1045 return EFI_NOT_STARTED;
1046 }
1047
1048 if (Procedure == NULL) {
1049 return EFI_INVALID_PARAMETER;
1050 }
1051
1052 //
1053 // Check whether caller processor is BSP
1054 //
1055 MpInitLibWhoAmI (&CallerNumber);
1056 if (CallerNumber != CpuMpData->BspNumber) {
1057 return EFI_DEVICE_ERROR;
1058 }
1059
1060 //
1061 // Update AP state
1062 //
1064
1065 ProcessorCount = CpuMpData->CpuCount;
1066 HasEnabledAp = FALSE;
1067 //
1068 // Check whether all enabled APs are idle.
1069 // If any enabled AP is not idle, return EFI_NOT_READY.
1070 //
1071 for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
1072 CpuData = &CpuMpData->CpuData[ProcessorNumber];
1073 if (ProcessorNumber != CpuMpData->BspNumber) {
1074 ApState = GetApState (CpuData);
1075 if (ApState != CpuStateDisabled) {
1076 HasEnabledAp = TRUE;
1077 if (ApState != CpuStateIdle) {
1078 //
1079 // If any enabled APs are busy, return EFI_NOT_READY.
1080 //
1081 return EFI_NOT_READY;
1082 }
1083 }
1084 }
1085 }
1086
1087 if (!HasEnabledAp && ExcludeBsp) {
1088 //
1089 // If no enabled AP exists and not include Bsp to do the procedure, return EFI_NOT_STARTED.
1090 //
1091 return EFI_NOT_STARTED;
1092 }
1093
1094 CpuMpData->RunningCount = 0;
1095 for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
1096 CpuData = &CpuMpData->CpuData[ProcessorNumber];
1097 CpuData->Waiting = FALSE;
1098 if (ProcessorNumber != CpuMpData->BspNumber) {
1099 if (CpuData->State == CpuStateIdle) {
1100 //
1101 // Mark this processor as responsible for current calling.
1102 //
1103 CpuData->Waiting = TRUE;
1104 CpuMpData->RunningCount++;
1105 }
1106 }
1107 }
1108
1109 CpuMpData->Procedure = Procedure;
1110 CpuMpData->ProcArguments = ProcedureArgument;
1111 CpuMpData->SingleThread = SingleThread;
1112 CpuMpData->FinishedCount = 0;
1113 CpuMpData->ExpectedTime = CalculateTimeout (
1114 TimeoutInMicroseconds,
1115 &CpuMpData->CurrentTime
1116 );
1117 CpuMpData->TotalTime = 0;
1118 CpuMpData->WaitEvent = WaitEvent;
1119
1120 if (!SingleThread) {
1121 WakeUpAP (CpuMpData, TRUE, 0, Procedure, ProcedureArgument, FALSE);
1122 } else {
1123 for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
1124 if (ProcessorNumber == CallerNumber) {
1125 continue;
1126 }
1127
1128 if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
1129 WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument, TRUE);
1130 break;
1131 }
1132 }
1133 }
1134
1135 if (!ExcludeBsp) {
1136 //
1137 // Start BSP.
1138 //
1139 Procedure (ProcedureArgument);
1140 }
1141
1142 Status = EFI_SUCCESS;
1143 if (WaitEvent == NULL) {
1144 do {
1145 Status = CheckAllAPs ();
1146 } while (Status == EFI_NOT_READY);
1147 }
1148
1149 return Status;
1150}
1151
1177 IN EFI_AP_PROCEDURE Procedure,
1178 IN UINTN ProcessorNumber,
1179 IN EFI_EVENT WaitEvent OPTIONAL,
1180 IN UINTN TimeoutInMicroseconds,
1181 IN VOID *ProcedureArgument OPTIONAL,
1182 OUT BOOLEAN *Finished OPTIONAL
1183 )
1184{
1185 EFI_STATUS Status;
1186 CPU_MP_DATA *CpuMpData;
1187 CPU_AP_DATA *CpuData;
1188 UINTN CallerNumber;
1189
1190 CpuMpData = GetCpuMpData ();
1191
1192 if (Finished != NULL) {
1193 *Finished = FALSE;
1194 }
1195
1196 //
1197 // Check whether caller processor is BSP
1198 //
1199 MpInitLibWhoAmI (&CallerNumber);
1200 if (CallerNumber != CpuMpData->BspNumber) {
1201 return EFI_DEVICE_ERROR;
1202 }
1203
1204 //
1205 // Check whether processor with the handle specified by ProcessorNumber exists
1206 //
1207 if (ProcessorNumber >= CpuMpData->CpuCount) {
1208 return EFI_NOT_FOUND;
1209 }
1210
1211 //
1212 // Check whether specified processor is BSP
1213 //
1214 if (ProcessorNumber == CpuMpData->BspNumber) {
1215 return EFI_INVALID_PARAMETER;
1216 }
1217
1218 //
1219 // Check parameter Procedure
1220 //
1221 if (Procedure == NULL) {
1222 return EFI_INVALID_PARAMETER;
1223 }
1224
1225 //
1226 // Update AP state
1227 //
1229
1230 //
1231 // Check whether specified AP is disabled
1232 //
1233 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) {
1234 return EFI_INVALID_PARAMETER;
1235 }
1236
1237 CpuData = &CpuMpData->CpuData[ProcessorNumber];
1238 CpuData->WaitEvent = WaitEvent;
1239 CpuData->Finished = Finished;
1240 CpuData->ExpectedTime = CalculateTimeout (TimeoutInMicroseconds, &CpuData->CurrentTime);
1241 CpuData->TotalTime = 0;
1242
1243 WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument, FALSE);
1244
1245 //
1246 // If WaitEvent is NULL, execute in blocking mode.
1247 // BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires.
1248 //
1249 Status = EFI_SUCCESS;
1250 if (WaitEvent == NULL) {
1251 do {
1252 Status = CheckThisAP (ProcessorNumber);
1253 } while (Status == EFI_NOT_READY);
1254 }
1255
1256 return Status;
1257}
1258
1286EFIAPI
1288 IN EFI_AP_PROCEDURE Procedure,
1289 IN UINTN TimeoutInMicroseconds,
1290 IN VOID *ProcedureArgument OPTIONAL
1291 )
1292{
1293 return StartupAllCPUsWorker (
1294 Procedure,
1295 TRUE,
1296 FALSE,
1297 NULL,
1298 TimeoutInMicroseconds,
1299 ProcedureArgument,
1300 NULL
1301 );
1302}
1303
1318EFIAPI
1320 VOID
1321 )
1322{
1323 CPU_MP_DATA *OldCpuMpData;
1324 CPU_INFO_IN_HOB *CpuInfoInHob;
1325 UINT32 MaxLogicalProcessorNumber;
1326 UINTN BufferSize;
1327 UINTN MonitorBufferSize;
1328 VOID *MpBuffer;
1329 CPU_MP_DATA *CpuMpData;
1330 UINTN Index;
1331
1332 OldCpuMpData = GetCpuMpDataFromGuidedHob ();
1333 if (OldCpuMpData == NULL) {
1334 MaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
1335 } else {
1336 MaxLogicalProcessorNumber = OldCpuMpData->CpuCount;
1337 }
1338
1339 ASSERT (MaxLogicalProcessorNumber != 0);
1340
1341 MonitorBufferSize = sizeof (WAKEUP_AP_SIGNAL) * MaxLogicalProcessorNumber;
1342
1343 BufferSize = 0;
1344 BufferSize += MonitorBufferSize;
1345 BufferSize += sizeof (CPU_MP_DATA);
1346 BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;
1347 MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
1348 ASSERT (MpBuffer != NULL);
1349 ZeroMem (MpBuffer, BufferSize);
1350
1351 CpuMpData = (CPU_MP_DATA *)MpBuffer;
1352
1353 CpuMpData->CpuCount = 1;
1354 CpuMpData->BspNumber = 0;
1355 CpuMpData->CpuData = (CPU_AP_DATA *)(CpuMpData + 1);
1356 CpuMpData->CpuInfoInHob = (UINT64)(UINTN)(CpuMpData->CpuData + MaxLogicalProcessorNumber);
1357
1358 InitializeSpinLock (&CpuMpData->MpLock);
1359
1360 //
1361 // Set BSP basic information
1362 //
1363 InitializeApData (CpuMpData, 0, 0);
1364
1365 //
1366 // Set up APs wakeup signal buffer and initialization APs ApicId status.
1367 //
1368 for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
1369 CpuMpData->CpuData[Index].StartupApSignal =
1370 (UINT32 *)((MpBuffer + BufferSize - MonitorBufferSize) + (sizeof (WAKEUP_AP_SIGNAL) * Index));
1371 if ((OldCpuMpData == NULL) && (Index != CpuMpData->BspNumber)) {
1372 ((CPU_INFO_IN_HOB *)CpuMpData->CpuInfoInHob)[Index].ApicId = INVALID_APIC_ID;
1373 }
1374 }
1375
1376 if (OldCpuMpData == NULL) {
1377 if (MaxLogicalProcessorNumber > 1) {
1378 //
1379 // Wakeup all APs and calculate the processor count in system
1380 //
1381 CollectProcessorCount (CpuMpData);
1382 }
1383 } else {
1384 //
1385 // APs have been wakeup before, just get the CPU Information
1386 // from HOB
1387 //
1388 CpuMpData->CpuCount = OldCpuMpData->CpuCount;
1389 CpuMpData->BspNumber = OldCpuMpData->BspNumber;
1390 CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob;
1391 CpuMpData->MpCpuExchangeInfo = OldCpuMpData->MpCpuExchangeInfo;
1392
1393 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
1394 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
1395 InitializeSpinLock (&CpuMpData->CpuData[Index].ApLock);
1396 CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0) ? TRUE : FALSE;
1397 }
1398
1399 if (CpuMpData->CpuCount > 1) {
1400 //
1401 // Only needs to use this flag for DXE phase to update the wake up
1402 // buffer. Wakeup buffer allocated in PEI phase is no longer valid
1403 // in DXE.
1404 //
1405 CpuMpData->InitFlag = ApInitReconfig;
1406 WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, TRUE);
1407
1408 //
1409 // Wait for all APs finished initialization
1410 //
1411 while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
1412 CpuPause ();
1413 }
1414
1415 CpuMpData->InitFlag = ApInitDone;
1416 }
1417
1418 if (MaxLogicalProcessorNumber > 1) {
1419 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
1420 SetApState (&CpuMpData->CpuData[Index], CpuStateIdle);
1421 }
1422 }
1423 }
1424
1425 //
1426 // Initialize global data for MP support
1427 //
1428 InitMpGlobalData (CpuMpData);
1429
1430 return EFI_SUCCESS;
1431}
1432
1451EFIAPI
1453 IN UINTN ProcessorNumber,
1454 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer,
1455 OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL
1456 )
1457{
1458 CPU_MP_DATA *CpuMpData;
1459 UINTN CallerNumber;
1460 CPU_INFO_IN_HOB *CpuInfoInHob;
1461
1462 CpuMpData = GetCpuMpData ();
1463 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
1464
1465 //
1466 // Check whether caller processor is BSP
1467 //
1468 MpInitLibWhoAmI (&CallerNumber);
1469 if (CallerNumber != CpuMpData->BspNumber) {
1470 return EFI_DEVICE_ERROR;
1471 }
1472
1473 if (ProcessorInfoBuffer == NULL) {
1474 return EFI_INVALID_PARAMETER;
1475 }
1476
1477 if (ProcessorNumber >= CpuMpData->CpuCount) {
1478 return EFI_NOT_FOUND;
1479 }
1480
1481 ProcessorInfoBuffer->ProcessorId = (UINT64)CpuInfoInHob[ProcessorNumber].ApicId;
1482 ProcessorInfoBuffer->StatusFlag = 0;
1483 if (ProcessorNumber == CpuMpData->BspNumber) {
1484 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
1485 }
1486
1487 if (CpuMpData->CpuData[ProcessorNumber].CpuHealthy) {
1488 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
1489 }
1490
1491 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) {
1492 ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
1493 } else {
1494 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
1495 }
1496
1497 if (HealthData != NULL) {
1498 HealthData->Uint32 = CpuInfoInHob[ProcessorNumber].Health;
1499 }
1500
1501 return EFI_SUCCESS;
1502}
1503
1521EFIAPI
1523 OUT UINTN *ProcessorNumber
1524 )
1525{
1526 CPU_MP_DATA *CpuMpData;
1527
1528 if (ProcessorNumber == NULL) {
1529 return EFI_INVALID_PARAMETER;
1530 }
1531
1532 CpuMpData = GetCpuMpData ();
1533
1534 return GetProcessorNumber (CpuMpData, ProcessorNumber);
1535}
1536
1558EFIAPI
1560 OUT UINTN *NumberOfProcessors OPTIONAL,
1561 OUT UINTN *NumberOfEnabledProcessors OPTIONAL
1562 )
1563{
1564 CPU_MP_DATA *CpuMpData;
1565 UINTN CallerNumber;
1566 UINTN ProcessorNumber;
1567 UINTN EnabledProcessorNumber;
1568 UINTN Index;
1569
1570 CpuMpData = GetCpuMpData ();
1571
1572 if ((NumberOfProcessors == NULL) && (NumberOfEnabledProcessors == NULL)) {
1573 return EFI_INVALID_PARAMETER;
1574 }
1575
1576 //
1577 // Check whether caller processor is BSP
1578 //
1579 MpInitLibWhoAmI (&CallerNumber);
1580 if (CallerNumber != CpuMpData->BspNumber) {
1581 return EFI_DEVICE_ERROR;
1582 }
1583
1584 ProcessorNumber = CpuMpData->CpuCount;
1585 EnabledProcessorNumber = 0;
1586 for (Index = 0; Index < ProcessorNumber; Index++) {
1587 if (GetApState (&CpuMpData->CpuData[Index]) != CpuStateDisabled) {
1588 EnabledProcessorNumber++;
1589 }
1590 }
1591
1592 if (NumberOfProcessors != NULL) {
1593 *NumberOfProcessors = ProcessorNumber;
1594 }
1595
1596 if (NumberOfEnabledProcessors != NULL) {
1597 *NumberOfEnabledProcessors = EnabledProcessorNumber;
1598 }
1599
1600 return EFI_SUCCESS;
1601}
1602
1610 VOID
1611 )
1612{
1613 EFI_HOB_GUID_TYPE *GuidHob;
1614 VOID *DataInHob;
1615 CPU_MP_DATA *CpuMpData;
1616
1617 CpuMpData = NULL;
1618 GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid);
1619
1620 if (GuidHob != NULL) {
1621 DataInHob = GET_GUID_HOB_DATA (GuidHob);
1622 CpuMpData = (CPU_MP_DATA *)(*(UINTN *)DataInHob);
1623 }
1624
1625 return CpuMpData;
1626}
UINT64 UINTN
UINT64 EFIAPI GetPerformanceCounterProperties(OUT UINT64 *StartValue OPTIONAL, OUT UINT64 *EndValue OPTIONAL)
UINT64 EFIAPI GetPerformanceCounter(VOID)
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
UINT64 EFIAPI MultU64x64(IN UINT64 Multiplicand, IN UINT64 Multiplier)
Definition: MultU64x64.c:27
VOID EFIAPI CpuPause(VOID)
VOID EFIAPI EnableInterrupts(VOID)
Definition: CpuBreakpoint.c:67
VOID EFIAPI DisableInterrupts(VOID)
Definition: CpuBreakpoint.c:54
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI CpuSleep(VOID)
UINTN EFIAPI CsrRead(IN UINT16 Select)
Definition: Csr.c:37
VOID CheckAndUpdateApsStatus(VOID)
Definition: DxeMpLib.c:235
CPU_MP_DATA * GetCpuMpData(VOID)
Definition: DxeMpLib.c:56
VOID InitMpGlobalData(IN CPU_MP_DATA *CpuMpData)
Definition: DxeMpLib.c:499
PROCESSOR_RESOURCE_DATA * GetProcessorResourceDataFromGuidedHob(VOID)
Definition: MpLib.c:196
EFI_STATUS StartupThisAPWorker(IN EFI_AP_PROCEDURE Procedure, IN UINTN ProcessorNumber, IN EFI_EVENT WaitEvent OPTIONAL, IN UINTN TimeoutInMicroseconds, IN VOID *ProcedureArgument OPTIONAL, OUT BOOLEAN *Finished OPTIONAL)
Definition: MpLib.c:1176
CPU_STATE GetApState(IN CPU_AP_DATA *CpuData)
Definition: MpLib.c:27
CPU_MP_DATA * GetCpuMpDataFromGuidedHob(VOID)
Definition: MpLib.c:1609
VOID EFIAPI ApWakeupFunction(IN UINTN ApIndex, IN MP_CPU_EXCHANGE_INFO *ExchangeInfo)
Definition: MpLib.c:326
EFI_STATUS EFIAPI MpInitLibWhoAmI(OUT UINTN *ProcessorNumber)
Definition: MpLib.c:1522
EFI_STATUS EFIAPI MpInitLibGetNumberOfProcessors(OUT UINTN *NumberOfProcessors OPTIONAL, OUT UINTN *NumberOfEnabledProcessors OPTIONAL)
Definition: MpLib.c:1559
VOID SortApicId(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:109
VOID WakeUpAP(IN CPU_MP_DATA *CpuMpData, IN BOOLEAN Broadcast, IN UINTN ProcessorNumber, IN EFI_AP_PROCEDURE Procedure OPTIONAL, IN VOID *ProcedureArgument OPTIONAL, IN BOOLEAN WakeUpDisabledAps)
Definition: MpLib.c:672
UINT64 CalculateTimeout(IN UINTN TimeoutInMicroseconds, OUT UINT64 *CurrentTime)
Definition: MpLib.c:444
EFI_STATUS EFIAPI MpInitLibStartupAllCPUs(IN EFI_AP_PROCEDURE Procedure, IN UINTN TimeoutInMicroseconds, IN VOID *ProcedureArgument OPTIONAL)
Definition: MpLib.c:1287
VOID TimedWaitForApFinish(IN CPU_MP_DATA *CpuMpData, IN UINT32 FinishedApLimit, IN UINT32 TimeLimit)
Definition: MpLib.c:571
VOID WaitApWakeup(IN volatile UINT32 *ApStartupSignalBuffer)
Definition: MpLib.c:621
EFI_STATUS EFIAPI MpInitLibGetProcessorInfo(IN UINTN ProcessorNumber, OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL)
Definition: MpLib.c:1452
EFI_STATUS GetProcessorNumber(IN CPU_MP_DATA *CpuMpData, OUT UINTN *ProcessorNumber)
Definition: MpLib.c:78
UINT32 GetApicId(VOID)
Definition: MpLib.c:57
BOOLEAN CheckTimeout(IN OUT UINT64 *PreviousTime, IN UINT64 *TotalTime, IN UINT64 Timeout)
Definition: MpLib.c:520
UINTN CollectProcessorCount(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:222
VOID FillExchangeInfoData(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:646
EFI_STATUS StartupAllCPUsWorker(IN EFI_AP_PROCEDURE Procedure, IN BOOLEAN SingleThread, IN BOOLEAN ExcludeBsp, IN EFI_EVENT WaitEvent OPTIONAL, IN UINTN TimeoutInMicroseconds, IN VOID *ProcedureArgument OPTIONAL, OUT UINTN **FailedCpuList OPTIONAL)
Definition: MpLib.c:1019
EFI_STATUS CheckThisAP(IN UINTN ProcessorNumber)
Definition: MpLib.c:863
VOID InitializeApData(IN OUT CPU_MP_DATA *CpuMpData, IN UINTN ProcessorNumber, IN UINT32 BistData)
Definition: MpLib.c:295
VOID SetApState(IN CPU_AP_DATA *CpuData, IN CPU_STATE State)
Definition: MpLib.c:41
EFI_STATUS EFIAPI MpInitLibInitialize(VOID)
Definition: MpLib.c:1319
EFI_STATUS CheckAllAPs(VOID)
Definition: MpLib.c:910
EFI_STATUS GetNextWaitingProcessorNumber(OUT UINTN *NextProcessorNumber)
Definition: MpLib.c:832
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PROCESSOR_HEALTH_STATUS_BIT
Definition: MpService.h:84
#define PROCESSOR_AS_BSP_BIT
Definition: MpService.h:70
#define PROCESSOR_ENABLED_BIT
Definition: MpService.h:77
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID(EFIAPI * EFI_AP_PROCEDURE)(IN OUT VOID *Buffer)
Definition: PiMultiPhase.h:198
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID *EFIAPI AllocatePages(IN UINTN Pages)
UINT32 EFIAPI InterlockedIncrement(IN volatile UINT32 *Value)
SPIN_LOCK *EFIAPI AcquireSpinLock(IN OUT SPIN_LOCK *SpinLock)
UINT32 EFIAPI InterlockedCompareExchange32(IN OUT volatile UINT32 *Value, IN UINT32 CompareValue, IN UINT32 ExchangeValue)
SPIN_LOCK *EFIAPI InitializeSpinLock(OUT SPIN_LOCK *SpinLock)
SPIN_LOCK *EFIAPI ReleaseSpinLock(IN OUT SPIN_LOCK *SpinLock)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
Definition: Base.h:213