VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm

最後變更 在這個檔案是 101291,由 vboxsync 提交於 18 月 前

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:mime-type 設為 text/x-asm
檔案大小: 13.9 KB
 
1;------------------------------------------------------------------------------ ;
2; Copyright (c) 2012 - 2022, 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%include "Nasm.inc"
17
18;
19; Equivalent NASM structure of IA32_DESCRIPTOR
20;
21struc IA32_DESCRIPTOR
22 .Limit CTYPE_UINT16 1
23 .Base CTYPE_UINTN 1
24endstruc
25
26;
27; Equivalent NASM structure of IA32_IDT_GATE_DESCRIPTOR
28;
29struc IA32_IDT_GATE_DESCRIPTOR
30 .OffsetLow CTYPE_UINT16 1
31 .Selector CTYPE_UINT16 1
32 .Reserved_0 CTYPE_UINT8 1
33 .GateType CTYPE_UINT8 1
34 .OffsetHigh CTYPE_UINT16 1
35 .OffsetUpper CTYPE_UINT32 1
36 .Reserved_1 CTYPE_UINT32 1
37endstruc
38
39;
40; CommonExceptionHandler()
41;
42
43%define VC_EXCEPTION 29
44
45extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
46extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
47extern ASM_PFX(CommonExceptionHandler)
48
49SECTION .data
50
51DEFAULT REL
52SECTION .text
53
54ALIGN 8
55
56; Generate 256 IDT vectors.
57AsmIdtVectorBegin:
58%assign Vector 0
59%rep 256
60 push strict dword %[Vector] ; This instruction pushes sign-extended 8-byte value on stack
61 push rax
62%ifdef NO_ABSOLUTE_RELOCS_IN_TEXT
63 mov rax, strict qword 0 ; mov rax, ASM_PFX(CommonInterruptEntry)
64%else
65 mov rax, ASM_PFX(CommonInterruptEntry)
66%endif
67 jmp rax
68%assign Vector Vector+1
69%endrep
70AsmIdtVectorEnd:
71
72HookAfterStubHeaderBegin:
73 push strict dword 0 ; 0 will be fixed
74VectorNum:
75 push rax
76%ifdef NO_ABSOLUTE_RELOCS_IN_TEXT
77 mov rax, strict qword 0 ; mov rax, HookAfterStubHeaderEnd
78JmpAbsoluteAddress:
79%else
80 mov rax, HookAfterStubHeaderEnd
81%endif
82 jmp rax
83HookAfterStubHeaderEnd:
84 mov rax, rsp
85 and sp, 0xfff0 ; make sure 16-byte aligned for exception context
86 sub rsp, 0x18 ; reserve room for filling exception data later
87 push rcx
88 mov rcx, [rax + 8]
89 bt [ASM_PFX(mErrorCodeFlag)], ecx
90 jnc .0
91 push qword [rsp] ; push additional rcx to make stack alignment
92.0:
93 xchg rcx, [rsp] ; restore rcx, save Exception Number in stack
94 push qword [rax] ; push rax into stack to keep code consistence
95
96;---------------------------------------;
97; CommonInterruptEntry ;
98;---------------------------------------;
99; The follow algorithm is used for the common interrupt routine.
100; Entry from each interrupt with a push eax and eax=interrupt number
101; Stack frame would be as follows as specified in IA32 manuals:
102;
103; +---------------------+ <-- 16-byte aligned ensured by processor
104; + Old SS +
105; +---------------------+
106; + Old RSP +
107; +---------------------+
108; + RFlags +
109; +---------------------+
110; + CS +
111; +---------------------+
112; + RIP +
113; +---------------------+
114; + Error Code +
115; +---------------------+
116; + Vector Number +
117; +---------------------+
118; + RBP +
119; +---------------------+ <-- RBP, 16-byte aligned
120; The follow algorithm is used for the common interrupt routine.
121global ASM_PFX(CommonInterruptEntry)
122ASM_PFX(CommonInterruptEntry):
123 cli
124 pop rax
125 ;
126 ; All interrupt handlers are invoked through interrupt gates, so
127 ; IF flag automatically cleared at the entry point
128 ;
129 xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx
130 and rcx, 0xFF
131 cmp ecx, 32 ; Intel reserved vector for exceptions?
132 jae NoErrorCode
133 bt [ASM_PFX(mErrorCodeFlag)], ecx
134 jc HasErrorCode
135
136NoErrorCode:
137
138 ;
139 ; Push a dummy error code on the stack
140 ; to maintain coherent stack map
141 ;
142 push qword [rsp]
143 mov qword [rsp + 8], 0
144HasErrorCode:
145 push rbp
146 mov rbp, rsp
147 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
148 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
149
150 ;
151 ; Stack:
152 ; +---------------------+ <-- 16-byte aligned ensured by processor
153 ; + Old SS +
154 ; +---------------------+
155 ; + Old RSP +
156 ; +---------------------+
157 ; + RFlags +
158 ; +---------------------+
159 ; + CS +
160 ; +---------------------+
161 ; + RIP +
162 ; +---------------------+
163 ; + Error Code +
164 ; +---------------------+
165 ; + RCX / Vector Number +
166 ; +---------------------+
167 ; + RBP +
168 ; +---------------------+ <-- RBP, 16-byte aligned
169 ;
170
171 ;
172 ; Since here the stack pointer is 16-byte aligned, so
173 ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
174 ; is 16-byte aligned
175 ;
176
177;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
178;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
179 push r15
180 push r14
181 push r13
182 push r12
183 push r11
184 push r10
185 push r9
186 push r8
187 push rax
188 push qword [rbp + 8] ; RCX
189 push rdx
190 push rbx
191 push qword [rbp + 48] ; RSP
192 push qword [rbp] ; RBP
193 push rsi
194 push rdi
195
196;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
197 movzx rax, word [rbp + 56]
198 push rax ; for ss
199 movzx rax, word [rbp + 32]
200 push rax ; for cs
201 mov rax, ds
202 push rax
203 mov rax, es
204 push rax
205 mov rax, fs
206 push rax
207 mov rax, gs
208 push rax
209
210 mov [rbp + 8], rcx ; save vector number
211
212;; UINT64 Rip;
213 push qword [rbp + 24]
214
215;; UINT64 Gdtr[2], Idtr[2];
216 xor rax, rax
217 push rax
218 push rax
219 sidt [rsp]
220 mov bx, word [rsp]
221 mov rax, qword [rsp + 2]
222 mov qword [rsp], rax
223 mov word [rsp + 8], bx
224
225 xor rax, rax
226 push rax
227 push rax
228 sgdt [rsp]
229 mov bx, word [rsp]
230 mov rax, qword [rsp + 2]
231 mov qword [rsp], rax
232 mov word [rsp + 8], bx
233
234;; UINT64 Ldtr, Tr;
235 xor rax, rax
236 str ax
237 push rax
238 sldt ax
239 push rax
240
241;; UINT64 RFlags;
242 push qword [rbp + 40]
243
244;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
245 mov rax, cr8
246 push rax
247 mov rax, cr4
248 or rax, 0x208
249 mov cr4, rax
250 push rax
251 mov rax, cr3
252 push rax
253 mov rax, cr2
254 push rax
255 xor rax, rax
256 push rax
257 mov rax, cr0
258 push rax
259
260;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
261 cmp qword [rbp + 8], VC_EXCEPTION
262 je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
263
264 mov rax, dr7
265 push rax
266 mov rax, dr6
267 push rax
268 mov rax, dr3
269 push rax
270 mov rax, dr2
271 push rax
272 mov rax, dr1
273 push rax
274 mov rax, dr0
275 push rax
276 jmp DrFinish
277
278VcDebugRegs:
279;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7 are skipped for #VC to avoid exception recursion
280 xor rax, rax
281 push rax
282 push rax
283 push rax
284 push rax
285 push rax
286 push rax
287
288DrFinish:
289;; FX_SAVE_STATE_X64 FxSaveState;
290 sub rsp, 512
291 mov rdi, rsp
292 fxsave [rdi]
293
294;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
295 cld
296
297;; UINT32 ExceptionData;
298 push qword [rbp + 16]
299
300;; Prepare parameter and call
301 mov rcx, [rbp + 8]
302 mov rdx, rsp
303 ;
304 ; Per X64 calling convention, allocate maximum parameter stack space
305 ; and make sure RSP is 16-byte aligned
306 ;
307 sub rsp, 4 * 8 + 8
308 call ASM_PFX(CommonExceptionHandler)
309 add rsp, 4 * 8 + 8
310
311 ; The follow algorithm is used for clear shadow stack token busy bit.
312 ; The comment is based on the sample shadow stack.
313 ; Shadow stack is 32 bytes aligned.
314 ; The sample shadow stack layout :
315 ; Address | Context
316 ; +-------------------------+
317 ; 0xFB8 | FREE | It is 0xFC0|0x02|(LMA & CS.L), after SAVEPREVSSP.
318 ; +-------------------------+
319 ; 0xFC0 | Prev SSP |
320 ; +-------------------------+
321 ; 0xFC8 | RIP |
322 ; +-------------------------+
323 ; 0xFD0 | CS |
324 ; +-------------------------+
325 ; 0xFD8 | 0xFD8 | BUSY | BUSY flag cleared after CLRSSBSY
326 ; +-------------------------+
327 ; 0xFE0 | 0xFC0|0x02|(LMA & CS.L) |
328 ; +-------------------------+
329 ; Instructions for Intel Control Flow Enforcement Technology (CET) are supported since NASM version 2.15.01.
330 cmp qword [ASM_PFX(mDoFarReturnFlag)], 0
331 jz CetDone
332 mov rax, cr4
333 and rax, 0x800000 ; Check if CET is enabled
334 jz CetDone
335 sub rsp, 0x10
336 sidt [rsp]
337 mov rcx, qword [rsp + IA32_DESCRIPTOR.Base]; Get IDT base address
338 add rsp, 0x10
339 mov rax, qword [rbp + 8]; Get exception number
340 sal rax, 0x04 ; Get IDT offset
341 add rax, rcx ; Get IDT gate descriptor address
342 mov al, byte [rax + IA32_IDT_GATE_DESCRIPTOR.Reserved_0]
343 and rax, 0x01 ; Check IST field
344 jz CetDone
345 ; SSP should be 0xFC0 at this point
346 mov rax, 0x04 ; advance past cs:lip:prevssp;supervisor shadow stack token
347 incsspq rax ; After this SSP should be 0xFE0
348 saveprevssp ; now the shadow stack restore token will be created at 0xFB8
349 rdsspq rax ; Read new SSP, SSP should be 0xFE8
350 sub rax, 0x10
351 clrssbsy [rax] ; Clear token at 0xFD8, SSP should be 0 after this
352 sub rax, 0x20
353 rstorssp [rax] ; Restore to token at 0xFB8, new SSP will be 0xFB8
354 mov rax, 0x01 ; Pop off the new save token created
355 incsspq rax ; SSP should be 0xFC0 now
356CetDone:
357
358 cli
359;; UINT64 ExceptionData;
360 add rsp, 8
361
362;; FX_SAVE_STATE_X64 FxSaveState;
363
364 mov rsi, rsp
365 fxrstor [rsi]
366 add rsp, 512
367
368;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
369;; Skip restoration of DRx registers to support in-circuit emualators
370;; or debuggers set breakpoint in interrupt/exception context
371 add rsp, 8 * 6
372
373;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
374 pop rax
375 mov cr0, rax
376 add rsp, 8 ; not for Cr1
377 pop rax
378 mov cr2, rax
379 pop rax
380 mov cr3, rax
381 pop rax
382 mov cr4, rax
383 pop rax
384 mov cr8, rax
385
386;; UINT64 RFlags;
387 pop qword [rbp + 40]
388
389;; UINT64 Ldtr, Tr;
390;; UINT64 Gdtr[2], Idtr[2];
391;; Best not let anyone mess with these particular registers...
392 add rsp, 48
393
394;; UINT64 Rip;
395 pop qword [rbp + 24]
396
397;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
398 pop rax
399 ; mov gs, rax ; not for gs
400 pop rax
401 ; mov fs, rax ; not for fs
402 ; (X64 will not use fs and gs, so we do not restore it)
403 pop rax
404 mov es, rax
405 pop rax
406 mov ds, rax
407 pop qword [rbp + 32] ; for cs
408 pop qword [rbp + 56] ; for ss
409
410;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
411;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
412 pop rdi
413 pop rsi
414 add rsp, 8 ; not for rbp
415 pop qword [rbp + 48] ; for rsp
416 pop rbx
417 pop rdx
418 pop rcx
419 pop rax
420 pop r8
421 pop r9
422 pop r10
423 pop r11
424 pop r12
425 pop r13
426 pop r14
427 pop r15
428
429 mov rsp, rbp
430 pop rbp
431 add rsp, 16
432 cmp qword [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
433 jz DoReturn
434 cmp qword [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
435 jz ErrorCode
436 jmp qword [rsp - 32]
437ErrorCode:
438 sub rsp, 8
439 jmp qword [rsp - 24]
440
441DoReturn:
442 cmp qword [ASM_PFX(mDoFarReturnFlag)], 0 ; Check if need to do far return instead of IRET
443 jz DoIret
444 push rax
445 mov rax, rsp ; save old RSP to rax
446 mov rsp, [rsp + 0x20]
447 push qword [rax + 0x10] ; save CS in new location
448 push qword [rax + 0x8] ; save EIP in new location
449 push qword [rax + 0x18] ; save EFLAGS in new location
450 mov rax, [rax] ; restore rax
451 popfq ; restore EFLAGS
452 retfq
453DoIret:
454 iretq
455
456;-------------------------------------------------------------------------------------
457; GetTemplateAddressMap (&AddressMap);
458;-------------------------------------------------------------------------------------
459; comments here for definition of address map
460global ASM_PFX(AsmGetTemplateAddressMap)
461ASM_PFX(AsmGetTemplateAddressMap):
462 lea rax, [AsmIdtVectorBegin]
463 mov qword [rcx], rax
464 mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 256
465 lea rax, [HookAfterStubHeaderBegin]
466 mov qword [rcx + 0x10], rax
467
468%ifdef NO_ABSOLUTE_RELOCS_IN_TEXT
469; Fix up CommonInterruptEntry address
470 lea rax, [ASM_PFX(CommonInterruptEntry)]
471 lea rcx, [AsmIdtVectorBegin]
472%rep 256
473 mov qword [rcx + (JmpAbsoluteAddress - 8 - HookAfterStubHeaderBegin)], rax
474 add rcx, (AsmIdtVectorEnd - AsmIdtVectorBegin) / 256
475%endrep
476; Fix up HookAfterStubHeaderEnd
477 lea rax, [HookAfterStubHeaderEnd]
478 lea rcx, [JmpAbsoluteAddress]
479 mov qword [rcx - 8], rax
480%endif
481
482 ret
483
484;-------------------------------------------------------------------------------------
485; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
486;-------------------------------------------------------------------------------------
487global ASM_PFX(AsmVectorNumFixup)
488ASM_PFX(AsmVectorNumFixup):
489 mov rax, rdx
490 mov [rcx + (VectorNum - 4 - HookAfterStubHeaderBegin)], al
491 ret
492
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette