]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm
UefiCpuPkg/CpuExceptionHandler: Add base support for the #VC exception
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / X64 / Xcode5ExceptionHandlerAsm.nasm
CommitLineData
ec94e97a
TL
1;------------------------------------------------------------------------------ ;\r
2; Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>\r
3; SPDX-License-Identifier: BSD-2-Clause-Patent\r
4;\r
5; Module Name:\r
6;\r
7; ExceptionHandlerAsm.Asm\r
8;\r
9; Abstract:\r
10;\r
11; x64 CPU Exception Handler\r
12;\r
13; Notes:\r
14;\r
15;------------------------------------------------------------------------------\r
16\r
17;\r
18; CommonExceptionHandler()\r
19;\r
20\r
5277540e
TL
21%define VC_EXCEPTION 29\r
22\r
ec94e97a
TL
23extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions\r
24extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag\r
25extern ASM_PFX(CommonExceptionHandler)\r
26\r
27SECTION .data\r
28\r
29DEFAULT REL\r
30SECTION .text\r
31\r
32ALIGN 8\r
33\r
34AsmIdtVectorBegin:\r
35%rep 32\r
36 db 0x6a ; push #VectorNum\r
37 db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum\r
38 push rax\r
39 mov rax, strict qword 0 ; mov rax, ASM_PFX(CommonInterruptEntry)\r
40 jmp rax\r
41%endrep\r
42AsmIdtVectorEnd:\r
43\r
44HookAfterStubHeaderBegin:\r
45 db 0x6a ; push\r
46@VectorNum:\r
47 db 0 ; 0 will be fixed\r
48 push rax\r
49 mov rax, strict qword 0 ; mov rax, HookAfterStubHeaderEnd\r
50JmpAbsoluteAddress:\r
51 jmp rax\r
52HookAfterStubHeaderEnd:\r
53 mov rax, rsp\r
54 and sp, 0xfff0 ; make sure 16-byte aligned for exception context\r
55 sub rsp, 0x18 ; reserve room for filling exception data later\r
56 push rcx\r
57 mov rcx, [rax + 8]\r
58 bt [ASM_PFX(mErrorCodeFlag)], ecx\r
59 jnc .0\r
60 push qword [rsp] ; push additional rcx to make stack alignment\r
61.0:\r
62 xchg rcx, [rsp] ; restore rcx, save Exception Number in stack\r
63 push qword [rax] ; push rax into stack to keep code consistence\r
64\r
65;---------------------------------------;\r
66; CommonInterruptEntry ;\r
67;---------------------------------------;\r
68; The follow algorithm is used for the common interrupt routine.\r
69; Entry from each interrupt with a push eax and eax=interrupt number\r
70; Stack frame would be as follows as specified in IA32 manuals:\r
71;\r
72; +---------------------+ <-- 16-byte aligned ensured by processor\r
73; + Old SS +\r
74; +---------------------+\r
75; + Old RSP +\r
76; +---------------------+\r
77; + RFlags +\r
78; +---------------------+\r
79; + CS +\r
80; +---------------------+\r
81; + RIP +\r
82; +---------------------+\r
83; + Error Code +\r
84; +---------------------+\r
85; + Vector Number +\r
86; +---------------------+\r
87; + RBP +\r
88; +---------------------+ <-- RBP, 16-byte aligned\r
89; The follow algorithm is used for the common interrupt routine.\r
90global ASM_PFX(CommonInterruptEntry)\r
91ASM_PFX(CommonInterruptEntry):\r
92 cli\r
93 pop rax\r
94 ;\r
95 ; All interrupt handlers are invoked through interrupt gates, so\r
96 ; IF flag automatically cleared at the entry point\r
97 ;\r
98 xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx\r
99 and rcx, 0xFF\r
100 cmp ecx, 32 ; Intel reserved vector for exceptions?\r
101 jae NoErrorCode\r
102 bt [ASM_PFX(mErrorCodeFlag)], ecx\r
103 jc HasErrorCode\r
104\r
105NoErrorCode:\r
106\r
107 ;\r
108 ; Push a dummy error code on the stack\r
109 ; to maintain coherent stack map\r
110 ;\r
111 push qword [rsp]\r
112 mov qword [rsp + 8], 0\r
113HasErrorCode:\r
114 push rbp\r
115 mov rbp, rsp\r
116 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
117 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
118\r
119 ;\r
120 ; Stack:\r
121 ; +---------------------+ <-- 16-byte aligned ensured by processor\r
122 ; + Old SS +\r
123 ; +---------------------+\r
124 ; + Old RSP +\r
125 ; +---------------------+\r
126 ; + RFlags +\r
127 ; +---------------------+\r
128 ; + CS +\r
129 ; +---------------------+\r
130 ; + RIP +\r
131 ; +---------------------+\r
132 ; + Error Code +\r
133 ; +---------------------+\r
134 ; + RCX / Vector Number +\r
135 ; +---------------------+\r
136 ; + RBP +\r
137 ; +---------------------+ <-- RBP, 16-byte aligned\r
138 ;\r
139\r
140 ;\r
141 ; Since here the stack pointer is 16-byte aligned, so\r
142 ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
143 ; is 16-byte aligned\r
144 ;\r
145\r
146;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
147;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
148 push r15\r
149 push r14\r
150 push r13\r
151 push r12\r
152 push r11\r
153 push r10\r
154 push r9\r
155 push r8\r
156 push rax\r
157 push qword [rbp + 8] ; RCX\r
158 push rdx\r
159 push rbx\r
160 push qword [rbp + 48] ; RSP\r
161 push qword [rbp] ; RBP\r
162 push rsi\r
163 push rdi\r
164\r
165;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
166 movzx rax, word [rbp + 56]\r
167 push rax ; for ss\r
168 movzx rax, word [rbp + 32]\r
169 push rax ; for cs\r
170 mov rax, ds\r
171 push rax\r
172 mov rax, es\r
173 push rax\r
174 mov rax, fs\r
175 push rax\r
176 mov rax, gs\r
177 push rax\r
178\r
179 mov [rbp + 8], rcx ; save vector number\r
180\r
181;; UINT64 Rip;\r
182 push qword [rbp + 24]\r
183\r
184;; UINT64 Gdtr[2], Idtr[2];\r
185 xor rax, rax\r
186 push rax\r
187 push rax\r
188 sidt [rsp]\r
189 mov bx, word [rsp]\r
190 mov rax, qword [rsp + 2]\r
191 mov qword [rsp], rax\r
192 mov word [rsp + 8], bx\r
193\r
194 xor rax, rax\r
195 push rax\r
196 push rax\r
197 sgdt [rsp]\r
198 mov bx, word [rsp]\r
199 mov rax, qword [rsp + 2]\r
200 mov qword [rsp], rax\r
201 mov word [rsp + 8], bx\r
202\r
203;; UINT64 Ldtr, Tr;\r
204 xor rax, rax\r
205 str ax\r
206 push rax\r
207 sldt ax\r
208 push rax\r
209\r
210;; UINT64 RFlags;\r
211 push qword [rbp + 40]\r
212\r
213;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
214 mov rax, cr8\r
215 push rax\r
216 mov rax, cr4\r
217 or rax, 0x208\r
218 mov cr4, rax\r
219 push rax\r
220 mov rax, cr3\r
221 push rax\r
222 mov rax, cr2\r
223 push rax\r
224 xor rax, rax\r
225 push rax\r
226 mov rax, cr0\r
227 push rax\r
228\r
229;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
5277540e
TL
230 cmp qword [rbp + 8], VC_EXCEPTION\r
231 je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored\r
232\r
ec94e97a
TL
233 mov rax, dr7\r
234 push rax\r
235 mov rax, dr6\r
236 push rax\r
237 mov rax, dr3\r
238 push rax\r
239 mov rax, dr2\r
240 push rax\r
241 mov rax, dr1\r
242 push rax\r
243 mov rax, dr0\r
244 push rax\r
5277540e
TL
245 jmp DrFinish\r
246\r
247VcDebugRegs:\r
248;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7 are skipped for #VC to avoid exception recursion\r
249 xor rax, rax\r
250 push rax\r
251 push rax\r
252 push rax\r
253 push rax\r
254 push rax\r
255 push rax\r
ec94e97a 256\r
5277540e 257DrFinish:\r
ec94e97a
TL
258;; FX_SAVE_STATE_X64 FxSaveState;\r
259 sub rsp, 512\r
260 mov rdi, rsp\r
261 db 0xf, 0xae, 0x7 ;fxsave [rdi]\r
262\r
263;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
264 cld\r
265\r
266;; UINT32 ExceptionData;\r
267 push qword [rbp + 16]\r
268\r
269;; Prepare parameter and call\r
270 mov rcx, [rbp + 8]\r
271 mov rdx, rsp\r
272 ;\r
273 ; Per X64 calling convention, allocate maximum parameter stack space\r
274 ; and make sure RSP is 16-byte aligned\r
275 ;\r
276 sub rsp, 4 * 8 + 8\r
277 call ASM_PFX(CommonExceptionHandler)\r
278 add rsp, 4 * 8 + 8\r
279\r
280 cli\r
281;; UINT64 ExceptionData;\r
282 add rsp, 8\r
283\r
284;; FX_SAVE_STATE_X64 FxSaveState;\r
285\r
286 mov rsi, rsp\r
287 db 0xf, 0xae, 0xE ; fxrstor [rsi]\r
288 add rsp, 512\r
289\r
290;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
291;; Skip restoration of DRx registers to support in-circuit emualators\r
292;; or debuggers set breakpoint in interrupt/exception context\r
293 add rsp, 8 * 6\r
294\r
295;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
296 pop rax\r
297 mov cr0, rax\r
298 add rsp, 8 ; not for Cr1\r
299 pop rax\r
300 mov cr2, rax\r
301 pop rax\r
302 mov cr3, rax\r
303 pop rax\r
304 mov cr4, rax\r
305 pop rax\r
306 mov cr8, rax\r
307\r
308;; UINT64 RFlags;\r
309 pop qword [rbp + 40]\r
310\r
311;; UINT64 Ldtr, Tr;\r
312;; UINT64 Gdtr[2], Idtr[2];\r
313;; Best not let anyone mess with these particular registers...\r
314 add rsp, 48\r
315\r
316;; UINT64 Rip;\r
317 pop qword [rbp + 24]\r
318\r
319;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
320 pop rax\r
321 ; mov gs, rax ; not for gs\r
322 pop rax\r
323 ; mov fs, rax ; not for fs\r
324 ; (X64 will not use fs and gs, so we do not restore it)\r
325 pop rax\r
326 mov es, rax\r
327 pop rax\r
328 mov ds, rax\r
329 pop qword [rbp + 32] ; for cs\r
330 pop qword [rbp + 56] ; for ss\r
331\r
332;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
333;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
334 pop rdi\r
335 pop rsi\r
336 add rsp, 8 ; not for rbp\r
337 pop qword [rbp + 48] ; for rsp\r
338 pop rbx\r
339 pop rdx\r
340 pop rcx\r
341 pop rax\r
342 pop r8\r
343 pop r9\r
344 pop r10\r
345 pop r11\r
346 pop r12\r
347 pop r13\r
348 pop r14\r
349 pop r15\r
350\r
351 mov rsp, rbp\r
352 pop rbp\r
353 add rsp, 16\r
354 cmp qword [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
355 jz DoReturn\r
356 cmp qword [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
357 jz ErrorCode\r
358 jmp qword [rsp - 32]\r
359ErrorCode:\r
360 sub rsp, 8\r
361 jmp qword [rsp - 24]\r
362\r
363DoReturn:\r
364 cmp qword [ASM_PFX(mDoFarReturnFlag)], 0 ; Check if need to do far return instead of IRET\r
365 jz DoIret\r
366 push rax\r
367 mov rax, rsp ; save old RSP to rax\r
368 mov rsp, [rsp + 0x20]\r
369 push qword [rax + 0x10] ; save CS in new location\r
370 push qword [rax + 0x8] ; save EIP in new location\r
371 push qword [rax + 0x18] ; save EFLAGS in new location\r
372 mov rax, [rax] ; restore rax\r
373 popfq ; restore EFLAGS\r
374 DB 0x48 ; prefix to composite "retq" with next "retf"\r
375 retf ; far return\r
376DoIret:\r
377 iretq\r
378\r
379;-------------------------------------------------------------------------------------\r
380; GetTemplateAddressMap (&AddressMap);\r
381;-------------------------------------------------------------------------------------\r
382; comments here for definition of address map\r
383global ASM_PFX(AsmGetTemplateAddressMap)\r
384ASM_PFX(AsmGetTemplateAddressMap):\r
385 lea rax, [AsmIdtVectorBegin]\r
386 mov qword [rcx], rax\r
387 mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32\r
388 lea rax, [HookAfterStubHeaderBegin]\r
389 mov qword [rcx + 0x10], rax\r
390\r
391; Fix up CommonInterruptEntry address\r
392 lea rax, [ASM_PFX(CommonInterruptEntry)]\r
393 lea rcx, [AsmIdtVectorBegin]\r
394%rep 32\r
395 mov qword [rcx + (JmpAbsoluteAddress - 8 - HookAfterStubHeaderBegin)], rax\r
396 add rcx, (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32\r
397%endrep\r
398; Fix up HookAfterStubHeaderEnd\r
399 lea rax, [HookAfterStubHeaderEnd]\r
400 lea rcx, [JmpAbsoluteAddress]\r
401 mov qword [rcx - 8], rax\r
402\r
403 ret\r
404\r
405;-------------------------------------------------------------------------------------\r
406; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);\r
407;-------------------------------------------------------------------------------------\r
408global ASM_PFX(AsmVectorNumFixup)\r
409ASM_PFX(AsmVectorNumFixup):\r
410 mov rax, rdx\r
411 mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al\r
412 ret\r
413\r