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