3668c083 |
1 | # TITLE CpuAsm.S: |
a47463f2 |
2 | |
3 | #------------------------------------------------------------------------------ |
4 | #* |
5 | #* Copyright 2008 - 2009, Intel Corporation |
6 | #* All rights reserved. This program and the accompanying materials |
7 | #* are licensed and made available under the terms and conditions of the BSD License |
8 | #* which accompanies this distribution. The full text of the license may be found at |
9 | #* http://opensource.org/licenses/bsd-license.php |
10 | #* |
11 | #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, |
12 | #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. |
13 | #* |
14 | #* CpuAsm.S |
15 | #* |
16 | #* Abstract: |
17 | #* |
18 | #------------------------------------------------------------------------------ |
19 | |
20 | |
21 | #text SEGMENT |
22 | |
23 | |
24 | #EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions |
25 | |
26 | |
27 | # |
28 | # point to the external interrupt vector table |
29 | # |
30 | ExternalVectorTablePtr: |
31 | .byte 0, 0, 0, 0, 0, 0, 0, 0 |
32 | |
a47463f2 |
33 | ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr) |
34 | ASM_PFX(InitializeExternalVectorTablePtr): |
3668c083 |
35 | lea ExternalVectorTablePtr(%rip), %rax # save vector number |
36 | mov %rcx, (%rax) |
a47463f2 |
37 | ret |
38 | |
39 | |
40 | #------------------------------------------------------------------------------ |
41 | # VOID |
42 | # SetCodeSelector ( |
43 | # UINT16 Selector |
44 | # ); |
45 | #------------------------------------------------------------------------------ |
a47463f2 |
46 | ASM_GLOBAL ASM_PFX(SetCodeSelector) |
47 | ASM_PFX(SetCodeSelector): |
3668c083 |
48 | subq $0x10, %rsp |
49 | leaq setCodeSelectorLongJump(%rip), %rax |
50 | movq %rax, (%rsp) |
51 | movw %cx, 4(%rsp) |
52 | .byte 0xFF, 0x2C, 0x24 # jmp (%rsp) note:fword jmp |
a47463f2 |
53 | setCodeSelectorLongJump: |
3668c083 |
54 | addq $0x10, %rsp |
a47463f2 |
55 | ret |
56 | |
57 | #------------------------------------------------------------------------------ |
58 | # VOID |
59 | # SetDataSelectors ( |
60 | # UINT16 Selector |
61 | # ); |
62 | #------------------------------------------------------------------------------ |
a47463f2 |
63 | ASM_GLOBAL ASM_PFX(SetDataSelectors) |
64 | ASM_PFX(SetDataSelectors): |
3668c083 |
65 | movw %cx, %ss |
66 | movw %cx, %ds |
67 | movw %cx, %es |
68 | movw %cx, %fs |
69 | movw %cx, %gs |
a47463f2 |
70 | ret |
71 | |
72 | #---------------------------------------; |
73 | # CommonInterruptEntry ; |
74 | #---------------------------------------; |
75 | # The follow algorithm is used for the common interrupt routine. |
76 | |
a47463f2 |
77 | ASM_GLOBAL ASM_PFX(CommonInterruptEntry) |
78 | ASM_PFX(CommonInterruptEntry): |
79 | cli |
80 | # |
81 | # All interrupt handlers are invoked through interrupt gates, so |
82 | # IF flag automatically cleared at the entry point |
83 | # |
84 | # |
85 | # Calculate vector number |
86 | # |
3668c083 |
87 | xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number. |
88 | movzwl (%rcx), %ecx |
89 | cmp $32, %ecx # Intel reserved vector for exceptions? |
a47463f2 |
90 | jae NoErrorCode |
3668c083 |
91 | pushq %rax |
92 | leaq ASM_PFX(mErrorCodeFlag)(%rip), %rax |
93 | bt %ecx, (%rax) |
94 | popq %rax |
a47463f2 |
95 | jc CommonInterruptEntry_al_0000 |
96 | |
97 | NoErrorCode: |
98 | |
99 | # |
100 | # Push a dummy error code on the stack |
101 | # to maintain coherent stack map |
102 | # |
3668c083 |
103 | pushq (%rsp) |
104 | movq $0, 8(%rsp) |
a47463f2 |
105 | CommonInterruptEntry_al_0000: |
3668c083 |
106 | pushq %rbp |
107 | movq %rsp, %rbp |
a47463f2 |
108 | |
109 | # |
110 | # Stack: |
111 | # +---------------------+ <-- 16-byte aligned ensured by processor |
112 | # + Old SS + |
113 | # +---------------------+ |
114 | # + Old RSP + |
115 | # +---------------------+ |
116 | # + RFlags + |
117 | # +---------------------+ |
118 | # + CS + |
119 | # +---------------------+ |
120 | # + RIP + |
121 | # +---------------------+ |
122 | # + Error Code + |
123 | # +---------------------+ |
124 | # + RCX / Vector Number + |
125 | # +---------------------+ |
126 | # + RBP + |
127 | # +---------------------+ <-- RBP, 16-byte aligned |
128 | # |
129 | |
130 | |
131 | # |
132 | # Since here the stack pointer is 16-byte aligned, so |
133 | # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64 |
134 | # is 16-byte aligned |
135 | # |
136 | |
137 | #; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; |
138 | #; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; |
3668c083 |
139 | pushq %r15 |
140 | pushq %r14 |
141 | pushq %r13 |
142 | pushq %r12 |
143 | pushq %r11 |
144 | pushq %r10 |
145 | pushq %r9 |
146 | pushq %r8 |
147 | pushq %rax |
148 | pushq 8(%rbp) # RCX |
149 | pushq %rdx |
150 | pushq %rbx |
151 | pushq 48(%rbp) # RSP |
152 | pushq (%rbp) # RBP |
153 | pushq %rsi |
154 | pushq %rdi |
a47463f2 |
155 | |
156 | #; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero |
3668c083 |
157 | movzwq 56(%rbp), %rax |
158 | pushq %rax # for ss |
159 | movzwq 32(%rbp), %rax |
160 | pushq %rax # for cs |
161 | movq %ds, %rax |
162 | pushq %rax |
163 | movq %es, %rax |
164 | pushq %rax |
165 | movq %fs, %rax |
166 | pushq %rax |
167 | movq %gs, %rax |
168 | pushq %rax |
169 | |
170 | movq %rcx, 8(%rbp) # save vector number |
a47463f2 |
171 | |
172 | #; UINT64 Rip; |
3668c083 |
173 | pushq 24(%rbp) |
a47463f2 |
174 | |
175 | #; UINT64 Gdtr[2], Idtr[2]; |
3668c083 |
176 | xorq %rax, %rax |
177 | pushq %rax |
178 | pushq %rax |
179 | sidt (%rsp) |
180 | xchgq 2(%rsp), %rax |
181 | xchgq (%rsp), %rax |
182 | xchgq 8(%rsp), %rax |
183 | |
184 | xorq %rax, %rax |
185 | pushq %rax |
186 | pushq %rax |
187 | sgdt (%rsp) |
188 | xchgq 2(%rsp), %rax |
189 | xchgq (%rsp), %rax |
190 | xchgq 8(%rsp), %rax |
a47463f2 |
191 | |
192 | #; UINT64 Ldtr, Tr; |
3668c083 |
193 | xorq %rax, %rax |
a47463f2 |
194 | str %ax |
3668c083 |
195 | pushq %rax |
a47463f2 |
196 | sldt %ax |
3668c083 |
197 | pushq %rax |
a47463f2 |
198 | |
199 | #; UINT64 RFlags; |
3668c083 |
200 | pushq 40(%rbp) |
a47463f2 |
201 | |
202 | #; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; |
3668c083 |
203 | movq %cr8, %rax |
204 | pushq %rax |
205 | movq %cr4, %rax |
206 | orq $0x208, %rax |
207 | movq %rax, %cr4 |
208 | pushq %rax |
209 | mov %cr3, %rax |
210 | pushq %rax |
211 | mov %cr2, %rax |
212 | pushq %rax |
213 | xorq %rax, %rax |
214 | pushq %rax |
215 | mov %cr0, %rax |
216 | pushq %rax |
a47463f2 |
217 | |
218 | #; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; |
3668c083 |
219 | movq %dr7, %rax |
220 | pushq %rax |
a47463f2 |
221 | #; clear Dr7 while executing debugger itself |
3668c083 |
222 | xorq %rax, %rax |
223 | movq %rax, %dr7 |
a47463f2 |
224 | |
3668c083 |
225 | movq %dr6, %rax |
226 | pushq %rax |
a47463f2 |
227 | #; insure all status bits in dr6 are clear... |
3668c083 |
228 | xorq %rax, %rax |
229 | movq %rax, %dr6 |
230 | |
231 | movq %dr3, %rax |
232 | pushq %rax |
233 | movq %dr2, %rax |
234 | pushq %rax |
235 | movq %dr1, %rax |
236 | pushq %rax |
237 | movq %dr0, %rax |
238 | pushq %rax |
a47463f2 |
239 | |
240 | #; FX_SAVE_STATE_X64 FxSaveState; |
3668c083 |
241 | subq $512, %rsp |
242 | movq %rsp, %rdi |
a47463f2 |
243 | .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi] |
244 | |
245 | #; UINT32 ExceptionData; |
3668c083 |
246 | pushq 16(%rbp) |
a47463f2 |
247 | |
248 | #; call into exception handler |
3668c083 |
249 | movq 8(%rbp), %rcx |
250 | leaq ExternalVectorTablePtr(%rip), %rax |
251 | movl (%eax), %eax |
252 | movq (%rax,%rcx,8), %rax |
253 | orq %rax, %rax # NULL? |
a47463f2 |
254 | |
255 | je nonNullValue# |
256 | |
257 | #; Prepare parameter and call |
258 | # mov rcx, [rbp + 8] |
3668c083 |
259 | mov %rsp, %rdx |
a47463f2 |
260 | # |
261 | # Per X64 calling convention, allocate maximum parameter stack space |
262 | # and make sure RSP is 16-byte aligned |
263 | # |
3668c083 |
264 | subq $40, %rsp |
265 | call *%rax |
266 | addq $40, %rsp |
a47463f2 |
267 | |
268 | nonNullValue: |
269 | cli |
270 | #; UINT64 ExceptionData; |
3668c083 |
271 | addq $8, %rsp |
a47463f2 |
272 | |
273 | #; FX_SAVE_STATE_X64 FxSaveState; |
274 | |
3668c083 |
275 | movq %rsp, %rsi |
a47463f2 |
276 | .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi] |
3668c083 |
277 | addq $512, %rsp |
a47463f2 |
278 | |
279 | #; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; |
3668c083 |
280 | popq %rax |
281 | movq %rax, %dr0 |
282 | popq %rax |
283 | movq %rax, %dr1 |
284 | popq %rax |
285 | movq %rax, %dr2 |
286 | popq %rax |
287 | movq %rax, %dr3 |
a47463f2 |
288 | #; skip restore of dr6. We cleared dr6 during the context save. |
3668c083 |
289 | addq $8, %rsp |
290 | popq %rax |
291 | movq %rax, %dr7 |
a47463f2 |
292 | |
293 | #; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; |
3668c083 |
294 | popq %rax |
295 | movq %rax, %cr0 |
296 | addq $8, %rsp # not for Cr1 |
297 | popq %rax |
298 | movq %rax, %cr2 |
299 | popq %rax |
300 | movq %rax, %cr3 |
301 | popq %rax |
302 | movq %rax, %cr4 |
303 | popq %rax |
304 | movq %rax, %cr8 |
a47463f2 |
305 | |
306 | #; UINT64 RFlags; |
3668c083 |
307 | popq 40(%rbp) |
a47463f2 |
308 | |
309 | #; UINT64 Ldtr, Tr; |
310 | #; UINT64 Gdtr[2], Idtr[2]; |
311 | #; Best not let anyone mess with these particular registers... |
3668c083 |
312 | addq $48, %rsp |
a47463f2 |
313 | |
314 | #; UINT64 Rip; |
3668c083 |
315 | popq 24(%rbp) |
a47463f2 |
316 | |
317 | #; UINT64 Gs, Fs, Es, Ds, Cs, Ss; |
3668c083 |
318 | popq %rax |
319 | # mov %rax, %gs ; not for gs |
320 | popq %rax |
321 | # mov %rax, %fs ; not for fs |
a47463f2 |
322 | # (X64 will not use fs and gs, so we do not restore it) |
3668c083 |
323 | popq %rax |
324 | movq %rax, %es |
325 | popq %rax |
326 | movq %rax, %ds |
327 | popq 32(%rbp) # for cs |
328 | popq 56(%rbp) # for ss |
a47463f2 |
329 | |
330 | #; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; |
331 | #; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; |
3668c083 |
332 | popq %rdi |
333 | popq %rsi |
334 | addq $8, %rsp # not for rbp |
335 | popq 48(%rbp) # for rsp |
336 | popq %rbx |
337 | popq %rdx |
338 | popq %rcx |
339 | popq %rax |
340 | popq %r8 |
341 | popq %r9 |
342 | popq %r10 |
343 | popq %r11 |
344 | popq %r12 |
345 | popq %r13 |
346 | popq %r14 |
347 | popq %r15 |
348 | |
349 | movq %rbp, %rsp |
350 | popq %rbp |
351 | addq $16, %rsp |
a47463f2 |
352 | iretq |
353 | |
354 | |
355 | #text ENDS |
356 | |
357 | #END |
358 | |
359 | |