UefiCpuPkg: Add Unit tests for PeiCpuExceptionHandlerLib
The previous change adds unit test for DxeCpuExeptionHandlerLib in 64bit mode. This change create a PEIM to add unit test for PeiCpuExceptionHandlerLib based on previous change.It can run in both 32bit and 64bit modes. Signed-off-by: Dun Tan <dun.tan@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com>
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
/** @file
|
||||
Unit tests of the CpuExceptionHandlerLib.
|
||||
|
||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "CpuExceptionHandlerTest.h"
|
||||
#include <Library/PeimEntryPoint.h>
|
||||
#include <Library/PeiServicesLib.h>
|
||||
#include <Library/PeiServicesTablePointerLib.h>
|
||||
|
||||
/**
|
||||
Initialize Bsp Idt with a new Idt table and return the IA32_DESCRIPTOR buffer.
|
||||
In PEIM, store original PeiServicePointer before new Idt table.
|
||||
|
||||
@return Pointer to the allocated IA32_DESCRIPTOR buffer.
|
||||
**/
|
||||
VOID *
|
||||
InitializeBspIdt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN *NewIdtTable;
|
||||
IA32_DESCRIPTOR *Idtr;
|
||||
|
||||
Idtr = AllocateZeroPool (sizeof (IA32_DESCRIPTOR));
|
||||
ASSERT (Idtr != NULL);
|
||||
NewIdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM + sizeof (UINTN));
|
||||
ASSERT (NewIdtTable != NULL);
|
||||
//
|
||||
// Store original PeiServicePointer before new Idt table
|
||||
//
|
||||
*NewIdtTable = (UINTN)GetPeiServicesTablePointer ();
|
||||
NewIdtTable = (UINTN *)((UINTN)NewIdtTable + sizeof (UINTN));
|
||||
|
||||
Idtr->Base = (UINTN)NewIdtTable;
|
||||
Idtr->Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);
|
||||
|
||||
AsmWriteIdtr (Idtr);
|
||||
return Idtr;
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieve the number of logical processor in the platform and the number of those logical processors that
|
||||
are enabled on this boot.
|
||||
|
||||
@param[in] MpServices MP_SERVICES structure.
|
||||
@param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
|
||||
the BSP and disabled APs.
|
||||
@param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
|
||||
|
||||
@retval EFI_SUCCESS Retrieve the number of logical processor successfully
|
||||
@retval Others Retrieve the number of logical processor unsuccessfully
|
||||
**/
|
||||
EFI_STATUS
|
||||
MpServicesUnitTestGetNumberOfProcessors (
|
||||
IN MP_SERVICES MpServices,
|
||||
OUT UINTN *NumberOfProcessors,
|
||||
OUT UINTN *NumberOfEnabledProcessors
|
||||
)
|
||||
{
|
||||
return MpServices.Ppi->GetNumberOfProcessors (MpServices.Ppi, NumberOfProcessors, NumberOfEnabledProcessors);
|
||||
}
|
||||
|
||||
/**
|
||||
Caller gets one enabled AP to execute a caller-provided function.
|
||||
|
||||
@param[in] MpServices MP_SERVICES structure.
|
||||
@param[in] Procedure Pointer to the function to be run on enabled APs of the system.
|
||||
@param[in] ProcessorNumber The handle number of the AP.
|
||||
@param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
|
||||
for blocking mode only. Zero means infinity.
|
||||
@param[in] ProcedureArgument The parameter passed into Procedure for all APs.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
|
||||
@retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
|
||||
**/
|
||||
EFI_STATUS
|
||||
MpServicesUnitTestStartupThisAP (
|
||||
IN MP_SERVICES MpServices,
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN UINTN ProcessorNumber,
|
||||
IN UINTN TimeoutInMicroSeconds,
|
||||
IN VOID *ProcedureArgument
|
||||
)
|
||||
{
|
||||
return MpServices.Ppi->StartupThisAP (MpServices.Ppi, Procedure, ProcessorNumber, TimeoutInMicroSeconds, ProcedureArgument);
|
||||
}
|
||||
|
||||
/**
|
||||
Execute a caller provided function on all enabled APs.
|
||||
|
||||
@param[in] MpServices MP_SERVICES structure.
|
||||
@param[in] Procedure Pointer to the function to be run on enabled APs of the system.
|
||||
@param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
|
||||
one by one, in ascending order of processor handle number.
|
||||
If FALSE, then all the enabled APs execute the function specified by Procedure
|
||||
simultaneously.
|
||||
@param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
|
||||
for blocking mode only. Zero means infinity.
|
||||
@param[in] ProcedureArgument The parameter passed into Procedure for all APs.
|
||||
|
||||
@retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
|
||||
@retval Others Execute a caller provided function on all enabled APs unsuccessfully
|
||||
**/
|
||||
EFI_STATUS
|
||||
MpServicesUnitTestStartupAllAPs (
|
||||
IN MP_SERVICES MpServices,
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN BOOLEAN SingleThread,
|
||||
IN UINTN TimeoutInMicroSeconds,
|
||||
IN VOID *ProcedureArgument
|
||||
)
|
||||
{
|
||||
return MpServices.Ppi->StartupAllAPs (MpServices.Ppi, Procedure, SingleThread, TimeoutInMicroSeconds, ProcedureArgument);
|
||||
}
|
||||
|
||||
/**
|
||||
Get the handle number for the calling processor.
|
||||
|
||||
@param[in] MpServices MP_SERVICES structure.
|
||||
@param[out] ProcessorNumber The handle number for the calling processor.
|
||||
|
||||
@retval EFI_SUCCESS Get the handle number for the calling processor successfully.
|
||||
@retval Others Get the handle number for the calling processor unsuccessfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
MpServicesUnitTestWhoAmI (
|
||||
IN MP_SERVICES MpServices,
|
||||
OUT UINTN *ProcessorNumber
|
||||
)
|
||||
{
|
||||
return MpServices.Ppi->WhoAmI (MpServices.Ppi, ProcessorNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
Get EDKII_PEI_MP_SERVICES2_PPI pointer.
|
||||
|
||||
@param[out] MpServices Pointer to the buffer where EDKII_PEI_MP_SERVICES2_PPI is stored
|
||||
|
||||
@retval EFI_SUCCESS EDKII_PEI_MP_SERVICES2_PPI interface is returned
|
||||
@retval EFI_NOT_FOUND EDKII_PEI_MP_SERVICES2_PPI interface is not found
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetMpServices (
|
||||
OUT MP_SERVICES *MpServices
|
||||
)
|
||||
{
|
||||
return PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOID **)&MpServices->Ppi);
|
||||
}
|
||||
|
||||
/**
|
||||
Entry point of CpuExceptionHandlerPeiTest PEIM.
|
||||
|
||||
@param[in] FileHandle Handle of the file being invoked.
|
||||
@param[in] PeiServices Describes the list of possible PEI Services.
|
||||
|
||||
@retval EFI_SUCCESS The PEIM executed normally.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiEntryPoint (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UNIT_TEST_FRAMEWORK_HANDLE Framework;
|
||||
|
||||
Framework = NULL;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
|
||||
|
||||
//
|
||||
// Start setting up the test framework for running the tests.
|
||||
//
|
||||
Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
Status = AddCommonTestCase (Framework);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status = %r\n", Status));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Execute the tests.
|
||||
//
|
||||
Status = RunAllTestSuites (Framework);
|
||||
|
||||
EXIT:
|
||||
if (Framework) {
|
||||
FreeUnitTestFramework (Framework);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
Reference in New Issue
Block a user