3 #------------------------------------------------------------------------------
5 #* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
6 #* This program and the accompanying materials
7 #* are licensed and made available under the terms and conditions of the BSD License
8 #* which accompanies this distribution. The full text of the license may be found at
9 #* http://opensource.org/licenses/bsd-license.php
11 #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #------------------------------------------------------------------------------
24 #EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
28 # point to the external interrupt vector table
30 ExternalVectorTablePtr:
31 .byte 0, 0, 0, 0, 0, 0, 0, 0
33 ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)
34 ASM_PFX(InitializeExternalVectorTablePtr):
35 lea ExternalVectorTablePtr(%rip), %rax # save vector number
40 #------------------------------------------------------------------------------
45 #------------------------------------------------------------------------------
46 ASM_GLOBAL ASM_PFX(SetCodeSelector)
47 ASM_PFX(SetCodeSelector):
49 leaq setCodeSelectorLongJump(%rip), %rax
52 .byte 0xFF, 0x2C, 0x24 # jmp (%rsp) note:fword jmp
53 setCodeSelectorLongJump:
57 #------------------------------------------------------------------------------
62 #------------------------------------------------------------------------------
63 ASM_GLOBAL ASM_PFX(SetDataSelectors)
64 ASM_PFX(SetDataSelectors):
72 #---------------------------------------;
73 # CommonInterruptEntry ;
74 #---------------------------------------;
75 # The follow algorithm is used for the common interrupt routine.
77 ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
78 ASM_PFX(CommonInterruptEntry):
81 # All interrupt handlers are invoked through interrupt gates, so
82 # IF flag automatically cleared at the entry point
85 # Calculate vector number
87 xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number.
89 cmp $32, %ecx # Intel reserved vector for exceptions?
92 leaq ASM_PFX(mErrorCodeFlag)(%rip), %rax
95 jc CommonInterruptEntry_al_0000
100 # Push a dummy error code on the stack
101 # to maintain coherent stack map
105 CommonInterruptEntry_al_0000:
111 # +---------------------+ <-- 16-byte aligned ensured by processor
113 # +---------------------+
115 # +---------------------+
117 # +---------------------+
119 # +---------------------+
121 # +---------------------+
123 # +---------------------+
124 # + RCX / Vector Number +
125 # +---------------------+
127 # +---------------------+ <-- RBP, 16-byte aligned
132 # Since here the stack pointer is 16-byte aligned, so
133 # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
137 #; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
138 #; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
156 #; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
157 movzwq 56(%rbp), %rax
159 movzwq 32(%rbp), %rax
170 movq %rcx, 8(%rbp) # save vector number
175 #; UINT64 Gdtr[2], Idtr[2];
202 #; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
218 #; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
232 #; FX_SAVE_STATE_X64 FxSaveState;
235 .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi]
237 #; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
240 #; UINT32 ExceptionData;
243 #; call into exception handler
245 leaq ExternalVectorTablePtr(%rip), %rax
247 movq (%rax,%rcx,8), %rax
248 orq %rax, %rax # NULL?
252 #; Prepare parameter and call
256 # Per X64 calling convention, allocate maximum parameter stack space
257 # and make sure RSP is 16-byte aligned
265 #; UINT64 ExceptionData;
268 #; FX_SAVE_STATE_X64 FxSaveState;
271 .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi]
274 #; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
275 #; Skip restoration of DRx registers to support in-circuit emualators
276 #; or debuggers set breakpoint in interrupt/exception context
279 #; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
282 addq $8, %rsp # not for Cr1
296 #; UINT64 Gdtr[2], Idtr[2];
297 #; Best not let anyone mess with these particular registers...
303 #; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
305 # mov %rax, %gs ; not for gs
307 # mov %rax, %fs ; not for fs
308 # (X64 will not use fs and gs, so we do not restore it)
313 popq 32(%rbp) # for cs
314 popq 56(%rbp) # for ss
316 #; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
317 #; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
320 addq $8, %rsp # not for rbp
321 popq 48(%rbp) # for rsp