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