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