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