Add target based unit tests for the DxeCpuExceptionHandlerLib. A DXE driver is created to test DxeCpuExceptionHandlerLib. 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 the test case, only no error code exception is triggered and tested by INTn instruction. b.Test if exception handler can be registered/unregistered for GP and PF. In the test case, GP exception is triggered and tested by setting CR4_RESERVED_BIT to 1. PF exception is triggered by writting to not-present or RO address. c.Test if CpuContext 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. 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>
		
			
				
	
	
		
			167 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @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"
 | |
| 
 | |
| GENERAL_REGISTER  mActualContextInHandler;
 | |
| GENERAL_REGISTER  mActualContextAfterException;
 | |
| 
 | |
| //
 | |
| // In TestCpuContextConsistency, Cpu registers will be set to mExpectedContextInHandler/mExpectedContextAfterException.
 | |
| // Rcx in mExpectedContextInHandler is set runtime since Rcx is needed in assembly code.
 | |
| // For GP and PF, Rcx is set to FaultParameter. For other exception triggered by INTn, Rcx is set to ExceptionType.
 | |
| //
 | |
| GENERAL_REGISTER  mExpectedContextInHandler      = { 1, 2, 3, 4, 5, 0, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe };
 | |
| GENERAL_REGISTER  mExpectedContextAfterException = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e };
 | |
| 
 | |
| /**
 | |
|   Special handler for fault exception.
 | |
|   Rip/Eip in SystemContext will be modified to the instruction 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
 | |
|   )
 | |
| {
 | |
|   mExceptionType                       = ExceptionType;
 | |
|   SystemContext.SystemContextX64->Rip += mFaultInstructionLength;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Special handler for ConsistencyOfCpuContext test case.
 | |
| 
 | |
|   @param ExceptionType  Exception type.
 | |
|   @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| AdjustCpuContextHandler (
 | |
|   IN EFI_EXCEPTION_TYPE  ExceptionType,
 | |
|   IN EFI_SYSTEM_CONTEXT  SystemContext
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Store SystemContext in mActualContextInHandler.
 | |
|   //
 | |
|   mActualContextInHandler.Rdi = SystemContext.SystemContextX64->Rdi;
 | |
|   mActualContextInHandler.Rsi = SystemContext.SystemContextX64->Rsi;
 | |
|   mActualContextInHandler.Rbx = SystemContext.SystemContextX64->Rbx;
 | |
|   mActualContextInHandler.Rdx = SystemContext.SystemContextX64->Rdx;
 | |
|   mActualContextInHandler.Rcx = SystemContext.SystemContextX64->Rcx;
 | |
|   mActualContextInHandler.Rax = SystemContext.SystemContextX64->Rax;
 | |
|   mActualContextInHandler.R8  = SystemContext.SystemContextX64->R8;
 | |
|   mActualContextInHandler.R9  = SystemContext.SystemContextX64->R9;
 | |
|   mActualContextInHandler.R10 = SystemContext.SystemContextX64->R10;
 | |
|   mActualContextInHandler.R11 = SystemContext.SystemContextX64->R11;
 | |
|   mActualContextInHandler.R12 = SystemContext.SystemContextX64->R12;
 | |
|   mActualContextInHandler.R13 = SystemContext.SystemContextX64->R13;
 | |
|   mActualContextInHandler.R14 = SystemContext.SystemContextX64->R14;
 | |
|   mActualContextInHandler.R15 = SystemContext.SystemContextX64->R15;
 | |
| 
 | |
|   //
 | |
|   // Modify cpu context. These registers will be stored in mActualContextAfterException.
 | |
|   // Do not handle Rsp and Rbp. CpuExceptionHandlerLib doesn't set Rsp and Rbp register
 | |
|   // to the value in SystemContext.
 | |
|   //
 | |
|   SystemContext.SystemContextX64->Rdi = mExpectedContextAfterException.Rdi;
 | |
|   SystemContext.SystemContextX64->Rsi = mExpectedContextAfterException.Rsi;
 | |
|   SystemContext.SystemContextX64->Rbx = mExpectedContextAfterException.Rbx;
 | |
|   SystemContext.SystemContextX64->Rdx = mExpectedContextAfterException.Rdx;
 | |
|   SystemContext.SystemContextX64->Rcx = mExpectedContextAfterException.Rcx;
 | |
|   SystemContext.SystemContextX64->Rax = mExpectedContextAfterException.Rax;
 | |
|   SystemContext.SystemContextX64->R8  = mExpectedContextAfterException.R8;
 | |
|   SystemContext.SystemContextX64->R9  = mExpectedContextAfterException.R9;
 | |
|   SystemContext.SystemContextX64->R10 = mExpectedContextAfterException.R10;
 | |
|   SystemContext.SystemContextX64->R11 = mExpectedContextAfterException.R11;
 | |
|   SystemContext.SystemContextX64->R12 = mExpectedContextAfterException.R12;
 | |
|   SystemContext.SystemContextX64->R13 = mExpectedContextAfterException.R13;
 | |
|   SystemContext.SystemContextX64->R14 = mExpectedContextAfterException.R14;
 | |
|   SystemContext.SystemContextX64->R15 = mExpectedContextAfterException.R15;
 | |
| 
 | |
|   //
 | |
|   // When fault exception happens, eip/rip points to the faulting instruction.
 | |
|   // For now, olny GP and PF are tested in fault exception.
 | |
|   //
 | |
|   if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) || (ExceptionType == EXCEPT_IA32_GP_FAULT)) {
 | |
|     AdjustRipForFaultHandler (ExceptionType, 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
 | |
|   )
 | |
| {
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.Rdi, mExpectedContextInHandler.Rdi);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.Rsi, mExpectedContextInHandler.Rsi);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.Rbx, mExpectedContextInHandler.Rbx);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.Rdx, mExpectedContextInHandler.Rdx);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.Rcx, mExpectedContextInHandler.Rcx);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.Rax, mExpectedContextInHandler.Rax);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R8, mExpectedContextInHandler.R8);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R9, mExpectedContextInHandler.R9);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R10, mExpectedContextInHandler.R10);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R11, mExpectedContextInHandler.R11);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R12, mExpectedContextInHandler.R12);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R13, mExpectedContextInHandler.R13);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R14, mExpectedContextInHandler.R14);
 | |
|   UT_ASSERT_EQUAL (mActualContextInHandler.R15, mExpectedContextInHandler.R15);
 | |
| 
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.Rdi, mExpectedContextAfterException.Rdi);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.Rsi, mExpectedContextAfterException.Rsi);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.Rbx, mExpectedContextAfterException.Rbx);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.Rdx, mExpectedContextAfterException.Rdx);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.Rcx, mExpectedContextAfterException.Rcx);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.Rax, mExpectedContextAfterException.Rax);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R8, mExpectedContextAfterException.R8);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R9, mExpectedContextAfterException.R9);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R10, mExpectedContextAfterException.R10);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R11, mExpectedContextAfterException.R11);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R12, mExpectedContextAfterException.R12);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R13, mExpectedContextAfterException.R13);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R14, mExpectedContextAfterException.R14);
 | |
|   UT_ASSERT_EQUAL (mActualContextAfterException.R15, mExpectedContextAfterException.R15);
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   )
 | |
| {
 | |
|   UINTN  LocalVariable;
 | |
| 
 | |
|   AdjustRipForFaultHandler (ExceptionType, SystemContext);
 | |
|   mRspAddress[0] = (UINTN)SystemContext.SystemContextX64->Rsp;
 | |
|   mRspAddress[1] = (UINTN)(&LocalVariable);
 | |
| 
 | |
|   return;
 | |
| }
 |