TianoCore EDK2 master
Loading...
Searching...
No Matches
MpLib.c
Go to the documentation of this file.
1
11#include "MpLib.h"
12#include <Library/CcExitLib.h>
14#include <Register/Amd/Ghcb.h>
15
16EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
17EFI_GUID mMpHandOffGuid = MP_HANDOFF_GUID;
18EFI_GUID mMpHandOffConfigGuid = MP_HANDOFF_CONFIG_GUID;
19
20RELOCATE_AP_LOOP_ENTRY mReservedApLoop;
21UINTN mReservedTopOfApStack;
22volatile UINT32 mNumberToFinish = 0;
23UINTN mApPageTable;
24
30VOID
32 OUT CPU_VOLATILE_REGISTERS *VolatileRegisters
33 );
34
42VOID
44 IN CPU_VOLATILE_REGISTERS *VolatileRegisters
45 );
46
58BOOLEAN
60 VOID
61 )
62{
63 UINT32 Eax;
66 BOOLEAN Enabled;
67 IA32_CR0 Cr0;
68
69 Enabled = FALSE;
70 Cr0.UintN = AsmReadCr0 ();
71 if (Cr0.Bits.PG != 0) {
72 //
73 // If CR0 Paging bit is set
74 //
75 AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL);
76 if (Eax >= CPUID_EXTENDED_CPU_SIG) {
78 //
79 // CPUID 0x80000001
80 // Bit 20: Execute Disable Bit available.
81 //
82 if (Edx.Bits.NX != 0) {
84 //
85 // MSR 0xC0000080
86 // Bit 11: Execute Disable Bit enable.
87 //
88 if (EferMsr.Bits.NXE != 0) {
89 Enabled = TRUE;
90 }
91 }
92 }
93 }
94
95 return Enabled;
96}
97
106VOID
107EFIAPI
109 IN VOID *Buffer
110 )
111{
112 CPU_MP_DATA *DataInHob;
113
114 DataInHob = (CPU_MP_DATA *)Buffer;
115 //
116 // Save and restore volatile registers when switch BSP
117 //
118 SaveVolatileRegisters (&DataInHob->APInfo.VolatileRegisters);
119 AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
120 RestoreVolatileRegisters (&DataInHob->APInfo.VolatileRegisters);
121}
122
130CPU_STATE
132 IN CPU_AP_DATA *CpuData
133 )
134{
135 return CpuData->State;
136}
137
144VOID
146 IN CPU_AP_DATA *CpuData,
147 IN CPU_STATE State
148 )
149{
150 AcquireSpinLock (&CpuData->ApLock);
151 CpuData->State = State;
152 ReleaseSpinLock (&CpuData->ApLock);
153}
154
160VOID
162 IN CPU_MP_DATA *CpuMpData
163 )
164{
165 CpuMpData->InitTimerCount = GetApicTimerInitCount ();
166 if (CpuMpData->InitTimerCount != 0) {
167 //
168 // Record the current local APIC timer setting of BSP
169 //
171 &CpuMpData->DivideValue,
172 &CpuMpData->PeriodicMode,
173 &CpuMpData->Vector
174 );
175
176 CpuMpData->TimerInterruptState = GetApicTimerInterruptState ();
177 }
178}
179
185VOID
187 IN CPU_MP_DATA *CpuMpData
188 )
189{
190 if (CpuMpData->InitTimerCount != 0) {
191 //
192 // Sync local APIC timer setting from BSP to AP
193 //
195 CpuMpData->DivideValue,
196 CpuMpData->InitTimerCount,
197 CpuMpData->PeriodicMode,
198 CpuMpData->Vector
199 );
200 //
201 // Disable AP's local APIC timer interrupt
202 //
204 }
205}
206
212VOID
214 OUT CPU_VOLATILE_REGISTERS *VolatileRegisters
215 )
216{
217 CPUID_VERSION_INFO_EDX VersionInfoEdx;
218
219 VolatileRegisters->Cr0 = AsmReadCr0 ();
220 VolatileRegisters->Cr3 = AsmReadCr3 ();
221 VolatileRegisters->Cr4 = AsmReadCr4 ();
222
223 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
224 if (VersionInfoEdx.Bits.DE != 0) {
225 //
226 // If processor supports Debugging Extensions feature
227 // by CPUID.[EAX=01H]:EDX.BIT2
228 //
229 VolatileRegisters->Dr0 = AsmReadDr0 ();
230 VolatileRegisters->Dr1 = AsmReadDr1 ();
231 VolatileRegisters->Dr2 = AsmReadDr2 ();
232 VolatileRegisters->Dr3 = AsmReadDr3 ();
233 VolatileRegisters->Dr6 = AsmReadDr6 ();
234 VolatileRegisters->Dr7 = AsmReadDr7 ();
235 }
236
237 AsmReadGdtr (&VolatileRegisters->Gdtr);
238 AsmReadIdtr (&VolatileRegisters->Idtr);
239 VolatileRegisters->Tr = AsmReadTr ();
240}
241
248VOID
250 IN CPU_VOLATILE_REGISTERS *VolatileRegisters
251 )
252{
253 CPUID_VERSION_INFO_EDX VersionInfoEdx;
254 IA32_TSS_DESCRIPTOR *Tss;
255
256 AsmWriteCr3 (VolatileRegisters->Cr3);
257 AsmWriteCr4 (VolatileRegisters->Cr4);
258 AsmWriteCr0 (VolatileRegisters->Cr0);
259
260 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
261 if (VersionInfoEdx.Bits.DE != 0) {
262 //
263 // If processor supports Debugging Extensions feature
264 // by CPUID.[EAX=01H]:EDX.BIT2
265 //
266 AsmWriteDr0 (VolatileRegisters->Dr0);
267 AsmWriteDr1 (VolatileRegisters->Dr1);
268 AsmWriteDr2 (VolatileRegisters->Dr2);
269 AsmWriteDr3 (VolatileRegisters->Dr3);
270 AsmWriteDr6 (VolatileRegisters->Dr6);
271 AsmWriteDr7 (VolatileRegisters->Dr7);
272 }
273
274 AsmWriteGdtr (&VolatileRegisters->Gdtr);
275 AsmWriteIdtr (&VolatileRegisters->Idtr);
276 if ((VolatileRegisters->Tr != 0) &&
277 (VolatileRegisters->Tr < VolatileRegisters->Gdtr.Limit))
278 {
279 Tss = (IA32_TSS_DESCRIPTOR *)(VolatileRegisters->Gdtr.Base +
280 VolatileRegisters->Tr);
281 if (Tss->Bits.P == 1) {
282 Tss->Bits.Type &= 0xD; // 1101 - Clear busy bit just in case
283 AsmWriteTr (VolatileRegisters->Tr);
284 }
285 }
286}
287
294BOOLEAN
296 VOID
297 )
298{
299 CPUID_VERSION_INFO_ECX VersionInfoEcx;
300
301 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL);
302 return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE;
303}
304
312UINT8
314 OUT UINT32 *MonitorFilterSize
315 )
316{
317 UINT8 ApLoopMode;
318 CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx;
319
320 ASSERT (MonitorFilterSize != NULL);
321
322 ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
323 ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);
324 if (ApLoopMode == ApInMwaitLoop) {
325 if (!IsMwaitSupport ()) {
326 //
327 // If processor does not support MONITOR/MWAIT feature,
328 // force AP in Hlt-loop mode
329 //
330 ApLoopMode = ApInHltLoop;
331 }
332
333 if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) &&
334 !ConfidentialComputingGuestHas (CCAttrAmdSevSnp))
335 {
336 //
337 // For SEV-ES (SEV-SNP is also considered SEV-ES), force AP in Hlt-loop
338 // mode in order to use the GHCB protocol for starting APs
339 //
340 ApLoopMode = ApInHltLoop;
341 }
342 }
343
344 if (ApLoopMode != ApInMwaitLoop) {
345 *MonitorFilterSize = sizeof (UINT32);
346 } else {
347 //
348 // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes
349 // CPUID.[EAX=05H].EDX: C-states supported using MWAIT
350 //
351 AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL);
352 *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize;
353 }
354
355 return ApLoopMode;
356}
357
366VOID
368 IN CPU_MP_DATA *CpuMpData
369 )
370{
371 UINTN Index1;
372 UINTN Index2;
373 UINTN Index3;
374 UINT32 ApicId;
375 CPU_INFO_IN_HOB CpuInfo;
376 CPU_AP_DATA CpuApData;
377 UINT32 ApCount;
378 CPU_INFO_IN_HOB *CpuInfoInHob;
379
380 ApCount = CpuMpData->CpuCount - 1;
381 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
382 if (ApCount != 0) {
383 for (Index1 = 0; Index1 < ApCount; Index1++) {
384 Index3 = Index1;
385 //
386 // Sort key is the hardware default APIC ID
387 //
388 ApicId = CpuInfoInHob[Index1].ApicId;
389 for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) {
390 if (ApicId > CpuInfoInHob[Index2].ApicId) {
391 Index3 = Index2;
392 ApicId = CpuInfoInHob[Index2].ApicId;
393 }
394 }
395
396 if (Index3 != Index1) {
397 CopyMem (&CpuInfo, &CpuInfoInHob[Index3], sizeof (CPU_INFO_IN_HOB));
398 CopyMem (
399 &CpuInfoInHob[Index3],
400 &CpuInfoInHob[Index1],
401 sizeof (CPU_INFO_IN_HOB)
402 );
403 CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB));
404
405 CopyMem (&CpuApData, &CpuMpData->CpuData[Index3], sizeof (CPU_AP_DATA));
406 CopyMem (
407 &CpuMpData->CpuData[Index3],
408 &CpuMpData->CpuData[Index1],
409 sizeof (CPU_AP_DATA)
410 );
411 CopyMem (&CpuMpData->CpuData[Index1], &CpuApData, sizeof (CPU_AP_DATA));
412 }
413 }
414
415 //
416 // Get the processor number for the BSP
417 //
418 ApicId = GetInitialApicId ();
419 for (Index1 = 0; Index1 < CpuMpData->CpuCount; Index1++) {
420 if (CpuInfoInHob[Index1].ApicId == ApicId) {
421 CpuMpData->BspNumber = (UINT32)Index1;
422 break;
423 }
424 }
425 }
426}
427
433VOID
434EFIAPI
436 IN OUT VOID *Buffer
437 )
438{
440}
441
447VOID
448EFIAPI
450 IN OUT VOID *Buffer
451 )
452{
453 CPU_MP_DATA *CpuMpData;
454 UINTN ProcessorNumber;
455 EFI_STATUS Status;
456
457 CpuMpData = (CPU_MP_DATA *)Buffer;
458 Status = GetProcessorNumber (CpuMpData, &ProcessorNumber);
459 ASSERT_EFI_ERROR (Status);
460 //
461 // Load microcode on AP
462 //
463 MicrocodeDetect (CpuMpData, ProcessorNumber);
464 //
465 // Sync BSP's MTRR table to AP
466 //
467 MtrrSetAllMtrrs (&CpuMpData->MtrrTable);
468}
469
481 IN CPU_MP_DATA *CpuMpData,
482 OUT UINTN *ProcessorNumber
483 )
484{
485 UINTN TotalProcessorNumber;
486 UINTN Index;
487 CPU_INFO_IN_HOB *CpuInfoInHob;
488 UINT32 CurrentApicId;
489
490 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
491
492 TotalProcessorNumber = CpuMpData->CpuCount;
493 CurrentApicId = GetApicId ();
494 for (Index = 0; Index < TotalProcessorNumber; Index++) {
495 if (CpuInfoInHob[Index].ApicId == CurrentApicId) {
496 *ProcessorNumber = Index;
497 return EFI_SUCCESS;
498 }
499 }
500
501 return EFI_NOT_FOUND;
502}
503
511VOID
513 IN CPU_MP_DATA *CpuMpData
514 )
515{
516 BOOLEAN X2Apic;
517 UINTN Index;
518 CPU_INFO_IN_HOB *CpuInfoInHob;
519
520 //
521 // Enable x2APIC mode if
522 // 1. Number of CPU is greater than 255; or
523 // 2. There are any logical processors reporting an Initial APIC ID of 255 or greater.
524 //
525 X2Apic = FALSE;
526 if (CpuMpData->CpuCount > 255) {
527 //
528 // If there are more than 255 processor found, force to enable X2APIC
529 //
530 X2Apic = TRUE;
531 } else {
532 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
533 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
534 if (CpuInfoInHob[Index].InitialApicId >= 0xFF) {
535 X2Apic = TRUE;
536 break;
537 }
538 }
539 }
540
541 if (X2Apic) {
542 DEBUG ((DEBUG_INFO, "Force x2APIC mode!\n"));
543 //
544 // Wakeup all APs to enable x2APIC mode
545 //
546 WakeUpAP (CpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL, TRUE);
547 //
548 // Wait for all known APs finished
549 //
550 while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
551 CpuPause ();
552 }
553
554 //
555 // Enable x2APIC on BSP
556 //
558 //
559 // Set BSP/Aps state to IDLE
560 //
561 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
562 SetApState (&CpuMpData->CpuData[Index], CpuStateIdle);
563 }
564 }
565
566 DEBUG ((DEBUG_INFO, "APIC MODE is %d\n", GetApicMode ()));
567}
568
576UINTN
578 IN CPU_MP_DATA *CpuMpData
579 )
580{
581 //
582 // Send 1st broadcast IPI to APs to wakeup APs
583 //
584 CpuMpData->InitFlag = ApInitConfig;
585 WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, TRUE);
586 CpuMpData->InitFlag = ApInitDone;
587 //
588 // When InitFlag == ApInitConfig, WakeUpAP () guarantees all APs are checked in.
589 // FinishedCount is the number of check-in APs.
590 //
591 CpuMpData->CpuCount = CpuMpData->FinishedCount + 1;
592 ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
593
594 return CpuMpData->CpuCount;
595}
596
606VOID
608 IN OUT CPU_MP_DATA *CpuMpData,
609 IN UINTN ProcessorNumber,
610 IN UINT32 BistData,
611 IN UINT64 ApTopOfStack
612 )
613{
614 CPU_INFO_IN_HOB *CpuInfoInHob;
615 MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;
616 AP_STACK_DATA *ApStackData;
617
618 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
619 CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();
620 CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();
621 CpuInfoInHob[ProcessorNumber].Health = BistData;
622 CpuInfoInHob[ProcessorNumber].ApTopOfStack = ApTopOfStack;
623
624 //
625 // AP_STACK_DATA is stored at the top of AP Stack
626 //
627 ApStackData = (AP_STACK_DATA *)((UINTN)ApTopOfStack - sizeof (AP_STACK_DATA));
628 ApStackData->MpData = CpuMpData;
629
630 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
631 CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;
632
633 //
634 // NOTE: PlatformId is not relevant on AMD platforms.
635 //
637 PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
638 CpuMpData->CpuData[ProcessorNumber].PlatformId = (UINT8)PlatformIdMsr.Bits.PlatformId;
639 }
640
641 AsmCpuid (
643 &CpuMpData->CpuData[ProcessorNumber].ProcessorSignature,
644 NULL,
645 NULL,
646 NULL
647 );
648
649 InitializeSpinLock (&CpuMpData->CpuData[ProcessorNumber].ApLock);
650 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
651}
652
658VOID
660 IN CPU_MP_DATA *CpuMpData
661 )
662{
663 while (TRUE) {
665 if (CpuMpData->UseSevEsAPMethod) {
666 SevEsPlaceApHlt (CpuMpData);
667 } else {
668 CpuSleep ();
669 }
670
671 CpuPause ();
672 }
673}
674
682VOID
684 IN UINT8 ApLoopMode,
685 IN volatile UINT32 *ApStartupSignalBuffer,
686 IN UINT8 ApTargetCState
687 )
688{
689 while (TRUE) {
691 if (ApLoopMode == ApInMwaitLoop) {
692 //
693 // Place AP in MWAIT-loop
694 //
695 AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0);
696 if ((*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) && (*ApStartupSignalBuffer != MP_HAND_OFF_SIGNAL)) {
697 //
698 // Check AP start-up signal again.
699 // If AP start-up signal is not set, place AP into
700 // the specified C-state
701 //
702 AsmMwait (ApTargetCState << 4, 0);
703 }
704 } else if (ApLoopMode == ApInRunLoop) {
705 //
706 // Place AP in Run-loop
707 //
708 CpuPause ();
709 } else {
710 ASSERT (FALSE);
711 }
712
713 //
714 // If AP start-up signal is written, AP is waken up
715 // otherwise place AP in loop again
716 //
717 if ((*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) || (*ApStartupSignalBuffer == MP_HAND_OFF_SIGNAL)) {
718 break;
719 }
720 }
721}
722
729VOID
730EFIAPI
732 IN CPU_MP_DATA *CpuMpData,
733 IN UINTN ApIndex
734 )
735{
736 UINTN ProcessorNumber;
737 EFI_AP_PROCEDURE Procedure;
738 VOID *Parameter;
739 UINT32 BistData;
740 volatile UINT32 *ApStartupSignalBuffer;
741 CPU_INFO_IN_HOB *CpuInfoInHob;
742 UINT64 ApTopOfStack;
743 UINTN CurrentApicMode;
744 AP_STACK_DATA *ApStackData;
745 UINT32 OriginalValue;
746
747 //
748 // AP's local APIC settings will be lost after received INIT IPI
749 // We need to re-initialize them at here
750 //
752 //
753 // Mask the LINT0 and LINT1 so that AP doesn't enter the system timer interrupt handler.
754 //
756 SyncLocalApicTimerSetting (CpuMpData);
757
758 CurrentApicMode = GetApicMode ();
759 while (TRUE) {
760 if (CpuMpData->InitFlag == ApInitConfig) {
761 //
762 // Synchronize APIC mode with BSP in the first time AP wakeup ONLY.
763 //
764 SetApicMode (CpuMpData->InitialBspApicMode);
765 CurrentApicMode = CpuMpData->InitialBspApicMode;
766
767 ProcessorNumber = ApIndex;
768 //
769 // This is first time AP wakeup, get BIST information from AP stack
770 //
771 ApTopOfStack = CpuMpData->Buffer + (ProcessorNumber + 1) * CpuMpData->CpuApStackSize;
772 ApStackData = (AP_STACK_DATA *)((UINTN)ApTopOfStack - sizeof (AP_STACK_DATA));
773 BistData = (UINT32)ApStackData->Bist;
774
775 //
776 // CpuMpData->CpuData[ProcessorNumber].VolatileRegisters is initialized based on BSP environment,
777 // to initialize AP in InitConfig path.
778 // NOTE: IDTR.BASE stored in CpuMpData->CpuData[ProcessorNumber].VolatileRegisters points to a different IDT shared by all APs.
779 //
780 RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
781 InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack);
782 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
783 } else {
784 //
785 // Execute AP function if AP is ready
786 //
787 GetProcessorNumber (CpuMpData, &ProcessorNumber);
788 //
789 // Clear AP start-up signal when AP waken up
790 //
791 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
792 OriginalValue = InterlockedCompareExchange32 (
793 (UINT32 *)ApStartupSignalBuffer,
794 MP_HAND_OFF_SIGNAL,
795 0
796 );
797 if (OriginalValue == MP_HAND_OFF_SIGNAL) {
798 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateReady);
799 }
800
802 (UINT32 *)ApStartupSignalBuffer,
803 WAKEUP_AP_SIGNAL,
804 0
805 );
806
807 RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
808
809 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {
810 Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;
811 Parameter = (VOID *)CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument;
812 if (Procedure != NULL) {
813 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);
814 //
815 // Enable source debugging on AP function
816 //
818 //
819 // Invoke AP function here
820 //
821 Procedure (Parameter);
822 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
823 if (CpuMpData->SwitchBspFlag) {
824 //
825 // Re-get the processor number due to BSP/AP maybe exchange in AP function
826 //
827 GetProcessorNumber (CpuMpData, &ProcessorNumber);
828 CpuMpData->CpuData[ProcessorNumber].ApFunction = 0;
829 CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument = 0;
830 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
831 CpuInfoInHob[ProcessorNumber].ApTopOfStack = CpuInfoInHob[CpuMpData->NewBspNumber].ApTopOfStack;
832 } else {
833 if ((CpuInfoInHob[ProcessorNumber].ApicId != GetApicId ()) ||
834 (CpuInfoInHob[ProcessorNumber].InitialApicId != GetInitialApicId ()))
835 {
836 if (CurrentApicMode != GetApicMode ()) {
837 //
838 // If APIC mode change happened during AP function execution,
839 // we do not support APIC ID value changed.
840 //
841 ASSERT (FALSE);
842 CpuDeadLoop ();
843 } else {
844 //
845 // Re-get the CPU APICID and Initial APICID if they are changed
846 //
847 CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();
848 CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();
849 }
850 }
851 }
852 }
853
854 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);
855 }
856 }
857
858 SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
859
860 //
861 // AP finished executing C code
862 //
863 InterlockedIncrement ((UINT32 *)&CpuMpData->FinishedCount);
864
865 if (CpuMpData->InitFlag == ApInitConfig) {
866 //
867 // Delay decrementing the APs executing count when SEV-ES is enabled
868 // to allow the APs to issue an AP_RESET_HOLD before the BSP possibly
869 // performs another INIT-SIPI-SIPI sequence.
870 //
871 if (!CpuMpData->UseSevEsAPMethod) {
872 InterlockedDecrement ((UINT32 *)&CpuMpData->MpCpuExchangeInfo->NumApsExecuting);
873 }
874 }
875
876 //
877 // Place AP is specified loop mode
878 //
879 if (CpuMpData->ApLoopMode == ApInHltLoop) {
880 PlaceAPInHltLoop (CpuMpData);
881 //
882 // Never run here
883 //
884 } else {
885 PlaceAPInMwaitLoopOrRunLoop (CpuMpData->ApLoopMode, ApStartupSignalBuffer, CpuMpData->ApTargetCState);
886 }
887 }
888}
889
897VOID
898EFIAPI
900 CPU_MP_DATA *CpuMpData
901 )
902{
903 UINTN ProcessorNumber;
905
906 GetProcessorNumber (CpuMpData, &ProcessorNumber);
907 if (CpuMpData->EnableExecuteDisableForSwitchContext) {
909 EferMsr.Bits.NXE = 1;
911 }
912
913 RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
914 InterlockedIncrement ((UINT32 *)&CpuMpData->FinishedCount);
916 CpuMpData->ApLoopMode,
917 CpuMpData->CpuData[ProcessorNumber].StartupApSignal,
918 CpuMpData->ApTargetCState
919 );
920 ApWakeupFunction (CpuMpData, ProcessorNumber);
921}
922
928VOID
930 IN volatile UINT32 *ApStartupSignalBuffer
931 )
932{
933 //
934 // If AP is waken up, StartupApSignal should be cleared.
935 // Otherwise, write StartupApSignal again till AP waken up.
936 //
938 (UINT32 *)ApStartupSignalBuffer,
939 WAKEUP_AP_SIGNAL,
940 WAKEUP_AP_SIGNAL
941 ) != 0)
942 {
943 CpuPause ();
944 }
945}
946
954STATIC
955VOID
957 IN MP_ASSEMBLY_ADDRESS_MAP *AddressMap,
958 OUT UINTN *SizeBelow1Mb OPTIONAL,
959 OUT UINTN *SizeAbove1Mb OPTIONAL
960 )
961{
962 if (SizeBelow1Mb != NULL) {
963 *SizeBelow1Mb = AddressMap->ModeTransitionOffset + sizeof (MP_CPU_EXCHANGE_INFO);
964 }
965
966 if (SizeAbove1Mb != NULL) {
967 *SizeAbove1Mb = AddressMap->RendezvousFunnelSize - AddressMap->ModeTransitionOffset;
968 }
969}
970
977VOID
979 IN CPU_MP_DATA *CpuMpData
980 )
981{
982 volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
983 UINTN Size;
984 IA32_SEGMENT_DESCRIPTOR *Selector;
985 IA32_CR4 Cr4;
986
987 ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
988 ExchangeInfo->StackStart = CpuMpData->Buffer;
989 ExchangeInfo->StackSize = CpuMpData->CpuApStackSize;
990 ExchangeInfo->BufferStart = CpuMpData->WakeupBuffer;
991 ExchangeInfo->ModeOffset = CpuMpData->AddressMap.ModeEntryOffset;
992
993 ExchangeInfo->CodeSegment = AsmReadCs ();
994 ExchangeInfo->DataSegment = AsmReadDs ();
995
996 ExchangeInfo->Cr3 = AsmReadCr3 ();
997
998 ExchangeInfo->CFunction = (UINTN)ApWakeupFunction;
999 ExchangeInfo->ApIndex = 0;
1000 ExchangeInfo->NumApsExecuting = 0;
1001 ExchangeInfo->InitFlag = (UINTN)CpuMpData->InitFlag;
1002 ExchangeInfo->CpuInfo = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
1003 ExchangeInfo->CpuMpData = CpuMpData;
1004
1005 ExchangeInfo->EnableExecuteDisable = IsBspExecuteDisableEnabled ();
1006
1007 ExchangeInfo->InitializeFloatingPointUnitsAddress = (UINTN)InitializeFloatingPointUnits;
1008
1009 //
1010 // We can check either CPUID(7).ECX[bit16] or check CR4.LA57[bit12]
1011 // to determin whether 5-Level Paging is enabled.
1012 // CPUID(7).ECX[bit16] shows CPU's capability, CR4.LA57[bit12] shows
1013 // current system setting.
1014 // Using latter way is simpler because it also eliminates the needs to
1015 // check whether platform wants to enable it.
1016 //
1017 Cr4.UintN = AsmReadCr4 ();
1018 ExchangeInfo->Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
1019 DEBUG ((DEBUG_INFO, "%a: 5-Level Paging = %d\n", gEfiCallerBaseName, ExchangeInfo->Enable5LevelPaging));
1020
1021 ExchangeInfo->SevEsIsEnabled = CpuMpData->SevEsIsEnabled;
1022 ExchangeInfo->SevSnpIsEnabled = CpuMpData->SevSnpIsEnabled;
1023 ExchangeInfo->GhcbBase = (UINTN)CpuMpData->GhcbBase;
1024
1025 //
1026 // Populate SEV-ES specific exchange data.
1027 //
1028 if (ExchangeInfo->SevSnpIsEnabled) {
1029 FillExchangeInfoDataSevEs (ExchangeInfo);
1030 }
1031
1032 //
1033 // Get the BSP's data of GDT and IDT
1034 //
1035 AsmReadGdtr ((IA32_DESCRIPTOR *)&ExchangeInfo->GdtrProfile);
1036 AsmReadIdtr ((IA32_DESCRIPTOR *)&ExchangeInfo->IdtrProfile);
1037
1038 //
1039 // Find a 32-bit code segment
1040 //
1041 Selector = (IA32_SEGMENT_DESCRIPTOR *)ExchangeInfo->GdtrProfile.Base;
1042 Size = ExchangeInfo->GdtrProfile.Limit + 1;
1043 while (Size > 0) {
1044 if ((Selector->Bits.L == 0) && (Selector->Bits.Type >= 8)) {
1045 ExchangeInfo->ModeTransitionSegment =
1046 (UINT16)((UINTN)Selector - ExchangeInfo->GdtrProfile.Base);
1047 break;
1048 }
1049
1050 Selector += 1;
1051 Size -= sizeof (IA32_SEGMENT_DESCRIPTOR);
1052 }
1053
1054 ExchangeInfo->ModeTransitionMemory = (UINT32)CpuMpData->WakeupBufferHigh;
1055
1056 ExchangeInfo->ModeHighMemory = ExchangeInfo->ModeTransitionMemory +
1057 (UINT32)ExchangeInfo->ModeOffset -
1058 (UINT32)CpuMpData->AddressMap.ModeTransitionOffset;
1059 ExchangeInfo->ModeHighSegment = (UINT16)ExchangeInfo->CodeSegment;
1060}
1061
1070VOID
1072 IN CPU_MP_DATA *CpuMpData,
1073 IN UINT32 FinishedApLimit,
1074 IN UINT32 TimeLimit
1075 );
1076
1082VOID
1084 IN CPU_MP_DATA *CpuMpData
1085 )
1086{
1087 CopyMem (
1088 (VOID *)CpuMpData->BackupBuffer,
1089 (VOID *)CpuMpData->WakeupBuffer,
1090 CpuMpData->BackupBufferSize
1091 );
1092 CopyMem (
1093 (VOID *)CpuMpData->WakeupBuffer,
1094 (VOID *)CpuMpData->AddressMap.RendezvousFunnelAddress,
1095 CpuMpData->BackupBufferSize - sizeof (MP_CPU_EXCHANGE_INFO)
1096 );
1097}
1098
1104VOID
1106 IN CPU_MP_DATA *CpuMpData
1107 )
1108{
1109 CopyMem (
1110 (VOID *)CpuMpData->WakeupBuffer,
1111 (VOID *)CpuMpData->BackupBuffer,
1112 CpuMpData->BackupBufferSize
1113 );
1114}
1115
1121VOID
1123 IN OUT CPU_MP_DATA *CpuMpData
1124 )
1125{
1126 UINTN ApResetStackSize;
1127
1128 if (CpuMpData->WakeupBuffer == (UINTN)-1) {
1129 CpuMpData->WakeupBuffer = GetWakeupBuffer (CpuMpData->BackupBufferSize);
1130 CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *)(UINTN)
1131 (CpuMpData->WakeupBuffer + CpuMpData->BackupBufferSize - sizeof (MP_CPU_EXCHANGE_INFO));
1132 DEBUG ((
1133 DEBUG_INFO,
1134 "AP Vector: 16-bit = %p/%x, ExchangeInfo = %p/%x\n",
1135 CpuMpData->WakeupBuffer,
1136 CpuMpData->BackupBufferSize - sizeof (MP_CPU_EXCHANGE_INFO),
1137 CpuMpData->MpCpuExchangeInfo,
1138 sizeof (MP_CPU_EXCHANGE_INFO)
1139 ));
1140 //
1141 // The AP reset stack is only used by SEV-ES guests. Do not allocate it
1142 // if SEV-ES is not enabled. An SEV-SNP guest is also considered
1143 // an SEV-ES guest, but uses a different method of AP startup, eliminating
1144 // the need for the allocation.
1145 //
1146 if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) &&
1147 !ConfidentialComputingGuestHas (CCAttrAmdSevSnp))
1148 {
1149 //
1150 // Stack location is based on ProcessorNumber, so use the total number
1151 // of processors for calculating the total stack area.
1152 //
1153 ApResetStackSize = (AP_RESET_STACK_SIZE *
1154 PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
1155
1156 //
1157 // Invoke GetWakeupBuffer a second time to allocate the stack area
1158 // below 1MB. The returned buffer will be page aligned and sized and
1159 // below the previously allocated buffer.
1160 //
1161 CpuMpData->SevEsAPResetStackStart = GetWakeupBuffer (ApResetStackSize);
1162
1163 //
1164 // Check to be sure that the "allocate below" behavior hasn't changed.
1165 // This will also catch a failed allocation, as "-1" is returned on
1166 // failure.
1167 //
1168 if (CpuMpData->SevEsAPResetStackStart >= CpuMpData->WakeupBuffer) {
1169 DEBUG ((
1170 DEBUG_ERROR,
1171 "SEV-ES AP reset stack is not below wakeup buffer\n"
1172 ));
1173
1174 ASSERT (FALSE);
1175 CpuDeadLoop ();
1176 }
1177 }
1178 }
1179
1180 BackupAndPrepareWakeupBuffer (CpuMpData);
1181}
1182
1188VOID
1190 IN CPU_MP_DATA *CpuMpData
1191 )
1192{
1193 //
1194 // If SEV-ES is enabled, the reset area is needed for AP parking and
1195 // and AP startup in the OS, so the reset area is reserved. Do not
1196 // perform the restore as this will overwrite memory which has data
1197 // needed by SEV-ES.
1198 //
1199 if (!CpuMpData->UseSevEsAPMethod) {
1200 RestoreWakeupBuffer (CpuMpData);
1201 }
1202}
1203
1215VOID
1217 IN CPU_MP_DATA *CpuMpData,
1218 IN BOOLEAN Broadcast,
1219 IN UINTN ProcessorNumber,
1220 IN EFI_AP_PROCEDURE Procedure OPTIONAL,
1221 IN VOID *ProcedureArgument OPTIONAL,
1222 IN BOOLEAN WakeUpDisabledAps
1223 )
1224{
1225 volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
1226 UINTN Index;
1227 CPU_AP_DATA *CpuData;
1228 BOOLEAN ResetVectorRequired;
1229 CPU_INFO_IN_HOB *CpuInfoInHob;
1230
1231 CpuMpData->FinishedCount = 0;
1232 ResetVectorRequired = FALSE;
1233
1234 if (CpuMpData->WakeUpByInitSipiSipi ||
1235 (CpuMpData->InitFlag == ApInitConfig))
1236 {
1237 ResetVectorRequired = TRUE;
1238 AllocateResetVectorBelow1Mb (CpuMpData);
1239 AllocateSevEsAPMemory (CpuMpData);
1240 FillExchangeInfoData (CpuMpData);
1241 }
1242
1243 if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
1244 //
1245 // Get AP target C-state each time when waking up AP,
1246 // for it maybe updated by platform again
1247 //
1248 CpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate);
1249 }
1250
1251 ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
1252
1253 if (Broadcast) {
1254 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
1255 if (Index != CpuMpData->BspNumber) {
1256 CpuData = &CpuMpData->CpuData[Index];
1257 //
1258 // All AP(include disabled AP) will be woke up by INIT-SIPI-SIPI, but
1259 // the AP procedure will be skipped for disabled AP because AP state
1260 // is not CpuStateReady.
1261 //
1262 if ((GetApState (CpuData) == CpuStateDisabled) && !WakeUpDisabledAps) {
1263 continue;
1264 }
1265
1266 CpuData->ApFunction = (UINTN)Procedure;
1267 CpuData->ApFunctionArgument = (UINTN)ProcedureArgument;
1268 SetApState (CpuData, CpuStateReady);
1269 if (CpuMpData->InitFlag == ApInitDone) {
1270 *(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
1271 }
1272 }
1273 }
1274
1275 if (ResetVectorRequired) {
1276 //
1277 // For SEV-ES and SEV-SNP, the initial AP boot address will be defined by
1278 // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address
1279 // from the original INIT-SIPI-SIPI.
1280 //
1281 if (CpuMpData->SevEsIsEnabled) {
1282 SetSevEsJumpTable (ExchangeInfo->BufferStart);
1283 }
1284
1285 //
1286 // Wakeup all APs
1287 // Must use the INIT-SIPI-SIPI method for initial configuration in
1288 // order to obtain the APIC ID if not an SEV-SNP guest and the
1289 // list of APIC IDs is not available.
1290 //
1291 if (CanUseSevSnpCreateAP (CpuMpData)) {
1292 SevSnpCreateAP (CpuMpData, -1);
1293 } else {
1294 if ((CpuMpData->InitFlag == ApInitConfig) && FixedPcdGetBool (PcdFirstTimeWakeUpAPsBySipi)) {
1295 //
1296 // SIPI can be used for the first time wake up after reset to reduce boot time.
1297 //
1298 SendStartupIpiAllExcludingSelf ((UINT32)ExchangeInfo->BufferStart);
1299 } else {
1300 SendInitSipiSipiAllExcludingSelf ((UINT32)ExchangeInfo->BufferStart);
1301 }
1302 }
1303 }
1304
1305 if (CpuMpData->InitFlag == ApInitConfig) {
1306 if (PcdGet32 (PcdCpuBootLogicalProcessorNumber) > 0) {
1307 //
1308 // The AP enumeration algorithm below is suitable only when the
1309 // platform can tell us the *exact* boot CPU count in advance.
1310 //
1311 // The wait below finishes only when the detected AP count reaches
1312 // (PcdCpuBootLogicalProcessorNumber - 1), regardless of how long that
1313 // takes. If at least one AP fails to check in (meaning a platform
1314 // hardware bug), the detection hangs forever, by design. If the actual
1315 // boot CPU count in the system is higher than
1316 // PcdCpuBootLogicalProcessorNumber (meaning a platform
1317 // misconfiguration), then some APs may complete initialization after
1318 // the wait finishes, and cause undefined behavior.
1319 //
1321 CpuMpData,
1322 PcdGet32 (PcdCpuBootLogicalProcessorNumber) - 1,
1323 MAX_UINT32 // approx. 71 minutes
1324 );
1325 } else {
1326 //
1327 // The AP enumeration algorithm below is suitable for two use cases.
1328 //
1329 // (1) The check-in time for an individual AP is bounded, and APs run
1330 // through their initialization routines strongly concurrently. In
1331 // particular, the number of concurrently running APs
1332 // ("NumApsExecuting") is never expected to fall to zero
1333 // *temporarily* -- it is expected to fall to zero only when all
1334 // APs have checked-in.
1335 //
1336 // In this case, the platform is supposed to set
1337 // PcdCpuApInitTimeOutInMicroSeconds to a low-ish value (just long
1338 // enough for one AP to start initialization). The timeout will be
1339 // reached soon, and remaining APs are collected by watching
1340 // NumApsExecuting fall to zero. If NumApsExecuting falls to zero
1341 // mid-process, while some APs have not completed initialization,
1342 // the behavior is undefined.
1343 //
1344 // (2) The check-in time for an individual AP is unbounded, and/or APs
1345 // may complete their initializations widely spread out. In
1346 // particular, some APs may finish initialization before some APs
1347 // even start.
1348 //
1349 // In this case, the platform is supposed to set
1350 // PcdCpuApInitTimeOutInMicroSeconds to a high-ish value. The AP
1351 // enumeration will always take that long (except when the boot CPU
1352 // count happens to be maximal, that is,
1353 // PcdCpuMaxLogicalProcessorNumber). All APs are expected to
1354 // check-in before the timeout, and NumApsExecuting is assumed zero
1355 // at timeout. APs that miss the time-out may cause undefined
1356 // behavior.
1357 //
1359 CpuMpData,
1360 PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1,
1361 PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)
1362 );
1363
1364 while (CpuMpData->MpCpuExchangeInfo->NumApsExecuting != 0) {
1365 CpuPause ();
1366 }
1367 }
1368 } else {
1369 //
1370 // Wait all APs waken up if this is not the 1st broadcast of SIPI
1371 //
1372 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
1373 CpuData = &CpuMpData->CpuData[Index];
1374 if (Index != CpuMpData->BspNumber) {
1375 WaitApWakeup (CpuData->StartupApSignal);
1376 }
1377 }
1378 }
1379 } else {
1380 CpuData = &CpuMpData->CpuData[ProcessorNumber];
1381 CpuData->ApFunction = (UINTN)Procedure;
1382 CpuData->ApFunctionArgument = (UINTN)ProcedureArgument;
1383 SetApState (CpuData, CpuStateReady);
1384 //
1385 // Wakeup specified AP
1386 //
1387 ASSERT (CpuMpData->InitFlag == ApInitDone);
1388 *(UINT32 *)CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
1389 if (ResetVectorRequired) {
1390 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
1391
1392 //
1393 // For SEV-ES and SEV-SNP, the initial AP boot address will be defined by
1394 // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address
1395 // from the original INIT-SIPI-SIPI.
1396 //
1397 if (CpuMpData->SevEsIsEnabled) {
1398 SetSevEsJumpTable (ExchangeInfo->BufferStart);
1399 }
1400
1401 if (CanUseSevSnpCreateAP (CpuMpData)) {
1402 SevSnpCreateAP (CpuMpData, (INTN)ProcessorNumber);
1403 } else {
1405 CpuInfoInHob[ProcessorNumber].ApicId,
1406 (UINT32)ExchangeInfo->BufferStart
1407 );
1408 }
1409 }
1410
1411 //
1412 // Wait specified AP waken up
1413 //
1414 WaitApWakeup (CpuData->StartupApSignal);
1415 }
1416
1417 if (ResetVectorRequired) {
1418 FreeResetVector (CpuMpData);
1419 }
1420
1421 //
1422 // After one round of Wakeup Ap actions, need to re-sync ApLoopMode with
1423 // WakeUpByInitSipiSipi flag. WakeUpByInitSipiSipi flag maybe changed by
1424 // S3SmmInitDone Ppi.
1425 //
1426 CpuMpData->WakeUpByInitSipiSipi = (CpuMpData->ApLoopMode == ApInHltLoop);
1427}
1428
1444UINT64
1446 IN UINTN TimeoutInMicroseconds,
1447 OUT UINT64 *CurrentTime
1448 )
1449{
1450 UINT64 TimeoutInSeconds;
1451 UINT64 TimestampCounterFreq;
1452
1453 //
1454 // Read the current value of the performance counter
1455 //
1456 *CurrentTime = GetPerformanceCounter ();
1457
1458 //
1459 // If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
1460 // as infinity.
1461 //
1462 if (TimeoutInMicroseconds == 0) {
1463 return 0;
1464 }
1465
1466 //
1467 // GetPerformanceCounterProperties () returns the timestamp counter's frequency
1468 // in Hz.
1469 //
1470 TimestampCounterFreq = GetPerformanceCounterProperties (NULL, NULL);
1471
1472 //
1473 // Check the potential overflow before calculate the number of ticks for the timeout value.
1474 //
1475 if (DivU64x64Remainder (MAX_UINT64, TimeoutInMicroseconds, NULL) < TimestampCounterFreq) {
1476 //
1477 // Convert microseconds into seconds if direct multiplication overflows
1478 //
1479 TimeoutInSeconds = DivU64x32 (TimeoutInMicroseconds, 1000000);
1480 //
1481 // Assertion if the final tick count exceeds MAX_UINT64
1482 //
1483 ASSERT (DivU64x64Remainder (MAX_UINT64, TimeoutInSeconds, NULL) >= TimestampCounterFreq);
1484 return MultU64x64 (TimestampCounterFreq, TimeoutInSeconds);
1485 } else {
1486 //
1487 // No overflow case, multiply the return value with TimeoutInMicroseconds and then divide
1488 // it by 1,000,000, to get the number of ticks for the timeout value.
1489 //
1490 return DivU64x32 (
1491 MultU64x64 (
1492 TimestampCounterFreq,
1493 TimeoutInMicroseconds
1494 ),
1495 1000000
1496 );
1497 }
1498}
1499
1504VOID
1505EFIAPI
1507 VOID
1508 )
1509{
1510 UINTN ProcessorNumber;
1511 CPU_MP_DATA *CpuMpData;
1512 CPU_INFO_IN_HOB *CpuInfoInHob;
1513
1514 CpuMpData = GetCpuMpData ();
1515 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
1516 GetProcessorNumber (CpuMpData, &ProcessorNumber);
1517
1518 SwitchStack (
1520 (VOID *)(UINTN)CpuMpData,
1521 NULL,
1522 (VOID *)((UINTN)CpuInfoInHob[ProcessorNumber].ApTopOfStack)
1523 );
1524}
1525
1546BOOLEAN
1548 IN OUT UINT64 *PreviousTime,
1549 IN UINT64 *TotalTime,
1550 IN UINT64 Timeout
1551 )
1552{
1553 UINT64 Start;
1554 UINT64 End;
1555 UINT64 CurrentTime;
1556 INT64 Delta;
1557 INT64 Cycle;
1558
1559 if (Timeout == 0) {
1560 return FALSE;
1561 }
1562
1563 GetPerformanceCounterProperties (&Start, &End);
1564 Cycle = End - Start;
1565 if (Cycle < 0) {
1566 Cycle = -Cycle;
1567 }
1568
1569 Cycle++;
1570 CurrentTime = GetPerformanceCounter ();
1571 Delta = (INT64)(CurrentTime - *PreviousTime);
1572 if (Start > End) {
1573 Delta = -Delta;
1574 }
1575
1576 if (Delta < 0) {
1577 Delta += Cycle;
1578 }
1579
1580 *TotalTime += Delta;
1581 *PreviousTime = CurrentTime;
1582 if (*TotalTime > Timeout) {
1583 return TRUE;
1584 }
1585
1586 return FALSE;
1587}
1588
1597VOID
1599 IN CPU_MP_DATA *CpuMpData,
1600 IN UINT32 FinishedApLimit,
1601 IN UINT32 TimeLimit
1602 )
1603{
1604 //
1605 // CalculateTimeout() and CheckTimeout() consider a TimeLimit of 0
1606 // "infinity", so check for (TimeLimit == 0) explicitly.
1607 //
1608 if (TimeLimit == 0) {
1609 return;
1610 }
1611
1612 CpuMpData->TotalTime = 0;
1613 CpuMpData->ExpectedTime = CalculateTimeout (
1614 TimeLimit,
1615 &CpuMpData->CurrentTime
1616 );
1617 while (CpuMpData->FinishedCount < FinishedApLimit &&
1618 !CheckTimeout (
1619 &CpuMpData->CurrentTime,
1620 &CpuMpData->TotalTime,
1621 CpuMpData->ExpectedTime
1622 ))
1623 {
1624 CpuPause ();
1625 }
1626
1627 if (CpuMpData->FinishedCount >= FinishedApLimit) {
1628 DEBUG ((
1629 DEBUG_VERBOSE,
1630 "%a: reached FinishedApLimit=%u in %Lu microseconds\n",
1631 __func__,
1632 FinishedApLimit,
1634 MultU64x32 (CpuMpData->TotalTime, 1000000),
1636 NULL
1637 )
1638 ));
1639 }
1640}
1641
1650VOID
1652 IN UINTN ProcessorNumber
1653 )
1654{
1655 CPU_MP_DATA *CpuMpData;
1656
1657 CpuMpData = GetCpuMpData ();
1658
1659 CpuMpData->WakeUpByInitSipiSipi = TRUE;
1660 if (CpuMpData == NULL) {
1661 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData. Aborting the AP reset to idle.\n", __func__));
1662 return;
1663 }
1664
1665 WakeUpAP (CpuMpData, FALSE, ProcessorNumber, NULL, NULL, TRUE);
1666 while (CpuMpData->FinishedCount < 1) {
1667 CpuPause ();
1668 }
1669
1670 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
1671}
1672
1686 OUT UINTN *NextProcessorNumber
1687 )
1688{
1689 UINTN ProcessorNumber;
1690 CPU_MP_DATA *CpuMpData;
1691
1692 CpuMpData = GetCpuMpData ();
1693
1694 if (CpuMpData == NULL) {
1695 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
1696 return EFI_LOAD_ERROR;
1697 }
1698
1699 for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
1700 if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
1701 *NextProcessorNumber = ProcessorNumber;
1702 return EFI_SUCCESS;
1703 }
1704 }
1705
1706 return EFI_NOT_FOUND;
1707}
1708
1722 IN UINTN ProcessorNumber
1723 )
1724{
1725 CPU_MP_DATA *CpuMpData;
1726 CPU_AP_DATA *CpuData;
1727
1728 CpuMpData = GetCpuMpData ();
1729
1730 if (CpuMpData == NULL) {
1731 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
1732 return EFI_LOAD_ERROR;
1733 }
1734
1735 CpuData = &CpuMpData->CpuData[ProcessorNumber];
1736
1737 //
1738 // Check the CPU state of AP. If it is CpuStateIdle, then the AP has finished its task.
1739 // Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the
1740 // value of state after setting the it to CpuStateIdle, so BSP can safely make use of its value.
1741 //
1742 //
1743 // If the AP finishes for StartupThisAP(), return EFI_SUCCESS.
1744 //
1745 if (GetApState (CpuData) == CpuStateFinished) {
1746 if (CpuData->Finished != NULL) {
1747 *(CpuData->Finished) = TRUE;
1748 }
1749
1750 SetApState (CpuData, CpuStateIdle);
1751 return EFI_SUCCESS;
1752 } else {
1753 //
1754 // If timeout expires for StartupThisAP(), report timeout.
1755 //
1756 if (CheckTimeout (&CpuData->CurrentTime, &CpuData->TotalTime, CpuData->ExpectedTime)) {
1757 if (CpuData->Finished != NULL) {
1758 *(CpuData->Finished) = FALSE;
1759 }
1760
1761 //
1762 // Reset failed AP to idle state
1763 //
1764 ResetProcessorToIdleState (ProcessorNumber);
1765
1766 return EFI_TIMEOUT;
1767 }
1768 }
1769
1770 return EFI_NOT_READY;
1771}
1772
1785 VOID
1786 )
1787{
1788 UINTN ProcessorNumber;
1789 UINTN NextProcessorNumber;
1790 UINTN ListIndex;
1791 EFI_STATUS Status;
1792 CPU_MP_DATA *CpuMpData;
1793 CPU_AP_DATA *CpuData;
1794
1795 CpuMpData = GetCpuMpData ();
1796
1797 if (CpuMpData == NULL) {
1798 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
1799 return EFI_LOAD_ERROR;
1800 }
1801
1802 NextProcessorNumber = 0;
1803
1804 //
1805 // Go through all APs that are responsible for the StartupAllAPs().
1806 //
1807 for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
1808 if (!CpuMpData->CpuData[ProcessorNumber].Waiting) {
1809 continue;
1810 }
1811
1812 CpuData = &CpuMpData->CpuData[ProcessorNumber];
1813 //
1814 // Check the CPU state of AP. If it is CpuStateIdle, then the AP has finished its task.
1815 // Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the
1816 // value of state after setting the it to CpuStateIdle, so BSP can safely make use of its value.
1817 //
1818 if (GetApState (CpuData) == CpuStateFinished) {
1819 CpuMpData->RunningCount--;
1820 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
1821 SetApState (CpuData, CpuStateIdle);
1822
1823 //
1824 // If in Single Thread mode, then search for the next waiting AP for execution.
1825 //
1826 if (CpuMpData->SingleThread) {
1827 Status = GetNextWaitingProcessorNumber (&NextProcessorNumber);
1828
1829 if (!EFI_ERROR (Status)) {
1830 WakeUpAP (
1831 CpuMpData,
1832 FALSE,
1833 (UINT32)NextProcessorNumber,
1834 CpuMpData->Procedure,
1835 CpuMpData->ProcArguments,
1836 TRUE
1837 );
1838 }
1839 }
1840 }
1841 }
1842
1843 //
1844 // If all APs finish, return EFI_SUCCESS.
1845 //
1846 if (CpuMpData->RunningCount == 0) {
1847 return EFI_SUCCESS;
1848 }
1849
1850 //
1851 // If timeout expires, report timeout.
1852 //
1853 if (CheckTimeout (
1854 &CpuMpData->CurrentTime,
1855 &CpuMpData->TotalTime,
1856 CpuMpData->ExpectedTime
1857 )
1858 )
1859 {
1860 //
1861 // If FailedCpuList is not NULL, record all failed APs in it.
1862 //
1863 if (CpuMpData->FailedCpuList != NULL) {
1864 *CpuMpData->FailedCpuList =
1865 AllocatePool ((CpuMpData->RunningCount + 1) * sizeof (UINTN));
1866 ASSERT (*CpuMpData->FailedCpuList != NULL);
1867 }
1868
1869 ListIndex = 0;
1870
1871 for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
1872 //
1873 // Check whether this processor is responsible for StartupAllAPs().
1874 //
1875 if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
1876 //
1877 // Reset failed APs to idle state
1878 //
1879 ResetProcessorToIdleState (ProcessorNumber);
1880 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
1881 if (CpuMpData->FailedCpuList != NULL) {
1882 (*CpuMpData->FailedCpuList)[ListIndex++] = ProcessorNumber;
1883 }
1884 }
1885 }
1886
1887 if (CpuMpData->FailedCpuList != NULL) {
1888 (*CpuMpData->FailedCpuList)[ListIndex] = END_OF_CPU_LIST;
1889 }
1890
1891 return EFI_TIMEOUT;
1892 }
1893
1894 return EFI_NOT_READY;
1895}
1896
1903UINT32
1905 IN CONST MP_HAND_OFF *FirstMpHandOff
1906 )
1907{
1908 UINT32 ApicId;
1909 UINT32 Index;
1910 CONST MP_HAND_OFF *MpHandOff;
1911
1912 //
1913 // Get the processor number for the BSP
1914 //
1915 ApicId = GetInitialApicId ();
1916
1917 for (MpHandOff = FirstMpHandOff;
1918 MpHandOff != NULL;
1919 MpHandOff = GetNextMpHandOffHob (MpHandOff))
1920 {
1921 for (Index = 0; Index < MpHandOff->CpuCount; Index++) {
1922 if (MpHandOff->Info[Index].ApicId == ApicId) {
1923 return MpHandOff->ProcessorIndex + Index;
1924 }
1925 }
1926 }
1927
1928 ASSERT_EFI_ERROR (EFI_NOT_FOUND);
1929 return 0;
1930}
1931
1944VOID
1946 IN CONST MP_HAND_OFF_CONFIG *MpHandOffConfig,
1947 IN CONST MP_HAND_OFF *FirstMpHandOff
1948 )
1949{
1950 UINTN Index;
1951 UINT32 BspNumber;
1952 CONST MP_HAND_OFF *MpHandOff;
1953
1954 BspNumber = GetBspNumber (FirstMpHandOff);
1955
1956 for (MpHandOff = FirstMpHandOff;
1957 MpHandOff != NULL;
1958 MpHandOff = GetNextMpHandOffHob (MpHandOff))
1959 {
1960 for (Index = 0; Index < MpHandOff->CpuCount; Index++) {
1961 if (MpHandOff->ProcessorIndex + Index != BspNumber) {
1962 *(UINTN *)(UINTN)MpHandOff->Info[Index].StartupProcedureAddress = (UINTN)SwitchContextPerAp;
1963 *(UINT32 *)(UINTN)MpHandOff->Info[Index].StartupSignalAddress = MpHandOffConfig->StartupSignalValue;
1964 }
1965 }
1966 }
1967
1968 //
1969 // Wait all APs waken up if this is not the 1st broadcast of SIPI
1970 //
1971 for (MpHandOff = FirstMpHandOff;
1972 MpHandOff != NULL;
1973 MpHandOff = GetNextMpHandOffHob (MpHandOff))
1974 {
1975 for (Index = 0; Index < MpHandOff->CpuCount; Index++) {
1976 if (MpHandOff->ProcessorIndex + Index != BspNumber) {
1977 WaitApWakeup ((UINT32 *)(UINTN)(MpHandOff->Info[Index].StartupSignalAddress));
1978 }
1979 }
1980 }
1981}
1982
1990 VOID
1991 )
1992{
1993 EFI_HOB_GUID_TYPE *GuidHob;
1994
1995 GuidHob = GetFirstGuidHob (&mMpHandOffConfigGuid);
1996 if (GuidHob == NULL) {
1997 return NULL;
1998 }
1999
2000 return (MP_HAND_OFF_CONFIG *)GET_GUID_HOB_DATA (GuidHob);
2001}
2002
2012 IN CONST MP_HAND_OFF *MpHandOff
2013 )
2014{
2015 EFI_HOB_GUID_TYPE *GuidHob;
2016
2017 if (MpHandOff == NULL) {
2018 GuidHob = GetFirstGuidHob (&mMpHandOffGuid);
2019 } else {
2020 GuidHob = (VOID *)(((UINT8 *)MpHandOff) - sizeof (EFI_HOB_GUID_TYPE));
2021 GuidHob = GetNextGuidHob (&mMpHandOffGuid, GET_NEXT_HOB (GuidHob));
2022 }
2023
2024 if (GuidHob == NULL) {
2025 return NULL;
2026 }
2027
2028 return (MP_HAND_OFF *)GET_GUID_HOB_DATA (GuidHob);
2029}
2030
2045EFIAPI
2047 VOID
2048 )
2049{
2050 MP_HAND_OFF_CONFIG *MpHandOffConfig;
2051 MP_HAND_OFF *FirstMpHandOff;
2052 MP_HAND_OFF *MpHandOff;
2053 CPU_INFO_IN_HOB *CpuInfoInHob;
2054 UINT32 MaxLogicalProcessorNumber;
2055 UINT32 ApStackSize;
2056 MP_ASSEMBLY_ADDRESS_MAP AddressMap;
2057 CPU_VOLATILE_REGISTERS VolatileRegisters;
2058 UINTN BufferSize;
2059 UINT32 MonitorFilterSize;
2060 VOID *MpBuffer;
2061 UINTN Buffer;
2062 CPU_MP_DATA *CpuMpData;
2063 UINT8 ApLoopMode;
2064 UINT8 *MonitorBuffer;
2065 UINT32 Index, HobIndex;
2066 UINTN ApResetVectorSizeBelow1Mb;
2067 UINTN ApResetVectorSizeAbove1Mb;
2068 UINTN BackupBufferAddr;
2069 UINTN ApIdtBase;
2070
2071 FirstMpHandOff = GetNextMpHandOffHob (NULL);
2072 if (FirstMpHandOff != NULL) {
2073 MaxLogicalProcessorNumber = 0;
2074 for (MpHandOff = FirstMpHandOff;
2075 MpHandOff != NULL;
2076 MpHandOff = GetNextMpHandOffHob (MpHandOff))
2077 {
2078 DEBUG ((
2079 DEBUG_INFO,
2080 "%a: ProcessorIndex=%u CpuCount=%u\n",
2081 __func__,
2082 MpHandOff->ProcessorIndex,
2083 MpHandOff->CpuCount
2084 ));
2085 ASSERT (MaxLogicalProcessorNumber == MpHandOff->ProcessorIndex);
2086 MaxLogicalProcessorNumber += MpHandOff->CpuCount;
2087 }
2088 } else {
2089 MaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
2090 }
2091
2092 ASSERT (MaxLogicalProcessorNumber != 0);
2093
2094 AsmGetAddressMap (&AddressMap);
2095 GetApResetVectorSize (&AddressMap, &ApResetVectorSizeBelow1Mb, &ApResetVectorSizeAbove1Mb);
2096 ApStackSize = PcdGet32 (PcdCpuApStackSize);
2097 //
2098 // ApStackSize must be power of 2
2099 //
2100 ASSERT ((ApStackSize & (ApStackSize - 1)) == 0);
2101 ApLoopMode = GetApLoopMode (&MonitorFilterSize);
2102
2103 //
2104 // Save BSP's Control registers for APs.
2105 //
2106 SaveVolatileRegisters (&VolatileRegisters);
2107
2108 BufferSize = ApStackSize * MaxLogicalProcessorNumber;
2109 //
2110 // Allocate extra ApStackSize to let AP stack align on ApStackSize bounday
2111 //
2112 BufferSize += ApStackSize;
2113 BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;
2114 BufferSize += ApResetVectorSizeBelow1Mb;
2115 BufferSize = ALIGN_VALUE (BufferSize, 8);
2116 BufferSize += VolatileRegisters.Idtr.Limit + 1;
2117 BufferSize += sizeof (CPU_MP_DATA);
2118 BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;
2119 MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
2120 ASSERT (MpBuffer != NULL);
2121 if (MpBuffer == NULL) {
2122 return EFI_OUT_OF_RESOURCES;
2123 }
2124
2125 ZeroMem (MpBuffer, BufferSize);
2126 Buffer = ALIGN_VALUE ((UINTN)MpBuffer, ApStackSize);
2127
2128 //
2129 // The layout of the Buffer is as below (lower address on top):
2130 //
2131 // +--------------------+ <-- Buffer (Pointer of CpuMpData is stored in the top of each AP's stack.)
2132 // AP Stacks (N) (StackTop = (RSP + ApStackSize) & ~ApStackSize))
2133 // +--------------------+ <-- MonitorBuffer
2134 // AP Monitor Filters (N)
2135 // +--------------------+ <-- BackupBufferAddr (CpuMpData->BackupBuffer)
2136 // Backup Buffer
2137 // +--------------------+
2138 // Padding
2139 // +--------------------+ <-- ApIdtBase (8-byte boundary)
2140 // AP IDT All APs share one separate IDT.
2141 // +--------------------+ <-- CpuMpData
2142 // CPU_MP_DATA
2143 // +--------------------+ <-- CpuMpData->CpuData
2144 // CPU_AP_DATA (N)
2145 // +--------------------+ <-- CpuMpData->CpuInfoInHob
2146 // CPU_INFO_IN_HOB (N)
2147 // +--------------------+
2148 //
2149 MonitorBuffer = (UINT8 *)(Buffer + ApStackSize * MaxLogicalProcessorNumber);
2150 BackupBufferAddr = (UINTN)MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber;
2151 ApIdtBase = ALIGN_VALUE (BackupBufferAddr + ApResetVectorSizeBelow1Mb, 8);
2152 CpuMpData = (CPU_MP_DATA *)(ApIdtBase + VolatileRegisters.Idtr.Limit + 1);
2153 CpuMpData->Buffer = Buffer;
2154 CpuMpData->CpuApStackSize = ApStackSize;
2155 CpuMpData->BackupBuffer = BackupBufferAddr;
2156 CpuMpData->BackupBufferSize = ApResetVectorSizeBelow1Mb;
2157 CpuMpData->WakeupBuffer = (UINTN)-1;
2158 CpuMpData->CpuCount = 1;
2159 if (FirstMpHandOff == NULL) {
2160 CpuMpData->BspNumber = 0;
2161 } else {
2162 CpuMpData->BspNumber = GetBspNumber (FirstMpHandOff);
2163 }
2164
2165 CpuMpData->WaitEvent = NULL;
2166 CpuMpData->SwitchBspFlag = FALSE;
2167 CpuMpData->CpuData = (CPU_AP_DATA *)(CpuMpData + 1);
2168 CpuMpData->CpuInfoInHob = (UINT64)(UINTN)(CpuMpData->CpuData + MaxLogicalProcessorNumber);
2169 InitializeSpinLock (&CpuMpData->MpLock);
2170 CpuMpData->SevEsIsEnabled = ConfidentialComputingGuestHas (CCAttrAmdSevEs);
2171 CpuMpData->SevSnpIsEnabled = ConfidentialComputingGuestHas (CCAttrAmdSevSnp);
2172 CpuMpData->SevEsAPBuffer = (UINTN)-1;
2173 CpuMpData->GhcbBase = PcdGet64 (PcdGhcbBase);
2174 CpuMpData->UseSevEsAPMethod = CpuMpData->SevEsIsEnabled && !CpuMpData->SevSnpIsEnabled;
2175
2176 if (CpuMpData->SevSnpIsEnabled) {
2177 ASSERT ((PcdGet64 (PcdGhcbHypervisorFeatures) & GHCB_HV_FEATURES_SNP_AP_CREATE) == GHCB_HV_FEATURES_SNP_AP_CREATE);
2178 }
2179
2180 //
2181 // Make sure no memory usage outside of the allocated buffer.
2182 // (ApStackSize - (Buffer - (UINTN)MpBuffer)) is the redundant caused by alignment
2183 //
2184 ASSERT (
2185 (CpuMpData->CpuInfoInHob + sizeof (CPU_INFO_IN_HOB) * MaxLogicalProcessorNumber) ==
2186 (UINTN)MpBuffer + BufferSize - (ApStackSize - Buffer + (UINTN)MpBuffer)
2187 );
2188
2189 //
2190 // Duplicate BSP's IDT to APs.
2191 // All APs share one separate IDT. So AP can get the address of CpuMpData by using IDTR.BASE + IDTR.LIMIT + 1
2192 //
2193 CopyMem ((VOID *)ApIdtBase, (VOID *)VolatileRegisters.Idtr.Base, VolatileRegisters.Idtr.Limit + 1);
2194 VolatileRegisters.Idtr.Base = ApIdtBase;
2195 //
2196 // Don't pass BSP's TR to APs to avoid AP init failure.
2197 //
2198 VolatileRegisters.Tr = 0;
2199 //
2200 // Set DR as 0 since DR is set only for BSP.
2201 //
2202 VolatileRegisters.Dr0 = 0;
2203 VolatileRegisters.Dr1 = 0;
2204 VolatileRegisters.Dr2 = 0;
2205 VolatileRegisters.Dr3 = 0;
2206 VolatileRegisters.Dr6 = 0;
2207 VolatileRegisters.Dr7 = 0;
2208
2209 //
2210 // Copy volatile registers since either APs are the first time to bring up,
2211 // or BSP is in DXE phase but APs are still running in PEI context.
2212 // In both cases, APs need use volatile registers from BSP
2213 //
2214 for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
2215 CopyMem (&CpuMpData->CpuData[Index].VolatileRegisters, &VolatileRegisters, sizeof (VolatileRegisters));
2216 }
2217
2218 //
2219 // Set BSP basic information
2220 //
2221 InitializeApData (CpuMpData, CpuMpData->BspNumber, 0, CpuMpData->Buffer + ApStackSize * (CpuMpData->BspNumber + 1));
2222 //
2223 // Save assembly code information
2224 //
2225 CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));
2226 //
2227 // Finally set AP loop mode
2228 //
2229 CpuMpData->ApLoopMode = ApLoopMode;
2230 DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));
2231
2232 CpuMpData->WakeUpByInitSipiSipi = (CpuMpData->ApLoopMode == ApInHltLoop);
2233
2234 //
2235 // Set up APs wakeup signal buffer
2236 //
2237 for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
2238 CpuMpData->CpuData[Index].StartupApSignal =
2239 (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);
2240 }
2241
2242 //
2243 // Copy all 32-bit code and 64-bit code into memory with type of
2244 // EfiBootServicesCode to avoid page fault if NX memory protection is enabled.
2245 //
2246 CpuMpData->WakeupBufferHigh = AllocateCodeBuffer (ApResetVectorSizeAbove1Mb);
2247 CopyMem (
2248 (VOID *)CpuMpData->WakeupBufferHigh,
2249 CpuMpData->AddressMap.RendezvousFunnelAddress +
2250 CpuMpData->AddressMap.ModeTransitionOffset,
2251 ApResetVectorSizeAbove1Mb
2252 );
2253 DEBUG ((DEBUG_INFO, "AP Vector: non-16-bit = %p/%x\n", CpuMpData->WakeupBufferHigh, ApResetVectorSizeAbove1Mb));
2254
2255 //
2256 // Save APIC mode for AP to sync
2257 //
2258 CpuMpData->InitialBspApicMode = GetApicMode ();
2259
2260 //
2261 // Enable the local APIC for Virtual Wire Mode.
2262 //
2264 SaveLocalApicTimerSetting (CpuMpData);
2265
2266 if (FirstMpHandOff == NULL) {
2267 if (MaxLogicalProcessorNumber > 1) {
2268 //
2269 // Wakeup all APs and calculate the processor count in system
2270 //
2271 CollectProcessorCount (CpuMpData);
2272
2273 //
2274 // Enable X2APIC if needed.
2275 //
2276 if (CpuMpData->InitialBspApicMode == LOCAL_APIC_MODE_XAPIC) {
2277 AutoEnableX2Apic (CpuMpData);
2278 }
2279
2280 //
2281 // Sort BSP/Aps by CPU APIC ID in ascending order
2282 //
2283 SortApicId (CpuMpData);
2284
2285 DEBUG ((DEBUG_INFO, "MpInitLib: Find %d processors in system.\n", CpuMpData->CpuCount));
2286 }
2287 } else {
2288 //
2289 // APs have been wakeup before, just get the CPU Information
2290 // from HOB
2291 //
2292 CpuMpData->InitFlag = ApInitDone;
2293 if (CpuMpData->UseSevEsAPMethod) {
2294 AmdSevUpdateCpuMpData (CpuMpData);
2295 }
2296
2297 CpuMpData->CpuCount = MaxLogicalProcessorNumber;
2298 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
2299 for (MpHandOff = FirstMpHandOff;
2300 MpHandOff != NULL;
2301 MpHandOff = GetNextMpHandOffHob (MpHandOff))
2302 {
2303 for (HobIndex = 0; HobIndex < MpHandOff->CpuCount; HobIndex++) {
2304 Index = MpHandOff->ProcessorIndex + HobIndex;
2305 InitializeSpinLock (&CpuMpData->CpuData[Index].ApLock);
2306 CpuMpData->CpuData[Index].CpuHealthy = (MpHandOff->Info[HobIndex].Health == 0) ? TRUE : FALSE;
2307 CpuMpData->CpuData[Index].ApFunction = 0;
2308 CpuInfoInHob[Index].InitialApicId = MpHandOff->Info[HobIndex].ApicId;
2309 CpuInfoInHob[Index].ApTopOfStack = CpuMpData->Buffer + (Index + 1) * CpuMpData->CpuApStackSize;
2310 CpuInfoInHob[Index].ApicId = MpHandOff->Info[HobIndex].ApicId;
2311 CpuInfoInHob[Index].Health = MpHandOff->Info[HobIndex].Health;
2312 }
2313 }
2314
2315 MpHandOffConfig = GetMpHandOffConfigHob ();
2316 if (MpHandOffConfig == NULL) {
2317 DEBUG ((
2318 DEBUG_ERROR,
2319 "%a: at least one MpHandOff HOB, but no MpHandOffConfig HOB\n",
2320 __func__
2321 ));
2322 ASSERT (MpHandOffConfig != NULL);
2323 CpuDeadLoop ();
2324 }
2325
2326 DEBUG ((
2327 DEBUG_INFO,
2328 "FirstMpHandOff->WaitLoopExecutionMode: %04d, sizeof (VOID *): %04d\n",
2329 MpHandOffConfig->WaitLoopExecutionMode,
2330 sizeof (VOID *)
2331 ));
2332 if (MpHandOffConfig->WaitLoopExecutionMode == sizeof (VOID *)) {
2333 ASSERT (CpuMpData->ApLoopMode != ApInHltLoop);
2334
2335 CpuMpData->FinishedCount = 0;
2336 CpuMpData->EnableExecuteDisableForSwitchContext = IsBspExecuteDisableEnabled ();
2337 SaveCpuMpData (CpuMpData);
2338 //
2339 // In scenarios where both the PEI and DXE phases run in the same
2340 // execution mode (32bit or 64bit), the BSP triggers
2341 // a start-up signal during the DXE phase to wake up the APs. This causes any
2342 // APs that are currently in a loop on the memory prepared during the PEI
2343 // phase to awaken and run the SwitchContextPerAp procedure. This procedure
2344 // enables the APs to switch to a different memory section and continue their
2345 // looping process there.
2346 //
2347 SwitchApContext (MpHandOffConfig, FirstMpHandOff);
2348 //
2349 // Wait for all APs finished initialization
2350 //
2351 while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
2352 CpuPause ();
2353 }
2354
2355 //
2356 // Set Apstate as Idle, otherwise Aps cannot be waken-up again.
2357 // If any enabled AP is not idle, return EFI_NOT_READY during waken-up.
2358 //
2359 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
2360 SetApState (&CpuMpData->CpuData[Index], CpuStateIdle);
2361 }
2362
2363 //
2364 // Initialize global data for MP support
2365 //
2366 InitMpGlobalData (CpuMpData);
2367 return EFI_SUCCESS;
2368 } else {
2369 //
2370 // PEI and DXE are in different Execution Mode
2371 // Use Init Sipi Sipi for the first AP wake up in DXE phase.
2372 //
2373 CpuMpData->WakeUpByInitSipiSipi = TRUE;
2374 }
2375 }
2376
2378 &CpuMpData->MicrocodePatchAddress,
2379 &CpuMpData->MicrocodePatchRegionSize
2380 ))
2381 {
2382 //
2383 // The microcode patch information cache HOB does not exist, which means
2384 // the microcode patches data has not been loaded into memory yet
2385 //
2386 ShadowMicrocodeUpdatePatch (CpuMpData);
2387 }
2388
2389 //
2390 // Detect and apply Microcode on BSP
2391 //
2392 MicrocodeDetect (CpuMpData, CpuMpData->BspNumber);
2393 //
2394 // Store BSP's MTRR setting
2395 //
2396 MtrrGetAllMtrrs (&CpuMpData->MtrrTable);
2397
2398 //
2399 // Wakeup APs to do some AP initialize sync (Microcode & MTRR)
2400 //
2401 if (CpuMpData->CpuCount > 1) {
2402 WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData, TRUE);
2403 //
2404 // Wait for all APs finished initialization
2405 //
2406 while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
2407 CpuPause ();
2408 }
2409
2410 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
2411 SetApState (&CpuMpData->CpuData[Index], CpuStateIdle);
2412 }
2413 }
2414
2415 //
2416 // Dump the microcode revision for each core.
2417 //
2419 UINT32 ThreadId;
2420 UINT32 ExpectedMicrocodeRevision;
2421
2422 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
2423 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
2424 GetProcessorLocationByApicId (CpuInfoInHob[Index].InitialApicId, NULL, NULL, &ThreadId);
2425 if (ThreadId == 0) {
2426 //
2427 // MicrocodeDetect() loads microcode in first thread of each core, so,
2428 // CpuMpData->CpuData[Index].MicrocodeEntryAddr is initialized only for first thread of each core.
2429 //
2430 ExpectedMicrocodeRevision = 0;
2431 if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {
2432 ExpectedMicrocodeRevision = ((CPU_MICROCODE_HEADER *)(UINTN)CpuMpData->CpuData[Index].MicrocodeEntryAddr)->UpdateRevision;
2433 }
2434
2435 DEBUG ((
2436 DEBUG_INFO,
2437 "CPU[%04d]: Microcode revision = %08x, expected = %08x\n",
2438 Index,
2439 CpuMpData->CpuData[Index].MicrocodeRevision,
2440 ExpectedMicrocodeRevision
2441 ));
2442 }
2443 }
2444
2445 DEBUG_CODE_END ();
2446 //
2447 // Initialize global data for MP support
2448 //
2449 InitMpGlobalData (CpuMpData);
2450
2451 return EFI_SUCCESS;
2452}
2453
2474EFIAPI
2476 IN UINTN ProcessorNumber,
2477 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer,
2478 OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL
2479 )
2480{
2481 CPU_MP_DATA *CpuMpData;
2482 UINTN CallerNumber;
2483 CPU_INFO_IN_HOB *CpuInfoInHob;
2484 UINTN OriginalProcessorNumber;
2485 EFI_STATUS Status;
2486
2487 CpuMpData = GetCpuMpData ();
2488
2489 if (CpuMpData == NULL) {
2490 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
2491 return EFI_LOAD_ERROR;
2492 }
2493
2494 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
2495
2496 //
2497 // Lower 24 bits contains the actual processor number.
2498 //
2499 OriginalProcessorNumber = ProcessorNumber;
2500 ProcessorNumber &= BIT24 - 1;
2501
2502 //
2503 // Check whether caller processor is BSP
2504 //
2505 Status = MpInitLibWhoAmI (&CallerNumber);
2506
2507 if (EFI_ERROR (Status)) {
2508 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. Failed to get MpInit Processor info.\n", __func__));
2509 return Status;
2510 }
2511
2512 if (CallerNumber != CpuMpData->BspNumber) {
2513 return EFI_DEVICE_ERROR;
2514 }
2515
2516 if (ProcessorInfoBuffer == NULL) {
2517 return EFI_INVALID_PARAMETER;
2518 }
2519
2520 if (ProcessorNumber >= CpuMpData->CpuCount) {
2521 return EFI_NOT_FOUND;
2522 }
2523
2524 ProcessorInfoBuffer->ProcessorId = (UINT64)CpuInfoInHob[ProcessorNumber].ApicId;
2525 ProcessorInfoBuffer->StatusFlag = 0;
2526 if (ProcessorNumber == CpuMpData->BspNumber) {
2527 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
2528 }
2529
2530 if (CpuMpData->CpuData[ProcessorNumber].CpuHealthy) {
2531 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
2532 }
2533
2534 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) {
2535 ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
2536 } else {
2537 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
2538 }
2539
2540 //
2541 // Get processor location information
2542 //
2544 CpuInfoInHob[ProcessorNumber].ApicId,
2545 &ProcessorInfoBuffer->Location.Package,
2546 &ProcessorInfoBuffer->Location.Core,
2547 &ProcessorInfoBuffer->Location.Thread
2548 );
2549
2550 if ((OriginalProcessorNumber & CPU_V2_EXTENDED_TOPOLOGY) != 0) {
2552 CpuInfoInHob[ProcessorNumber].ApicId,
2553 &ProcessorInfoBuffer->ExtendedInformation.Location2.Package,
2554 &ProcessorInfoBuffer->ExtendedInformation.Location2.Die,
2555 &ProcessorInfoBuffer->ExtendedInformation.Location2.Tile,
2556 &ProcessorInfoBuffer->ExtendedInformation.Location2.Module,
2557 &ProcessorInfoBuffer->ExtendedInformation.Location2.Core,
2558 &ProcessorInfoBuffer->ExtendedInformation.Location2.Thread
2559 );
2560 }
2561
2562 if (HealthData != NULL) {
2563 HealthData->Uint32 = CpuInfoInHob[ProcessorNumber].Health;
2564 }
2565
2566 return EFI_SUCCESS;
2567}
2568
2582 IN UINTN ProcessorNumber,
2583 IN BOOLEAN EnableOldBSP
2584 )
2585{
2586 CPU_MP_DATA *CpuMpData;
2587 UINTN CallerNumber;
2588 CPU_STATE State;
2589 MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
2590 BOOLEAN OldInterruptState;
2591 BOOLEAN OldTimerInterruptState;
2592 EFI_STATUS Status;
2593
2594 //
2595 // Save and Disable Local APIC timer interrupt
2596 //
2597 OldTimerInterruptState = GetApicTimerInterruptState ();
2599 //
2600 // Before send both BSP and AP to a procedure to exchange their roles,
2601 // interrupt must be disabled. This is because during the exchange role
2602 // process, 2 CPU may use 1 stack. If interrupt happens, the stack will
2603 // be corrupted, since interrupt return address will be pushed to stack
2604 // by hardware.
2605 //
2606 OldInterruptState = SaveAndDisableInterrupts ();
2607
2608 //
2609 // Mask LINT0 & LINT1 for the old BSP
2610 //
2612
2613 CpuMpData = GetCpuMpData ();
2614
2615 if (CpuMpData == NULL) {
2616 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
2617 return EFI_LOAD_ERROR;
2618 }
2619
2620 //
2621 // Check whether caller processor is BSP
2622 //
2623 Status = MpInitLibWhoAmI (&CallerNumber);
2624
2625 if (EFI_ERROR (Status)) {
2626 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. Failed to get MpInit Processor info.\n", __func__));
2627 return Status;
2628 }
2629
2630 if (CallerNumber != CpuMpData->BspNumber) {
2631 return EFI_DEVICE_ERROR;
2632 }
2633
2634 if (ProcessorNumber >= CpuMpData->CpuCount) {
2635 return EFI_NOT_FOUND;
2636 }
2637
2638 //
2639 // Check whether specified AP is disabled
2640 //
2641 State = GetApState (&CpuMpData->CpuData[ProcessorNumber]);
2642 if (State == CpuStateDisabled) {
2643 return EFI_INVALID_PARAMETER;
2644 }
2645
2646 //
2647 // Check whether ProcessorNumber specifies the current BSP
2648 //
2649 if (ProcessorNumber == CpuMpData->BspNumber) {
2650 return EFI_INVALID_PARAMETER;
2651 }
2652
2653 //
2654 // Check whether specified AP is busy
2655 //
2656 if (State == CpuStateBusy) {
2657 return EFI_NOT_READY;
2658 }
2659
2660 CpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE;
2661 CpuMpData->APInfo.State = CPU_SWITCH_STATE_IDLE;
2662 CpuMpData->SwitchBspFlag = TRUE;
2663 CpuMpData->NewBspNumber = ProcessorNumber;
2664
2665 //
2666 // Clear the BSP bit of MSR_IA32_APIC_BASE
2667 //
2668 ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
2669 ApicBaseMsr.Bits.BSP = 0;
2671
2672 //
2673 // Save BSP's local APIC timer setting.
2674 //
2675 SaveLocalApicTimerSetting (CpuMpData);
2676
2677 //
2678 // Need to wakeUp AP (future BSP).
2679 //
2680 WakeUpAP (CpuMpData, FALSE, ProcessorNumber, FutureBSPProc, CpuMpData, TRUE);
2681
2682 //
2683 // Save and restore volatile registers when switch BSP
2684 //
2685 SaveVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters);
2686 AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo);
2687 RestoreVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters);
2688 //
2689 // Set the BSP bit of MSR_IA32_APIC_BASE on new BSP
2690 //
2691 ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
2692 ApicBaseMsr.Bits.BSP = 1;
2695
2696 //
2697 // Wait for old BSP finished AP task
2698 //
2699 while (GetApState (&CpuMpData->CpuData[CallerNumber]) != CpuStateFinished) {
2700 CpuPause ();
2701 }
2702
2703 CpuMpData->SwitchBspFlag = FALSE;
2704 //
2705 // Set old BSP enable state
2706 //
2707 if (!EnableOldBSP) {
2708 SetApState (&CpuMpData->CpuData[CallerNumber], CpuStateDisabled);
2709 } else {
2710 SetApState (&CpuMpData->CpuData[CallerNumber], CpuStateIdle);
2711 }
2712
2713 //
2714 // Save new BSP number
2715 //
2716 CpuMpData->BspNumber = (UINT32)ProcessorNumber;
2717
2718 //
2719 // Restore interrupt state.
2720 //
2721 SetInterruptState (OldInterruptState);
2722
2723 if (OldTimerInterruptState) {
2725 }
2726
2727 return EFI_SUCCESS;
2728}
2729
2746 IN UINTN ProcessorNumber,
2747 IN BOOLEAN EnableAP,
2748 IN UINT32 *HealthFlag OPTIONAL
2749 )
2750{
2751 CPU_MP_DATA *CpuMpData;
2752 UINTN CallerNumber;
2753 EFI_STATUS Status;
2754
2755 CpuMpData = GetCpuMpData ();
2756
2757 if (CpuMpData == NULL) {
2758 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
2759 return EFI_LOAD_ERROR;
2760 }
2761
2762 //
2763 // Check whether caller processor is BSP
2764 //
2765 Status = MpInitLibWhoAmI (&CallerNumber);
2766
2767 if (EFI_ERROR (Status)) {
2768 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. Failed to get MpInit Processor info.\n", __func__));
2769 return Status;
2770 }
2771
2772 if (CallerNumber != CpuMpData->BspNumber) {
2773 return EFI_DEVICE_ERROR;
2774 }
2775
2776 if (ProcessorNumber == CpuMpData->BspNumber) {
2777 return EFI_INVALID_PARAMETER;
2778 }
2779
2780 if (ProcessorNumber >= CpuMpData->CpuCount) {
2781 return EFI_NOT_FOUND;
2782 }
2783
2784 if (!EnableAP) {
2785 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateDisabled);
2786 } else {
2787 ResetProcessorToIdleState (ProcessorNumber);
2788 }
2789
2790 if (HealthFlag != NULL) {
2791 CpuMpData->CpuData[ProcessorNumber].CpuHealthy =
2792 (BOOLEAN)((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) != 0);
2793 }
2794
2795 return EFI_SUCCESS;
2796}
2797
2815EFIAPI
2817 OUT UINTN *ProcessorNumber
2818 )
2819{
2820 CPU_MP_DATA *CpuMpData;
2821
2822 if (ProcessorNumber == NULL) {
2823 return EFI_INVALID_PARAMETER;
2824 }
2825
2826 CpuMpData = GetCpuMpData ();
2827
2828 if (CpuMpData == NULL) {
2829 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
2830 return EFI_LOAD_ERROR;
2831 }
2832
2833 return GetProcessorNumber (CpuMpData, ProcessorNumber);
2834}
2835
2857EFIAPI
2859 OUT UINTN *NumberOfProcessors OPTIONAL,
2860 OUT UINTN *NumberOfEnabledProcessors OPTIONAL
2861 )
2862{
2863 CPU_MP_DATA *CpuMpData;
2864 UINTN CallerNumber;
2865 UINTN ProcessorNumber;
2866 UINTN EnabledProcessorNumber;
2867 UINTN Index;
2868 EFI_STATUS Status;
2869
2870 CpuMpData = GetCpuMpData ();
2871
2872 if (CpuMpData == NULL) {
2873 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
2874 return EFI_LOAD_ERROR;
2875 }
2876
2877 if ((NumberOfProcessors == NULL) && (NumberOfEnabledProcessors == NULL)) {
2878 return EFI_INVALID_PARAMETER;
2879 }
2880
2881 //
2882 // Check whether caller processor is BSP
2883 //
2884 Status = MpInitLibWhoAmI (&CallerNumber);
2885
2886 if (EFI_ERROR (Status)) {
2887 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. Failed to get MpInit Processor info.\n", __func__));
2888 return Status;
2889 }
2890
2891 if (CallerNumber != CpuMpData->BspNumber) {
2892 return EFI_DEVICE_ERROR;
2893 }
2894
2895 ProcessorNumber = CpuMpData->CpuCount;
2896 EnabledProcessorNumber = 0;
2897 for (Index = 0; Index < ProcessorNumber; Index++) {
2898 if (GetApState (&CpuMpData->CpuData[Index]) != CpuStateDisabled) {
2899 EnabledProcessorNumber++;
2900 }
2901 }
2902
2903 if (NumberOfProcessors != NULL) {
2904 *NumberOfProcessors = ProcessorNumber;
2905 }
2906
2907 if (NumberOfEnabledProcessors != NULL) {
2908 *NumberOfEnabledProcessors = EnabledProcessorNumber;
2909 }
2910
2911 return EFI_SUCCESS;
2912}
2913
2948 IN EFI_AP_PROCEDURE Procedure,
2949 IN BOOLEAN SingleThread,
2950 IN BOOLEAN ExcludeBsp,
2951 IN EFI_EVENT WaitEvent OPTIONAL,
2952 IN UINTN TimeoutInMicroseconds,
2953 IN VOID *ProcedureArgument OPTIONAL,
2954 OUT UINTN **FailedCpuList OPTIONAL
2955 )
2956{
2957 EFI_STATUS Status;
2958 CPU_MP_DATA *CpuMpData;
2959 UINTN ProcessorCount;
2960 UINTN ProcessorNumber;
2961 UINTN CallerNumber;
2962 CPU_AP_DATA *CpuData;
2963 BOOLEAN HasEnabledAp;
2964 CPU_STATE ApState;
2965
2966 CpuMpData = GetCpuMpData ();
2967
2968 if (FailedCpuList != NULL) {
2969 *FailedCpuList = NULL;
2970 }
2971
2972 if (CpuMpData == NULL) {
2973 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
2974 return EFI_LOAD_ERROR;
2975 }
2976
2977 if ((CpuMpData->CpuCount == 1) && ExcludeBsp) {
2978 return EFI_NOT_STARTED;
2979 }
2980
2981 if (Procedure == NULL) {
2982 return EFI_INVALID_PARAMETER;
2983 }
2984
2985 //
2986 // Check whether caller processor is BSP
2987 //
2988 Status = MpInitLibWhoAmI (&CallerNumber);
2989
2990 if (EFI_ERROR (Status)) {
2991 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. Failed to get MpInit Processor info.\n", __func__));
2992 return Status;
2993 }
2994
2995 if (CallerNumber != CpuMpData->BspNumber) {
2996 return EFI_DEVICE_ERROR;
2997 }
2998
2999 //
3000 // Update AP state
3001 //
3003
3004 ProcessorCount = CpuMpData->CpuCount;
3005 HasEnabledAp = FALSE;
3006 //
3007 // Check whether all enabled APs are idle.
3008 // If any enabled AP is not idle, return EFI_NOT_READY.
3009 //
3010 for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
3011 CpuData = &CpuMpData->CpuData[ProcessorNumber];
3012 if (ProcessorNumber != CpuMpData->BspNumber) {
3013 ApState = GetApState (CpuData);
3014 if (ApState != CpuStateDisabled) {
3015 HasEnabledAp = TRUE;
3016 if (ApState != CpuStateIdle) {
3017 //
3018 // If any enabled APs are busy, return EFI_NOT_READY.
3019 //
3020 return EFI_NOT_READY;
3021 }
3022 }
3023 }
3024 }
3025
3026 if (!HasEnabledAp && ExcludeBsp) {
3027 //
3028 // If no enabled AP exists and not include Bsp to do the procedure, return EFI_NOT_STARTED.
3029 //
3030 return EFI_NOT_STARTED;
3031 }
3032
3033 CpuMpData->RunningCount = 0;
3034 for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
3035 CpuData = &CpuMpData->CpuData[ProcessorNumber];
3036 CpuData->Waiting = FALSE;
3037 if (ProcessorNumber != CpuMpData->BspNumber) {
3038 if (CpuData->State == CpuStateIdle) {
3039 //
3040 // Mark this processor as responsible for current calling.
3041 //
3042 CpuData->Waiting = TRUE;
3043 CpuMpData->RunningCount++;
3044 }
3045 }
3046 }
3047
3048 CpuMpData->Procedure = Procedure;
3049 CpuMpData->ProcArguments = ProcedureArgument;
3050 CpuMpData->SingleThread = SingleThread;
3051 CpuMpData->FinishedCount = 0;
3052 CpuMpData->FailedCpuList = FailedCpuList;
3053 CpuMpData->ExpectedTime = CalculateTimeout (
3054 TimeoutInMicroseconds,
3055 &CpuMpData->CurrentTime
3056 );
3057 CpuMpData->TotalTime = 0;
3058 CpuMpData->WaitEvent = WaitEvent;
3059
3060 if (!SingleThread) {
3061 WakeUpAP (CpuMpData, TRUE, 0, Procedure, ProcedureArgument, FALSE);
3062 } else {
3063 for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {
3064 if (ProcessorNumber == CallerNumber) {
3065 continue;
3066 }
3067
3068 if (CpuMpData->CpuData[ProcessorNumber].Waiting) {
3069 WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument, TRUE);
3070 break;
3071 }
3072 }
3073 }
3074
3075 if (!ExcludeBsp) {
3076 //
3077 // Start BSP.
3078 //
3079 Procedure (ProcedureArgument);
3080 }
3081
3082 Status = EFI_SUCCESS;
3083 if (WaitEvent == NULL) {
3084 do {
3085 Status = CheckAllAPs ();
3086 } while (Status == EFI_NOT_READY);
3087 }
3088
3089 return Status;
3090}
3091
3117 IN EFI_AP_PROCEDURE Procedure,
3118 IN UINTN ProcessorNumber,
3119 IN EFI_EVENT WaitEvent OPTIONAL,
3120 IN UINTN TimeoutInMicroseconds,
3121 IN VOID *ProcedureArgument OPTIONAL,
3122 OUT BOOLEAN *Finished OPTIONAL
3123 )
3124{
3125 EFI_STATUS Status;
3126 CPU_MP_DATA *CpuMpData;
3127 CPU_AP_DATA *CpuData;
3128 UINTN CallerNumber;
3129
3130 CpuMpData = GetCpuMpData ();
3131
3132 if (Finished != NULL) {
3133 *Finished = FALSE;
3134 }
3135
3136 if (CpuMpData == NULL) {
3137 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get CpuMpData.\n", __func__));
3138 return EFI_LOAD_ERROR;
3139 }
3140
3141 //
3142 // Check whether caller processor is BSP
3143 //
3144 Status = MpInitLibWhoAmI (&CallerNumber);
3145
3146 if (EFI_ERROR (Status)) {
3147 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. Failed to get MpInit Processor info.\n", __func__));
3148 return Status;
3149 }
3150
3151 if (CallerNumber != CpuMpData->BspNumber) {
3152 return EFI_DEVICE_ERROR;
3153 }
3154
3155 //
3156 // Check whether processor with the handle specified by ProcessorNumber exists
3157 //
3158 if (ProcessorNumber >= CpuMpData->CpuCount) {
3159 return EFI_NOT_FOUND;
3160 }
3161
3162 //
3163 // Check whether specified processor is BSP
3164 //
3165 if (ProcessorNumber == CpuMpData->BspNumber) {
3166 return EFI_INVALID_PARAMETER;
3167 }
3168
3169 //
3170 // Check parameter Procedure
3171 //
3172 if (Procedure == NULL) {
3173 return EFI_INVALID_PARAMETER;
3174 }
3175
3176 //
3177 // Update AP state
3178 //
3180
3181 //
3182 // Check whether specified AP is disabled
3183 //
3184 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) {
3185 return EFI_INVALID_PARAMETER;
3186 }
3187
3188 //
3189 // If WaitEvent is not NULL, execute in non-blocking mode.
3190 // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.
3191 // CheckAPsStatus() will check completion and timeout periodically.
3192 //
3193 CpuData = &CpuMpData->CpuData[ProcessorNumber];
3194 CpuData->WaitEvent = WaitEvent;
3195 CpuData->Finished = Finished;
3196 CpuData->ExpectedTime = CalculateTimeout (TimeoutInMicroseconds, &CpuData->CurrentTime);
3197 CpuData->TotalTime = 0;
3198
3199 WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument, TRUE);
3200
3201 //
3202 // If WaitEvent is NULL, execute in blocking mode.
3203 // BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires.
3204 //
3205 Status = EFI_SUCCESS;
3206 if (WaitEvent == NULL) {
3207 do {
3208 Status = CheckThisAP (ProcessorNumber);
3209 } while (Status == EFI_NOT_READY);
3210 }
3211
3212 return Status;
3213}
3214
3222 VOID
3223 )
3224{
3225 EFI_HOB_GUID_TYPE *GuidHob;
3226 VOID *DataInHob;
3227 CPU_MP_DATA *CpuMpData;
3228
3229 CpuMpData = NULL;
3230 GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid);
3231 if (GuidHob != NULL) {
3232 DataInHob = GET_GUID_HOB_DATA (GuidHob);
3233 CpuMpData = (CPU_MP_DATA *)(*(UINTN *)DataInHob);
3234 }
3235
3236 return CpuMpData;
3237}
3238
3266EFIAPI
3268 IN EFI_AP_PROCEDURE Procedure,
3269 IN UINTN TimeoutInMicroseconds,
3270 IN VOID *ProcedureArgument OPTIONAL
3271 )
3272{
3273 return StartupAllCPUsWorker (
3274 Procedure,
3275 FALSE,
3276 FALSE,
3277 NULL,
3278 TimeoutInMicroseconds,
3279 ProcedureArgument,
3280 NULL
3281 );
3282}
3283
3294STATIC
3295BOOLEAN
3297 IN UINT64 CurrentAttr,
3298 IN CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr
3299 )
3300{
3301 UINT64 CurrentLevel;
3302
3303 CurrentLevel = CurrentAttr & CCAttrTypeMask;
3304
3305 switch (Attr) {
3306 case CCAttrAmdSev:
3307 //
3308 // SEV is automatically enabled if SEV-ES or SEV-SNP is active.
3309 //
3310 return CurrentLevel >= CCAttrAmdSev;
3311 case CCAttrAmdSevEs:
3312 //
3313 // SEV-ES is automatically enabled if SEV-SNP is active.
3314 //
3315 return CurrentLevel >= CCAttrAmdSevEs;
3316 case CCAttrAmdSevSnp:
3317 return CurrentLevel == CCAttrAmdSevSnp;
3318 case CCAttrFeatureAmdSevEsDebugVirtualization:
3319 return !!(CurrentAttr & CCAttrFeatureAmdSevEsDebugVirtualization);
3320 default:
3321 return FALSE;
3322 }
3323}
3324
3334BOOLEAN
3335EFIAPI
3337 IN CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr
3338 )
3339{
3340 UINT64 CurrentAttr;
3341
3342 //
3343 // Get the current CC attribute.
3344 //
3345 CurrentAttr = PcdGet64 (PcdConfidentialComputingGuestAttr);
3346
3347 //
3348 // If attr is for the AMD group then call AMD specific checks.
3349 //
3350 if (((RShiftU64 (CurrentAttr, 8)) & 0xff) == 1) {
3351 return AmdMemEncryptionAttrCheck (CurrentAttr, Attr);
3352 }
3353
3354 return (CurrentAttr == Attr);
3355}
3356
3362VOID
3363EFIAPI
3365 IN OUT VOID *Buffer
3366 )
3367{
3368 CPU_MP_DATA *CpuMpData;
3369 BOOLEAN MwaitSupport;
3370 UINTN ProcessorNumber;
3371 UINTN StackStart;
3372 EFI_STATUS Status;
3373
3374 Status = MpInitLibWhoAmI (&ProcessorNumber);
3375
3376 if (EFI_ERROR (Status)) {
3377 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. Aborting AP sync.\n", __func__));
3378 return;
3379 }
3380
3381 CpuMpData = GetCpuMpData ();
3382 MwaitSupport = IsMwaitSupport ();
3383 if (CpuMpData->UseSevEsAPMethod) {
3384 //
3385 // 64-bit AMD processors with SEV-ES
3386 //
3387 StackStart = CpuMpData->SevEsAPResetStackStart;
3388 mReservedApLoop.AmdSevEntry (
3389 MwaitSupport,
3390 CpuMpData->ApTargetCState,
3391 CpuMpData->PmCodeSegment,
3392 StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
3393 (UINTN)&mNumberToFinish,
3394 CpuMpData->Pm16CodeSegment,
3395 CpuMpData->SevEsAPBuffer,
3396 CpuMpData->WakeupBuffer
3397 );
3398 } else {
3399 //
3400 // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
3401 //
3402 StackStart = mReservedTopOfApStack;
3403 mReservedApLoop.GenericEntry (
3404 MwaitSupport,
3405 CpuMpData->ApTargetCState,
3406 StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
3407 (UINTN)&mNumberToFinish,
3408 mApPageTable
3409 );
3410 }
3411
3412 //
3413 // It should never reach here
3414 //
3415 ASSERT (FALSE);
3416}
3417
3423VOID
3425 IN CPU_MP_DATA *CpuMpData
3426 )
3427{
3428 EFI_PHYSICAL_ADDRESS Address;
3429 MP_ASSEMBLY_ADDRESS_MAP *AddressMap;
3430 UINT8 *ApLoopFunc;
3431 UINTN ApLoopFuncSize;
3432 UINTN StackPages;
3433 UINTN FuncPages;
3434 IA32_CR0 Cr0;
3435
3436 AddressMap = &CpuMpData->AddressMap;
3437 if (CpuMpData->UseSevEsAPMethod) {
3438 //
3439 // 64-bit AMD processors with SEV-ES
3440 //
3441 Address = BASE_4GB - 1;
3442 ApLoopFunc = AddressMap->RelocateApLoopFuncAddressAmdSev;
3443 ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeAmdSev;
3444 } else {
3445 //
3446 // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
3447 //
3448 Address = MAX_ADDRESS;
3449 ApLoopFunc = AddressMap->RelocateApLoopFuncAddressGeneric;
3450 ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeGeneric;
3451 }
3452
3453 //
3454 // Avoid APs access invalid buffer data which allocated by BootServices,
3455 // so we will allocate reserved data for AP loop code. We also need to
3456 // allocate this buffer below 4GB due to APs may be transferred to 32bit
3457 // protected mode on long mode DXE.
3458 // Allocating it in advance since memory services are not available in
3459 // Exit Boot Services callback function.
3460 //
3461 // +------------+ (TopOfApStack)
3462 // | Stack * N |
3463 // +------------+ (stack base, 4k aligned)
3464 // | Padding |
3465 // +------------+
3466 // | Ap Loop |
3467 // +------------+ ((low address, 4k-aligned)
3468 //
3469
3470 StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE);
3471 FuncPages = EFI_SIZE_TO_PAGES (ApLoopFuncSize);
3472
3473 AllocateApLoopCodeBuffer (StackPages + FuncPages, &Address);
3474 ASSERT (Address != 0);
3475
3476 Cr0.UintN = AsmReadCr0 ();
3477 if (Cr0.Bits.PG != 0) {
3478 //
3479 // Make sure that the buffer memory is executable if NX protection is enabled
3480 // for EfiReservedMemoryType.
3481 //
3482 RemoveNxprotection (Address, EFI_PAGES_TO_SIZE (FuncPages));
3483 }
3484
3485 mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages);
3486 ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
3487 mReservedApLoop.Data = (VOID *)(UINTN)Address;
3488 ASSERT (mReservedApLoop.Data != NULL);
3489 CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize);
3490 if (!CpuMpData->UseSevEsAPMethod) {
3491 //
3492 // processors without SEV-ES and paging is enabled
3493 //
3494 mApPageTable = CreatePageTable (
3495 (UINTN)Address,
3496 EFI_PAGES_TO_SIZE (StackPages+FuncPages)
3497 );
3498 }
3499}
UINT64 UINTN
INT64 INTN
#define CPU_STACK_ALIGNMENT
#define MAX_ADDRESS
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
VOID *EFIAPI GetNextGuidHob(IN CONST EFI_GUID *Guid, IN CONST VOID *HobStart)
Definition: HobLib.c:176
BOOLEAN EFIAPI SetInterruptState(IN BOOLEAN InterruptState)
Definition: Cpu.c:48
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
BOOLEAN EFIAPI SaveAndDisableInterrupts(VOID)
Definition: Cpu.c:21
VOID EFIAPI SwitchStack(IN SWITCH_STACK_ENTRY_POINT EntryPoint, IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL, IN VOID *NewStack,...)
Definition: SwitchStack.c:42
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID EFIAPI CpuPause(VOID)
VOID EFIAPI DisableInterrupts(VOID)
Definition: CpuBreakpoint.c:54
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
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 * SWITCH_STACK_ENTRY_POINT)(IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL)
Definition: BaseLib.h:5019
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)
VOID CheckAndUpdateApsStatus(VOID)
Definition: DxeMpLib.c:235
VOID RemoveNxprotection(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINTN Length)
Definition: DxeMpLib.c:427
UINTN GetWakeupBuffer(IN UINTN WakeupBufferSize)
Definition: DxeMpLib.c:86
VOID AllocateApLoopCodeBuffer(IN UINTN Pages, IN OUT EFI_PHYSICAL_ADDRESS *Address)
Definition: DxeMpLib.c:401
UINTN AllocateCodeBuffer(IN UINTN BufferSize)
Definition: DxeMpLib.c:163
CPU_MP_DATA * GetCpuMpData(VOID)
Definition: DxeMpLib.c:56
VOID InitMpGlobalData(IN CPU_MP_DATA *CpuMpData)
Definition: DxeMpLib.c:499
VOID EnableDebugAgent(VOID)
Definition: DxeMpLib.c:40
VOID SaveCpuMpData(IN CPU_MP_DATA *CpuMpData)
Definition: DxeMpLib.c:70
UINTN CreatePageTable(IN UINTN Address, IN UINTN Length)
UINTN EFIAPI AsmWriteDr1(UINTN Dr1)
UINT16 EFIAPI AsmReadTr(VOID)
UINTN EFIAPI AsmReadDr1(VOID)
UINTN EFIAPI AsmReadDr0(VOID)
UINTN EFIAPI AsmWriteDr7(UINTN Dr7)
UINTN EFIAPI AsmWriteDr3(UINTN Dr3)
UINTN EFIAPI AsmReadCr3(VOID)
UINTN EFIAPI AsmReadDr2(VOID)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
Definition: GccInlinePriv.c:60
UINTN EFIAPI AsmWriteCr3(UINTN Cr3)
UINTN EFIAPI AsmWriteCr4(UINTN Cr4)
UINTN EFIAPI AsmReadCr0(VOID)
UINTN EFIAPI AsmWriteDr2(UINTN Dr2)
UINTN EFIAPI AsmWriteDr0(UINTN Dr0)
UINTN EFIAPI AsmWriteCr0(UINTN Cr0)
UINT16 EFIAPI AsmReadCs(VOID)
UINT64 EFIAPI AsmWriteMsr64(IN UINT32 Index, IN UINT64 Value)
UINTN EFIAPI AsmReadDr3(VOID)
UINTN EFIAPI AsmReadCr4(VOID)
UINTN EFIAPI AsmReadDr6(VOID)
UINTN EFIAPI AsmWriteDr6(UINTN Dr6)
UINT16 EFIAPI AsmReadDs(VOID)
UINTN EFIAPI AsmReadDr7(VOID)
VOID EFIAPI SendInitSipiSipiAllExcludingSelf(IN UINT32 StartupRoutine)
Definition: BaseXApicLib.c:577
BOOLEAN EFIAPI GetApicTimerInterruptState(VOID)
Definition: BaseXApicLib.c:870
VOID EFIAPI DisableLvtInterrupts(VOID)
Definition: BaseXApicLib.c:676
VOID EFIAPI GetApicTimerState(OUT UINTN *DivideValue OPTIONAL, OUT BOOLEAN *PeriodicMode OPTIONAL, OUT UINT8 *Vector OPTIONAL)
Definition: BaseXApicLib.c:790
UINT32 EFIAPI GetInitialApicId(VOID)
Definition: BaseXApicLib.c:298
#define LOCAL_APIC_MODE_X2APIC
x2APIC mode.
Definition: LocalApicLib.h:16
UINTN EFIAPI GetApicMode(VOID)
Definition: BaseXApicLib.c:242
VOID EFIAPI ProgramVirtualWireMode(VOID)
Definition: BaseXApicLib.c:633
VOID EFIAPI EnableApicTimerInterrupt(VOID)
Definition: BaseXApicLib.c:835
#define LOCAL_APIC_MODE_XAPIC
xAPIC mode.
Definition: LocalApicLib.h:15
VOID EFIAPI SendStartupIpiAllExcludingSelf(IN UINT32 StartupRoutine)
Definition: BaseXApicLib.c:510
VOID EFIAPI SetApicMode(IN UINTN ApicMode)
Definition: BaseXApicLib.c:279
UINT32 EFIAPI GetApicTimerInitCount(VOID)
Definition: BaseXApicLib.c:698
VOID EFIAPI GetProcessorLocation2ByApicId(IN UINT32 InitialApicId, OUT UINT32 *Package OPTIONAL, OUT UINT32 *Die OPTIONAL, OUT UINT32 *Tile OPTIONAL, OUT UINT32 *Module OPTIONAL, OUT UINT32 *Core OPTIONAL, OUT UINT32 *Thread OPTIONAL)
VOID EFIAPI GetProcessorLocationByApicId(IN UINT32 InitialApicId, OUT UINT32 *Package OPTIONAL, OUT UINT32 *Core OPTIONAL, OUT UINT32 *Thread OPTIONAL)
Definition: BaseXApicLib.c:985
VOID EFIAPI InitializeApicTimer(IN UINTN DivideValue, IN UINT32 InitCount, IN BOOLEAN PeriodicMode, IN UINT8 Vector)
Definition: BaseXApicLib.c:732
VOID EFIAPI SendInitSipiSipi(IN UINT32 ApicId, IN UINT32 StartupRoutine)
Definition: BaseXApicLib.c:541
VOID EFIAPI DisableApicTimerInterrupt(VOID)
Definition: BaseXApicLib.c:851
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 CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#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 ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
#define MSR_IA32_PLATFORM_ID
#define MSR_IA32_APIC_BASE
#define MSR_IA32_EFER
#define CPUID_VERSION_INFO
Definition: Cpuid.h:81
#define CPUID_MONITOR_MWAIT
Definition: Cpuid.h:967
#define CPUID_EXTENDED_CPU_SIG
Definition: Cpuid.h:3768
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuId.c:36
VOID ShadowMicrocodeUpdatePatch(IN OUT CPU_MP_DATA *CpuMpData)
Definition: Microcode.c:330
VOID MicrocodeDetect(IN CPU_MP_DATA *CpuMpData, IN UINTN ProcessorNumber)
Definition: Microcode.c:20
BOOLEAN GetMicrocodePatchInfoFromHob(UINT64 *Address, UINT64 *RegionSize)
Definition: Microcode.c:358
UINTN EFIAPI AsmMonitor(IN UINTN RegisterEax, IN UINTN RegisterEcx, IN UINTN RegisterEdx)
Definition: Monitor.c:27
VOID RestoreVolatileRegisters(IN CPU_VOLATILE_REGISTERS *VolatileRegisters)
Definition: MpLib.c:249
VOID EFIAPI RelocateApLoop(IN OUT VOID *Buffer)
Definition: MpLib.c:3364
VOID BackupAndPrepareWakeupBuffer(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:1083
VOID SaveLocalApicTimerSetting(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:161
VOID EFIAPI DxeApEntryPoint(CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:899
EFI_STATUS EnableDisableApWorker(IN UINTN ProcessorNumber, IN BOOLEAN EnableAP, IN UINT32 *HealthFlag OPTIONAL)
Definition: MpLib.c:2745
VOID EFIAPI ApFuncEnableX2Apic(IN OUT VOID *Buffer)
Definition: MpLib.c:435
VOID EFIAPI FutureBSPProc(IN VOID *Buffer)
Definition: MpLib.c:108
VOID SwitchApContext(IN CONST MP_HAND_OFF_CONFIG *MpHandOffConfig, IN CONST MP_HAND_OFF *FirstMpHandOff)
Definition: MpLib.c:1945
VOID AllocateResetVectorBelow1Mb(IN OUT CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:1122
VOID SaveVolatileRegisters(OUT CPU_VOLATILE_REGISTERS *VolatileRegisters)
Definition: MpLib.c:213
BOOLEAN IsBspExecuteDisableEnabled(VOID)
Definition: MpLib.c:59
BOOLEAN EFIAPI ConfidentialComputingGuestHas(IN CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr)
Definition: MpLib.c:3336
VOID PlaceAPInHltLoop(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:659
MP_HAND_OFF * GetNextMpHandOffHob(IN CONST MP_HAND_OFF *MpHandOff)
Definition: MpLib.c:2011
STATIC VOID GetApResetVectorSize(IN MP_ASSEMBLY_ADDRESS_MAP *AddressMap, OUT UINTN *SizeBelow1Mb OPTIONAL, OUT UINTN *SizeAbove1Mb OPTIONAL)
Definition: MpLib.c:956
VOID AutoEnableX2Apic(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:512
VOID PrepareApLoopCode(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:3424
VOID PlaceAPInMwaitLoopOrRunLoop(IN UINT8 ApLoopMode, IN volatile UINT32 *ApStartupSignalBuffer, IN UINT8 ApTargetCState)
Definition: MpLib.c:683
UINT32 GetBspNumber(IN CONST MP_HAND_OFF *FirstMpHandOff)
Definition: MpLib.c:1904
VOID SyncLocalApicTimerSetting(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:186
VOID EFIAPI ApInitializeSync(IN OUT VOID *Buffer)
Definition: MpLib.c:449
BOOLEAN IsMwaitSupport(VOID)
Definition: MpLib.c:295
VOID ResetProcessorToIdleState(IN UINTN ProcessorNumber)
Definition: MpLib.c:1651
STATIC BOOLEAN AmdMemEncryptionAttrCheck(IN UINT64 CurrentAttr, IN CONFIDENTIAL_COMPUTING_GUEST_ATTR Attr)
Definition: MpLib.c:3296
EFI_STATUS SwitchBSPWorker(IN UINTN ProcessorNumber, IN BOOLEAN EnableOldBSP)
Definition: MpLib.c:2581
MP_HAND_OFF_CONFIG * GetMpHandOffConfigHob(VOID)
Definition: MpLib.c:1989
UINT8 GetApLoopMode(OUT UINT32 *MonitorFilterSize)
Definition: MpLib.c:313
VOID RestoreWakeupBuffer(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:1105
VOID EFIAPI SwitchContextPerAp(VOID)
Definition: MpLib.c:1506
VOID FreeResetVector(IN CPU_MP_DATA *CpuMpData)
Definition: MpLib.c:1189
VOID EFIAPI AsmExchangeRole(IN CPU_EXCHANGE_ROLE_INFO *MyInfo, IN CPU_EXCHANGE_ROLE_INFO *OthersInfo)
VOID EFIAPI AsmGetAddressMap(OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap)
#define END_OF_CPU_LIST
Definition: MpService.h:63
#define PROCESSOR_HEALTH_STATUS_BIT
Definition: MpService.h:84
#define PROCESSOR_AS_BSP_BIT
Definition: MpService.h:70
#define CPU_V2_EXTENDED_TOPOLOGY
Definition: MpService.h:53
#define PROCESSOR_ENABLED_BIT
Definition: MpService.h:77
MTRR_SETTINGS *EFIAPI MtrrSetAllMtrrs(IN MTRR_SETTINGS *MtrrSetting)
Definition: MtrrLib.c:2908
MTRR_SETTINGS *EFIAPI MtrrGetAllMtrrs(OUT MTRR_SETTINGS *MtrrSetting)
Definition: MtrrLib.c:2851
UINTN EFIAPI AsmMwait(IN UINTN RegisterEax, IN UINTN RegisterEcx)
Definition: Mwait.c:25
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define FixedPcdGetBool(TokenName)
Definition: PcdLib.h:120
#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)
UINT32 EFIAPI InterlockedDecrement(IN volatile UINT32 *Value)
SPIN_LOCK *EFIAPI InitializeSpinLock(OUT SPIN_LOCK *SpinLock)
SPIN_LOCK *EFIAPI ReleaseSpinLock(IN OUT SPIN_LOCK *SpinLock)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
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
VOID AllocateSevEsAPMemory(IN OUT CPU_MP_DATA *CpuMpData)
Definition: AmdSev.c:158
VOID AmdSevUpdateCpuMpData(IN CPU_MP_DATA *CpuMpData)
Definition: AmdSev.c:304
VOID SetSevEsJumpTable(IN UINTN SipiVector)
Definition: AmdSev.c:174
VOID SevEsPlaceApHlt(CPU_MP_DATA *CpuMpData)
Definition: AmdSev.c:223
VOID FillExchangeInfoDataSevEs(IN volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo)
Definition: AmdSev.c:276
VOID SevSnpCreateAP(IN CPU_MP_DATA *CpuMpData, IN INTN ProcessorNumber)
Definition: AmdSev.c:41
BOOLEAN CanUseSevSnpCreateAP(IN CPU_MP_DATA *CpuMpData)
Definition: AmdSev.c:61
BOOLEAN EFIAPI StandardSignatureIsAuthenticAMD(VOID)
Definition: X86BaseCpuLib.c:27
VOID EFIAPI InitializeFloatingPointUnits(VOID)
VOID EFIAPI AsmReadGdtr(OUT IA32_DESCRIPTOR *Gdtr)
Definition: X86ReadGdtr.c:24
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
Definition: X86ReadIdtr.c:24
VOID EFIAPI AsmWriteTr(IN UINT16 Selector)
VOID EFIAPI AsmWriteGdtr(IN CONST IA32_DESCRIPTOR *Gdtr)
VOID EFIAPI AsmWriteIdtr(IN CONST IA32_DESCRIPTOR *Idtr)
Definition: Base.h:213
struct CPUID_MONITOR_MWAIT_EBX::@702 Bits
UINT32 LargestMonitorLineSize
Definition: Cpuid.h:1004
struct CPUID_VERSION_INFO_ECX::@695 Bits
struct CPUID_VERSION_INFO_EDX::@696 Bits
struct MSR_IA32_APIC_BASE_REGISTER::@627 Bits
struct MSR_IA32_EFER_REGISTER::@691 Bits
struct MSR_IA32_PLATFORM_ID_REGISTER::@626 Bits