mirror of https://github.com/acidanthera/audk.git
346 lines
12 KiB
C
346 lines
12 KiB
C
/** @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;
|
|
|
|
typedef struct {
|
|
UINT32 Edi;
|
|
UINT32 Esi;
|
|
UINT32 Ebx;
|
|
UINT32 Edx;
|
|
UINT32 Ecx;
|
|
UINT32 Eax;
|
|
} GENERAL_REGISTER_IA32;
|
|
|
|
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
|