#------------------------------------------------------------------------------
#
# Copyright (c) 2006 - 2008, 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.
#
# Module Name:
#
# AsmFuncs.S
#
# Abstract:
#
# Debug interrupt handle functions.
#
#------------------------------------------------------------------------------
#include "DebugException.h"
ASM_GLOBAL ASM_PFX(InterruptProcess)
ASM_GLOBAL ASM_PFX(Exception0Handle)
ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize)
ASM_GLOBAL ASM_PFX(TimerInterruptHandle)
ASM_GLOBAL ASM_PFX(CommonEntry)
.data
ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle)
.text
ASM_PFX(Exception0Handle):
cli
pushq %rcx
mov $0, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception1Handle):
cli
pushq %rcx
mov $1, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception2Handle):
cli
pushq %rcx
mov $2, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception3Handle):
cli
pushq %rcx
mov $3, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception4Handle):
cli
pushq %rcx
mov $4, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception5Handle):
cli
pushq %rcx
mov $5, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception6Handle):
cli
pushq %rcx
mov $6, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception7Handle):
cli
pushq %rcx
mov $7, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception8Handle):
cli
pushq %rcx
mov $8, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception9Handle):
cli
pushq %rcx
mov $9, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception10Handle):
cli
pushq %rcx
mov $10, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception11Handle):
cli
pushq %rcx
mov $11, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception12Handle):
cli
pushq %rcx
mov $12, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception13Handle):
cli
pushq %rcx
mov $13, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception14Handle):
cli
pushq %rcx
mov $14, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception15Handle):
cli
pushq %rcx
mov $15, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception16Handle):
cli
pushq %rcx
mov $16, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception17Handle):
cli
pushq %rcx
mov $17, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception18Handle):
cli
pushq %rcx
mov $18, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(Exception19Handle):
cli
pushq %rcx
mov $19, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(TimerInterruptHandle):
cli
pushq %rcx
mov $32, %rcx
jmp ASM_PFX(CommonEntry)
ASM_PFX(CommonEntry):
#---------------------------------------;
# CommonInterruptEntry ;
#---------------------------------------;
# The follow algorithm is used for the common interrupt routine.
#
# +---------------------+ <-- 16-byte aligned ensured by processor
# + Old SS +
# +---------------------+
# + Old RSP +
# +---------------------+
# + RFlags +
# +---------------------+
# + CS +
# +---------------------+
# + RIP +
# +---------------------+
# + Error Code +
# +---------------------+
# + RCX / Vector Number +
# +---------------------+
# + RBP +
# +---------------------+ <-- RBP, 16-byte aligned
#
# We need to determine if any extra data was pushed by the exception
cmpq $DEBUG_EXCEPT_DOUBLE_FAULT, %rcx
je NoExtrPush
cmpq $DEBUG_EXCEPT_INVALID_TSS, %rcx
je NoExtrPush
cmpq $DEBUG_EXCEPT_SEG_NOT_PRESENT, %rcx
je NoExtrPush
cmpq $DEBUG_EXCEPT_STACK_FAULT, %rcx
je NoExtrPush
cmpq $DEBUG_EXCEPT_GP_FAULT, %rcx
je NoExtrPush
cmpq $DEBUG_EXCEPT_PAGE_FAULT, %rcx
je NoExtrPush
cmpq $DEBUG_EXCEPT_ALIGNMENT_CHECK, %rcx
je NoExtrPush
pushq (%rsp)
movq $0, 8(%rsp)
NoExtrPush:
#
# All interrupt handlers are invoked through interrupt gates, so
# IF flag automatically cleared at the entry point
pushq %rbp
movq %rsp, %rbp
#
# 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 R8, R9, R10, R11, R12, R13, R14, R15;
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %r11
pushq %r10
pushq %r9
pushq %r8
movq %cr8, %r8
pushq %r8
## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
pushq %rax
pushq %rbx
pushq 8(%rbp) # original rcx
pushq %rdx
pushq 48(%rbp) # original rsp
pushq (%rbp) # original rbp
pushq %rsi
pushq %rdi
## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4;
movq %cr4, %rax
orq $0x208, %rax
movq %rax, %cr4
pushq %rax
movq %cr3, %rax
pushq %rax
movq %cr2, %rax
pushq %rax
xorq %rax, %rax
pushq %rax
movq %cr0, %rax
pushq %rax
## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
xorq %rax, %rax # set rax to 0
movzwq 56(%rbp), %rax
# movq %ss, %rax
pushq %rax
movzwq 32(%rbp), %rax
# movq %cs, %rax
pushq %rax
movq %ds, %rax
pushq %rax
movq %es, %rax
pushq %rax
movq %fs, %rax
pushq %rax
movq %gs, %rax
pushq %rax
## UINT64 Rip;
pushq 24(%rbp)
## UINT64 Gdtr[2], Idtr[2];
subq $16, %rsp
sidt (%rsp)
subq $16, %rsp
sgdt (%rsp)
## UINT64 Ldtr, Tr;
xorq %rax, %rax
strw %ax
pushq %rax
sldtw %ax
pushq %rax
## UINT64 RFlags;
pushq 40(%rbp)
## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
movq %dr7, %rax
pushq %rax
## clear Dr7 while executing debugger itself
xorq %rax, %rax
#debug movq %rax, %dr7
movq %dr6, %rax
pushq %rax
## insure all status bits in dr6 are clear...
xorq %rax, %rax
movq %rax, %dr6
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, 0xae, 0b00000111
## Clear Direction Flag
cld
## Prepare parameter and call
# movq 8(%rbp), %rcx
movq %rsp, %rdx
movq %rcx, %r15 # save vector in r15
#
# Per X64 calling convention, allocate maximum parameter stack space
# and make sure RSP is 16-byte aligned
#
subq $(4 * 8), %rsp
call ASM_PFX(InterruptProcess)
addq $(4 * 8), %rsp
## FX_SAVE_STATE_X64 FxSaveState;
movq %rsp, %rsi
.byte 0x0f, 0xae, 0b00001110
addq $512, %rsp
## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
popq %rax
movq %rax, %dr0
popq %rax
movq %rax, %dr1
popq %rax
movq %rax, %dr2
popq %rax
movq %rax, %dr3
## skip restore of dr6. We cleared dr6 during the context save.
addq $8, %rsp
popq %rax
movq %rax, %dr7
## 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 gs, rax ; not for gs
popq %rax
# mov fs, rax ; not for fs
# (X64 will not use fs and gs, so we do not restore it)
popq %rax
movw %rax, %es
popq %rax
movw %rax, %ds
popq 32(%rbp)
popq 56(%rbp)
## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
popq %rax
movq %rax, %cr0
addq $8, %rsp
popq %rax
movq %rax, %cr2
popq %rax
movq %rax, %cr3
popq %rax
movq %rax, %cr4
## 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
addq $8, %rsp
popq %rdx
popq %rcx
popq %rbx
popq %rax
popq %r8
movq %r8, %cr8
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