From 8f07f895fb03800e54c23225639116f34d2ce7b1 Mon Sep 17 00:00:00 2001 From: vanjeff Date: Thu, 15 Mar 2012 05:24:07 +0000 Subject: Import two CPU Exception Handler Library instances: SecPeiCpuExceptionHandler.inf and DxeSmmCpuExceptionHandler.inf. Signed-off-by: vanjeff Reviewed-by: jyao1 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13098 6f19259b-4bc3-4df7-8a09-765794883524 --- .../X64/ArchExceptionHandler.c | 192 ++++++++++ .../X64/ExceptionHandlerAsm.S | 406 ++++++++++++++++++++ .../X64/ExceptionHandlerAsm.asm | 407 +++++++++++++++++++++ 3 files changed, 1005 insertions(+) create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm (limited to 'UefiCpuPkg/Library/CpuExceptionHandlerLib/X64') diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c new file mode 100644 index 0000000000..664472a667 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -0,0 +1,192 @@ +/** @file + x64 CPU Exception Hanlder. + + Copyright (c) 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "CpuExceptionCommon.h" + +/** + Internal function to setup CPU exception handlers. + +**/ +VOID +InternalSetupCpuExceptionHandlers ( + VOID + ) +{ + IA32_DESCRIPTOR IdtDescriptor; + UINTN IdtSize; + EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap; + UINT16 CodeSegment; + IA32_IDT_GATE_DESCRIPTOR *IdtEntry; + UINTN Index; + UINTN InterruptHandler; + + // + // Read IDT descriptor and calculate IDT size + // + AsmReadIdtr (&IdtDescriptor); + IdtSize = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); + if (IdtSize > CPU_EXCEPTION_NUM) { + // + // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most + // + IdtSize = CPU_EXCEPTION_NUM; + } + + // + // Use current CS as the segment selector of interrupt gate in IDT + // + CodeSegment = AsmReadCs (); + IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; + + GetTemplateAddressMap (&TemplateMap); + + for (Index = 0; Index < IdtSize; Index ++) { + InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize; + IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; + IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); + IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32); + IdtEntry[Index].Bits.Selector = CodeSegment; + IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; + } +} + +/** + Common exception handler. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +VOID +DumpCpuContent ( + IN UINTN ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINTN ImageBase; + UINTN EntryPoint; + + InternalPrintMessage ( + "!!!! X64 Exception Type - %016lx CPU Apic ID - %08x !!!!\n", + ExceptionType, + GetApicId () + ); + InternalPrintMessage ( + "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n", + SystemContext.SystemContextX64->Rip, + SystemContext.SystemContextX64->Cs, + SystemContext.SystemContextX64->Rflags + ); + if (mErrorCodeFlag & (1 << ExceptionType)) { + InternalPrintMessage ( + "ExceptionData - %016lx\n", + SystemContext.SystemContextX64->ExceptionData + ); + } + InternalPrintMessage ( + "RAX - %016lx, RCX - %016lx, RDX - %016lx\n", + SystemContext.SystemContextX64->Rax, + SystemContext.SystemContextX64->Rcx, + SystemContext.SystemContextX64->Rdx + ); + InternalPrintMessage ( + "RBX - %016lx, RSP - %016lx, RBP - %016lx\n", + SystemContext.SystemContextX64->Rbx, + SystemContext.SystemContextX64->Rsp, + SystemContext.SystemContextX64->Rbp + ); + InternalPrintMessage ( + "RSI - %016lx, RDI - %016lx\n", + SystemContext.SystemContextX64->Rsi, + SystemContext.SystemContextX64->Rdi + ); + InternalPrintMessage ( + "R8 - %016lx, R9 - %016lx, R10 - %016lx\n", + SystemContext.SystemContextX64->R8, + SystemContext.SystemContextX64->R9, + SystemContext.SystemContextX64->R10 + ); + InternalPrintMessage ( + "R11 - %016lx, R12 - %016lx, R13 - %016lx\n", + SystemContext.SystemContextX64->R11, + SystemContext.SystemContextX64->R12, + SystemContext.SystemContextX64->R13 + ); + InternalPrintMessage ( + "R14 - %016lx, R15 - %016lx\n", + SystemContext.SystemContextX64->R14, + SystemContext.SystemContextX64->R15 + ); + InternalPrintMessage ( + "DS - %016lx, ES - %016lx, FS - %016lx\n", + SystemContext.SystemContextX64->Ds, + SystemContext.SystemContextX64->Es, + SystemContext.SystemContextX64->Fs + ); + InternalPrintMessage ( + "GS - %016lx, SS - %016lx\n", + SystemContext.SystemContextX64->Gs, + SystemContext.SystemContextX64->Ss + ); + InternalPrintMessage ( + "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n", + SystemContext.SystemContextX64->Cr0, + SystemContext.SystemContextX64->Cr2, + SystemContext.SystemContextX64->Cr3 + ); + InternalPrintMessage ( + "CR4 - %016lx, CR8 - %016lx\n", + SystemContext.SystemContextX64->Cr4, + SystemContext.SystemContextX64->Cr8 + ); + InternalPrintMessage ( + "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n", + SystemContext.SystemContextX64->Dr0, + SystemContext.SystemContextX64->Dr1, + SystemContext.SystemContextX64->Dr2 + ); + InternalPrintMessage ( + "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n", + SystemContext.SystemContextX64->Dr3, + SystemContext.SystemContextX64->Dr6, + SystemContext.SystemContextX64->Dr7 + ); + InternalPrintMessage ( + "GDTR - %016lx %016lx, LDTR - %016lx\n", + SystemContext.SystemContextX64->Gdtr[0], + SystemContext.SystemContextX64->Gdtr[1], + SystemContext.SystemContextX64->Ldtr + ); + InternalPrintMessage ( + "IDTR - %016lx %016lx, TR - %016lx\n", + SystemContext.SystemContextX64->Idtr[0], + SystemContext.SystemContextX64->Idtr[1], + SystemContext.SystemContextX64->Tr + ); + InternalPrintMessage ( + "FXSAVE_STATE - %016lx\n", + &SystemContext.SystemContextX64->FxSaveState + ); + + // + // Find module image base and module entry point by RIP + // + ImageBase = FindModuleImageBase (SystemContext.SystemContextX64->Rip, &EntryPoint); + if (ImageBase != 0) { + InternalPrintMessage ( + " (ImageBase=%016lx, EntryPoint=%016lx) !!!!\n", + ImageBase, + EntryPoint + ); + } +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S new file mode 100644 index 0000000000..cd101475a7 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S @@ -0,0 +1,406 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2012, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ExceptionHandlerAsm.S +# +# Abstract: +# +# x64 CPU Exception Handler +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions + +ASM_GLOBAL ASM_PFX(CommonExceptionHandler) +ASM_GLOBAL ASM_PFX(CommonInterruptEntry) + + +.text + +# +# point to the external interrupt vector table +# +Exception0Handle: + pushq $0 + jmp ASM_PFX(CommonInterruptEntry) +Exception1Handle: + pushq $1 + jmp ASM_PFX(CommonInterruptEntry) +Exception2Handle: + pushq $2 + jmp ASM_PFX(CommonInterruptEntry) +Exception3Handle: + pushq $3 + jmp ASM_PFX(CommonInterruptEntry) +Exception4Handle: + pushq $4 + jmp ASM_PFX(CommonInterruptEntry) +Exception5Handle: + pushq $5 + jmp ASM_PFX(CommonInterruptEntry) +Exception6Handle: + pushq $6 + jmp ASM_PFX(CommonInterruptEntry) +Exception7Handle: + pushq $7 + jmp ASM_PFX(CommonInterruptEntry) +Exception8Handle: + pushq $8 + jmp ASM_PFX(CommonInterruptEntry) +Exception9Handle: + pushq $9 + jmp ASM_PFX(CommonInterruptEntry) +Exception10Handle: + pushq $10 + jmp ASM_PFX(CommonInterruptEntry) +Exception11Handle: + pushq $11 + jmp ASM_PFX(CommonInterruptEntry) +Exception12Handle: + pushq $12 + jmp ASM_PFX(CommonInterruptEntry) +Exception13Handle: + pushq $13 + jmp ASM_PFX(CommonInterruptEntry) +Exception14Handle: + pushq $14 + jmp ASM_PFX(CommonInterruptEntry) +Exception15Handle: + pushq $15 + jmp ASM_PFX(CommonInterruptEntry) +Exception16Handle: + pushq $16 + jmp ASM_PFX(CommonInterruptEntry) +Exception17Handle: + pushq $17 + jmp ASM_PFX(CommonInterruptEntry) +Exception18Handle: + pushq $18 + jmp ASM_PFX(CommonInterruptEntry) +Exception19Handle: + pushq $19 + jmp ASM_PFX(CommonInterruptEntry) +Exception20Handle: + pushq $20 + jmp ASM_PFX(CommonInterruptEntry) +Exception21Handle: + pushq $21 + jmp ASM_PFX(CommonInterruptEntry) +Exception22Handle: + pushq $22 + jmp ASM_PFX(CommonInterruptEntry) +Exception23Handle: + pushq $23 + jmp ASM_PFX(CommonInterruptEntry) +Exception24Handle: + pushq $24 + jmp ASM_PFX(CommonInterruptEntry) +Exception25Handle: + pushq $25 + jmp ASM_PFX(CommonInterruptEntry) +Exception26Handle: + pushq $26 + jmp ASM_PFX(CommonInterruptEntry) +Exception27Handle: + pushq $27 + jmp ASM_PFX(CommonInterruptEntry) +Exception28Handle: + pushq $28 + jmp ASM_PFX(CommonInterruptEntry) +Exception29Handle: + pushq $29 + jmp ASM_PFX(CommonInterruptEntry) +Exception30Handle: + pushq $30 + jmp ASM_PFX(CommonInterruptEntry) +Exception31Handle: + pushq $31 + jmp ASM_PFX(CommonInterruptEntry) + + +#---------------------------------------; +# CommonInterruptEntry ; +#---------------------------------------; +# The follow algorithm is used for the common interrupt routine. + +ASM_GLOBAL ASM_PFX(CommonInterruptEntry) +ASM_PFX(CommonInterruptEntry): + cli + # + # All interrupt handlers are invoked through interrupt gates, so + # IF flag automatically cleared at the entry point + # + # + # Calculate vector number + # + xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number. + cmp $32, %ecx # Intel reserved vector for exceptions? + jae NoErrorCode + pushq %rax + leaq ASM_PFX(mErrorCodeFlag)(%rip), %rax + bt %ecx, (%rax) + popq %rax + jc CommonInterruptEntry_al_0000 + +NoErrorCode: + + # + # Push a dummy error code on the stack + # to maintain coherent stack map + # + pushq (%rsp) + movq $0, 8(%rsp) +CommonInterruptEntry_al_0000: + pushq %rbp + movq %rsp, %rbp + + # + # Stack: + # +---------------------+ <-- 16-byte aligned ensured by processor + # + Old SS + + # +---------------------+ + # + Old RSP + + # +---------------------+ + # + RFlags + + # +---------------------+ + # + CS + + # +---------------------+ + # + RIP + + # +---------------------+ + # + Error Code + + # +---------------------+ + # + RCX / Vector Number + + # +---------------------+ + # + RBP + + # +---------------------+ <-- RBP, 16-byte aligned + # + + + # + # Since here the stack pointer is 16-byte aligned, so + # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64 + # is 16-byte aligned + # + +#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; +#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + pushq %r9 + pushq %r8 + pushq %rax + pushq 8(%rbp) # RCX + pushq %rdx + pushq %rbx + pushq 48(%rbp) # RSP + pushq (%rbp) # RBP + pushq %rsi + pushq %rdi + +#; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero + movzwq 56(%rbp), %rax + pushq %rax # for ss + movzwq 32(%rbp), %rax + pushq %rax # for cs + movl %ds, %eax + pushq %rax + movl %es, %eax + pushq %rax + movl %fs, %eax + pushq %rax + movl %gs, %eax + pushq %rax + + movq %rcx, 8(%rbp) # save vector number + +#; UINT64 Rip; + pushq 24(%rbp) + +#; UINT64 Gdtr[2], Idtr[2]; + xorq %rax, %rax + pushq %rax + pushq %rax + sidt (%rsp) + xchgq 2(%rsp), %rax + xchgq (%rsp), %rax + xchgq 8(%rsp), %rax + + xorq %rax, %rax + pushq %rax + pushq %rax + sgdt (%rsp) + xchgq 2(%rsp), %rax + xchgq (%rsp), %rax + xchgq 8(%rsp), %rax + +#; UINT64 Ldtr, Tr; + xorq %rax, %rax + str %ax + pushq %rax + sldt %ax + pushq %rax + +#; UINT64 RFlags; + pushq 40(%rbp) + +#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; + movq %cr8, %rax + pushq %rax + movq %cr4, %rax + orq $0x208, %rax + movq %rax, %cr4 + pushq %rax + mov %cr3, %rax + pushq %rax + mov %cr2, %rax + pushq %rax + xorq %rax, %rax + pushq %rax + mov %cr0, %rax + pushq %rax + +#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + movq %dr7, %rax + pushq %rax + movq %dr6, %rax + pushq %rax + movq %dr3, %rax + pushq %rax + movq %dr2, %rax + pushq %rax + movq %dr1, %rax + pushq %rax + movq %dr0, %rax + pushq %rax + +#; FX_SAVE_STATE_X64 FxSaveState; + subq $512, %rsp + movq %rsp, %rdi + .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi] + +#; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear + cld + +#; UINT32 ExceptionData; + pushq 16(%rbp) + +#; Prepare parameter and call + mov 8(%rbp), %rcx + mov %rsp, %rdx + # + # Per X64 calling convention, allocate maximum parameter stack space + # and make sure RSP is 16-byte aligned + # + subq $40, %rsp + call ASM_PFX(CommonExceptionHandler) + addq $40, %rsp + + cli +#; UINT64 ExceptionData; + addq $8, %rsp + +#; FX_SAVE_STATE_X64 FxSaveState; + + movq %rsp, %rsi + .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi] + addq $512, %rsp + +#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; +#; Skip restoration of DRx registers to support in-circuit emualators +#; or debuggers set breakpoint in interrupt/exception context + addq $48, %rsp + +#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; + popq %rax + movq %rax, %cr0 + addq $8, %rsp # not for Cr1 + popq %rax + movq %rax, %cr2 + popq %rax + movq %rax, %cr3 + popq %rax + movq %rax, %cr4 + popq %rax + movq %rax, %cr8 + +#; UINT64 RFlags; + popq 40(%rbp) + +#; UINT64 Ldtr, Tr; +#; UINT64 Gdtr[2], Idtr[2]; +#; Best not let anyone mess with these particular registers... + addq $48, %rsp + +#; UINT64 Rip; + popq 24(%rbp) + +#; UINT64 Gs, Fs, Es, Ds, Cs, Ss; + popq %rax + # mov %rax, %gs ; not for gs + popq %rax + # mov %rax, %fs ; not for fs + # (X64 will not use fs and gs, so we do not restore it) + popq %rax + movl %eax, %es + popq %rax + movl %eax, %ds + popq 32(%rbp) # for cs + popq 56(%rbp) # for ss + +#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; +#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; + popq %rdi + popq %rsi + addq $8, %rsp # not for rbp + popq 48(%rbp) # for rsp + popq %rbx + popq %rdx + popq %rcx + popq %rax + popq %r8 + popq %r9 + popq %r10 + popq %r11 + popq %r12 + popq %r13 + popq %r14 + popq %r15 + + movq %rbp, %rsp + popq %rbp + addq $16, %rsp + iretq + + +#------------------------------------------------------------------------------------- +# AsmGetAddressMap (&AddressMap); +#------------------------------------------------------------------------------------- +# comments here for definition of address map +ASM_GLOBAL ASM_PFX(GetTemplateAddressMap) +ASM_PFX(GetTemplateAddressMap): + + movabsq $Exception0Handle, %rax + movq %rax, (%rcx) + movq $(Exception1Handle - Exception0Handle), 0x08(%rcx) + + ret + +#END + + diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm new file mode 100644 index 0000000000..1fa7cb8702 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm @@ -0,0 +1,407 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2012, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; ExceptionHandlerAsm.Asm +; +; Abstract: +; +; x64 CPU Exception Handler +; +; Notes: +; +;------------------------------------------------------------------------------ + +; +; CommonExceptionHandler() +; +CommonExceptionHandler PROTO C + +EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions + +data SEGMENT + +CommonEntryAddr dq CommonInterruptEntry; + +.code + +Exception0Handle: + push 0 + jmp qword ptr [CommonEntryAddr] +Exception1Handle: + push 1 + jmp qword ptr [CommonEntryAddr] +Exception2Handle: + push 2 + jmp qword ptr [CommonEntryAddr] +Exception3Handle: + push 3 + jmp qword ptr [CommonEntryAddr] +Exception4Handle: + push 4 + jmp qword ptr [CommonEntryAddr] +Exception5Handle: + push 5 + jmp qword ptr [CommonEntryAddr] +Exception6Handle: + push 6 + jmp qword ptr [CommonEntryAddr] +Exception7Handle: + push 7 + jmp qword ptr [CommonEntryAddr] +Exception8Handle: + push 8 + jmp qword ptr [CommonEntryAddr] +Exception9Handle: + push 9 + jmp qword ptr [CommonEntryAddr] +Exception10Handle: + push 10 + jmp qword ptr [CommonEntryAddr] +Exception11Handle: + push 11 + jmp qword ptr [CommonEntryAddr] +Exception12Handle: + push 12 + jmp qword ptr [CommonEntryAddr] +Exception13Handle: + push 13 + jmp qword ptr [CommonEntryAddr] +Exception14Handle: + push 14 + jmp qword ptr [CommonEntryAddr] +Exception15Handle: + push 15 + jmp qword ptr [CommonEntryAddr] +Exception16Handle: + push 16 + jmp qword ptr [CommonEntryAddr] +Exception17Handle: + push 17 + jmp qword ptr [CommonEntryAddr] +Exception18Handle: + push 18 + jmp qword ptr [CommonEntryAddr] +Exception19Handle: + push 19 + jmp qword ptr [CommonEntryAddr] +Exception20Handle: + push 20 + jmp qword ptr [CommonEntryAddr] +Exception21Handle: + push 21 + jmp qword ptr [CommonEntryAddr] +Exception22Handle: + push 22 + jmp qword ptr [CommonEntryAddr] +Exception23Handle: + push 23 + jmp qword ptr [CommonEntryAddr] +Exception24Handle: + push 24 + jmp qword ptr [CommonEntryAddr] +Exception25Handle: + push 25 + jmp qword ptr [CommonEntryAddr] +Exception26Handle: + push 26 + jmp qword ptr [CommonEntryAddr] +Exception27Handle: + push 27 + jmp qword ptr [CommonEntryAddr] +Exception28Handle: + push 28 + jmp qword ptr [CommonEntryAddr] +Exception29Handle: + push 29 + jmp qword ptr [CommonEntryAddr] +Exception30Handle: + push 30 + jmp qword ptr [CommonEntryAddr] +Exception31Handle: + push 31 + jmp qword ptr [CommonEntryAddr] + +;CommonInterruptEntrypoint: +;---------------------------------------; +; _CommonEntry ; +;----------------------------------------------------------------------------; +; The follow algorithm is used for the common interrupt routine. +; Entry from each interrupt with a push eax and eax=interrupt number + +;---------------------------------------; +; CommonInterruptEntry ; +;---------------------------------------; +; The follow algorithm is used for the common interrupt routine. + +CommonInterruptEntry PROC PUBLIC + cli + ; + ; All interrupt handlers are invoked through interrupt gates, so + ; IF flag automatically cleared at the entry point + ; + ; + ; Calculate vector number + ; + xchg rcx, [rsp] ; get the return address of call, actually, it is the address of vector number. + cmp ecx, 32 ; Intel reserved vector for exceptions? + jae NoErrorCode + bt mErrorCodeFlag, ecx + jc @F + +NoErrorCode: + + ; + ; Push a dummy error code on the stack + ; to maintain coherent stack map + ; + push [rsp] + mov qword ptr [rsp + 8], 0 +@@: + push rbp + mov rbp, rsp + + ; + ; Stack: + ; +---------------------+ <-- 16-byte aligned ensured by processor + ; + Old SS + + ; +---------------------+ + ; + Old RSP + + ; +---------------------+ + ; + RFlags + + ; +---------------------+ + ; + CS + + ; +---------------------+ + ; + RIP + + ; +---------------------+ + ; + Error Code + + ; +---------------------+ + ; + RCX / Vector Number + + ; +---------------------+ + ; + RBP + + ; +---------------------+ <-- RBP, 16-byte aligned + ; + + + ; + ; Since here the stack pointer is 16-byte aligned, so + ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64 + ; is 16-byte aligned + ; + +;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; +;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + push rax + push qword ptr [rbp + 8] ; RCX + push rdx + push rbx + push qword ptr [rbp + 48] ; RSP + push qword ptr [rbp] ; RBP + push rsi + push rdi + +;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero + movzx rax, word ptr [rbp + 56] + push rax ; for ss + movzx rax, word ptr [rbp + 32] + push rax ; for cs + mov rax, ds + push rax + mov rax, es + push rax + mov rax, fs + push rax + mov rax, gs + push rax + + mov [rbp + 8], rcx ; save vector number + +;; UINT64 Rip; + push qword ptr [rbp + 24] + +;; UINT64 Gdtr[2], Idtr[2]; + xor rax, rax + push rax + push rax + sidt [rsp] + xchg rax, [rsp + 2] + xchg rax, [rsp] + xchg rax, [rsp + 8] + + xor rax, rax + push rax + push rax + sgdt [rsp] + xchg rax, [rsp + 2] + xchg rax, [rsp] + xchg rax, [rsp + 8] + +;; UINT64 Ldtr, Tr; + xor rax, rax + str ax + push rax + sldt ax + push rax + +;; UINT64 RFlags; + push qword ptr [rbp + 40] + +;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; + mov rax, cr8 + push rax + mov rax, cr4 + or rax, 208h + mov cr4, rax + push rax + mov rax, cr3 + push rax + mov rax, cr2 + push rax + xor rax, rax + push rax + mov rax, cr0 + push rax + +;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + mov rax, dr7 + push rax + mov rax, dr6 + push rax + mov rax, dr3 + push rax + mov rax, dr2 + push rax + mov rax, dr1 + push rax + mov rax, dr0 + push rax + +;; FX_SAVE_STATE_X64 FxSaveState; + sub rsp, 512 + mov rdi, rsp + db 0fh, 0aeh, 07h ;fxsave [rdi] + +;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear + cld + +;; UINT32 ExceptionData; + push qword ptr [rbp + 16] + +;; Prepare parameter and call + mov rcx, [rbp + 8] + mov rdx, rsp + ; + ; Per X64 calling convention, allocate maximum parameter stack space + ; and make sure RSP is 16-byte aligned + ; + sub rsp, 4 * 8 + 8 + mov rax, CommonExceptionHandler + call rax + add rsp, 4 * 8 + 8 + + cli +;; UINT64 ExceptionData; + add rsp, 8 + +;; FX_SAVE_STATE_X64 FxSaveState; + + mov rsi, rsp + db 0fh, 0aeh, 0Eh ; fxrstor [rsi] + add rsp, 512 + +;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; +;; Skip restoration of DRx registers to support in-circuit emualators +;; or debuggers set breakpoint in interrupt/exception context + add rsp, 8 * 6 + +;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; + pop rax + mov cr0, rax + add rsp, 8 ; not for Cr1 + pop rax + mov cr2, rax + pop rax + mov cr3, rax + pop rax + mov cr4, rax + pop rax + mov cr8, rax + +;; UINT64 RFlags; + pop qword ptr [rbp + 40] + +;; UINT64 Ldtr, Tr; +;; UINT64 Gdtr[2], Idtr[2]; +;; Best not let anyone mess with these particular registers... + add rsp, 48 + +;; UINT64 Rip; + pop qword ptr [rbp + 24] + +;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; + pop rax + ; mov gs, rax ; not for gs + pop rax + ; mov fs, rax ; not for fs + ; (X64 will not use fs and gs, so we do not restore it) + pop rax + mov es, rax + pop rax + mov ds, rax + pop qword ptr [rbp + 32] ; for cs + pop qword ptr [rbp + 56] ; for ss + +;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; +;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; + pop rdi + pop rsi + add rsp, 8 ; not for rbp + pop qword ptr [rbp + 48] ; for rsp + pop rbx + pop rdx + pop rcx + pop rax + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + mov rsp, rbp + pop rbp + add rsp, 16 + iretq + +CommonInterruptEntry ENDP + +;------------------------------------------------------------------------------------- +; GetTemplateAddressMap (&AddressMap); +;------------------------------------------------------------------------------------- +; comments here for definition of address map +GetTemplateAddressMap PROC + mov rax, offset Exception0Handle + mov qword ptr [rcx], rax + mov qword ptr [rcx+8h], Exception1Handle - Exception0Handle + ret +GetTemplateAddressMap ENDP + +END -- cgit v1.2.3