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