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