]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S
Remove CPU dead loop code from IA32 assembly codes.
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / Ia32 / CpuAsm.S
... / ...
CommitLineData
1#------------------------------------------------------------------------------\r
2#*\r
3#* Copyright (c) 2006 - 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#* CpuAsm.S\r
13#*\r
14#* Abstract:\r
15#*\r
16#------------------------------------------------------------------------------\r
17\r
18\r
19#.MMX\r
20#.XMM\r
21\r
22#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions\r
23\r
24\r
25#\r
26# point to the external interrupt vector table\r
27#\r
28ExternalVectorTablePtr:\r
29 .byte 0, 0, 0, 0\r
30\r
31ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)\r
32ASM_PFX(InitializeExternalVectorTablePtr):\r
33 movl 4(%esp), %eax\r
34 movl %eax, ExternalVectorTablePtr\r
35 ret\r
36\r
37#------------------------------------------------------------------------------\r
38# VOID\r
39# SetCodeSelector (\r
40# UINT16 Selector\r
41# );\r
42#------------------------------------------------------------------------------\r
43ASM_GLOBAL ASM_PFX(SetCodeSelector)\r
44ASM_PFX(SetCodeSelector):\r
45 movl 4(%esp), %ecx\r
46 subl $0x10, %esp \r
47 leal setCodeSelectorLongJump, %eax \r
48 movl %eax, (%esp)\r
49 movw %cx, 4(%esp)\r
50 .byte 0xFF, 0x2C, 0x24 # jmp *(%esp) note:(FWORD jmp) \r
51setCodeSelectorLongJump:\r
52 addl $0x10, %esp \r
53 ret\r
54\r
55#------------------------------------------------------------------------------\r
56# VOID\r
57# SetDataSelectors (\r
58# UINT16 Selector\r
59# );\r
60#------------------------------------------------------------------------------\r
61ASM_GLOBAL ASM_PFX(SetDataSelectors)\r
62ASM_PFX(SetDataSelectors):\r
63 movl 4(%esp), %ecx\r
64 movw %cx, %ss\r
65 movw %cx, %ds\r
66 movw %cx, %es\r
67 movw %cx, %fs\r
68 movw %cx, %gs\r
69 ret\r
70\r
71#---------------------------------------;\r
72# CommonInterruptEntry ;\r
73#---------------------------------------;\r
74# The follow algorithm is used for the common interrupt routine.\r
75\r
76ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
77ASM_PFX(CommonInterruptEntry):\r
78 cli\r
79 #\r
80 # All interrupt handlers are invoked through interrupt gates, so\r
81 # IF flag automatically cleared at the entry point\r
82 #\r
83\r
84 #\r
85 # Calculate vector number\r
86 #\r
87 # Get the return address of call, actually, it is the\r
88 # address of vector number.\r
89 #\r
90 xchgl (%esp), %ecx\r
91 movw (%ecx), %cx\r
92 andl $0x0FFFF, %ecx\r
93 cmpl $32, %ecx # Intel reserved vector for exceptions?\r
94 jae NoErrorCode\r
95 bt %ecx, ASM_PFX(mErrorCodeFlag)\r
96 jc HasErrorCode\r
97\r
98NoErrorCode:\r
99\r
100 #\r
101 # Stack:\r
102 # +---------------------+\r
103 # + EFlags +\r
104 # +---------------------+\r
105 # + CS +\r
106 # +---------------------+\r
107 # + EIP +\r
108 # +---------------------+\r
109 # + ECX +\r
110 # +---------------------+ <-- ESP\r
111 #\r
112 # Registers:\r
113 # ECX - Vector Number\r
114 #\r
115\r
116 #\r
117 # Put Vector Number on stack\r
118 #\r
119 pushl %ecx\r
120\r
121 #\r
122 # Put 0 (dummy) error code on stack, and restore ECX\r
123 #\r
124 xorl %ecx, %ecx # ECX = 0\r
125 xchgl 4(%esp), %ecx\r
126\r
127 jmp ErrorCodeAndVectorOnStack\r
128\r
129HasErrorCode:\r
130\r
131 #\r
132 # Stack:\r
133 # +---------------------+\r
134 # + EFlags +\r
135 # +---------------------+\r
136 # + CS +\r
137 # +---------------------+\r
138 # + EIP +\r
139 # +---------------------+\r
140 # + Error Code +\r
141 # +---------------------+\r
142 # + ECX +\r
143 # +---------------------+ <-- ESP\r
144 #\r
145 # Registers:\r
146 # ECX - Vector Number\r
147 #\r
148\r
149 #\r
150 # Put Vector Number on stack and restore ECX\r
151 #\r
152 xchgl (%esp), %ecx \r
153\r
154ErrorCodeAndVectorOnStack:\r
155 pushl %ebp\r
156 movl %esp, %ebp\r
157\r
158 #\r
159 # Stack:\r
160 # +---------------------+\r
161 # + EFlags +\r
162 # +---------------------+\r
163 # + CS +\r
164 # +---------------------+\r
165 # + EIP +\r
166 # +---------------------+\r
167 # + Error Code +\r
168 # +---------------------+\r
169 # + Vector Number +\r
170 # +---------------------+\r
171 # + EBP +\r
172 # +---------------------+ <-- EBP\r
173 #\r
174\r
175 #\r
176 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
177 # is 16-byte aligned\r
178 #\r
179 andl $0x0fffffff0, %esp \r
180 subl $12, %esp\r
181\r
182#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
183 pushl %eax\r
184 pushl %ecx\r
185 pushl %edx\r
186 pushl %ebx\r
187 leal 24(%ebp), %ecx\r
188 pushl %ecx # ESP\r
189 pushl (%ebp) # EBP\r
190 pushl %esi\r
191 pushl %edi\r
192\r
193#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
194 movl %ss, %eax\r
195 pushl %eax\r
196 movzwl 16(%ebp), %eax \r
197 pushl %eax\r
198 movl %ds, %eax\r
199 pushl %eax\r
200 movl %es, %eax\r
201 pushl %eax\r
202 movl %fs, %eax\r
203 pushl %eax\r
204 movl %gs, %eax\r
205 pushl %eax\r
206\r
207#; UINT32 Eip;\r
208 movl 12(%ebp), %eax\r
209 pushl %eax\r
210\r
211#; UINT32 Gdtr[2], Idtr[2];\r
212 subl $8, %esp\r
213 sidt (%esp)\r
214 movl 2(%esp), %eax\r
215 xchgl (%esp), %eax\r
216 andl $0x0FFFF, %eax \r
217 movl %eax, 4(%esp)\r
218\r
219 subl $8, %esp\r
220 sgdt (%esp)\r
221 movl 2(%esp), %eax\r
222 xchgl (%esp), %eax\r
223 andl $0x0FFFF, %eax \r
224 movl %eax, 4(%esp)\r
225\r
226#; UINT32 Ldtr, Tr;\r
227 xorl %eax, %eax\r
228 str %ax\r
229 pushl %eax\r
230 sldt %ax\r
231 pushl %eax\r
232\r
233#; UINT32 EFlags;\r
234 movl 20(%ebp), %eax\r
235 pushl %eax\r
236\r
237#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
238 movl %cr4, %eax\r
239 orl $0x208, %eax\r
240 movl %eax, %cr4\r
241 pushl %eax\r
242 movl %cr3, %eax\r
243 pushl %eax\r
244 movl %cr2, %eax\r
245 pushl %eax\r
246 xorl %eax, %eax\r
247 pushl %eax\r
248 movl %cr0, %eax\r
249 pushl %eax\r
250\r
251#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
252 movl %dr7, %eax\r
253 pushl %eax\r
254 movl %dr6, %eax\r
255 pushl %eax\r
256 movl %dr3, %eax\r
257 pushl %eax\r
258 movl %dr2, %eax\r
259 pushl %eax\r
260 movl %dr1, %eax\r
261 pushl %eax\r
262 movl %dr0, %eax\r
263 pushl %eax\r
264\r
265#; FX_SAVE_STATE_IA32 FxSaveState;\r
266 subl $512, %esp\r
267 movl %esp, %edi\r
268 .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]\r
269\r
270#; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
271 cld\r
272\r
273#; UINT32 ExceptionData;\r
274 pushl 8(%ebp)\r
275\r
276#; call into exception handler\r
277 movl ExternalVectorTablePtr, %eax # get the interrupt vectors base\r
278 orl %eax, %eax # NULL?\r
279 jz nullExternalExceptionHandler\r
280\r
281 mov 4(%ebp), %ecx\r
282 movl (%eax,%ecx,4), %eax\r
283 orl %eax, %eax # NULL?\r
284 jz nullExternalExceptionHandler\r
285\r
286#; Prepare parameter and call\r
287 movl %esp, %edx\r
288 pushl %edx\r
289 movl 4(%ebp), %edx\r
290 pushl %edx\r
291\r
292 #\r
293 # Call External Exception Handler\r
294 #\r
295 call *%eax\r
296 addl $8, %esp\r
297\r
298nullExternalExceptionHandler:\r
299\r
300 cli\r
301#; UINT32 ExceptionData;\r
302 addl $4, %esp\r
303\r
304#; FX_SAVE_STATE_IA32 FxSaveState;\r
305 movl %esp, %esi\r
306 .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]\r
307 addl $512, %esp\r
308\r
309#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
310#; Skip restoration of DRx registers to support in-circuit emualators\r
311#; or debuggers set breakpoint in interrupt/exception context\r
312 addl $24, %esp\r
313\r
314#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
315 popl %eax\r
316 movl %eax, %cr0\r
317 addl $4, %esp # not for Cr1\r
318 popl %eax\r
319 movl %eax, %cr2\r
320 popl %eax\r
321 movl %eax, %cr3\r
322 popl %eax\r
323 movl %eax, %cr4\r
324\r
325#; UINT32 EFlags;\r
326 popl 20(%ebp)\r
327\r
328#; UINT32 Ldtr, Tr;\r
329#; UINT32 Gdtr[2], Idtr[2];\r
330#; Best not let anyone mess with these particular registers...\r
331 addl $24, %esp\r
332\r
333#; UINT32 Eip;\r
334 popl 12(%ebp)\r
335\r
336#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
337#; NOTE - modified segment registers could hang the debugger... We\r
338#; could attempt to insulate ourselves against this possibility,\r
339#; but that poses risks as well.\r
340#;\r
341 popl %gs\r
342 popl %fs\r
343 popl %es\r
344 popl %ds\r
345 popl 16(%ebp)\r
346 popl %ss\r
347\r
348#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
349 popl %edi\r
350 popl %esi\r
351 addl $4, %esp # not for ebp\r
352 addl $4, %esp # not for esp\r
353 popl %ebx\r
354 popl %edx\r
355 popl %ecx\r
356 popl %eax\r
357\r
358 movl %ebp, %esp\r
359 popl %ebp\r
360 addl $8, %esp\r
361 iretl\r
362\r
363\r
364#END\r
365\r