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