]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm
Add CPU DXE driver for IA32 & X64 processor architectures.
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / Ia32 / CpuAsm.asm
CommitLineData
a47463f2 1 TITLE CpuAsm.asm:\r
2;------------------------------------------------------------------------------\r
3;*\r
4;* Copyright 2006 - 2009, Intel Corporation\r
5;* All rights reserved. This program and the accompanying materials\r
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
259;; clear Dr7 while executing debugger itself\r
260 xor eax, eax\r
261 mov dr7, eax\r
262\r
263 mov eax, dr6\r
264 push eax\r
265;; insure all status bits in dr6 are clear...\r
266 xor eax, eax\r
267 mov dr6, eax\r
268\r
269 mov eax, dr3\r
270 push eax\r
271 mov eax, dr2\r
272 push eax\r
273 mov eax, dr1\r
274 push eax\r
275 mov eax, dr0\r
276 push eax\r
277\r
278;; FX_SAVE_STATE_IA32 FxSaveState;\r
279 sub esp, 512\r
280 mov edi, esp\r
281 db 0fh, 0aeh, 07h ;fxsave [edi]\r
282\r
283;; UINT32 ExceptionData;\r
284 push dword ptr [ebp + 2 * 4]\r
285\r
286;; call into exception handler\r
287 mov eax, ExternalVectorTablePtr ; get the interrupt vectors base\r
288 or eax, eax ; NULL?\r
289 jz nullExternalExceptionHandler\r
290\r
291 mov ecx, [ebp + 4]\r
292 mov eax, [eax + ecx * 4]\r
293 or eax, eax ; NULL?\r
294 jz nullExternalExceptionHandler\r
295\r
296;; Prepare parameter and call\r
297 mov edx, esp\r
298 push edx\r
299 mov edx, dword ptr [ebp + 1 * 4]\r
300 push edx\r
301\r
302 ;\r
303 ; Call External Exception Handler\r
304 ;\r
305 call eax\r
306 add esp, 8\r
307\r
308nullExternalExceptionHandler:\r
309\r
310 cli\r
311;; UINT32 ExceptionData;\r
312 add esp, 4\r
313\r
314;; FX_SAVE_STATE_IA32 FxSaveState;\r
315 mov esi, esp\r
316 db 0fh, 0aeh, 0eh ; fxrstor [esi]\r
317 add esp, 512\r
318\r
319;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
320 pop eax\r
321 mov dr0, eax\r
322 pop eax\r
323 mov dr1, eax\r
324 pop eax\r
325 mov dr2, eax\r
326 pop eax\r
327 mov dr3, eax\r
328;; skip restore of dr6. We cleared dr6 during the context save.\r
329 add esp, 4\r
330 pop eax\r
331 mov dr7, eax\r
332\r
333;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
334 pop eax\r
335 mov cr0, eax\r
336 add esp, 4 ; not for Cr1\r
337 pop eax\r
338 mov cr2, eax\r
339 pop eax\r
340 mov cr3, eax\r
341 pop eax\r
342 mov cr4, eax\r
343\r
344;; UINT32 EFlags;\r
345 pop dword ptr [ebp + 5 * 4]\r
346\r
347;; UINT32 Ldtr, Tr;\r
348;; UINT32 Gdtr[2], Idtr[2];\r
349;; Best not let anyone mess with these particular registers...\r
350 add esp, 24\r
351\r
352;; UINT32 Eip;\r
353 pop dword ptr [ebp + 3 * 4]\r
354\r
355;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
356;; NOTE - modified segment registers could hang the debugger... We\r
357;; could attempt to insulate ourselves against this possibility,\r
358;; but that poses risks as well.\r
359;;\r
360 pop gs\r
361 pop fs\r
362 pop es\r
363 pop ds\r
364 pop dword ptr [ebp + 4 * 4]\r
365 pop ss\r
366\r
367;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
368 pop edi\r
369 pop esi\r
370 add esp, 4 ; not for ebp\r
371 add esp, 4 ; not for esp\r
372 pop ebx\r
373 pop edx\r
374 pop ecx\r
375 pop eax\r
376\r
377 mov esp, ebp\r
378 pop ebp\r
379 add esp, 8\r
380 iretd\r
381\r
382CommonInterruptEntry ENDP\r
383\r
384END\r