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