]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm
UefiCpuPkg: CpuExceptionHandlerLib: Make self modifying code work with Xcode
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / Ia32 / ExceptionHandlerAsm.asm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
3 ; This program and the accompanying materials
4 ; are licensed and made available under the terms and conditions of the BSD License
5 ; which accompanies this distribution. The full text of the license may be found at
6 ; http://opensource.org/licenses/bsd-license.php.
7 ;
8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10 ;
11 ; Module Name:
12 ;
13 ; ExceptionHandlerAsm.Asm
14 ;
15 ; Abstract:
16 ;
17 ; IA32 CPU Exception Handler
18 ;
19 ; Notes:
20 ;
21 ;------------------------------------------------------------------------------
22
23 .686
24 .model flat,C
25
26 ;
27 ; CommonExceptionHandler()
28 ;
29 CommonExceptionHandler PROTO C
30
31 .data
32
33 EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
34 EXTRN mDoFarReturnFlag:DWORD ; Do far return flag
35
36 .code
37
38 ALIGN 8
39
40 ;
41 ; exception handler stub table
42 ;
43 AsmIdtVectorBegin:
44 REPEAT 32
45 db 6ah ; push #VectorNum
46 db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
47 push eax
48 mov eax, CommonInterruptEntry
49 jmp eax
50 ENDM
51 AsmIdtVectorEnd:
52
53 HookAfterStubBegin:
54 db 6ah ; push
55 VectorNum:
56 db 0 ; 0 will be fixed
57 push eax
58 mov eax, HookAfterStubHeaderEnd
59 jmp eax
60 HookAfterStubHeaderEnd:
61 pop eax
62 sub esp, 8 ; reserve room for filling exception data later
63 push [esp + 8]
64 xchg ecx, [esp] ; get vector number
65 bt mErrorCodeFlag, ecx
66 jnc @F
67 push [esp] ; addition push if exception data needed
68 @@:
69 xchg ecx, [esp] ; restore ecx
70 push eax
71
72 ;----------------------------------------------------------------------------;
73 ; CommonInterruptEntry ;
74 ;----------------------------------------------------------------------------;
75 ; The follow algorithm is used for the common interrupt routine.
76 ; Entry from each interrupt with a push eax and eax=interrupt number
77 ; Stack:
78 ; +---------------------+
79 ; + EFlags +
80 ; +---------------------+
81 ; + CS +
82 ; +---------------------+
83 ; + EIP +
84 ; +---------------------+
85 ; + Error Code +
86 ; +---------------------+
87 ; + Vector Number +
88 ; +---------------------+
89 ; + EBP +
90 ; +---------------------+ <-- EBP
91 CommonInterruptEntry PROC PUBLIC
92 cli
93 pop eax
94 ;
95 ; All interrupt handlers are invoked through interrupt gates, so
96 ; IF flag automatically cleared at the entry point
97 ;
98
99 ;
100 ; Get vector number from top of stack
101 ;
102 xchg ecx, [esp]
103 and ecx, 0FFh ; Vector number should be less than 256
104 cmp ecx, 32 ; Intel reserved vector for exceptions?
105 jae NoErrorCode
106 bt mErrorCodeFlag, ecx
107 jc HasErrorCode
108
109 NoErrorCode:
110
111 ;
112 ; Stack:
113 ; +---------------------+
114 ; + EFlags +
115 ; +---------------------+
116 ; + CS +
117 ; +---------------------+
118 ; + EIP +
119 ; +---------------------+
120 ; + ECX +
121 ; +---------------------+ <-- ESP
122 ;
123 ; Registers:
124 ; ECX - Vector Number
125 ;
126
127 ;
128 ; Put Vector Number on stack
129 ;
130 push ecx
131
132 ;
133 ; Put 0 (dummy) error code on stack, and restore ECX
134 ;
135 xor ecx, ecx ; ECX = 0
136 xchg ecx, [esp+4]
137
138 jmp ErrorCodeAndVectorOnStack
139
140 HasErrorCode:
141
142 ;
143 ; Stack:
144 ; +---------------------+
145 ; + EFlags +
146 ; +---------------------+
147 ; + CS +
148 ; +---------------------+
149 ; + EIP +
150 ; +---------------------+
151 ; + Error Code +
152 ; +---------------------+
153 ; + ECX +
154 ; +---------------------+ <-- ESP
155 ;
156 ; Registers:
157 ; ECX - Vector Number
158 ;
159
160 ;
161 ; Put Vector Number on stack and restore ECX
162 ;
163 xchg ecx, [esp]
164
165 ErrorCodeAndVectorOnStack:
166 push ebp
167 mov ebp, esp
168
169 ;
170 ; Stack:
171 ; +---------------------+
172 ; + EFlags +
173 ; +---------------------+
174 ; + CS +
175 ; +---------------------+
176 ; + EIP +
177 ; +---------------------+
178 ; + Error Code +
179 ; +---------------------+
180 ; + Vector Number +
181 ; +---------------------+
182 ; + EBP +
183 ; +---------------------+ <-- EBP
184 ;
185
186 ;
187 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
188 ; is 16-byte aligned
189 ;
190 and esp, 0fffffff0h
191 sub esp, 12
192
193 sub esp, 8
194 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
195 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
196
197 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
198 push eax
199 push ecx
200 push edx
201 push ebx
202 lea ecx, [ebp + 6 * 4]
203 push ecx ; ESP
204 push dword ptr [ebp] ; EBP
205 push esi
206 push edi
207
208 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
209 mov eax, ss
210 push eax
211 movzx eax, word ptr [ebp + 4 * 4]
212 push eax
213 mov eax, ds
214 push eax
215 mov eax, es
216 push eax
217 mov eax, fs
218 push eax
219 mov eax, gs
220 push eax
221
222 ;; UINT32 Eip;
223 mov eax, [ebp + 3 * 4]
224 push eax
225
226 ;; UINT32 Gdtr[2], Idtr[2];
227 sub esp, 8
228 sidt [esp]
229 mov eax, [esp + 2]
230 xchg eax, [esp]
231 and eax, 0FFFFh
232 mov [esp+4], eax
233
234 sub esp, 8
235 sgdt [esp]
236 mov eax, [esp + 2]
237 xchg eax, [esp]
238 and eax, 0FFFFh
239 mov [esp+4], eax
240
241 ;; UINT32 Ldtr, Tr;
242 xor eax, eax
243 str ax
244 push eax
245 sldt ax
246 push eax
247
248 ;; UINT32 EFlags;
249 mov eax, [ebp + 5 * 4]
250 push eax
251
252 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
253 mov eax, cr4
254 or eax, 208h
255 mov cr4, eax
256 push eax
257 mov eax, cr3
258 push eax
259 mov eax, cr2
260 push eax
261 xor eax, eax
262 push eax
263 mov eax, cr0
264 push eax
265
266 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
267 mov eax, dr7
268 push eax
269 mov eax, dr6
270 push eax
271 mov eax, dr3
272 push eax
273 mov eax, dr2
274 push eax
275 mov eax, dr1
276 push eax
277 mov eax, dr0
278 push eax
279
280 ;; FX_SAVE_STATE_IA32 FxSaveState;
281 sub esp, 512
282 mov edi, esp
283 db 0fh, 0aeh, 07h ;fxsave [edi]
284
285 ;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
286 cld
287
288 ;; UINT32 ExceptionData;
289 push dword ptr [ebp + 2 * 4]
290
291 ;; Prepare parameter and call
292 mov edx, esp
293 push edx
294 mov edx, dword ptr [ebp + 1 * 4]
295 push edx
296
297 ;
298 ; Call External Exception Handler
299 ;
300 mov eax, CommonExceptionHandler
301 call eax
302 add esp, 8
303
304 cli
305 ;; UINT32 ExceptionData;
306 add esp, 4
307
308 ;; FX_SAVE_STATE_IA32 FxSaveState;
309 mov esi, esp
310 db 0fh, 0aeh, 0eh ; fxrstor [esi]
311 add esp, 512
312
313 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
314 ;; Skip restoration of DRx registers to support in-circuit emualators
315 ;; or debuggers set breakpoint in interrupt/exception context
316 add esp, 4 * 6
317
318 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
319 pop eax
320 mov cr0, eax
321 add esp, 4 ; not for Cr1
322 pop eax
323 mov cr2, eax
324 pop eax
325 mov cr3, eax
326 pop eax
327 mov cr4, eax
328
329 ;; UINT32 EFlags;
330 pop dword ptr [ebp + 5 * 4]
331
332 ;; UINT32 Ldtr, Tr;
333 ;; UINT32 Gdtr[2], Idtr[2];
334 ;; Best not let anyone mess with these particular registers...
335 add esp, 24
336
337 ;; UINT32 Eip;
338 pop dword ptr [ebp + 3 * 4]
339
340 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
341 ;; NOTE - modified segment registers could hang the debugger... We
342 ;; could attempt to insulate ourselves against this possibility,
343 ;; but that poses risks as well.
344 ;;
345 pop gs
346 pop fs
347 pop es
348 pop ds
349 pop dword ptr [ebp + 4 * 4]
350 pop ss
351
352 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
353 pop edi
354 pop esi
355 add esp, 4 ; not for ebp
356 add esp, 4 ; not for esp
357 pop ebx
358 pop edx
359 pop ecx
360 pop eax
361
362 pop dword ptr [ebp - 8]
363 pop dword ptr [ebp - 4]
364 mov esp, ebp
365 pop ebp
366 add esp, 8
367 cmp dword ptr [esp - 16], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
368 jz DoReturn
369 cmp dword ptr [esp - 20], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
370 jz ErrorCode
371 jmp dword ptr [esp - 16]
372 ErrorCode:
373 sub esp, 4
374 jmp dword ptr [esp - 12]
375
376 DoReturn:
377 cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET
378 jz DoIret
379 push [esp + 8] ; save EFLAGS
380 add esp, 16
381 push [esp - 8] ; save CS in new location
382 push [esp - 8] ; save EIP in new location
383 push [esp - 8] ; save EFLAGS in new location
384 popfd ; restore EFLAGS
385 retf ; far return
386
387 DoIret:
388 iretd
389
390 CommonInterruptEntry ENDP
391
392 ;---------------------------------------;
393 ; _AsmGetTemplateAddressMap ;
394 ;----------------------------------------------------------------------------;
395 ;
396 ; Protocol prototype
397 ; AsmGetTemplateAddressMap (
398 ; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
399 ; );
400 ;
401 ; Routine Description:
402 ;
403 ; Return address map of interrupt handler template so that C code can generate
404 ; interrupt table.
405 ;
406 ; Arguments:
407 ;
408 ;
409 ; Returns:
410 ;
411 ; Nothing
412 ;
413 ;
414 ; Input: [ebp][0] = Original ebp
415 ; [ebp][4] = Return address
416 ;
417 ; Output: Nothing
418 ;
419 ; Destroys: Nothing
420 ;-----------------------------------------------------------------------------;
421 AsmGetTemplateAddressMap proc near public
422 push ebp ; C prolog
423 mov ebp, esp
424 pushad
425
426 mov ebx, dword ptr [ebp + 08h]
427 mov dword ptr [ebx], AsmIdtVectorBegin
428 mov dword ptr [ebx + 4h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
429 mov dword ptr [ebx + 8h], HookAfterStubBegin
430
431 popad
432 pop ebp
433 ret
434 AsmGetTemplateAddressMap ENDP
435
436 ;-------------------------------------------------------------------------------------
437 ; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
438 ;-------------------------------------------------------------------------------------
439 AsmVectorNumFixup proc near public
440 mov eax, dword ptr [esp + 8]
441 mov ecx, [esp + 4]
442 mov [ecx + (VectorNum - HookAfterStubBegin)], al
443 ret
444 AsmVectorNumFixup ENDP
445 END