--- /dev/null
+/** @file\r
+ Unit tests of the CpuExceptionHandlerLib.\r
+\r
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "CpuExceptionHandlerTest.h"\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+/**\r
+ Initialize Bsp Idt with a new Idt table and return the IA32_DESCRIPTOR buffer.\r
+ In PEIM, store original PeiServicePointer before new Idt table.\r
+\r
+ @return Pointer to the allocated IA32_DESCRIPTOR buffer.\r
+**/\r
+VOID *\r
+InitializeBspIdt (\r
+ VOID\r
+ )\r
+{\r
+ UINTN *NewIdtTable;\r
+ IA32_DESCRIPTOR *Idtr;\r
+\r
+ Idtr = AllocateZeroPool (sizeof (IA32_DESCRIPTOR));\r
+ ASSERT (Idtr != NULL);\r
+ NewIdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM);\r
+ ASSERT (NewIdtTable != NULL);\r
+ Idtr->Base = (UINTN)NewIdtTable;\r
+ Idtr->Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);\r
+\r
+ AsmWriteIdtr (Idtr);\r
+ return Idtr;\r
+}\r
+\r
+/**\r
+ Retrieve the number of logical processor in the platform and the number of those logical processors that\r
+ are enabled on this boot.\r
+\r
+ @param[in] MpServices MP_SERVICES structure.\r
+ @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including\r
+ the BSP and disabled APs.\r
+ @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.\r
+\r
+ @retval EFI_SUCCESS Retrieve the number of logical processor successfully\r
+ @retval Others Retrieve the number of logical processor unsuccessfully\r
+**/\r
+EFI_STATUS\r
+MpServicesUnitTestGetNumberOfProcessors (\r
+ IN MP_SERVICES MpServices,\r
+ OUT UINTN *NumberOfProcessors,\r
+ OUT UINTN *NumberOfEnabledProcessors\r
+ )\r
+{\r
+ return MpServices.Protocol->GetNumberOfProcessors (MpServices.Protocol, NumberOfProcessors, NumberOfEnabledProcessors);\r
+}\r
+\r
+/**\r
+ Get the handle number for the calling processor.\r
+\r
+ @param[in] MpServices MP_SERVICES structure.\r
+ @param[out] ProcessorNumber The handle number for the calling processor.\r
+\r
+ @retval EFI_SUCCESS Get the handle number for the calling processor successfully.\r
+ @retval Others Get the handle number for the calling processor unsuccessfully.\r
+**/\r
+EFI_STATUS\r
+MpServicesUnitTestWhoAmI (\r
+ IN MP_SERVICES MpServices,\r
+ OUT UINTN *ProcessorNumber\r
+ )\r
+{\r
+ return MpServices.Protocol->WhoAmI (MpServices.Protocol, ProcessorNumber);\r
+}\r
+\r
+/**\r
+ Caller gets one enabled AP to execute a caller-provided function.\r
+\r
+ @param[in] MpServices MP_SERVICES structure.\r
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.\r
+ @param[in] ProcessorNumber The handle number of the AP.\r
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,\r
+ for blocking mode only. Zero means infinity.\r
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.\r
+\r
+\r
+ @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully\r
+ @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully\r
+**/\r
+EFI_STATUS\r
+MpServicesUnitTestStartupThisAP (\r
+ IN MP_SERVICES MpServices,\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN UINTN ProcessorNumber,\r
+ IN UINTN TimeoutInMicroSeconds,\r
+ IN VOID *ProcedureArgument\r
+ )\r
+{\r
+ return MpServices.Protocol->StartupThisAP (MpServices.Protocol, Procedure, ProcessorNumber, NULL, TimeoutInMicroSeconds, ProcedureArgument, NULL);\r
+}\r
+\r
+/**\r
+ Execute a caller provided function on all enabled APs.\r
+\r
+ @param[in] MpServices MP_SERVICES structure.\r
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.\r
+ @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure\r
+ one by one, in ascending order of processor handle number.\r
+ If FALSE, then all the enabled APs execute the function specified by Procedure\r
+ simultaneously.\r
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,\r
+ for blocking mode only. Zero means infinity.\r
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.\r
+\r
+ @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully\r
+ @retval Others Execute a caller provided function on all enabled APs unsuccessfully\r
+**/\r
+EFI_STATUS\r
+MpServicesUnitTestStartupAllAPs (\r
+ IN MP_SERVICES MpServices,\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN BOOLEAN SingleThread,\r
+ IN UINTN TimeoutInMicroSeconds,\r
+ IN VOID *ProcedureArgument\r
+ )\r
+{\r
+ return MpServices.Protocol->StartupAllAPs (MpServices.Protocol, Procedure, SingleThread, NULL, TimeoutInMicroSeconds, ProcedureArgument, NULL);\r
+}\r
+\r
+/**\r
+ Get EFI_MP_SERVICES_PROTOCOL pointer.\r
+\r
+ @param[out] MpServices Pointer to the buffer where EFI_MP_SERVICES_PROTOCOL is stored\r
+\r
+ @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL interface is returned\r
+ @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL interface is not found\r
+**/\r
+EFI_STATUS\r
+GetMpServices (\r
+ OUT MP_SERVICES *MpServices\r
+ )\r
+{\r
+ return gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices->Protocol);\r
+}\r
+\r
+/**\r
+ Entry for CpuExceptionHandlerDxeTest driver.\r
+\r
+ @param ImageHandle Image handle this driver.\r
+ @param SystemTable Pointer to the System Table.\r
+\r
+ @retval EFI_SUCCESS The driver executed normally.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuExceptionHandlerTestEntry (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;\r
+\r
+ Framework = NULL;\r
+\r
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));\r
+\r
+ //\r
+ // Start setting up the test framework for running the tests.\r
+ //\r
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));\r
+ goto EXIT;\r
+ }\r
+\r
+ Status = AddCommonTestCase (Framework);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status = %r\n", Status));\r
+ goto EXIT;\r
+ }\r
+\r
+ //\r
+ // Execute the tests.\r
+ //\r
+ Status = RunAllTestSuites (Framework);\r
+\r
+EXIT:\r
+ if (Framework) {\r
+ FreeUnitTestFramework (Framework);\r
+ }\r
+\r
+ return Status;\r
+}\r