TianoCore EDK2 master
Loading...
Searching...
No Matches
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 //
549 SecPlatformInformation2 = GET_GUID_HOB_DATA (GuidHob);
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) {
558 SecPlatformInformation = GET_GUID_HOB_DATA (GuidHob);
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
599//
600// Structure for InitializeSeparateExceptionStacks
601//
602typedef struct {
603 VOID *Buffer;
604 UINTN BufferSize;
605 EFI_STATUS Status;
607
617VOID
618EFIAPI
620 IN OUT VOID *Buffer
621 )
622{
623 EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData;
624 UINTN Index;
625 EFI_STATUS Status;
626
627 Status = MpInitLibWhoAmI (&Index);
628
629 if (EFI_ERROR (Status)) {
630 DEBUG ((DEBUG_ERROR, "[%a] - Failed to get processor number. The exception stack was not initialized.\n", __func__));
631 return;
632 }
633
634 SwitchStackData = (EXCEPTION_STACK_SWITCH_CONTEXT *)Buffer;
635
636 //
637 // This may be called twice for each Cpu. Only run InitializeSeparateExceptionStacks
638 // if this is the first call or the first call failed because of size too small.
639 //
640 if ((SwitchStackData[Index].Status == EFI_NOT_STARTED) || (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL)) {
641 SwitchStackData[Index].Status = InitializeSeparateExceptionStacks (SwitchStackData[Index].Buffer, &SwitchStackData[Index].BufferSize);
642 }
643}
644
652VOID
654 VOID
655 )
656{
657 UINTN Index;
658 EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData;
659 UINTN BufferSize;
660 EFI_STATUS Status;
661 UINT8 *Buffer;
662
663 SwitchStackData = AllocateZeroPool (mNumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT));
664 ASSERT (SwitchStackData != NULL);
665 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
666 //
667 // Because the procedure may runs multiple times, use the status EFI_NOT_STARTED
668 // to indicate the procedure haven't been run yet.
669 //
670 SwitchStackData[Index].Status = EFI_NOT_STARTED;
671 }
672
673 Status = MpInitLibStartupAllCPUs (
675 0,
676 SwitchStackData
677 );
678 ASSERT_EFI_ERROR (Status);
679
680 BufferSize = 0;
681 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
682 if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {
683 ASSERT (SwitchStackData[Index].BufferSize != 0);
684 BufferSize += SwitchStackData[Index].BufferSize;
685 } else {
686 ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);
687 ASSERT (SwitchStackData[Index].BufferSize == 0);
688 }
689 }
690
691 if (BufferSize != 0) {
692 Buffer = AllocateRuntimeZeroPool (BufferSize);
693 ASSERT (Buffer != NULL);
694 BufferSize = 0;
695 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
696 if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {
697 SwitchStackData[Index].Buffer = (VOID *)(&Buffer[BufferSize]);
698 BufferSize += SwitchStackData[Index].BufferSize;
699 DEBUG ((
700 DEBUG_INFO,
701 "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlers: 0x%lX with size 0x%lX\n",
702 (UINT64)(UINTN)Index,
703 (UINT64)(UINTN)SwitchStackData[Index].Buffer,
704 (UINT64)(UINTN)SwitchStackData[Index].BufferSize
705 ));
706 }
707 }
708
709 Status = MpInitLibStartupAllCPUs (
711 0,
712 SwitchStackData
713 );
714 ASSERT_EFI_ERROR (Status);
715 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
716 ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);
717 }
718 }
719
720 FreePool (SwitchStackData);
721}
722
727VOID
729 VOID
730 )
731{
732 //
733 // Enable non-stop mode for #PF triggered by Heap Guard or NULL Pointer
734 // Detection.
735 //
736 if (HEAP_GUARD_NONSTOP_MODE || NULL_DETECTION_NONSTOP_MODE) {
737 RegisterCpuInterruptHandler (EXCEPT_IA32_DEBUG, DebugExceptionHandler);
738 RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT, PageFaultExceptionHandler);
739 }
740
741 //
742 // Setup stack switch for Stack Guard feature.
743 //
744 if (PcdGetBool (PcdCpuStackGuard)) {
746 }
747}
748
753VOID
755 VOID
756 )
757{
758 EFI_STATUS Status;
759 UINTN NumberOfProcessors;
760 UINTN NumberOfEnabledProcessors;
761
762 //
763 // Wakeup APs to do initialization
764 //
765 Status = MpInitLibInitialize ();
766 ASSERT_EFI_ERROR (Status);
767
768 Status = MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors);
769 ASSERT_EFI_ERROR (Status);
770 if (!EFI_ERROR (Status)) {
771 mNumberOfProcessors = NumberOfProcessors;
772 DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mNumberOfProcessors));
773
774 //
775 // Initialize special exception handlers for each logic processor.
776 //
778
779 //
780 // Update CPU healthy information from Guided HOB
781 //
783
784 Status = gBS->InstallMultipleProtocolInterfaces (
785 &mMpServiceHandle,
786 &gEfiMpServiceProtocolGuid,
787 &mMpServicesTemplate,
788 NULL
789 );
790 ASSERT_EFI_ERROR (Status);
791 }
792}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
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 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:619
EFI_STATUS EFIAPI WhoAmI(IN EFI_MP_SERVICES_PROTOCOL *This, OUT UINTN *ProcessorNumber)
Definition: CpuMp.c:507
VOID InitializeMpExceptionStackSwitchHandlers(VOID)
Definition: CpuMp.c:653
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:754
VOID InitializeMpExceptionHandlers(VOID)
Definition: CpuMp.c:728
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
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)
UINT32 EFIAPI GetApicId(VOID)
Definition: BaseXApicLib.c:337
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE(Type, Value)
EFI_STATUS EFIAPI MpInitLibEnableDisableAP(IN UINTN ProcessorNumber, IN BOOLEAN EnableAP, IN UINT32 *HealthFlag OPTIONAL)
Definition: DxeMpLib.c:920
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:682
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
EFI_STATUS EFIAPI MpInitLibSwitchBSP(IN UINTN ProcessorNumber, IN BOOLEAN EnableOldBSP)
Definition: DxeMpLib.c:847
EFI_STATUS EFIAPI MpInitLibStartupAllCPUs(IN EFI_AP_PROCEDURE Procedure, IN UINTN TimeoutInMicroseconds, IN VOID *ProcedureArgument OPTIONAL)
Definition: MpLib.c:1287
EFI_STATUS EFIAPI MpInitLibGetProcessorInfo(IN UINTN ProcessorNumber, OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL)
Definition: MpLib.c:1452
EFI_STATUS EFIAPI MpInitLibInitialize(VOID)
Definition: MpLib.c:1319
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:789
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
VOID(EFIAPI * EFI_AP_PROCEDURE)(IN OUT VOID *Buffer)
Definition: PiMultiPhase.h:198
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
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)