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