CpuAsm.S revision 01a1c0fc9e60dfd6b26bd6d9aa9c3a6242bbb608
1#------------------------------------------------------------------------------
2#*
3#*   Copyright (c) 2006 - 2009, 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#
28ExternalVectorTablePtr:
29    .byte      0, 0, 0, 0
30
31ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)
32ASM_PFX(InitializeExternalVectorTablePtr):
33    movl    4(%esp), %eax
34    movl    %eax, ExternalVectorTablePtr
35    ret
36
37#------------------------------------------------------------------------------
38# VOID
39# SetCodeSelector (
40#   UINT16 Selector
41#   );
42#------------------------------------------------------------------------------
43ASM_GLOBAL ASM_PFX(SetCodeSelector)
44ASM_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)
51setCodeSelectorLongJump:
52    addl    $0x10, %esp
53    ret
54
55#------------------------------------------------------------------------------
56# VOID
57# SetDataSelectors (
58#   UINT16 Selector
59#   );
60#------------------------------------------------------------------------------
61ASM_GLOBAL ASM_PFX(SetDataSelectors)
62ASM_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
76ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
77ASM_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
98NoErrorCode:
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
129HasErrorCode:
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    #
158CommonInterruptEntry_al_0000:
159    jmp CommonInterruptEntry_al_0000
160
161ErrorCodeAndVectorOnStack:
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#; clear Dr7 while executing debugger itself
262    xorl    %eax, %eax
263    movl    %eax, %dr7
264
265    movl    %dr6, %eax
266    pushl   %eax
267#; insure all status bits in dr6 are clear...
268    xorl    %eax, %eax
269    movl    %eax, %dr6
270
271    movl    %dr3, %eax
272    pushl   %eax
273    movl    %dr2, %eax
274    pushl   %eax
275    movl    %dr1, %eax
276    pushl   %eax
277    movl    %dr0, %eax
278    pushl   %eax
279
280#; FX_SAVE_STATE_IA32 FxSaveState;
281    subl    $512, %esp
282    movl    %esp, %edi
283    .byte      0x0f, 0x0ae, 0x07 #fxsave [edi]
284
285#; UINT32  ExceptionData;
286    pushl   8(%ebp)
287
288#; call into exception handler
289    movl    ExternalVectorTablePtr, %eax  # get the interrupt vectors base
290    orl     %eax, %eax                        # NULL?
291    jz      nullExternalExceptionHandler
292
293    mov     4(%ebp), %ecx
294    movl    (%eax,%ecx,4), %eax
295    orl     %eax, %eax                        # NULL?
296    jz      nullExternalExceptionHandler
297
298#; Prepare parameter and call
299    movl    %esp, %edx
300    pushl   %edx
301    movl    4(%ebp), %edx
302    pushl   %edx
303
304    #
305    # Call External Exception Handler
306    #
307    call    *%eax
308    addl    $8, %esp
309
310nullExternalExceptionHandler:
311
312    cli
313#; UINT32  ExceptionData;
314    addl    $4, %esp
315
316#; FX_SAVE_STATE_IA32 FxSaveState;
317    movl    %esp, %esi
318    .byte      0x0f, 0x0ae, 0x0e # fxrstor [esi]
319    addl    $512, %esp
320
321#; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
322    popl    %eax
323    movl    %eax, %dr0
324    popl    %eax
325    movl    %eax, %dr1
326    popl    %eax
327    movl    %eax, %dr2
328    popl    %eax
329    movl    %eax, %dr3
330#; skip restore of dr6.  We cleared dr6 during the context save.
331    addl    $4, %esp
332    popl    %eax
333    movl    %eax, %dr7
334
335#; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
336    popl    %eax
337    movl    %eax, %cr0
338    addl    $4, %esp    # not for Cr1
339    popl    %eax
340    movl    %eax, %cr2
341    popl    %eax
342    movl    %eax, %cr3
343    popl    %eax
344    movl    %eax, %cr4
345
346#; UINT32  EFlags;
347    popl    20(%ebp)
348
349#; UINT32  Ldtr, Tr;
350#; UINT32  Gdtr[2], Idtr[2];
351#; Best not let anyone mess with these particular registers...
352    addl    $24, %esp
353
354#; UINT32  Eip;
355    popl    12(%ebp)
356
357#; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
358#; NOTE - modified segment registers could hang the debugger...  We
359#;        could attempt to insulate ourselves against this possibility,
360#;        but that poses risks as well.
361#;
362    popl    %gs
363    popl    %fs
364    popl    %es
365    popl    %ds
366    popl    16(%ebp)
367    popl    %ss
368
369#; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
370    popl    %edi
371    popl    %esi
372    addl    $4, %esp   # not for ebp
373    addl    $4, %esp   # not for esp
374    popl    %ebx
375    popl    %edx
376    popl    %ecx
377    popl    %eax
378
379    movl    %ebp, %esp
380    popl    %ebp
381    addl    $8, %esp
382    iretl
383
384
385#END
386
387