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