;------------------------------------------------------------------------------ ;\r
-; Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+; Copyright (c) 2012 - 2014, 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
;\r
; CommonExceptionHandler()\r
;\r
-CommonExceptionHandler PROTO C\r
+externdef CommonExceptionHandler:near\r
\r
-EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+EXTRN mDoFarReturnFlag:QWORD ; Do far return flag\r
\r
data SEGMENT\r
\r
-CommonEntryAddr dq CommonInterruptEntry;\r
-\r
.code\r
\r
-Exception0Handle:\r
- push 0\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception1Handle:\r
- push 1\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception2Handle:\r
- push 2\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception3Handle:\r
- push 3\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception4Handle:\r
- push 4\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception5Handle:\r
- push 5\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception6Handle:\r
- push 6\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception7Handle:\r
- push 7\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception8Handle:\r
- push 8\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception9Handle:\r
- push 9\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception10Handle:\r
- push 10\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception11Handle:\r
- push 11\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception12Handle:\r
- push 12\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception13Handle:\r
- push 13\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception14Handle:\r
- push 14\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception15Handle:\r
- push 15\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception16Handle:\r
- push 16\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception17Handle:\r
- push 17\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception18Handle:\r
- push 18\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception19Handle:\r
- push 19\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception20Handle:\r
- push 20\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception21Handle:\r
- push 21\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception22Handle:\r
- push 22\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception23Handle:\r
- push 23\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception24Handle:\r
- push 24\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception25Handle:\r
- push 25\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception26Handle:\r
- push 26\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception27Handle:\r
- push 27\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception28Handle:\r
- push 28\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception29Handle:\r
- push 29\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception30Handle:\r
- push 30\r
- jmp qword ptr [CommonEntryAddr]\r
-Exception31Handle:\r
- push 31\r
- jmp qword ptr [CommonEntryAddr]\r
-\r
-;CommonInterruptEntrypoint:\r
-;---------------------------------------;\r
-; _CommonEntry ;\r
-;----------------------------------------------------------------------------;\r
-; The follow algorithm is used for the common interrupt routine.\r
-; Entry from each interrupt with a push eax and eax=interrupt number\r
+ALIGN 8\r
+\r
+AsmIdtVectorBegin:\r
+REPEAT 32\r
+ db 6ah ; push #VectorNum\r
+ db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum\r
+ push rax\r
+ mov rax, CommonInterruptEntry\r
+ jmp rax\r
+ENDM\r
+AsmIdtVectorEnd:\r
+\r
+HookAfterStubHeaderBegin:\r
+ db 6ah ; push\r
+@VectorNum:\r
+ db 0 ; 0 will be fixed\r
+ push rax\r
+ mov rax, HookAfterStubHeaderEnd\r
+ jmp rax\r
+HookAfterStubHeaderEnd:\r
+ mov rax, rsp\r
+ and sp, 0fff0h ; make sure 16-byte aligned for exception context\r
+ sub rsp, 18h ; reserve room for filling exception data later\r
+ push rcx\r
+ mov rcx, [rax + 8]\r
+ bt mErrorCodeFlag, ecx\r
+ jnc @F\r
+ push [rsp] ; push additional rcx to make stack alignment\r
+@@:\r
+ xchg rcx, [rsp] ; restore rcx, save Exception Number in stack\r
+ push [rax] ; push rax into stack to keep code consistence\r
\r
;---------------------------------------;\r
; CommonInterruptEntry ;\r
;---------------------------------------;\r
; The follow algorithm is used for the common interrupt routine.\r
-\r
-CommonInterruptEntry PROC PUBLIC \r
+; Entry from each interrupt with a push eax and eax=interrupt number\r
+; Stack frame would be as follows as specified in IA32 manuals:\r
+;\r
+; +---------------------+ <-- 16-byte aligned ensured by processor\r
+; + Old SS +\r
+; +---------------------+\r
+; + Old RSP +\r
+; +---------------------+\r
+; + RFlags +\r
+; +---------------------+\r
+; + CS +\r
+; +---------------------+\r
+; + RIP +\r
+; +---------------------+\r
+; + Error Code +\r
+; +---------------------+\r
+; + Vector Number +\r
+; +---------------------+\r
+; + RBP +\r
+; +---------------------+ <-- RBP, 16-byte aligned\r
+; The follow algorithm is used for the common interrupt routine.\r
+CommonInterruptEntry PROC PUBLIC\r
cli\r
+ pop rax\r
;\r
; All interrupt handlers are invoked through interrupt gates, so\r
; IF flag automatically cleared at the entry point\r
;\r
- ;\r
- ; Calculate vector number\r
- ;\r
- xchg rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.\r
+ xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx\r
+ and rcx, 0FFh\r
cmp ecx, 32 ; Intel reserved vector for exceptions?\r
jae NoErrorCode\r
bt mErrorCodeFlag, ecx\r
;\r
push [rsp]\r
mov qword ptr [rsp + 8], 0\r
-@@: \r
+@@:\r
push rbp\r
mov rbp, rsp\r
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
\r
;\r
; Stack:\r
mov rsp, rbp\r
pop rbp\r
add rsp, 16\r
+ cmp qword ptr [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
+ jz DoReturn\r
+ cmp qword ptr [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
+ jz ErrorCode\r
+ jmp qword ptr [rsp - 32]\r
+ErrorCode:\r
+ sub rsp, 8\r
+ jmp qword ptr [rsp - 24]\r
+\r
+DoReturn:\r
+ cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET\r
+ jz DoIret\r
+ push rax\r
+ mov rax, rsp ; save old RSP to rax\r
+ mov rsp, [rsp + 20h]\r
+ push [rax + 10h] ; save CS in new location\r
+ push [rax + 8h] ; save EIP in new location\r
+ push [rax + 18h] ; save EFLAGS in new location\r
+ mov rax, [rax] ; restore rax\r
+ popfq ; restore EFLAGS\r
+ DB 48h ; prefix to composite "retq" with next "retf"\r
+ retf ; far return\r
+DoIret:\r
iretq\r
\r
CommonInterruptEntry ENDP\r
; GetTemplateAddressMap (&AddressMap);\r
;-------------------------------------------------------------------------------------\r
; comments here for definition of address map\r
-GetTemplateAddressMap PROC\r
- mov rax, offset Exception0Handle\r
- mov qword ptr [rcx], rax\r
- mov qword ptr [rcx+8h], Exception1Handle - Exception0Handle\r
- ret\r
-GetTemplateAddressMap ENDP\r
+AsmGetTemplateAddressMap PROC\r
+ mov rax, offset AsmIdtVectorBegin\r
+ mov qword ptr [rcx], rax\r
+ mov qword ptr [rcx + 8h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32\r
+ mov rax, offset HookAfterStubHeaderBegin\r
+ mov qword ptr [rcx + 10h], rax\r
+ ret\r
+AsmGetTemplateAddressMap ENDP\r
+\r
+;-------------------------------------------------------------------------------------\r
+; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);\r
+;-------------------------------------------------------------------------------------\r
+AsmVectorNumFixup PROC\r
+ mov rax, rdx\r
+ mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al\r
+ ret\r
+AsmVectorNumFixup ENDP\r
\r
END\r