-#------------------------------------------------------------------------------\r
-#*\r
-#* Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>\r
-#* This program and the accompanying materials\r
-#* are licensed and made available under the terms and conditions of the BSD License\r
-#* which accompanies this distribution. The full text of the license may be found at\r
-#* http://opensource.org/licenses/bsd-license.php\r
-#*\r
-#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#*\r
-#* ExceptionHandlerAsm.S\r
-#*\r
-#* Abstract:\r
-#*\r
-#* IA32 CPU Exception Handler\r
-#\r
-#------------------------------------------------------------------------------\r
-\r
-\r
-#.MMX\r
-#.XMM\r
-\r
-ASM_GLOBAL ASM_PFX(CommonExceptionHandler)\r
-ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
-ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd)\r
-\r
-#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions\r
-#EXTRN ASM_PFX(mDoFarReturnFlag):DWORD # Do far return flag\r
-\r
-.text\r
-\r
-#\r
-# exception handler stub table\r
-#\r
-Exception0Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 0\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception1Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 1\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception2Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 2\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception3Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 3\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception4Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 4\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception5Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 5\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception6Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 6\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception7Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 7\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception8Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 8\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception9Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 9\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception10Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 10\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception11Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 11\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception12Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 12\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception13Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 13\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception14Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 14\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception15Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 15\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception16Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 16\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception17Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 17\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception18Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 18\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception19Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 19\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception20Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 20\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception21Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 21\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception22Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 22\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception23Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 23\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception24Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 24\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception25Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 25\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception26Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 26\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception27Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 27\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception28Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 28\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception29Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 29\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception30Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 30\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-Exception31Handle:\r
- .byte 0x6a # push #VectorNum\r
- .byte 31\r
- pushl %eax\r
- .byte 0xB8\r
- .long ASM_PFX(CommonInterruptEntry)\r
- jmp *%eax\r
-\r
-HookAfterStubBegin:\r
- .byte 0x6a # push\r
-VectorNum:\r
- .byte 0 # 0 will be fixed\r
- pushl %eax\r
- .byte 0xB8 # movl ASM_PFX(HookAfterStubHeaderEnd), %eax\r
- .long ASM_PFX(HookAfterStubHeaderEnd)\r
- jmp *%eax\r
-ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd)\r
-ASM_PFX(HookAfterStubHeaderEnd):\r
- popl %eax\r
- subl $8, %esp # reserve room for filling exception data later\r
- pushl 8(%esp)\r
- xchgl (%esp), %ecx # get vector number\r
- bt %ecx, ASM_PFX(mErrorCodeFlag)\r
- jnc NoErrorData\r
- pushl (%esp) # addition push if exception data needed\r
-NoErrorData:\r
- xchg (%esp), %ecx # restore ecx\r
- pushl %eax\r
-\r
-#---------------------------------------;\r
-# CommonInterruptEntry ;\r
-#---------------------------------------;\r
-# The follow algorithm is used for the common interrupt routine.\r
-\r
-ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
-ASM_PFX(CommonInterruptEntry):\r
- cli\r
- popl %eax\r
- #\r
- # All interrupt handlers are invoked through interrupt gates, so\r
- # IF flag automatically cleared at the entry point\r
- #\r
-\r
- #\r
- # Get vector number from top of stack\r
- #\r
- xchgl (%esp), %ecx\r
- andl $0x0FF, %ecx # Vector number should be less than 256\r
- cmpl $32, %ecx # Intel reserved vector for exceptions?\r
- jae NoErrorCode\r
- bt %ecx, ASM_PFX(mErrorCodeFlag)\r
- jc HasErrorCode\r
-\r
-NoErrorCode:\r
-\r
- #\r
- # Stack:\r
- # +---------------------+\r
- # + EFlags +\r
- # +---------------------+\r
- # + CS +\r
- # +---------------------+\r
- # + EIP +\r
- # +---------------------+\r
- # + ECX +\r
- # +---------------------+ <-- ESP\r
- #\r
- # Registers:\r
- # ECX - Vector Number\r
- #\r
-\r
- #\r
- # Put Vector Number on stack\r
- #\r
- pushl %ecx\r
-\r
- #\r
- # Put 0 (dummy) error code on stack, and restore ECX\r
- #\r
- xorl %ecx, %ecx # ECX = 0\r
- xchgl 4(%esp), %ecx\r
-\r
- jmp ErrorCodeAndVectorOnStack\r
-\r
-HasErrorCode:\r
-\r
- #\r
- # Stack:\r
- # +---------------------+\r
- # + EFlags +\r
- # +---------------------+\r
- # + CS +\r
- # +---------------------+\r
- # + EIP +\r
- # +---------------------+\r
- # + Error Code +\r
- # +---------------------+\r
- # + ECX +\r
- # +---------------------+ <-- ESP\r
- #\r
- # Registers:\r
- # ECX - Vector Number\r
- #\r
-\r
- #\r
- # Put Vector Number on stack and restore ECX\r
- #\r
- xchgl (%esp), %ecx\r
-\r
-ErrorCodeAndVectorOnStack:\r
- pushl %ebp\r
- movl %esp, %ebp\r
-\r
- #\r
- # Stack:\r
- # +---------------------+\r
- # + EFlags +\r
- # +---------------------+\r
- # + CS +\r
- # +---------------------+\r
- # + EIP +\r
- # +---------------------+\r
- # + Error Code +\r
- # +---------------------+\r
- # + Vector Number +\r
- # +---------------------+\r
- # + EBP +\r
- # +---------------------+ <-- EBP\r
- #\r
-\r
- #\r
- # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
- # is 16-byte aligned\r
- #\r
- andl $0x0fffffff0, %esp\r
- subl $12, %esp\r
-\r
- subl $8, %esp\r
- pushl $0 # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
- pushl $0 # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
-\r
-#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
- pushl %eax\r
- pushl %ecx\r
- pushl %edx\r
- pushl %ebx\r
- leal 24(%ebp), %ecx\r
- pushl %ecx # ESP\r
- pushl (%ebp) # EBP\r
- pushl %esi\r
- pushl %edi\r
-\r
-#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
- movl %ss, %eax\r
- pushl %eax\r
- movzwl 16(%ebp), %eax\r
- pushl %eax\r
- movl %ds, %eax\r
- pushl %eax\r
- movl %es, %eax\r
- pushl %eax\r
- movl %fs, %eax\r
- pushl %eax\r
- movl %gs, %eax\r
- pushl %eax\r
-\r
-#; UINT32 Eip;\r
- movl 12(%ebp), %eax\r
- pushl %eax\r
-\r
-#; UINT32 Gdtr[2], Idtr[2];\r
- subl $8, %esp\r
- sidt (%esp)\r
- movl 2(%esp), %eax\r
- xchgl (%esp), %eax\r
- andl $0x0FFFF, %eax\r
- movl %eax, 4(%esp)\r
-\r
- subl $8, %esp\r
- sgdt (%esp)\r
- movl 2(%esp), %eax\r
- xchgl (%esp), %eax\r
- andl $0x0FFFF, %eax\r
- movl %eax, 4(%esp)\r
-\r
-#; UINT32 Ldtr, Tr;\r
- xorl %eax, %eax\r
- str %ax\r
- pushl %eax\r
- sldt %ax\r
- pushl %eax\r
-\r
-#; UINT32 EFlags;\r
- movl 20(%ebp), %eax\r
- pushl %eax\r
-\r
-#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
-## insure FXSAVE/FXRSTOR is enabled in CR4...\r
-## ... while we're at it, make sure DE is also enabled...\r
- mov $1, %eax\r
- pushl %ebx # temporarily save value of ebx on stack\r
- cpuid # use CPUID to determine if FXSAVE/FXRESTOR\r
- # and DE are supported\r
- popl %ebx # retore value of ebx that was overwritten\r
- # by CPUID\r
- movl %cr4, %eax\r
- pushl %eax # push cr4 firstly\r
- testl $BIT24, %edx # Test for FXSAVE/FXRESTOR support\r
- jz L1\r
- orl $BIT9, %eax # Set CR4.OSFXSR\r
-L1:\r
- testl $BIT2, %edx # Test for Debugging Extensions support\r
- jz L2\r
- orl $BIT3, %eax # Set CR4.DE\r
-L2:\r
- movl %eax, %cr4\r
- movl %cr3, %eax\r
- pushl %eax\r
- movl %cr2, %eax\r
- pushl %eax\r
- xorl %eax, %eax\r
- pushl %eax\r
- movl %cr0, %eax\r
- pushl %eax\r
-\r
-#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
- movl %dr7, %eax\r
- pushl %eax\r
- movl %dr6, %eax\r
- pushl %eax\r
- movl %dr3, %eax\r
- pushl %eax\r
- movl %dr2, %eax\r
- pushl %eax\r
- movl %dr1, %eax\r
- pushl %eax\r
- movl %dr0, %eax\r
- pushl %eax\r
-\r
-#; FX_SAVE_STATE_IA32 FxSaveState;\r
- subl $512, %esp\r
- movl %esp, %edi\r
- testl $BIT24, %edx # Test for FXSAVE/FXRESTOR support.\r
- # edx still contains result from CPUID above\r
- jz L3\r
- .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]\r
-L3:\r
-\r
-#; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
- cld\r
-\r
-#; UINT32 ExceptionData;\r
- pushl 8(%ebp)\r
-\r
-#; Prepare parameter and call\r
- movl %esp, %edx\r
- pushl %edx\r
- movl 4(%ebp), %edx\r
- pushl %edx\r
-\r
- #\r
- # Call External Exception Handler\r
- #\r
- call ASM_PFX(CommonExceptionHandler)\r
- addl $8, %esp\r
-\r
- cli\r
-#; UINT32 ExceptionData;\r
- addl $4, %esp\r
-\r
-#; FX_SAVE_STATE_IA32 FxSaveState;\r
- movl %esp, %esi\r
- movl $1, %eax\r
- cpuid # use CPUID to determine if FXSAVE/FXRESTOR\r
- # are supported\r
- testl $BIT24, %edx # Test for FXSAVE/FXRESTOR support\r
- jz L4\r
- .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]\r
-L4:\r
- addl $512, %esp\r
-\r
-#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
-#; Skip restoration of DRx registers to support in-circuit emualators\r
-#; or debuggers set breakpoint in interrupt/exception context\r
- addl $24, %esp\r
-\r
-#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
- popl %eax\r
- movl %eax, %cr0\r
- addl $4, %esp # not for Cr1\r
- popl %eax\r
- movl %eax, %cr2\r
- popl %eax\r
- movl %eax, %cr3\r
- popl %eax\r
- movl %eax, %cr4\r
-\r
-#; UINT32 EFlags;\r
- popl 20(%ebp)\r
-\r
-#; UINT32 Ldtr, Tr;\r
-#; UINT32 Gdtr[2], Idtr[2];\r
-#; Best not let anyone mess with these particular registers...\r
- addl $24, %esp\r
-\r
-#; UINT32 Eip;\r
- popl 12(%ebp)\r
-\r
-#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
-#; NOTE - modified segment registers could hang the debugger... We\r
-#; could attempt to insulate ourselves against this possibility,\r
-#; but that poses risks as well.\r
-#;\r
- popl %gs\r
- popl %fs\r
- popl %es\r
- popl %ds\r
- popl 16(%ebp)\r
- popl %ss\r
-\r
-#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
- popl %edi\r
- popl %esi\r
- addl $4, %esp # not for ebp\r
- addl $4, %esp # not for esp\r
- popl %ebx\r
- popl %edx\r
- popl %ecx\r
- popl %eax\r
-\r
- popl -8(%ebp)\r
- popl -4(%ebp)\r
- movl %ebp, %esp\r
- popl %ebp\r
- addl $8, %esp\r
- cmpl $0, -16(%esp) # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
- jz DoReturn\r
- cmpl $1, -20(%esp) # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
- jz ErrorCode\r
- jmp *-16(%esp)\r
-ErrorCode:\r
- subl $4, %esp\r
- jmp *-12(%esp)\r
-\r
-DoReturn:\r
- cmpl $0, ASM_PFX(mDoFarReturnFlag)\r
- jz DoIret\r
- pushl 8(%esp) # save EFLAGS\r
- addl $16, %esp\r
- pushl -8(%esp) # save CS in new location\r
- pushl -8(%esp) # save EIP in new location\r
- pushl -8(%esp) # save EFLAGS in new location\r
- popfl # restore EFLAGS\r
- lret # far return\r
-\r
-DoIret:\r
- iretl\r
-\r
-\r
-#---------------------------------------;\r
-# _AsmGetTemplateAddressMap ;\r
-#---------------------------------------;\r
-#\r
-# Protocol prototype\r
-# AsmGetTemplateAddressMap (\r
-# EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap\r
-# );\r
-#\r
-# Routine Description:\r
-#\r
-# Return address map of interrupt handler template so that C code can generate\r
-# interrupt table.\r
-#\r
-# Arguments:\r
-#\r
-#\r
-# Returns:\r
-#\r
-# Nothing\r
-#\r
-#\r
-# Input: [ebp][0] = Original ebp\r
-# [ebp][4] = Return address\r
-#\r
-# Output: Nothing\r
-#\r
-# Destroys: Nothing\r
-#-----------------------------------------------------------------------------;\r
-#-------------------------------------------------------------------------------------\r
-# AsmGetAddressMap (&AddressMap);\r
-#-------------------------------------------------------------------------------------\r
-ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap)\r
-ASM_PFX(AsmGetTemplateAddressMap):\r
-\r
- pushl %ebp\r
- movl %esp,%ebp\r
- pushal\r
-\r
- movl 0x8(%ebp), %ebx\r
- movl $Exception0Handle, (%ebx)\r
- movl $(Exception1Handle - Exception0Handle), 0x4(%ebx)\r
- movl $(HookAfterStubBegin), 0x8(%ebx)\r
-\r
- popal\r
- popl %ebp\r
- ret\r
-#-------------------------------------------------------------------------------------\r
-# AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);\r
-#-------------------------------------------------------------------------------------\r
-ASM_GLOBAL ASM_PFX(AsmVectorNumFixup)\r
-ASM_PFX(AsmVectorNumFixup):\r
- movl 8(%esp), %eax\r
- movl 4(%esp), %ecx\r
- movb %al, (VectorNum - HookAfterStubBegin)(%ecx)\r
- ret\r