Update the copyright notice format
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / X64 / CpuAsm.asm
1 TITLE CpuAsm.asm:
2 ;------------------------------------------------------------------------------
3 ;*
4 ;* Copyright (c) 2008 - 2009, 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 ;; clear Dr7 while executing debugger itself
211 xor rax, rax
212 mov dr7, rax
213
214 mov rax, dr6
215 push rax
216 ;; insure all status bits in dr6 are clear...
217 xor rax, rax
218 mov dr6, rax
219
220 mov rax, dr3
221 push rax
222 mov rax, dr2
223 push rax
224 mov rax, dr1
225 push rax
226 mov rax, dr0
227 push rax
228
229 ;; FX_SAVE_STATE_X64 FxSaveState;
230 sub rsp, 512
231 mov rdi, rsp
232 db 0fh, 0aeh, 07h ;fxsave [rdi]
233
234 ;; UINT32 ExceptionData;
235 push qword ptr [rbp + 16]
236
237 ;; call into exception handler
238 mov rcx, [rbp + 8]
239 mov rax, ExternalVectorTablePtr ; get the interrupt vectors base
240 mov rax, [rax + rcx * 8]
241 or rax, rax ; NULL?
242
243 je nonNullValue;
244
245 ;; Prepare parameter and call
246 ; mov rcx, [rbp + 8]
247 mov rdx, rsp
248 ;
249 ; Per X64 calling convention, allocate maximum parameter stack space
250 ; and make sure RSP is 16-byte aligned
251 ;
252 sub rsp, 4 * 8 + 8
253 call rax
254 add rsp, 4 * 8 + 8
255
256 nonNullValue:
257 cli
258 ;; UINT64 ExceptionData;
259 add rsp, 8
260
261 ;; FX_SAVE_STATE_X64 FxSaveState;
262
263 mov rsi, rsp
264 db 0fh, 0aeh, 0Eh ; fxrstor [rsi]
265 add rsp, 512
266
267 ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
268 pop rax
269 mov dr0, rax
270 pop rax
271 mov dr1, rax
272 pop rax
273 mov dr2, rax
274 pop rax
275 mov dr3, rax
276 ;; skip restore of dr6. We cleared dr6 during the context save.
277 add rsp, 8
278 pop rax
279 mov dr7, rax
280
281 ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
282 pop rax
283 mov cr0, rax
284 add rsp, 8 ; not for Cr1
285 pop rax
286 mov cr2, rax
287 pop rax
288 mov cr3, rax
289 pop rax
290 mov cr4, rax
291 pop rax
292 mov cr8, rax
293
294 ;; UINT64 RFlags;
295 pop qword ptr [rbp + 40]
296
297 ;; UINT64 Ldtr, Tr;
298 ;; UINT64 Gdtr[2], Idtr[2];
299 ;; Best not let anyone mess with these particular registers...
300 add rsp, 48
301
302 ;; UINT64 Rip;
303 pop qword ptr [rbp + 24]
304
305 ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
306 pop rax
307 ; mov gs, rax ; not for gs
308 pop rax
309 ; mov fs, rax ; not for fs
310 ; (X64 will not use fs and gs, so we do not restore it)
311 pop rax
312 mov es, rax
313 pop rax
314 mov ds, rax
315 pop qword ptr [rbp + 32] ; for cs
316 pop qword ptr [rbp + 56] ; for ss
317
318 ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
319 ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
320 pop rdi
321 pop rsi
322 add rsp, 8 ; not for rbp
323 pop qword ptr [rbp + 48] ; for rsp
324 pop rbx
325 pop rdx
326 pop rcx
327 pop rax
328 pop r8
329 pop r9
330 pop r10
331 pop r11
332 pop r12
333 pop r13
334 pop r14
335 pop r15
336
337 mov rsp, rbp
338 pop rbp
339 add rsp, 16
340 iretq
341
342 CommonInterruptEntry ENDP
343
344 END
345