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