summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/CpuExceptionHandlerTest.h
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/CpuExceptionHandlerTest.h')
-rw-r--r--UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/CpuExceptionHandlerTest.h336
1 files changed, 336 insertions, 0 deletions
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/CpuExceptionHandlerTest.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/CpuExceptionHandlerTest.h
new file mode 100644
index 0000000000..936098fde8
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/CpuExceptionHandlerTest.h
@@ -0,0 +1,336 @@
+/** @file
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Four test cases are created in this Unit Test module.
+ a.Test if exception handler can be registered/unregistered for no error code exception
+ In this test case, only no error code exception is triggered and tested by INTn instruction.
+ The special hanlder for these exception will modify a global variable for check.
+
+ b.Test if exception handler can be registered/unregistered for GP and PF.
+ In this test case, GP exception is triggered and tested by setting CR4_RESERVED_BIT to 1.
+ PF exception is triggered and tested by writting to not-present or RO addres.
+ The special hanlder for these exceptions will set a global vartiable for check and adjust Rip to return from fault exception.
+
+ c.Test if Cpu Context is consistent before and after exception.
+ In this test case:
+ 1. Set Cpu register to mExpectedContextInHandler before exception.
+ 2. Trigger exception specified by ExceptionType.
+ 3. Store SystemContext in mActualContextInHandler and set SystemContext to mExpectedContextAfterException in handler.
+ 4. After return from exception, store Cpu registers in mActualContextAfterException.
+ The expectation is:
+ 1. Register values in mActualContextInHandler are the same with register values in mExpectedContextInHandler.
+ 2. Register values in mActualContextAfterException are the same with register values mActualContextAfterException.
+
+ d.Test if stack overflow can be captured by CpuStackGuard in both Bsp and AP.
+ In this test case, stack overflow is triggered by a funtion which calls itself continuously. This test case triggers stack
+ overflow in both BSP and AP. All AP use same Idt with Bsp. The expectation is:
+ 1. PF exception is triggered (leading to a DF if sepereated stack is not prepared for PF) when Rsp <= StackBase + SIZE_4KB
+ since [StackBase, StackBase + SIZE_4KB] is marked as not present in page table when PcdCpuStackGuard is TRUE.
+ 2. Stack for PF/DF exception handler in both Bsp and AP is succussfully switched by InitializeSeparateExceptionStacks.
+
+**/
+
+#ifndef CPU_EXCEPTION_HANDLER_TEST_H_
+#define CPU_EXCEPTION_HANDLER_TEST_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UnitTestHostBaseLib.h>
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/UefiLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/HobLib.h>
+#include <Library/CpuPageTableLib.h>
+#include <Guid/MemoryAllocationHob.h>
+#include <Protocol/MpService.h>
+#include <PiPei.h>
+#include <Ppi/MpServices2.h>
+
+#define UNIT_TEST_APP_NAME "Cpu Exception Handler Lib Unit Tests"
+#define UNIT_TEST_APP_VERSION "1.0"
+
+#define CPU_INTERRUPT_NUM 256
+#define SPEC_MAX_EXCEPTION_NUM 22
+#define CR4_RESERVED_BIT BIT15
+
+typedef struct {
+ IA32_DESCRIPTOR OriginalGdtr;
+ IA32_DESCRIPTOR OriginalIdtr;
+ UINT16 Tr;
+} CPU_REGISTER_BUFFER;
+
+typedef union {
+ EDKII_PEI_MP_SERVICES2_PPI *Ppi;
+ EFI_MP_SERVICES_PROTOCOL *Protocol;
+} MP_SERVICES;
+
+typedef struct {
+ VOID *Buffer;
+ UINTN BufferSize;
+ EFI_STATUS Status;
+} EXCEPTION_STACK_SWITCH_CONTEXT;
+
+typedef struct {
+ UINT64 Rdi;
+ UINT64 Rsi;
+ UINT64 Rbx;
+ UINT64 Rdx;
+ UINT64 Rcx;
+ UINT64 Rax;
+ UINT64 R8;
+ UINT64 R9;
+ UINT64 R10;
+ UINT64 R11;
+ UINT64 R12;
+ UINT64 R13;
+ UINT64 R14;
+ UINT64 R15;
+} GENERAL_REGISTER;
+
+extern UINTN mFaultInstructionLength;
+extern EFI_EXCEPTION_TYPE mExceptionType;
+extern UINTN mRspAddress[];
+
+/**
+ 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
+ );
+
+/**
+ Trigger no error code exception by INT n instruction.
+
+ @param[in] ExceptionType No error code exception type.
+**/
+VOID
+EFIAPI
+TriggerINTnException (
+ IN EFI_EXCEPTION_TYPE ExceptionType
+ );
+
+/**
+ Trigger GP exception by setting CR4_RESERVED_BIT to 1.
+
+ @param[in] Cr4ReservedBit Cr4 reserved bit.
+**/
+VOID
+EFIAPI
+TriggerGPException (
+ UINTN Cr4ReservedBit
+ );
+
+/**
+ Trigger PF exception by write to not present or ReadOnly address.
+
+ @param[in] PFAddress Not present or ReadOnly address in page table.
+**/
+VOID
+EFIAPI
+TriggerPFException (
+ UINTN PFAddress
+ );
+
+/**
+ Special handler for fault exception.
+ This handler sets Rip/Eip in SystemContext to the instruction address after the exception instruction.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+AdjustRipForFaultHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Test consistency of Cpu context. Four steps:
+ 1. Set Cpu register to mExpectedContextInHandler before exception.
+ 2. Trigger exception specified by ExceptionType.
+ 3. Store SystemContext in mActualContextInHandler and set SystemContext to mExpectedContextAfterException in handler.
+ 4. After return from exception, store Cpu registers in mActualContextAfterException.
+
+ Rcx/Ecx in mExpectedContextInHandler is decided by different exception type runtime since Rcx/Ecx is needed in assembly code.
+ For GP and PF, Rcx/Ecx is set to FaultParameter. For other exception triggered by INTn, Rcx/Ecx is set to ExceptionType.
+
+ @param[in] ExceptionType Exception type.
+ @param[in] FaultParameter Parameter for GP and PF. OPTIONAL
+**/
+VOID
+EFIAPI
+AsmTestConsistencyOfCpuContext (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN UINTN FaultParameter OPTIONAL
+ );
+
+/**
+ Special handler for ConsistencyOfCpuContext test case. General register in SystemContext
+ is modified to mExpectedContextInHandler in this handler.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+AdjustCpuContextHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Compare cpu context in ConsistencyOfCpuContext test case.
+ 1.Compare mActualContextInHandler with mExpectedContextInHandler.
+ 2.Compare mActualContextAfterException with mActualContextAfterException.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and it was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+CompareCpuContext (
+ VOID
+ );
+
+/**
+ Get EFI_MP_SERVICES_PROTOCOL/EDKII_PEI_MP_SERVICES2_PPI pointer.
+
+ @param[out] MpServices Pointer to the MP_SERVICES buffer
+
+ @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL/PPI interface is returned
+ @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL/PPI interface is not found
+**/
+EFI_STATUS
+GetMpServices (
+ OUT MP_SERVICES *MpServices
+ );
+
+/**
+ Create CpuExceptionLibUnitTestSuite and add test case.
+
+ @param[in] FrameworkHandle Unit test framework.
+
+ @return EFI_SUCCESS The unit test suite was created.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit test suite.
+**/
+EFI_STATUS
+AddCommonTestCase (
+ IN UNIT_TEST_FRAMEWORK_HANDLE Framework
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ Trigger stack overflow by calling itself continuously.
+**/
+VOID
+EFIAPI
+TriggerStackOverflow (
+ VOID
+ );
+
+/**
+ Special handler for CpuStackGuard test case.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+EFIAPI
+CpuStackGuardExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+#endif