]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuDxe/X64/CpuAsm.asm
Clear the direction flag in interrupt/exception handlers' assembly entry code before...
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / X64 / CpuAsm.asm
CommitLineData
a47463f2 1 TITLE CpuAsm.asm: \r
2;------------------------------------------------------------------------------\r
3;*\r
ad8cbf71 4;* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>\r
01a1c0fc 5;* This program and the accompanying materials \r
a47463f2 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
21EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
22\r
23;\r
24; point to the external interrupt vector table\r
25;\r
26ExternalVectorTablePtr QWORD 0\r
27\r
28InitializeExternalVectorTablePtr PROC PUBLIC\r
29 mov ExternalVectorTablePtr, rcx\r
30 ret\r
31InitializeExternalVectorTablePtr ENDP\r
32\r
33;------------------------------------------------------------------------------\r
34; VOID\r
35; SetCodeSelector (\r
36; UINT16 Selector\r
37; );\r
38;------------------------------------------------------------------------------\r
39SetCodeSelector 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
45setCodeSelectorLongJump:\r
46 add rsp, 0x10\r
47 ret\r
48SetCodeSelector ENDP\r
49\r
50;------------------------------------------------------------------------------\r
51; VOID\r
52; SetDataSelectors (\r
53; UINT16 Selector\r
54; );\r
55;------------------------------------------------------------------------------\r
56SetDataSelectors 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
63SetDataSelectors 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
70CommonInterruptEntry 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
86NoErrorCode:\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
a47463f2 210 mov rax, dr6\r
211 push rax\r
a47463f2 212 mov rax, dr3\r
213 push rax\r
214 mov rax, dr2\r
215 push rax\r
216 mov rax, dr1\r
217 push rax\r
218 mov rax, dr0\r
219 push rax\r
220\r
221;; FX_SAVE_STATE_X64 FxSaveState;\r
222 sub rsp, 512\r
223 mov rdi, rsp\r
224 db 0fh, 0aeh, 07h ;fxsave [rdi]\r
225\r
ad8cbf71 226;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
227 cld\r
228\r
a47463f2 229;; UINT32 ExceptionData;\r
230 push qword ptr [rbp + 16]\r
231\r
232;; call into exception handler\r
233 mov rcx, [rbp + 8]\r
234 mov rax, ExternalVectorTablePtr ; get the interrupt vectors base\r
235 mov rax, [rax + rcx * 8] \r
236 or rax, rax ; NULL?\r
237\r
238 je nonNullValue;\r
239\r
240;; Prepare parameter and call\r
241; mov rcx, [rbp + 8]\r
242 mov rdx, rsp\r
243 ;\r
244 ; Per X64 calling convention, allocate maximum parameter stack space\r
245 ; and make sure RSP is 16-byte aligned\r
246 ;\r
247 sub rsp, 4 * 8 + 8\r
248 call rax\r
249 add rsp, 4 * 8 + 8\r
250\r
251nonNullValue:\r
252 cli\r
253;; UINT64 ExceptionData;\r
254 add rsp, 8\r
255\r
256;; FX_SAVE_STATE_X64 FxSaveState;\r
257\r
258 mov rsi, rsp\r
259 db 0fh, 0aeh, 0Eh ; fxrstor [rsi]\r
260 add rsp, 512\r
261\r
262;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
61ece967 263;; Skip restoration of DRx registers to support in-circuit emualators\r
264;; or debuggers set breakpoint in interrupt/exception context\r
265 add rsp, 8 * 6\r
a47463f2 266\r
267;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
268 pop rax\r
269 mov cr0, rax\r
270 add rsp, 8 ; not for Cr1\r
271 pop rax\r
272 mov cr2, rax\r
273 pop rax\r
274 mov cr3, rax\r
275 pop rax\r
276 mov cr4, rax\r
277 pop rax\r
278 mov cr8, rax\r
279\r
280;; UINT64 RFlags;\r
281 pop qword ptr [rbp + 40]\r
282\r
283;; UINT64 Ldtr, Tr;\r
284;; UINT64 Gdtr[2], Idtr[2];\r
285;; Best not let anyone mess with these particular registers...\r
286 add rsp, 48\r
287\r
288;; UINT64 Rip;\r
289 pop qword ptr [rbp + 24]\r
290\r
291;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
292 pop rax\r
293 ; mov gs, rax ; not for gs\r
294 pop rax\r
295 ; mov fs, rax ; not for fs\r
296 ; (X64 will not use fs and gs, so we do not restore it)\r
297 pop rax\r
298 mov es, rax\r
299 pop rax\r
300 mov ds, rax\r
301 pop qword ptr [rbp + 32] ; for cs\r
302 pop qword ptr [rbp + 56] ; for ss\r
303\r
304;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
305;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
306 pop rdi\r
307 pop rsi\r
308 add rsp, 8 ; not for rbp\r
309 pop qword ptr [rbp + 48] ; for rsp\r
310 pop rbx\r
311 pop rdx\r
312 pop rcx\r
313 pop rax\r
314 pop r8\r
315 pop r9\r
316 pop r10\r
317 pop r11\r
318 pop r12\r
319 pop r13\r
320 pop r14\r
321 pop r15\r
322\r
323 mov rsp, rbp\r
324 pop rbp\r
325 add rsp, 16\r
326 iretq\r
327\r
328CommonInterruptEntry ENDP\r
329\r
330END\r
331\r