]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S
Remove CPU dead loop code from IA32 assembly codes.
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / Ia32 / ExceptionHandlerAsm.S
1 #------------------------------------------------------------------------------
2 #*
3 #* Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
4 #* This program and the accompanying materials
5 #* are licensed and made available under the terms and conditions of the BSD License
6 #* which accompanies this distribution. The full text of the license may be found at
7 #* http://opensource.org/licenses/bsd-license.php
8 #*
9 #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #*
12 #* ExceptionHandlerAsm.S
13 #*
14 #* Abstract:
15 #*
16 #* IA32 CPU Exception Handler
17 #
18 #------------------------------------------------------------------------------
19
20
21
22
23
24 #.MMX
25 #.XMM
26
27 ASM_GLOBAL ASM_PFX(CommonExceptionHandler)
28 ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
29
30 #EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
31
32 .text
33
34 #
35 # exception handler stub table
36 #
37 Exception0Handle:
38 pushl $0
39 jmp ASM_PFX(CommonInterruptEntry)
40 Exception1Handle:
41 pushl $1
42 jmp ASM_PFX(CommonInterruptEntry)
43 Exception2Handle:
44 pushl $2
45 jmp ASM_PFX(CommonInterruptEntry)
46 Exception3Handle:
47 pushl $3
48 jmp ASM_PFX(CommonInterruptEntry)
49 Exception4Handle:
50 pushl $4
51 jmp ASM_PFX(CommonInterruptEntry)
52 Exception5Handle:
53 pushl $5
54 jmp ASM_PFX(CommonInterruptEntry)
55 Exception6Handle:
56 pushl $6
57 jmp ASM_PFX(CommonInterruptEntry)
58 Exception7Handle:
59 pushl $7
60 jmp ASM_PFX(CommonInterruptEntry)
61 Exception8Handle:
62 pushl $8
63 jmp ASM_PFX(CommonInterruptEntry)
64 Exception9Handle:
65 pushl $9
66 jmp ASM_PFX(CommonInterruptEntry)
67 Exception10Handle:
68 pushl $10
69 jmp ASM_PFX(CommonInterruptEntry)
70 Exception11Handle:
71 pushl $11
72 jmp ASM_PFX(CommonInterruptEntry)
73 Exception12Handle:
74 pushl $12
75 jmp ASM_PFX(CommonInterruptEntry)
76 Exception13Handle:
77 pushl $13
78 jmp ASM_PFX(CommonInterruptEntry)
79 Exception14Handle:
80 pushl $14
81 jmp ASM_PFX(CommonInterruptEntry)
82 Exception15Handle:
83 pushl $15
84 jmp ASM_PFX(CommonInterruptEntry)
85 Exception16Handle:
86 pushl $16
87 jmp ASM_PFX(CommonInterruptEntry)
88 Exception17Handle:
89 pushl $17
90 jmp ASM_PFX(CommonInterruptEntry)
91 Exception18Handle:
92 pushl $18
93 jmp ASM_PFX(CommonInterruptEntry)
94 Exception19Handle:
95 pushl $19
96 jmp ASM_PFX(CommonInterruptEntry)
97 Exception20Handle:
98 pushl $20
99 jmp ASM_PFX(CommonInterruptEntry)
100 Exception21Handle:
101 pushl $21
102 jmp ASM_PFX(CommonInterruptEntry)
103 Exception22Handle:
104 pushl $22
105 jmp ASM_PFX(CommonInterruptEntry)
106 Exception23Handle:
107 pushl $23
108 jmp ASM_PFX(CommonInterruptEntry)
109 Exception24Handle:
110 pushl $24
111 jmp ASM_PFX(CommonInterruptEntry)
112 Exception25Handle:
113 pushl $25
114 jmp ASM_PFX(CommonInterruptEntry)
115 Exception26Handle:
116 pushl $26
117 jmp ASM_PFX(CommonInterruptEntry)
118 Exception27Handle:
119 pushl $27
120 jmp ASM_PFX(CommonInterruptEntry)
121 Exception28Handle:
122 pushl $28
123 jmp ASM_PFX(CommonInterruptEntry)
124 Exception29Handle:
125 pushl $29
126 jmp ASM_PFX(CommonInterruptEntry)
127 Exception30Handle:
128 pushl $30
129 jmp ASM_PFX(CommonInterruptEntry)
130 Exception31Handle:
131 pushl $31
132 jmp ASM_PFX(CommonInterruptEntry)
133
134 #---------------------------------------;
135 # CommonInterruptEntry ;
136 #---------------------------------------;
137 # The follow algorithm is used for the common interrupt routine.
138
139 ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
140 ASM_PFX(CommonInterruptEntry):
141 cli
142 #
143 # All interrupt handlers are invoked through interrupt gates, so
144 # IF flag automatically cleared at the entry point
145 #
146
147 #
148 # Calculate vector number
149 #
150 # Get the return address of call, actually, it is the
151 # address of vector number.
152 #
153 xchgl (%esp), %ecx
154 andl $0x0FFFF, %ecx
155 cmpl $32, %ecx # Intel reserved vector for exceptions?
156 jae NoErrorCode
157 bt %ecx, ASM_PFX(mErrorCodeFlag)
158 jc HasErrorCode
159
160 NoErrorCode:
161
162 #
163 # Stack:
164 # +---------------------+
165 # + EFlags +
166 # +---------------------+
167 # + CS +
168 # +---------------------+
169 # + EIP +
170 # +---------------------+
171 # + ECX +
172 # +---------------------+ <-- ESP
173 #
174 # Registers:
175 # ECX - Vector Number
176 #
177
178 #
179 # Put Vector Number on stack
180 #
181 pushl %ecx
182
183 #
184 # Put 0 (dummy) error code on stack, and restore ECX
185 #
186 xorl %ecx, %ecx # ECX = 0
187 xchgl 4(%esp), %ecx
188
189 jmp ErrorCodeAndVectorOnStack
190
191 HasErrorCode:
192
193 #
194 # Stack:
195 # +---------------------+
196 # + EFlags +
197 # +---------------------+
198 # + CS +
199 # +---------------------+
200 # + EIP +
201 # +---------------------+
202 # + Error Code +
203 # +---------------------+
204 # + ECX +
205 # +---------------------+ <-- ESP
206 #
207 # Registers:
208 # ECX - Vector Number
209 #
210
211 #
212 # Put Vector Number on stack and restore ECX
213 #
214 xchgl (%esp), %ecx
215
216 ErrorCodeAndVectorOnStack:
217 pushl %ebp
218 movl %esp, %ebp
219
220 #
221 # Stack:
222 # +---------------------+
223 # + EFlags +
224 # +---------------------+
225 # + CS +
226 # +---------------------+
227 # + EIP +
228 # +---------------------+
229 # + Error Code +
230 # +---------------------+
231 # + Vector Number +
232 # +---------------------+
233 # + EBP +
234 # +---------------------+ <-- EBP
235 #
236
237 #
238 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
239 # is 16-byte aligned
240 #
241 andl $0x0fffffff0, %esp
242 subl $12, %esp
243
244 #; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
245 pushl %eax
246 pushl %ecx
247 pushl %edx
248 pushl %ebx
249 leal 24(%ebp), %ecx
250 pushl %ecx # ESP
251 pushl (%ebp) # EBP
252 pushl %esi
253 pushl %edi
254
255 #; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
256 movl %ss, %eax
257 pushl %eax
258 movzwl 16(%ebp), %eax
259 pushl %eax
260 movl %ds, %eax
261 pushl %eax
262 movl %es, %eax
263 pushl %eax
264 movl %fs, %eax
265 pushl %eax
266 movl %gs, %eax
267 pushl %eax
268
269 #; UINT32 Eip;
270 movl 12(%ebp), %eax
271 pushl %eax
272
273 #; UINT32 Gdtr[2], Idtr[2];
274 subl $8, %esp
275 sidt (%esp)
276 movl 2(%esp), %eax
277 xchgl (%esp), %eax
278 andl $0x0FFFF, %eax
279 movl %eax, 4(%esp)
280
281 subl $8, %esp
282 sgdt (%esp)
283 movl 2(%esp), %eax
284 xchgl (%esp), %eax
285 andl $0x0FFFF, %eax
286 movl %eax, 4(%esp)
287
288 #; UINT32 Ldtr, Tr;
289 xorl %eax, %eax
290 str %ax
291 pushl %eax
292 sldt %ax
293 pushl %eax
294
295 #; UINT32 EFlags;
296 movl 20(%ebp), %eax
297 pushl %eax
298
299 #; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
300 movl %cr4, %eax
301 orl $0x208, %eax
302 movl %eax, %cr4
303 pushl %eax
304 movl %cr3, %eax
305 pushl %eax
306 movl %cr2, %eax
307 pushl %eax
308 xorl %eax, %eax
309 pushl %eax
310 movl %cr0, %eax
311 pushl %eax
312
313 #; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
314 movl %dr7, %eax
315 pushl %eax
316 movl %dr6, %eax
317 pushl %eax
318 movl %dr3, %eax
319 pushl %eax
320 movl %dr2, %eax
321 pushl %eax
322 movl %dr1, %eax
323 pushl %eax
324 movl %dr0, %eax
325 pushl %eax
326
327 #; FX_SAVE_STATE_IA32 FxSaveState;
328 subl $512, %esp
329 movl %esp, %edi
330 .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]
331
332 #; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
333 cld
334
335 #; UINT32 ExceptionData;
336 pushl 8(%ebp)
337
338 #; Prepare parameter and call
339 movl %esp, %edx
340 pushl %edx
341 movl 4(%ebp), %edx
342 pushl %edx
343
344 #
345 # Call External Exception Handler
346 #
347 call ASM_PFX(CommonExceptionHandler)
348 addl $8, %esp
349
350 cli
351 #; UINT32 ExceptionData;
352 addl $4, %esp
353
354 #; FX_SAVE_STATE_IA32 FxSaveState;
355 movl %esp, %esi
356 .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]
357 addl $512, %esp
358
359 #; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
360 #; Skip restoration of DRx registers to support in-circuit emualators
361 #; or debuggers set breakpoint in interrupt/exception context
362 addl $24, %esp
363
364 #; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
365 popl %eax
366 movl %eax, %cr0
367 addl $4, %esp # not for Cr1
368 popl %eax
369 movl %eax, %cr2
370 popl %eax
371 movl %eax, %cr3
372 popl %eax
373 movl %eax, %cr4
374
375 #; UINT32 EFlags;
376 popl 20(%ebp)
377
378 #; UINT32 Ldtr, Tr;
379 #; UINT32 Gdtr[2], Idtr[2];
380 #; Best not let anyone mess with these particular registers...
381 addl $24, %esp
382
383 #; UINT32 Eip;
384 popl 12(%ebp)
385
386 #; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
387 #; NOTE - modified segment registers could hang the debugger... We
388 #; could attempt to insulate ourselves against this possibility,
389 #; but that poses risks as well.
390 #;
391 popl %gs
392 popl %fs
393 popl %es
394 popl %ds
395 popl 16(%ebp)
396 popl %ss
397
398 #; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
399 popl %edi
400 popl %esi
401 addl $4, %esp # not for ebp
402 addl $4, %esp # not for esp
403 popl %ebx
404 popl %edx
405 popl %ecx
406 popl %eax
407
408 movl %ebp, %esp
409 popl %ebp
410 addl $8, %esp
411 iretl
412
413
414 #---------------------------------------;
415 # _GetTemplateAddressMap ;
416 #----------------------------------------------------------------------------;
417 #
418 # Protocol prototype
419 # GetTemplateAddressMap (
420 # EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
421 # );
422 #
423 # Routine Description:
424 #
425 # Return address map of interrupt handler template so that C code can generate
426 # interrupt table.
427 #
428 # Arguments:
429 #
430 #
431 # Returns:
432 #
433 # Nothing
434 #
435 #
436 # Input: [ebp][0] = Original ebp
437 # [ebp][4] = Return address
438 #
439 # Output: Nothing
440 #
441 # Destroys: Nothing
442 #-----------------------------------------------------------------------------;
443 #-------------------------------------------------------------------------------------
444 # AsmGetAddressMap (&AddressMap);
445 #-------------------------------------------------------------------------------------
446 ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
447 ASM_PFX(GetTemplateAddressMap):
448
449 pushl %ebp
450 movl %esp,%ebp
451 pushal
452
453 movl 0x8(%ebp), %ebx
454 movl $Exception0Handle, (%ebx)
455 movl $(Exception1Handle - Exception0Handle), 0x4(%ebx)
456
457 popal
458 popl %ebp
459 ret
460