audk/UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/X64/ArchExceptionHandlerTestAsm...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

257 lines
7.3 KiB
NASM
Raw Normal View History

UefiCpuPkg: Add Unit tests for DxeCpuExceptionHandlerLib 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>
2022-10-17 08:35:39 +02:00
;------------------------------------------------------------------------------
;
; 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