14UINTN mFaultInstructionLength = 0;
16UINTN mNumberOfProcessors = 1;
17UINTN mRspAddress[2] = { 0 };
25CONST UINT32 mErrorCodeExceptionFlag = 0x20227d00;
41 mExceptionType = ExceptionType;
57 IA32_TSS_DESCRIPTOR *Tss;
61 AsmWriteGdtr (&(CpuOriginalRegisterBuffer->OriginalGdtr));
62 AsmWriteIdtr (&(CpuOriginalRegisterBuffer->OriginalIdtr));
63 Tr = CpuOriginalRegisterBuffer->Tr;
64 if ((Tr != 0) && (Tr < CpuOriginalRegisterBuffer->OriginalGdtr.Limit)) {
65 Tss = (IA32_TSS_DESCRIPTOR *)(CpuOriginalRegisterBuffer->OriginalGdtr.Base + Tr);
66 if (Tss->Bits.P == 1) {
70 Tss->Bits.Type &= 0xD;
93 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
94 if (Index == BspProcessorNum) {
99 ASSERT (MpServices !=
NULL);
105 (VOID *)&CpuOriginalRegisterBuffer[Index]
123 IA32_DESCRIPTOR Gdtr;
124 IA32_DESCRIPTOR Idtr;
130 CpuOriginalRegisterBuffer->OriginalGdtr.Base = Gdtr.Base;
131 CpuOriginalRegisterBuffer->OriginalGdtr.Limit = Gdtr.Limit;
132 CpuOriginalRegisterBuffer->OriginalIdtr.Base = Idtr.Base;
133 CpuOriginalRegisterBuffer->OriginalIdtr.Limit = Idtr.Limit;
134 CpuOriginalRegisterBuffer->Tr =
AsmReadTr ();
148 UINTN BspProcessorNum
156 ASSERT (CpuOriginalRegisterBuffer !=
NULL);
158 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
159 if (Index == BspProcessorNum) {
164 ASSERT (MpServices !=
NULL);
170 (VOID *)&CpuOriginalRegisterBuffer[Index]
175 return CpuOriginalRegisterBuffer;
244 Status = InitializeCpuExceptionHandlers (
NULL);
247 for (Index = 0; Index < SPEC_MAX_EXCEPTION_NUM; Index++) {
251 if ((mErrorCodeExceptionFlag & (1 << Index)) != 0) {
255 DEBUG ((DEBUG_INFO,
"TestCase1: ExceptionType is %d\n", Index));
261 Status = RegisterCpuInterruptHandler (Index,
NULL);
266 FreePool (CpuOriginalRegisterBuffer);
268 return UNIT_TEST_PASSED;
287 ASSERT (StackBase !=
NULL);
289 while ((Hob.Raw =
GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) !=
NULL) {
290 MemoryHob = Hob.MemoryAllocation;
294 "%a: Bsp StackBase = 0x%016lx StackSize = 0x%016lx\n",
304 ASSERT ((*StackBase & EFI_PAGE_MASK) == 0);
308 Hob.Raw = GET_NEXT_HOB (Hob);
311 ASSERT (*StackBase != 0);
322 OUT VOID *ApStackBase
342 UINTN BspProcessorNum
345 UINTN *CpuStackBaseBuffer;
350 ASSERT (CpuStackBaseBuffer !=
NULL);
352 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
353 if (Index == BspProcessorNum) {
358 ASSERT (MpServices !=
NULL);
364 (VOID *)&CpuStackBaseBuffer[Index]
367 DEBUG ((DEBUG_INFO,
"AP[%d] StackBase = 0x%x\n", Index, CpuStackBaseBuffer[Index]));
370 return CpuStackBaseBuffer;
389 PAGING_MODE PagingMode;
390 BOOLEAN Enable5LevelPaging;
391 RETURN_STATUS Status;
395 UINTN PreviousAddress;
397 ASSERT (PFAddress !=
NULL);
400 if (Cr0.Bits.PG == 0) {
406 if (
sizeof (
UINTN) ==
sizeof (UINT32)) {
407 ASSERT (Cr4.Bits.PAE == 1);
408 PagingMode = PagingPae;
410 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
411 PagingMode = Enable5LevelPaging ? Paging5Level : Paging4Level;
422 for (Index = 0; Index < MapCount; Index++) {
425 "%02d: %016lx - %016lx, %016lx\n",
427 Map[Index].LinearAddress,
428 Map[Index].LinearAddress + Map[Index].Length,
429 Map[Index].Attribute.Uint64
435 if (Map[Index].LinearAddress > PreviousAddress) {
436 *PFAddress = PreviousAddress;
440 PreviousAddress = (
UINTN)(Map[Index].LinearAddress + Map[Index].Length);
445 if ((Cr0.Bits.WP != 0) && (Map[Index].Attribute.Bits.ReadWrite == 0)) {
446 *PFAddress = (
UINTN)Map[Index].LinearAddress;
483 Status = InitializeCpuExceptionHandlers (
NULL);
490 DEBUG ((DEBUG_INFO,
"TestCase2: ExceptionType is %d\n", EXCEPT_IA32_GP_FAULT));
496 Status = RegisterCpuInterruptHandler (EXCEPT_IA32_GP_FAULT,
NULL);
503 DEBUG ((DEBUG_INFO,
"TestCase2: ExceptionType is %d\n", EXCEPT_IA32_PAGE_FAULT));
509 Status = RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT,
NULL);
514 FreePool (CpuOriginalRegisterBuffer);
516 return UNIT_TEST_PASSED;
543 UINTN FaultParameter;
549 Status = InitializeCpuExceptionHandlers (
NULL);
552 for (Index = 0; Index < 22; Index++) {
553 if (Index == EXCEPT_IA32_PAGE_FAULT) {
557 }
else if (Index == EXCEPT_IA32_GP_FAULT) {
558 FaultParameter = CR4_RESERVED_BIT;
560 if ((mErrorCodeExceptionFlag & (1 << Index)) != 0) {
565 DEBUG ((DEBUG_INFO,
"TestCase3: ExceptionType is %d\n", Index));
574 Status = RegisterCpuInterruptHandler (Index,
NULL);
579 FreePool (CpuOriginalRegisterBuffer);
581 return UNIT_TEST_PASSED;
607 if ((CpuSwitchStackData->Status == EFI_NOT_STARTED) || (CpuSwitchStackData->Status == EFI_BUFFER_TOO_SMALL)) {
608 CpuSwitchStackData->Status = InitializeSeparateExceptionStacks (CpuSwitchStackData->Buffer, &CpuSwitchStackData->BufferSize);
626 UINTN BspProcessorNum
636 ASSERT (SwitchStackData !=
NULL);
637 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
642 SwitchStackData[Index].Status = EFI_NOT_STARTED;
643 if (Index == BspProcessorNum) {
653 (VOID *)&SwitchStackData[Index]
659 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
660 if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {
661 ASSERT (SwitchStackData[Index].BufferSize != 0);
662 BufferSize += SwitchStackData[Index].BufferSize;
664 ASSERT (SwitchStackData[Index].Status ==
EFI_SUCCESS);
665 ASSERT (SwitchStackData[Index].BufferSize == 0);
669 if (BufferSize != 0) {
671 ASSERT (Buffer !=
NULL);
673 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
674 if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {
675 SwitchStackData[Index].Buffer = (VOID *)(&Buffer[BufferSize]);
676 BufferSize += SwitchStackData[Index].BufferSize;
679 "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlersPerAp: 0x%lX with size 0x%lX\n",
680 (UINT64)(
UINTN)Index,
681 (UINT64)(
UINTN)SwitchStackData[Index].Buffer,
682 (UINT64)(
UINTN)SwitchStackData[Index].BufferSize
687 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
688 if (Index == BspProcessorNum) {
698 (VOID *)&SwitchStackData[Index]
703 for (Index = 0; Index < mNumberOfProcessors; ++Index) {
704 ASSERT (SwitchStackData[Index].Status ==
EFI_SUCCESS);
708 return SwitchStackData;
733 UINTN OriginalStackBase;
738 UINTN ProcessorNumber;
739 UINTN EnabledProcessorNum;
742 UINTN BspProcessorNum;
744 UINTN *CpuStackBaseBuffer;
747 return UNIT_TEST_PASSED;
758 mNumberOfProcessors = ProcessorNumber;
767 Status = InitializeCpuExceptionHandlers (
NULL);
785 for (Index = 0; Index < mNumberOfProcessors; Index++) {
786 OriginalStackBase = CpuStackBaseBuffer[Index];
787 NewStackTop = (
UINTN)(SwitchStackData[Index].Buffer) + SwitchStackData[Index].BufferSize;
788 NewStackBase = (
UINTN)(SwitchStackData[Index].Buffer);
789 if (Index == BspProcessorNum) {
801 DEBUG ((DEBUG_INFO,
"TestCase4: mRspAddress[0] is 0x%x, mRspAddress[1] is 0x%x\n", mRspAddress[0], mRspAddress[1]));
802 UT_ASSERT_TRUE ((mRspAddress[0] >= OriginalStackBase) && (mRspAddress[0] <= (OriginalStackBase + SIZE_4KB)));
803 UT_ASSERT_TRUE ((mRspAddress[1] >= NewStackBase) && (mRspAddress[1] < NewStackTop));
806 Status = RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT,
NULL);
808 Status = RegisterCpuInterruptHandler (EXCEPT_IA32_DOUBLE_FAULT,
NULL);
812 FreePool (CpuOriginalRegisterBuffer);
815 return UNIT_TEST_PASSED;
829 IN UNIT_TEST_FRAMEWORK_HANDLE Framework
833 UNIT_TEST_SUITE_HANDLE CpuExceptionLibUnitTestSuite;
838 Status =
CreateUnitTestSuite (&CpuExceptionLibUnitTestSuite, Framework,
"Test CpuExceptionHandlerLib",
"CpuExceptionHandlerLib.Manual",
NULL,
NULL);
839 if (EFI_ERROR (Status)) {
840 DEBUG ((DEBUG_ERROR,
"Failed in CreateUnitTestSuite for CpuExceptionHandlerLib Test Cases\n"));
841 Status = EFI_OUT_OF_RESOURCES;
VOID *EFIAPI GetNextHob(IN UINT16 Type, IN CONST VOID *HobStart)
VOID *EFIAPI GetHobList(VOID)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
EFI_STATUS MpServicesUnitTestWhoAmI(IN MP_SERVICES MpServices, OUT UINTN *ProcessorNumber)
VOID EFIAPI AdjustCpuContextHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID EFIAPI TriggerINTnException(IN EFI_EXCEPTION_TYPE ExceptionType)
VOID EFIAPI TriggerStackOverflow(VOID)
VOID EFIAPI AsmTestConsistencyOfCpuContext(IN EFI_EXCEPTION_TYPE ExceptionType, IN UINTN FaultParameter OPTIONAL)
EFI_STATUS MpServicesUnitTestStartupAllAPs(IN MP_SERVICES MpServices, IN EFI_AP_PROCEDURE Procedure, IN BOOLEAN SingleThread, IN UINTN TimeoutInMicroSeconds, IN VOID *ProcedureArgument)
EFI_STATUS GetMpServices(OUT MP_SERVICES *MpServices)
EFI_STATUS MpServicesUnitTestGetNumberOfProcessors(IN MP_SERVICES MpServices, OUT UINTN *NumberOfProcessors, OUT UINTN *NumberOfEnabledProcessors)
VOID EFIAPI AdjustRipForFaultHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID EFIAPI CpuStackGuardExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID EFIAPI TriggerPFException(UINTN PFAddress)
VOID EFIAPI TriggerGPException(UINTN Cr4ReservedBit)
UNIT_TEST_STATUS CompareCpuContext(VOID)
EFI_STATUS MpServicesUnitTestStartupThisAP(IN MP_SERVICES MpServices, IN EFI_AP_PROCEDURE Procedure, IN UINTN ProcessorNumber, IN UINTN TimeoutInMicroSeconds, IN VOID *ProcedureArgument)
VOID * InitializeBspIdt(VOID)
VOID EFIAPI SaveRegisterPerCpu(IN VOID *Buffer)
UINTN * GetAllCpuStackBase(MP_SERVICES *MpServices, UINTN BspProcessorNum)
VOID EFIAPI INTnExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
UNIT_TEST_STATUS EFIAPI TestRegisterHandlerForNoErrorCodeException(IN UNIT_TEST_CONTEXT Context)
VOID GetBspStackBase(OUT UINTN *StackBase)
VOID InitializeApIdt(MP_SERVICES MpServices, VOID *BspIdtr)
UNIT_TEST_STATUS EFIAPI TestCpuContextConsistency(IN UNIT_TEST_CONTEXT Context)
EXCEPTION_STACK_SWITCH_CONTEXT * InitializeMpExceptionStackSwitchHandlers(MP_SERVICES MpServices, UINTN BspProcessorNum)
VOID EFIAPI RestoreRegistersPerCpu(IN VOID *Buffer)
VOID EFIAPI InitializeExceptionStackSwitchHandlersPerAp(IN OUT VOID *Buffer)
EFI_STATUS AddCommonTestCase(IN UNIT_TEST_FRAMEWORK_HANDLE Framework)
BOOLEAN FindPFAddressInPageTable(OUT UINTN *PFAddress)
VOID EFIAPI InitializeIdtPerAp(IN VOID *Buffer)
VOID EFIAPI GetStackBasePerAp(OUT VOID *ApStackBase)
VOID RestoreAllCpuRegisters(MP_SERVICES *MpServices, OPTIONAL CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer, UINTN BspProcessorNum)
UNIT_TEST_STATUS EFIAPI TestRegisterHandlerForGPAndPF(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCpuStackGuardInBspAndAp(IN UNIT_TEST_CONTEXT Context)
CPU_REGISTER_BUFFER * SaveAllCpuRegisters(MP_SERVICES *MpServices, OPTIONAL UINTN BspProcessorNum)
RETURN_STATUS EFIAPI PageTableParse(IN UINTN PageTable, IN PAGING_MODE PagingMode, IN IA32_MAP_ENTRY *Map, IN OUT UINTN *MapCount)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
UINT16 EFIAPI AsmReadTr(VOID)
UINTN EFIAPI AsmReadCr3(VOID)
UINTN EFIAPI AsmReadCr0(VOID)
UINTN EFIAPI AsmReadCr4(VOID)
#define RETURN_BUFFER_TOO_SMALL
#define ALIGN_VALUE(Value, Alignment)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
#define PcdGet32(TokenName)
#define PcdGetBool(TokenName)
VOID(EFIAPI * EFI_AP_PROCEDURE)(IN OUT VOID *Buffer)
VOID *EFIAPI AllocatePages(IN UINTN Pages)
#define EFI_SIZE_TO_PAGES(Size)
#define UT_ASSERT_TRUE(Expression)
#define UT_ASSERT_EQUAL(ValueA, ValueB)
EFI_STATUS EFIAPI CreateUnitTestSuite(OUT UNIT_TEST_SUITE_HANDLE *SuiteHandle, IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle, IN CHAR8 *Title, IN CHAR8 *Name, IN UNIT_TEST_SUITE_SETUP Setup OPTIONAL, IN UNIT_TEST_SUITE_TEARDOWN Teardown OPTIONAL)
EFI_STATUS EFIAPI AddTestCase(IN UNIT_TEST_SUITE_HANDLE SuiteHandle, IN CHAR8 *Description, IN CHAR8 *Name, IN UNIT_TEST_FUNCTION Function, IN UNIT_TEST_PREREQUISITE Prerequisite OPTIONAL, IN UNIT_TEST_CLEANUP CleanUp OPTIONAL, IN UNIT_TEST_CONTEXT Context OPTIONAL)
VOID EFIAPI AsmReadGdtr(OUT IA32_DESCRIPTOR *Gdtr)
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
VOID EFIAPI AsmWriteTr(IN UINT16 Selector)
VOID EFIAPI AsmWriteGdtr(IN CONST IA32_DESCRIPTOR *Gdtr)
VOID EFIAPI AsmWriteIdtr(IN CONST IA32_DESCRIPTOR *Idtr)
EFI_PHYSICAL_ADDRESS MemoryBaseAddress
EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor