]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S
Import two CPU Exception Handler Library instances: SecPeiCpuExceptionHandler.inf...
[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 #
217 # Fall through to join main routine code
218 # at ErrorCodeAndVectorOnStack
219 #
220 CommonInterruptEntry_al_0000:
221 jmp CommonInterruptEntry_al_0000
222
223 ErrorCodeAndVectorOnStack:
224 pushl %ebp
225 movl %esp, %ebp
226
227 #
228 # Stack:
229 # +---------------------+
230 # + EFlags +
231 # +---------------------+
232 # + CS +
233 # +---------------------+
234 # + EIP +
235 # +---------------------+
236 # + Error Code +
237 # +---------------------+
238 # + Vector Number +
239 # +---------------------+
240 # + EBP +
241 # +---------------------+ <-- EBP
242 #
243
244 #
245 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
246 # is 16-byte aligned
247 #
248 andl $0x0fffffff0, %esp
249 subl $12, %esp
250
251 #; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
252 pushl %eax
253 pushl %ecx
254 pushl %edx
255 pushl %ebx
256 leal 24(%ebp), %ecx
257 pushl %ecx # ESP
258 pushl (%ebp) # EBP
259 pushl %esi
260 pushl %edi
261
262 #; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
263 movl %ss, %eax
264 pushl %eax
265 movzwl 16(%ebp), %eax
266 pushl %eax
267 movl %ds, %eax
268 pushl %eax
269 movl %es, %eax
270 pushl %eax
271 movl %fs, %eax
272 pushl %eax
273 movl %gs, %eax
274 pushl %eax
275
276 #; UINT32 Eip;
277 movl 12(%ebp), %eax
278 pushl %eax
279
280 #; UINT32 Gdtr[2], Idtr[2];
281 subl $8, %esp
282 sidt (%esp)
283 movl 2(%esp), %eax
284 xchgl (%esp), %eax
285 andl $0x0FFFF, %eax
286 movl %eax, 4(%esp)
287
288 subl $8, %esp
289 sgdt (%esp)
290 movl 2(%esp), %eax
291 xchgl (%esp), %eax
292 andl $0x0FFFF, %eax
293 movl %eax, 4(%esp)
294
295 #; UINT32 Ldtr, Tr;
296 xorl %eax, %eax
297 str %ax
298 pushl %eax
299 sldt %ax
300 pushl %eax
301
302 #; UINT32 EFlags;
303 movl 20(%ebp), %eax
304 pushl %eax
305
306 #; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
307 movl %cr4, %eax
308 orl $0x208, %eax
309 movl %eax, %cr4
310 pushl %eax
311 movl %cr3, %eax
312 pushl %eax
313 movl %cr2, %eax
314 pushl %eax
315 xorl %eax, %eax
316 pushl %eax
317 movl %cr0, %eax
318 pushl %eax
319
320 #; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
321 movl %dr7, %eax
322 pushl %eax
323 movl %dr6, %eax
324 pushl %eax
325 movl %dr3, %eax
326 pushl %eax
327 movl %dr2, %eax
328 pushl %eax
329 movl %dr1, %eax
330 pushl %eax
331 movl %dr0, %eax
332 pushl %eax
333
334 #; FX_SAVE_STATE_IA32 FxSaveState;
335 subl $512, %esp
336 movl %esp, %edi
337 .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]
338
339 #; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
340 cld
341
342 #; UINT32 ExceptionData;
343 pushl 8(%ebp)
344
345 #; Prepare parameter and call
346 movl %esp, %edx
347 pushl %edx
348 movl 4(%ebp), %edx
349 pushl %edx
350
351 #
352 # Call External Exception Handler
353 #
354 call ASM_PFX(CommonExceptionHandler)
355 addl $8, %esp
356
357 cli
358 #; UINT32 ExceptionData;
359 addl $4, %esp
360
361 #; FX_SAVE_STATE_IA32 FxSaveState;
362 movl %esp, %esi
363 .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]
364 addl $512, %esp
365
366 #; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
367 #; Skip restoration of DRx registers to support in-circuit emualators
368 #; or debuggers set breakpoint in interrupt/exception context
369 addl $24, %esp
370
371 #; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
372 popl %eax
373 movl %eax, %cr0
374 addl $4, %esp # not for Cr1
375 popl %eax
376 movl %eax, %cr2
377 popl %eax
378 movl %eax, %cr3
379 popl %eax
380 movl %eax, %cr4
381
382 #; UINT32 EFlags;
383 popl 20(%ebp)
384
385 #; UINT32 Ldtr, Tr;
386 #; UINT32 Gdtr[2], Idtr[2];
387 #; Best not let anyone mess with these particular registers...
388 addl $24, %esp
389
390 #; UINT32 Eip;
391 popl 12(%ebp)
392
393 #; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
394 #; NOTE - modified segment registers could hang the debugger... We
395 #; could attempt to insulate ourselves against this possibility,
396 #; but that poses risks as well.
397 #;
398 popl %gs
399 popl %fs
400 popl %es
401 popl %ds
402 popl 16(%ebp)
403 popl %ss
404
405 #; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
406 popl %edi
407 popl %esi
408 addl $4, %esp # not for ebp
409 addl $4, %esp # not for esp
410 popl %ebx
411 popl %edx
412 popl %ecx
413 popl %eax
414
415 movl %ebp, %esp
416 popl %ebp
417 addl $8, %esp
418 iretl
419
420
421 #---------------------------------------;
422 # _GetTemplateAddressMap ;
423 #----------------------------------------------------------------------------;
424 #
425 # Protocol prototype
426 # GetTemplateAddressMap (
427 # EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
428 # );
429 #
430 # Routine Description:
431 #
432 # Return address map of interrupt handler template so that C code can generate
433 # interrupt table.
434 #
435 # Arguments:
436 #
437 #
438 # Returns:
439 #
440 # Nothing
441 #
442 #
443 # Input: [ebp][0] = Original ebp
444 # [ebp][4] = Return address
445 #
446 # Output: Nothing
447 #
448 # Destroys: Nothing
449 #-----------------------------------------------------------------------------;
450 #-------------------------------------------------------------------------------------
451 # AsmGetAddressMap (&AddressMap);
452 #-------------------------------------------------------------------------------------
453 ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
454 ASM_PFX(GetTemplateAddressMap):
455
456 pushl %ebp
457 movl %esp,%ebp
458 pushal
459
460 movl 0x8(%ebp), %ebx
461 movl $Exception0Handle, (%ebx)
462 movl $(Exception1Handle - Exception0Handle), 0x4(%ebx)
463
464 popal
465 popl %ebp
466 ret
467