]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
UefiCpuPkg/CpuExceptionHandler: Revert CpuExceptionHandler binary patching
[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
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
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
9378310d 37 mov rax, ASM_PFX(CommonInterruptEntry)\r
fb501e33
LG
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
9378310d 47 mov rax, HookAfterStubHeaderEnd\r
fb501e33
LG
48 jmp rax\r
49HookAfterStubHeaderEnd:\r
50 mov rax, rsp\r
51 and sp, 0xfff0 ; make sure 16-byte aligned for exception context\r
52 sub rsp, 0x18 ; reserve room for filling exception data later\r
53 push rcx\r
54 mov rcx, [rax + 8]\r
55 bt [ASM_PFX(mErrorCodeFlag)], ecx\r
56 jnc .0\r
57 push qword [rsp] ; push additional rcx to make stack alignment\r
58.0:\r
59 xchg rcx, [rsp] ; restore rcx, save Exception Number in stack\r
60 push qword [rax] ; push rax into stack to keep code consistence\r
61\r
62;---------------------------------------;\r
63; CommonInterruptEntry ;\r
64;---------------------------------------;\r
65; The follow algorithm is used for the common interrupt routine.\r
66; Entry from each interrupt with a push eax and eax=interrupt number\r
67; Stack frame would be as follows as specified in IA32 manuals:\r
68;\r
69; +---------------------+ <-- 16-byte aligned ensured by processor\r
70; + Old SS +\r
71; +---------------------+\r
72; + Old RSP +\r
73; +---------------------+\r
74; + RFlags +\r
75; +---------------------+\r
76; + CS +\r
77; +---------------------+\r
78; + RIP +\r
79; +---------------------+\r
80; + Error Code +\r
81; +---------------------+\r
82; + Vector Number +\r
83; +---------------------+\r
84; + RBP +\r
85; +---------------------+ <-- RBP, 16-byte aligned\r
86; The follow algorithm is used for the common interrupt routine.\r
87global ASM_PFX(CommonInterruptEntry)\r
88ASM_PFX(CommonInterruptEntry):\r
89 cli\r
90 pop rax\r
91 ;\r
92 ; All interrupt handlers are invoked through interrupt gates, so\r
93 ; IF flag automatically cleared at the entry point\r
94 ;\r
95 xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx\r
96 and rcx, 0xFF\r
97 cmp ecx, 32 ; Intel reserved vector for exceptions?\r
98 jae NoErrorCode\r
99 bt [ASM_PFX(mErrorCodeFlag)], ecx\r
100 jc HasErrorCode\r
101\r
102NoErrorCode:\r
103\r
104 ;\r
105 ; Push a dummy error code on the stack\r
106 ; to maintain coherent stack map\r
107 ;\r
108 push qword [rsp]\r
109 mov qword [rsp + 8], 0\r
110HasErrorCode:\r
111 push rbp\r
112 mov rbp, rsp\r
113 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
114 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
115\r
116 ;\r
117 ; Stack:\r
118 ; +---------------------+ <-- 16-byte aligned ensured by processor\r
119 ; + Old SS +\r
120 ; +---------------------+\r
121 ; + Old RSP +\r
122 ; +---------------------+\r
123 ; + RFlags +\r
124 ; +---------------------+\r
125 ; + CS +\r
126 ; +---------------------+\r
127 ; + RIP +\r
128 ; +---------------------+\r
129 ; + Error Code +\r
130 ; +---------------------+\r
131 ; + RCX / Vector Number +\r
132 ; +---------------------+\r
133 ; + RBP +\r
134 ; +---------------------+ <-- RBP, 16-byte aligned\r
135 ;\r
136\r
137 ;\r
138 ; Since here the stack pointer is 16-byte aligned, so\r
139 ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
140 ; is 16-byte aligned\r
141 ;\r
142\r
143;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
144;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
145 push r15\r
146 push r14\r
147 push r13\r
148 push r12\r
149 push r11\r
150 push r10\r
151 push r9\r
152 push r8\r
153 push rax\r
154 push qword [rbp + 8] ; RCX\r
155 push rdx\r
156 push rbx\r
157 push qword [rbp + 48] ; RSP\r
158 push qword [rbp] ; RBP\r
159 push rsi\r
160 push rdi\r
161\r
162;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
163 movzx rax, word [rbp + 56]\r
164 push rax ; for ss\r
165 movzx rax, word [rbp + 32]\r
166 push rax ; for cs\r
167 mov rax, ds\r
168 push rax\r
169 mov rax, es\r
170 push rax\r
171 mov rax, fs\r
172 push rax\r
173 mov rax, gs\r
174 push rax\r
175\r
176 mov [rbp + 8], rcx ; save vector number\r
177\r
178;; UINT64 Rip;\r
179 push qword [rbp + 24]\r
180\r
181;; UINT64 Gdtr[2], Idtr[2];\r
182 xor rax, rax\r
183 push rax\r
184 push rax\r
185 sidt [rsp]\r
f4c898f2
JL
186 mov bx, word [rsp]\r
187 mov rax, qword [rsp + 2]\r
188 mov qword [rsp], rax\r
189 mov word [rsp + 8], bx\r
fb501e33
LG
190\r
191 xor rax, rax\r
192 push rax\r
193 push rax\r
194 sgdt [rsp]\r
f4c898f2
JL
195 mov bx, word [rsp]\r
196 mov rax, qword [rsp + 2]\r
197 mov qword [rsp], rax\r
198 mov word [rsp + 8], bx\r
fb501e33
LG
199\r
200;; UINT64 Ldtr, Tr;\r
201 xor rax, rax\r
202 str ax\r
203 push rax\r
204 sldt ax\r
205 push rax\r
206\r
207;; UINT64 RFlags;\r
208 push qword [rbp + 40]\r
209\r
210;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
211 mov rax, cr8\r
212 push rax\r
213 mov rax, cr4\r
214 or rax, 0x208\r
215 mov cr4, rax\r
216 push rax\r
217 mov rax, cr3\r
218 push rax\r
219 mov rax, cr2\r
220 push rax\r
221 xor rax, rax\r
222 push rax\r
223 mov rax, cr0\r
224 push rax\r
225\r
226;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
227 mov rax, dr7\r
228 push rax\r
229 mov rax, dr6\r
230 push rax\r
231 mov rax, dr3\r
232 push rax\r
233 mov rax, dr2\r
234 push rax\r
235 mov rax, dr1\r
236 push rax\r
237 mov rax, dr0\r
238 push rax\r
239\r
240;; FX_SAVE_STATE_X64 FxSaveState;\r
241 sub rsp, 512\r
242 mov rdi, rsp\r
243 db 0xf, 0xae, 0x7 ;fxsave [rdi]\r
244\r
245;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
246 cld\r
247\r
248;; UINT32 ExceptionData;\r
249 push qword [rbp + 16]\r
250\r
251;; Prepare parameter and call\r
252 mov rcx, [rbp + 8]\r
253 mov rdx, rsp\r
254 ;\r
255 ; Per X64 calling convention, allocate maximum parameter stack space\r
256 ; and make sure RSP is 16-byte aligned\r
257 ;\r
258 sub rsp, 4 * 8 + 8\r
9378310d
TL
259 mov rax, ASM_PFX(CommonExceptionHandler)\r
260 call rax\r
fb501e33
LG
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
9378310d 368 mov rax, AsmIdtVectorBegin\r
fb501e33
LG
369 mov qword [rcx], rax\r
370 mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32\r
9378310d 371 mov rax, HookAfterStubHeaderBegin\r
fb501e33
LG
372 mov qword [rcx + 0x10], rax\r
373 ret\r
374\r
375;-------------------------------------------------------------------------------------\r
376; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);\r
377;-------------------------------------------------------------------------------------\r
378global ASM_PFX(AsmVectorNumFixup)\r
379ASM_PFX(AsmVectorNumFixup):\r
380 mov rax, rdx\r
381 mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al\r
382 ret\r
383\r