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
|