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>
		
			
				
	
	
		
			257 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;------------------------------------------------------------------------------
 | |
| ;
 | |
| ; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
 | |
| ; SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| ;
 | |
| ; Module Name:
 | |
| ;
 | |
| ;   ArchExceptionHandlerTestAsm.nasm
 | |
| ;
 | |
| ; Abstract:
 | |
| ;
 | |
| ;   x64 CPU Exception Handler Lib Unit test
 | |
| ;
 | |
| ;------------------------------------------------------------------------------
 | |
| 
 | |
|     DEFAULT REL
 | |
|     SECTION .text
 | |
| 
 | |
| struc GENERAL_REGISTER
 | |
|   .Rdi:    resq    1
 | |
|   .Rsi:    resq    1
 | |
|   .Rbx:    resq    1
 | |
|   .Rdx:    resq    1
 | |
|   .Rcx:    resq    1
 | |
|   .Rax:    resq    1
 | |
|   .R8:     resq    1
 | |
|   .R9:     resq    1
 | |
|   .R10:    resq    1
 | |
|   .R11:    resq    1
 | |
|   .R12:    resq    1
 | |
|   .R13:    resq    1
 | |
|   .R14:    resq    1
 | |
|   .R15:    resq    1
 | |
| 
 | |
| endstruc
 | |
| 
 | |
| extern ASM_PFX(mExpectedContextInHandler)
 | |
| extern ASM_PFX(mActualContextAfterException)
 | |
| extern ASM_PFX(mFaultInstructionLength)
 | |
| 
 | |
| ;------------------------------------------------------------------------------
 | |
| ; VOID
 | |
| ; EFIAPI
 | |
| ; TriggerGPException (
 | |
| ;  UINTN  Cr4ReservedBit
 | |
| ;  );
 | |
| ;------------------------------------------------------------------------------
 | |
| global ASM_PFX(TriggerGPException)
 | |
| ASM_PFX(TriggerGPException):
 | |
|     ;
 | |
|     ; Set reserved bit 15 of cr4 to 1
 | |
|     ;
 | |
|     push rcx
 | |
|     lea  rcx, [ASM_PFX(mFaultInstructionLength)]
 | |
|     mov  qword[rcx], TriggerGPExceptionAfter - TriggerGPExceptionBefore
 | |
|     pop  rcx
 | |
| TriggerGPExceptionBefore:
 | |
|     mov  cr4, rcx
 | |
| TriggerGPExceptionAfter:
 | |
|     ret
 | |
| 
 | |
| ;------------------------------------------------------------------------------
 | |
| ; VOID
 | |
| ; EFIAPI
 | |
| ; TriggerPFException (
 | |
| ;  UINTN  PFAddress
 | |
| ;  );
 | |
| ;------------------------------------------------------------------------------
 | |
| global ASM_PFX(TriggerPFException)
 | |
| ASM_PFX(TriggerPFException):
 | |
|     push rcx
 | |
|     lea  rcx, [ASM_PFX(mFaultInstructionLength)]
 | |
|     mov  qword[rcx], TriggerPFExceptionAfter - TriggerPFExceptionBefore
 | |
|     pop  rcx
 | |
| TriggerPFExceptionBefore:
 | |
|     mov  qword[rcx], 0x1
 | |
| TriggerPFExceptionAfter:
 | |
|     ret
 | |
| 
 | |
| ;------------------------------------------------------------------------------
 | |
| ; ModifyRcxInGlobalBeforeException;
 | |
| ; This function is writed by assebly code because it's only called in this file.
 | |
| ; It's used to set Rcx in mExpectedContextInHandler for different exception.
 | |
| ;------------------------------------------------------------------------------
 | |
| global ASM_PFX(ModifyRcxInGlobalBeforeException)
 | |
| ASM_PFX(ModifyRcxInGlobalBeforeException):
 | |
|     push rax
 | |
|     lea  rax, [ASM_PFX(mExpectedContextInHandler)]
 | |
|     mov  [rax + GENERAL_REGISTER.Rcx], rcx
 | |
|     pop  rax
 | |
|     ret
 | |
| 
 | |
| ;------------------------------------------------------------------------------
 | |
| ;VOID
 | |
| ;EFIAPI
 | |
| ;AsmTestConsistencyOfCpuContext (
 | |
| ;  IN  EFI_EXCEPTION_TYPE ExceptionType
 | |
| ;  IN  UINTN              FaultParameter   OPTIONAL
 | |
| ;  );
 | |
| ;------------------------------------------------------------------------------
 | |
| global ASM_PFX(AsmTestConsistencyOfCpuContext)
 | |
| ASM_PFX(AsmTestConsistencyOfCpuContext):
 | |
|     ;
 | |
|     ; Push original register
 | |
|     ;
 | |
|     push r15
 | |
|     push r14
 | |
|     push r13
 | |
|     push r12
 | |
|     push r11
 | |
|     push r10
 | |
|     push r9
 | |
|     push r8
 | |
|     push rax
 | |
|     push rcx
 | |
|     push rbx
 | |
|     push rsi
 | |
|     push rdi
 | |
|     push rdx
 | |
|     push rdx
 | |
| 
 | |
|     ;
 | |
|     ; Modify registers to mExpectedContextInHandler. Do not handle Rsp and Rbp.
 | |
|     ; CpuExceptionHandlerLib doesn't set Rsp and Rsp register to the value in SystemContext.
 | |
|     ;
 | |
|     lea r15, [ASM_PFX(mExpectedContextInHandler)]
 | |
|     mov rdi, [r15 + GENERAL_REGISTER.Rdi]
 | |
|     mov rsi, [r15 + GENERAL_REGISTER.Rsi]
 | |
|     mov rbx, [r15 + GENERAL_REGISTER.Rbx]
 | |
|     mov rdx, [r15 + GENERAL_REGISTER.Rdx]
 | |
|     mov rax, [r15 + GENERAL_REGISTER.Rax]
 | |
|     mov r8,  [r15 + GENERAL_REGISTER.R8]
 | |
|     mov r9,  [r15 + GENERAL_REGISTER.R9]
 | |
|     mov r10, [r15 + GENERAL_REGISTER.R10]
 | |
|     mov r11, [r15 + GENERAL_REGISTER.R11]
 | |
|     mov r12, [r15 + GENERAL_REGISTER.R12]
 | |
|     mov r13, [r15 + GENERAL_REGISTER.R13]
 | |
|     mov r14, [r15 + GENERAL_REGISTER.R14]
 | |
|     mov r15, [r15 + GENERAL_REGISTER.R15]
 | |
| 
 | |
|     cmp  rcx, 0xd
 | |
|     jz   GPException
 | |
|     cmp  rcx, 0xe
 | |
|     jz   PFException
 | |
|     jmp  INTnException
 | |
| 
 | |
| PFException:
 | |
|     pop  rcx                                       ; Pop rdx(PFAddress) to rcx.
 | |
|     call ASM_PFX(ModifyRcxInGlobalBeforeException) ; Set mExpectedContextInHandler.Rcx to PFAddress.
 | |
|     call ASM_PFX(TriggerPFException)
 | |
|     jmp  AfterException
 | |
| 
 | |
| GPException:
 | |
|     pop  rcx                                       ; Pop rdx(Cr4ReservedBit) to rcx.
 | |
|     call ASM_PFX(ModifyRcxInGlobalBeforeException) ; Set mExpectedContextInHandler.Rcx to Cr4ReservedBit.
 | |
|     call ASM_PFX(TriggerGPException)
 | |
|     jmp  AfterException
 | |
| 
 | |
| INTnException:
 | |
|     ;
 | |
|     ; Modify Rcx in mExpectedContextInHandler.
 | |
|     ;
 | |
|     add  Rsp, 8                                    ; Discard the extra Rdx in stack. Rcx is ExceptionType now.
 | |
|     call ASM_PFX(ModifyRcxInGlobalBeforeException) ; Set mExpectedContextInHandler.Rcx to ExceptionType.
 | |
|     call ASM_PFX(TriggerINTnException)
 | |
| 
 | |
| AfterException:
 | |
|     ;
 | |
|     ; Save registers in mActualContextAfterException
 | |
|     ;
 | |
|     push rax
 | |
|     lea  rax, [ASM_PFX(mActualContextAfterException)]
 | |
|     mov  [rax + GENERAL_REGISTER.Rdi], rdi
 | |
|     mov  [rax + GENERAL_REGISTER.Rsi], rsi
 | |
|     mov  [rax + GENERAL_REGISTER.Rbx], rbx
 | |
|     mov  [rax + GENERAL_REGISTER.Rdx], rdx
 | |
|     mov  [rax + GENERAL_REGISTER.Rcx], rcx
 | |
|     pop  rcx
 | |
|     mov  [rax + GENERAL_REGISTER.Rax], rcx
 | |
|     mov  [rax + GENERAL_REGISTER.R8],  r8
 | |
|     mov  [rax + GENERAL_REGISTER.R9],  r9
 | |
|     mov  [rax + GENERAL_REGISTER.R10], r10
 | |
|     mov  [rax + GENERAL_REGISTER.R11], r11
 | |
|     mov  [rax + GENERAL_REGISTER.R12], r12
 | |
|     mov  [rax + GENERAL_REGISTER.R13], r13
 | |
|     mov  [rax + GENERAL_REGISTER.R14], r14
 | |
|     mov  [rax + GENERAL_REGISTER.R15], r15
 | |
| 
 | |
|     ;
 | |
|     ; restore original register
 | |
|     ;
 | |
|     pop rdx
 | |
|     pop rdi
 | |
|     pop rsi
 | |
|     pop rbx
 | |
|     pop rcx
 | |
|     pop rax
 | |
|     pop r8
 | |
|     pop r9
 | |
|     pop r10
 | |
|     pop r11
 | |
|     pop r12
 | |
|     pop r13
 | |
|     pop r14
 | |
|     pop r15
 | |
| 
 | |
|     ret
 | |
| 
 | |
| ;------------------------------------------------------------------------------
 | |
| ; VOID
 | |
| ; EFIAPI
 | |
| ; TriggerStackOverflow (
 | |
| ;  VOID
 | |
| ;  );
 | |
| ;------------------------------------------------------------------------------
 | |
| global ASM_PFX(TriggerStackOverflow)
 | |
| ASM_PFX(TriggerStackOverflow):
 | |
|     push rcx
 | |
|     lea  rcx, [ASM_PFX(mFaultInstructionLength)]
 | |
|     mov  qword[rcx], TriggerCpuStackGuardAfter - TriggerCpuStackGuardBefore
 | |
|     pop  rcx
 | |
| TriggerCpuStackGuardBefore:
 | |
|     call TriggerCpuStackGuardBefore
 | |
| TriggerCpuStackGuardAfter:
 | |
|     ret
 | |
| 
 | |
| ;------------------------------------------------------------------------------
 | |
| ; VOID
 | |
| ; EFIAPI
 | |
| ; TriggerINTnException (
 | |
| ;  IN  EFI_EXCEPTION_TYPE ExceptionType
 | |
| ;  );
 | |
| ;------------------------------------------------------------------------------
 | |
| global ASM_PFX(TriggerINTnException)
 | |
| ASM_PFX(TriggerINTnException):
 | |
|     push rax
 | |
|     push rdx
 | |
|     push rcx
 | |
|     lea  rax, [AsmTriggerException1 - AsmTriggerException0]
 | |
|     mul  rcx
 | |
|     mov  rcx, AsmTriggerException0
 | |
|     add  rax, rcx
 | |
|     pop  rcx
 | |
|     pop  rdx
 | |
|     jmp  rax
 | |
|     ;
 | |
|     ; rax = AsmTriggerException0 + (AsmTriggerException1 - AsmTriggerException0) * rcx
 | |
|     ;
 | |
| %assign Vector 0
 | |
| %rep  22
 | |
| AsmTriggerException %+ Vector:
 | |
|     pop rax
 | |
|     INT Vector
 | |
|     ret
 | |
| %assign Vector Vector+1
 | |
| %endrep
 |