1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
7 ; ExceptionHandlerAsm.Asm
11 ; IA32 CPU Exception Handler
15 ;------------------------------------------------------------------------------
18 ; CommonExceptionHandler()
20 extern ASM_PFX(CommonExceptionHandler)
24 extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
25 extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
32 ; exception handler stub table
36 db 0x6a ; push #VectorNum
37 db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
39 mov eax, ASM_PFX(CommonInterruptEntry)
47 db 0 ; 0 will be fixed
49 mov eax, HookAfterStubHeaderEnd
51 HookAfterStubHeaderEnd:
53 sub esp, 8 ; reserve room for filling exception data later
55 xchg ecx, [esp] ; get vector number
56 bt [ASM_PFX(mErrorCodeFlag)], ecx
58 push dword [esp] ; addition push if exception data needed
60 xchg ecx, [esp] ; restore ecx
63 ;----------------------------------------------------------------------------;
64 ; CommonInterruptEntry ;
65 ;----------------------------------------------------------------------------;
66 ; The follow algorithm is used for the common interrupt routine.
67 ; Entry from each interrupt with a push eax and eax=interrupt number
69 ; +---------------------+
71 ; +---------------------+
73 ; +---------------------+
75 ; +---------------------+
77 ; +---------------------+
79 ; +---------------------+
81 ; +---------------------+ <-- EBP
82 global ASM_PFX(CommonInterruptEntry)
83 ASM_PFX(CommonInterruptEntry):
87 ; All interrupt handlers are invoked through interrupt gates, so
88 ; IF flag automatically cleared at the entry point
92 ; Get vector number from top of stack
95 and ecx, 0xFF ; Vector number should be less than 256
96 cmp ecx, 32 ; Intel reserved vector for exceptions?
98 bt [ASM_PFX(mErrorCodeFlag)], ecx
105 ; +---------------------+
107 ; +---------------------+
109 ; +---------------------+
111 ; +---------------------+
113 ; +---------------------+ <-- ESP
116 ; ECX - Vector Number
120 ; Put Vector Number on stack
125 ; Put 0 (dummy) error code on stack, and restore ECX
127 xor ecx, ecx ; ECX = 0
130 jmp ErrorCodeAndVectorOnStack
136 ; +---------------------+
138 ; +---------------------+
140 ; +---------------------+
142 ; +---------------------+
144 ; +---------------------+
146 ; +---------------------+ <-- ESP
149 ; ECX - Vector Number
153 ; Put Vector Number on stack and restore ECX
157 ErrorCodeAndVectorOnStack:
163 ; +---------------------+
165 ; +---------------------+
167 ; +---------------------+
169 ; +---------------------+
171 ; +---------------------+
173 ; +---------------------+
175 ; +---------------------+ <-- EBP
179 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
186 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
187 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
189 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
194 lea ecx, [ebp + 6 * 4]
196 push dword [ebp] ; EBP
200 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
203 movzx eax, word [ebp + 4 * 4]
215 mov eax, [ebp + 3 * 4]
218 ;; UINT32 Gdtr[2], Idtr[2];
241 mov eax, [ebp + 5 * 4]
244 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
246 push ebx ; temporarily save value of ebx on stack
247 cpuid ; use CPUID to determine if FXSAVE/FXRESTOR and DE
249 pop ebx ; retore value of ebx that was overwritten by CPUID
251 push eax ; push cr4 firstly
252 test edx, BIT24 ; Test for FXSAVE/FXRESTOR support
254 or eax, BIT9 ; Set CR4.OSFXSR
256 test edx, BIT2 ; Test for Debugging Extensions support
258 or eax, BIT3 ; Set CR4.DE
270 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
284 ;; FX_SAVE_STATE_IA32 FxSaveState;
287 test edx, BIT24 ; Test for FXSAVE/FXRESTOR support.
288 ; edx still contains result from CPUID above
290 db 0xf, 0xae, 0x7 ;fxsave [edi]
293 ;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
296 ;; UINT32 ExceptionData;
297 push dword [ebp + 2 * 4]
299 ;; Prepare parameter and call
302 mov edx, dword [ebp + 1 * 4]
306 ; Call External Exception Handler
308 mov eax, ASM_PFX(CommonExceptionHandler)
313 ;; UINT32 ExceptionData;
316 ;; FX_SAVE_STATE_IA32 FxSaveState;
319 cpuid ; use CPUID to determine if FXSAVE/FXRESTOR
321 test edx, BIT24 ; Test for FXSAVE/FXRESTOR support
323 db 0xf, 0xae, 0xe ; fxrstor [esi]
327 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
328 ;; Skip restoration of DRx registers to support in-circuit emualators
329 ;; or debuggers set breakpoint in interrupt/exception context
332 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
335 add esp, 4 ; not for Cr1
344 pop dword [ebp + 5 * 4]
347 ;; UINT32 Gdtr[2], Idtr[2];
348 ;; Best not let anyone mess with these particular registers...
352 pop dword [ebp + 3 * 4]
354 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
355 ;; NOTE - modified segment registers could hang the debugger... We
356 ;; could attempt to insulate ourselves against this possibility,
357 ;; but that poses risks as well.
363 pop dword [ebp + 4 * 4]
366 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
369 add esp, 4 ; not for ebp
370 add esp, 4 ; not for esp
381 cmp dword [esp - 16], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
383 cmp dword [esp - 20], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
391 cmp dword [ASM_PFX(mDoFarReturnFlag)], 0 ; Check if need to do far return instead of IRET
393 push dword [esp + 8] ; save EFLAGS
395 push dword [esp - 8] ; save CS in new location
396 push dword [esp - 8] ; save EIP in new location
397 push dword [esp - 8] ; save EFLAGS in new location
398 popfd ; restore EFLAGS
404 ;---------------------------------------;
405 ; _AsmGetTemplateAddressMap ;
406 ;----------------------------------------------------------------------------;
409 ; AsmGetTemplateAddressMap (
410 ; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
413 ; Routine Description:
415 ; Return address map of interrupt handler template so that C code can generate
426 ; Input: [ebp][0] = Original ebp
427 ; [ebp][4] = Return address
432 ;-----------------------------------------------------------------------------;
433 global ASM_PFX(AsmGetTemplateAddressMap)
434 ASM_PFX(AsmGetTemplateAddressMap):
439 mov ebx, dword [ebp + 0x8]
440 mov dword [ebx], AsmIdtVectorBegin
441 mov dword [ebx + 0x4], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
442 mov dword [ebx + 0x8], HookAfterStubBegin
448 ;-------------------------------------------------------------------------------------
449 ; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
450 ;-------------------------------------------------------------------------------------
451 global ASM_PFX(AsmVectorNumFixup)
452 ASM_PFX(AsmVectorNumFixup):
453 mov eax, dword [esp + 8]
455 mov [ecx + (VectorNum - HookAfterStubBegin)], al