TianoCore EDK2 master
CpuMp.c
Go to the documentation of this file.
1
9#include "CpuDxe.h"
10#include "CpuMp.h"
11
12EFI_HANDLE mMpServiceHandle = NULL;
13UINTN mNumberOfProcessors = 1;
14
15EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = {
22 WhoAmI
23};
24
62EFIAPI
65 OUT UINTN *NumberOfProcessors,
66 OUT UINTN *NumberOfEnabledProcessors
67 )
68{
69 if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {
70 return EFI_INVALID_PARAMETER;
71 }
72
74 NumberOfProcessors,
75 NumberOfEnabledProcessors
76 );
77}
78
106EFIAPI
109 IN UINTN ProcessorNumber,
110 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
111 )
112{
113 return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL);
114}
115
253EFIAPI
256 IN EFI_AP_PROCEDURE Procedure,
257 IN BOOLEAN SingleThread,
258 IN EFI_EVENT WaitEvent OPTIONAL,
259 IN UINTN TimeoutInMicroseconds,
260 IN VOID *ProcedureArgument OPTIONAL,
261 OUT UINTN **FailedCpuList OPTIONAL
262 )
263{
265 Procedure,
266 SingleThread,
267 WaitEvent,
268 TimeoutInMicroseconds,
269 ProcedureArgument,
270 FailedCpuList
271 );
272}
273
361EFIAPI
364 IN EFI_AP_PROCEDURE Procedure,
365 IN UINTN ProcessorNumber,
366 IN EFI_EVENT WaitEvent OPTIONAL,
367 IN UINTN TimeoutInMicroseconds,
368 IN VOID *ProcedureArgument OPTIONAL,
369 OUT BOOLEAN *Finished OPTIONAL
370 )
371{
373 Procedure,
374 ProcessorNumber,
375 WaitEvent,
376 TimeoutInMicroseconds,
377 ProcedureArgument,
378 Finished
379 );
380}
381
418EFIAPI
421 IN UINTN ProcessorNumber,
422 IN BOOLEAN EnableOldBSP
423 )
424{
425 return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP);
426}
427
470EFIAPI
473 IN UINTN ProcessorNumber,
474 IN BOOLEAN EnableAP,
475 IN UINT32 *HealthFlag OPTIONAL
476 )
477{
478 return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);
479}
480
506EFIAPI
509 OUT UINTN *ProcessorNumber
510 )
511{
512 return MpInitLibWhoAmI (ProcessorNumber);
513}
514
522VOID
524 VOID
525 )
526{
527 EFI_HOB_GUID_TYPE *GuidHob;
530 UINTN NumberOfData;
533 UINTN ProcessorNumber;
534 EFI_PROCESSOR_INFORMATION ProcessorInfo;
535 EFI_HEALTH_FLAGS BistData;
536 UINTN CpuInstanceNumber;
537
540
541 //
542 // Get gEfiSecPlatformInformation2PpiGuid Guided HOB firstly
543 //
544 GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformation2PpiGuid);
545 if (GuidHob != NULL) {
546 //
547 // Sec Platform Information2 PPI includes BSP/APs' BIST information
548 //
550 NumberOfData = SecPlatformInformation2->NumberOfCpus;
551 CpuInstance = SecPlatformInformation2->CpuInstance;
552 } else {
553 //
554 // Otherwise, get gEfiSecPlatformInformationPpiGuid Guided HOB
555 //
556 GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);
557 if (GuidHob != NULL) {
559 NumberOfData = 1;
560 //
561 // SEC Platform Information only includes BSP's BIST information
562 // does not have BSP's APIC ID
563 //
564 BspCpuInstance.CpuLocation = GetApicId ();
565 BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32;
566 CpuInstance = &BspCpuInstance;
567 } else {
568 DEBUG ((DEBUG_INFO, "Does not find any HOB stored CPU BIST information!\n"));
569 //
570 // Does not find any HOB stored BIST information
571 //
572 return;
573 }
574 }
575
576 for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {
577 MpInitLibGetProcessorInfo (ProcessorNumber, &ProcessorInfo, &BistData);
578 for (CpuInstanceNumber = 0; CpuInstanceNumber < NumberOfData; CpuInstanceNumber++) {
579 if (ProcessorInfo.ProcessorId == CpuInstance[CpuInstanceNumber].CpuLocation) {
580 //
581 // Update CPU health status for MP Services Protocol according to BIST data.
582 //
583 BistData = CpuInstance[CpuInstanceNumber].InfoRecord.IA32HealthFlags;
584 }
585 }
586
587 if (BistData.Uint32 != 0) {
588 //
589 // Report Status Code that self test is failed
590 //
592 EFI_ERROR_CODE | EFI_ERROR_MAJOR,
593 (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
594 );
595 }
596 }
597}
598
608VOID
609EFIAPI
611 IN OUT VOID *Buffer
612 )
613{
614 AsmReadGdtr ((IA32_DESCRIPTOR *)Buffer);
615}
616
626VOID
627EFIAPI
629 IN OUT VOID *Buffer
630 )
631{
633 IA32_DESCRIPTOR Idtr;
634 EFI_STATUS Status;
635
636 EssData = Buffer;
637 //
638 // We don't plan to replace IDT table with a new one, but we should not assume
639 // the AP's IDT is the same as BSP's IDT either.
640 //
641 AsmReadIdtr (&Idtr);
642 EssData->Ia32.IdtTable = (VOID *)Idtr.Base;
643 EssData->Ia32.IdtTableSize = Idtr.Limit + 1;
644 Status = InitializeSeparateExceptionStacks (EssData);
645 ASSERT_EFI_ERROR (Status);
646}
647
655VOID
657 VOID
658 )
659{
660 UINTN Index;
661 UINTN Bsp;
662 UINTN ExceptionNumber;
663 UINTN OldGdtSize;
664 UINTN NewGdtSize;
665 UINTN NewStackSize;
666 IA32_DESCRIPTOR Gdtr;
668 UINT8 *GdtBuffer;
669 UINT8 *StackTop;
670
671 ExceptionNumber = FixedPcdGetSize (PcdCpuStackSwitchExceptionList);
672 NewStackSize = FixedPcdGet32 (PcdCpuKnownGoodStackSize) * ExceptionNumber;
673
674 StackTop = AllocateRuntimeZeroPool (NewStackSize * mNumberOfProcessors);
675 ASSERT (StackTop != NULL);
676 StackTop += NewStackSize * mNumberOfProcessors;
677
678 //
679 // The default exception handlers must have been initialized. Let's just skip
680 // it in this method.
681 //
682 EssData.Ia32.Revision = CPU_EXCEPTION_INIT_DATA_REV;
683 EssData.Ia32.InitDefaultHandlers = FALSE;
684
685 EssData.Ia32.StackSwitchExceptions = FixedPcdGetPtr (PcdCpuStackSwitchExceptionList);
686 EssData.Ia32.StackSwitchExceptionNumber = ExceptionNumber;
687 EssData.Ia32.KnownGoodStackSize = FixedPcdGet32 (PcdCpuKnownGoodStackSize);
688
689 //
690 // Initialize Gdtr to suppress incorrect compiler/analyzer warnings.
691 //
692 Gdtr.Base = 0;
693 Gdtr.Limit = 0;
694 MpInitLibWhoAmI (&Bsp);
695 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
696 //
697 // To support stack switch, we need to re-construct GDT but not IDT.
698 //
699 if (Index == Bsp) {
700 GetGdtr (&Gdtr);
701 } else {
702 //
703 // AP might have different size of GDT from BSP.
704 //
705 MpInitLibStartupThisAP (GetGdtr, Index, NULL, 0, (VOID *)&Gdtr, NULL);
706 }
707
708 //
709 // X64 needs only one TSS of current task working for all exceptions
710 // because of its IST feature. IA32 needs one TSS for each exception
711 // in addition to current task. Since AP is not supposed to allocate
712 // memory, we have to do it in BSP. To simplify the code, we allocate
713 // memory for IA32 case to cover both IA32 and X64 exception stack
714 // switch.
715 //
716 // Layout of memory to allocate for each processor:
717 // --------------------------------
718 // | Alignment | (just in case)
719 // --------------------------------
720 // | |
721 // | Original GDT |
722 // | |
723 // --------------------------------
724 // | Current task descriptor |
725 // --------------------------------
726 // | |
727 // | Exception task descriptors | X ExceptionNumber
728 // | |
729 // --------------------------------
730 // | Current task-state segment |
731 // --------------------------------
732 // | |
733 // | Exception task-state segment | X ExceptionNumber
734 // | |
735 // --------------------------------
736 //
737 OldGdtSize = Gdtr.Limit + 1;
738 EssData.Ia32.ExceptionTssDescSize = sizeof (IA32_TSS_DESCRIPTOR) *
739 (ExceptionNumber + 1);
740 EssData.Ia32.ExceptionTssSize = sizeof (IA32_TASK_STATE_SEGMENT) *
741 (ExceptionNumber + 1);
742 NewGdtSize = sizeof (IA32_TSS_DESCRIPTOR) +
743 OldGdtSize +
744 EssData.Ia32.ExceptionTssDescSize +
745 EssData.Ia32.ExceptionTssSize;
746
747 GdtBuffer = AllocateRuntimeZeroPool (NewGdtSize);
748 ASSERT (GdtBuffer != NULL);
749
750 //
751 // Make sure GDT table alignment
752 //
753 EssData.Ia32.GdtTable = ALIGN_POINTER (GdtBuffer, sizeof (IA32_TSS_DESCRIPTOR));
754 NewGdtSize -= ((UINT8 *)EssData.Ia32.GdtTable - GdtBuffer);
755 EssData.Ia32.GdtTableSize = NewGdtSize;
756
757 EssData.Ia32.ExceptionTssDesc = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize);
758 EssData.Ia32.ExceptionTss = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize +
759 EssData.Ia32.ExceptionTssDescSize);
760
761 EssData.Ia32.KnownGoodStackTop = (UINTN)StackTop;
762 DEBUG ((
763 DEBUG_INFO,
764 "Exception stack top[cpu%lu]: 0x%lX\n",
765 (UINT64)(UINTN)Index,
766 (UINT64)(UINTN)StackTop
767 ));
768
769 if (Index == Bsp) {
771 } else {
774 Index,
775 NULL,
776 0,
777 (VOID *)&EssData,
778 NULL
779 );
780 }
781
782 StackTop -= NewStackSize;
783 }
784}
785
790VOID
792 VOID
793 )
794{
795 //
796 // Enable non-stop mode for #PF triggered by Heap Guard or NULL Pointer
797 // Detection.
798 //
799 if (HEAP_GUARD_NONSTOP_MODE || NULL_DETECTION_NONSTOP_MODE) {
802 }
803
804 //
805 // Setup stack switch for Stack Guard feature.
806 //
807 if (PcdGetBool (PcdCpuStackGuard)) {
809 }
810}
811
816VOID
818 VOID
819 )
820{
821 EFI_STATUS Status;
822 UINTN NumberOfProcessors;
823 UINTN NumberOfEnabledProcessors;
824
825 //
826 // Wakeup APs to do initialization
827 //
828 Status = MpInitLibInitialize ();
829 ASSERT_EFI_ERROR (Status);
830
831 MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors);
832 mNumberOfProcessors = NumberOfProcessors;
833 DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mNumberOfProcessors));
834
835 //
836 // Initialize special exception handlers for each logic processor.
837 //
839
840 //
841 // Update CPU healthy information from Guided HOB
842 //
844
845 Status = gBS->InstallMultipleProtocolInterfaces (
846 &mMpServiceHandle,
847 &gEfiMpServiceProtocolGuid,
848 &mMpServicesTemplate,
849 NULL
850 );
851 ASSERT_EFI_ERROR (Status);
852}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
#define NULL
Definition: Base.h:312
#define ALIGN_POINTER(Pointer, Alignment)
Definition: Base.h:859
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI SecPlatformInformation2(IN CONST EFI_PEI_SERVICES **PeiServices, IN OUT UINT64 *StructureSize, OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2)
Definition: CpuBist.c:35
EFI_STATUS EFIAPI RegisterCpuInterruptHandler(IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler)
EFI_STATUS EFIAPI InitializeSeparateExceptionStacks(IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL)
EFI_STATUS EFIAPI StartupThisAP(IN EFI_MP_SERVICES_PROTOCOL *This, 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: CpuMp.c:362
EFI_STATUS EFIAPI EnableDisableAP(IN EFI_MP_SERVICES_PROTOCOL *This, IN UINTN ProcessorNumber, IN BOOLEAN EnableAP, IN UINT32 *HealthFlag OPTIONAL)
Definition: CpuMp.c:471
VOID EFIAPI InitializeExceptionStackSwitchHandlers(IN OUT VOID *Buffer)
Definition: CpuMp.c:628
VOID EFIAPI GetGdtr(IN OUT VOID *Buffer)
Definition: CpuMp.c:610
EFI_STATUS EFIAPI WhoAmI(IN EFI_MP_SERVICES_PROTOCOL *This, OUT UINTN *ProcessorNumber)
Definition: CpuMp.c:507
VOID InitializeMpExceptionStackSwitchHandlers(VOID)
Definition: CpuMp.c:656
EFI_STATUS EFIAPI StartupAllAPs(IN EFI_MP_SERVICES_PROTOCOL *This, IN EFI_AP_PROCEDURE Procedure, IN BOOLEAN SingleThread, IN EFI_EVENT WaitEvent OPTIONAL, IN UINTN TimeoutInMicroseconds, IN VOID *ProcedureArgument OPTIONAL, OUT UINTN **FailedCpuList OPTIONAL)
Definition: CpuMp.c:254
VOID CollectBistDataFromHob(VOID)
Definition: CpuMp.c:523
EFI_STATUS EFIAPI GetNumberOfProcessors(IN EFI_MP_SERVICES_PROTOCOL *This, OUT UINTN *NumberOfProcessors, OUT UINTN *NumberOfEnabledProcessors)
Definition: CpuMp.c:63
EFI_STATUS EFIAPI SwitchBSP(IN EFI_MP_SERVICES_PROTOCOL *This, IN UINTN ProcessorNumber, IN BOOLEAN EnableOldBSP)
Definition: CpuMp.c:419
EFI_STATUS EFIAPI GetProcessorInfo(IN EFI_MP_SERVICES_PROTOCOL *This, IN UINTN ProcessorNumber, OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer)
Definition: CpuMp.c:107
VOID InitializeMpSupport(VOID)
Definition: CpuMp.c:817
VOID InitializeMpExceptionHandlers(VOID)
Definition: CpuMp.c:791
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:440
#define DEBUG(Expression)
Definition: DebugLib.h:417
#define ASSERT(Expression)
Definition: DebugLib.h:391
VOID *EFIAPI AllocateRuntimeZeroPool(IN UINTN AllocationSize)
EFI_STATUS EFIAPI SecPlatformInformation(IN CONST EFI_PEI_SERVICES **PeiServices, IN OUT UINT64 *StructureSize, OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord)
#define GET_GUID_HOB_DATA(HobStart)
Definition: HobLib.h:544
UINT32 EFIAPI GetApicId(VOID)
Definition: BaseXApicLib.c:338
#define REPORT_STATUS_CODE(Type, Value)
EFI_STATUS EFIAPI MpInitLibEnableDisableAP(IN UINTN ProcessorNumber, IN BOOLEAN EnableAP, IN UINT32 *HealthFlag OPTIONAL)
Definition: DxeMpLib.c:947
EFI_STATUS EFIAPI MpInitLibStartupAllAPs(IN EFI_AP_PROCEDURE Procedure, IN BOOLEAN SingleThread, IN EFI_EVENT WaitEvent OPTIONAL, IN UINTN TimeoutInMicroseconds, IN VOID *ProcedureArgument OPTIONAL, OUT UINTN **FailedCpuList OPTIONAL)
Definition: DxeMpLib.c:709
EFI_STATUS EFIAPI MpInitLibWhoAmI(OUT UINTN *ProcessorNumber)
Definition: MpLib.c:2354
EFI_STATUS EFIAPI MpInitLibGetNumberOfProcessors(OUT UINTN *NumberOfProcessors OPTIONAL, OUT UINTN *NumberOfEnabledProcessors OPTIONAL)
Definition: MpLib.c:2391
EFI_STATUS EFIAPI MpInitLibSwitchBSP(IN UINTN ProcessorNumber, IN BOOLEAN EnableOldBSP)
Definition: DxeMpLib.c:874
EFI_STATUS EFIAPI MpInitLibGetProcessorInfo(IN UINTN ProcessorNumber, OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL)
Definition: MpLib.c:2059
EFI_STATUS EFIAPI MpInitLibInitialize(VOID)
Definition: MpLib.c:1764
EFI_STATUS EFIAPI MpInitLibStartupThisAP(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: DxeMpLib.c:816
#define FixedPcdGet32(TokenName)
Definition: PcdLib.h:92
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define FixedPcdGetPtr(TokenName)
Definition: PcdLib.h:134
#define FixedPcdGetSize(TokenName)
Definition: PcdLib.h:414
VOID(EFIAPI * EFI_AP_PROCEDURE)(IN OUT VOID *Buffer)
Definition: PiMultiPhase.h:191
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:28
VOID * EFI_EVENT
Definition: UefiBaseType.h:36
VOID * EFI_HANDLE
Definition: UefiBaseType.h:32
EFI_BOOT_SERVICES * gBS
VOID EFIAPI PageFaultExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID EFIAPI DebugExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID EFIAPI AsmReadGdtr(OUT IA32_DESCRIPTOR *Gdtr)
Definition: X86ReadGdtr.c:24
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
Definition: X86ReadIdtr.c:24