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