VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-asm
File size: 19.2 KB
Line 
1;------------------------------------------------------------------------------ ;
2; Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
3; SPDX-License-Identifier: BSD-2-Clause-Patent
4;
5; Module Name:
6;
7; SmiException.nasm
8;
9; Abstract:
10;
11; Exception handlers used in SM mode
12;
13;-------------------------------------------------------------------------------
14
15extern ASM_PFX(SmiPFHandler)
16extern ASM_PFX(mSetupDebugTrap)
17
18global ASM_PFX(gcSmiIdtr)
19global ASM_PFX(gcSmiGdtr)
20global ASM_PFX(gTaskGateDescriptor)
21global ASM_PFX(gcPsd)
22
23 SECTION .data
24
25NullSeg: DQ 0 ; reserved by architecture
26CodeSeg32:
27 DW -1 ; LimitLow
28 DW 0 ; BaseLow
29 DB 0 ; BaseMid
30 DB 0x9b
31 DB 0xcf ; LimitHigh
32 DB 0 ; BaseHigh
33ProtModeCodeSeg32:
34 DW -1 ; LimitLow
35 DW 0 ; BaseLow
36 DB 0 ; BaseMid
37 DB 0x9b
38 DB 0xcf ; LimitHigh
39 DB 0 ; BaseHigh
40ProtModeSsSeg32:
41 DW -1 ; LimitLow
42 DW 0 ; BaseLow
43 DB 0 ; BaseMid
44 DB 0x93
45 DB 0xcf ; LimitHigh
46 DB 0 ; BaseHigh
47DataSeg32:
48 DW -1 ; LimitLow
49 DW 0 ; BaseLow
50 DB 0 ; BaseMid
51 DB 0x93
52 DB 0xcf ; LimitHigh
53 DB 0 ; BaseHigh
54CodeSeg16:
55 DW -1
56 DW 0
57 DB 0
58 DB 0x9b
59 DB 0x8f
60 DB 0
61DataSeg16:
62 DW -1
63 DW 0
64 DB 0
65 DB 0x93
66 DB 0x8f
67 DB 0
68CodeSeg64:
69 DW -1 ; LimitLow
70 DW 0 ; BaseLow
71 DB 0 ; BaseMid
72 DB 0x9b
73 DB 0xaf ; LimitHigh
74 DB 0 ; BaseHigh
75GDT_SIZE equ $ - NullSeg
76
77TssSeg:
78 DW TSS_DESC_SIZE ; LimitLow
79 DW 0 ; BaseLow
80 DB 0 ; BaseMid
81 DB 0x89
82 DB 0x80 ; LimitHigh
83 DB 0 ; BaseHigh
84ExceptionTssSeg:
85 DW EXCEPTION_TSS_DESC_SIZE ; LimitLow
86 DW 0 ; BaseLow
87 DB 0 ; BaseMid
88 DB 0x89
89 DB 0x80 ; LimitHigh
90 DB 0 ; BaseHigh
91
92CODE_SEL equ CodeSeg32 - NullSeg
93DATA_SEL equ DataSeg32 - NullSeg
94TSS_SEL equ TssSeg - NullSeg
95EXCEPTION_TSS_SEL equ ExceptionTssSeg - NullSeg
96
97struc IA32_TSS
98 resw 1
99 resw 1
100 .ESP0: resd 1
101 .SS0: resw 1
102 resw 1
103 .ESP1: resd 1
104 .SS1: resw 1
105 resw 1
106 .ESP2: resd 1
107 .SS2: resw 1
108 resw 1
109 ._CR3: resd 1
110 .EIP: resd 1
111 .EFLAGS: resd 1
112 ._EAX: resd 1
113 ._ECX: resd 1
114 ._EDX: resd 1
115 ._EBX: resd 1
116 ._ESP: resd 1
117 ._EBP: resd 1
118 ._ESI: resd 1
119 ._EDI: resd 1
120 ._ES: resw 1
121 resw 1
122 ._CS: resw 1
123 resw 1
124 ._SS: resw 1
125 resw 1
126 ._DS: resw 1
127 resw 1
128 ._FS: resw 1
129 resw 1
130 ._GS: resw 1
131 resw 1
132 .LDT: resw 1
133 resw 1
134 resw 1
135 resw 1
136endstruc
137
138; Create 2 TSS segments just after GDT
139TssDescriptor:
140 DW 0 ; PreviousTaskLink
141 DW 0 ; Reserved
142 DD 0 ; ESP0
143 DW 0 ; SS0
144 DW 0 ; Reserved
145 DD 0 ; ESP1
146 DW 0 ; SS1
147 DW 0 ; Reserved
148 DD 0 ; ESP2
149 DW 0 ; SS2
150 DW 0 ; Reserved
151 DD 0 ; CR3
152 DD 0 ; EIP
153 DD 0 ; EFLAGS
154 DD 0 ; EAX
155 DD 0 ; ECX
156 DD 0 ; EDX
157 DD 0 ; EBX
158 DD 0 ; ESP
159 DD 0 ; EBP
160 DD 0 ; ESI
161 DD 0 ; EDI
162 DW 0 ; ES
163 DW 0 ; Reserved
164 DW 0 ; CS
165 DW 0 ; Reserved
166 DW 0 ; SS
167 DW 0 ; Reserved
168 DW 0 ; DS
169 DW 0 ; Reserved
170 DW 0 ; FS
171 DW 0 ; Reserved
172 DW 0 ; GS
173 DW 0 ; Reserved
174 DW 0 ; LDT Selector
175 DW 0 ; Reserved
176 DW 0 ; T
177 DW 0 ; I/O Map Base
178TSS_DESC_SIZE equ $ - TssDescriptor
179
180ExceptionTssDescriptor:
181 DW 0 ; PreviousTaskLink
182 DW 0 ; Reserved
183 DD 0 ; ESP0
184 DW 0 ; SS0
185 DW 0 ; Reserved
186 DD 0 ; ESP1
187 DW 0 ; SS1
188 DW 0 ; Reserved
189 DD 0 ; ESP2
190 DW 0 ; SS2
191 DW 0 ; Reserved
192 DD 0 ; CR3
193 DD PFHandlerEntry ; EIP
194 DD 00000002 ; EFLAGS
195 DD 0 ; EAX
196 DD 0 ; ECX
197 DD 0 ; EDX
198 DD 0 ; EBX
199 DD 0 ; ESP
200 DD 0 ; EBP
201 DD 0 ; ESI
202 DD 0 ; EDI
203 DW DATA_SEL ; ES
204 DW 0 ; Reserved
205 DW CODE_SEL ; CS
206 DW 0 ; Reserved
207 DW DATA_SEL ; SS
208 DW 0 ; Reserved
209 DW DATA_SEL ; DS
210 DW 0 ; Reserved
211 DW DATA_SEL ; FS
212 DW 0 ; Reserved
213 DW DATA_SEL ; GS
214 DW 0 ; Reserved
215 DW 0 ; LDT Selector
216 DW 0 ; Reserved
217 DW 0 ; T
218 DW 0 ; I/O Map Base
219 DD 0 ; SSP
220EXCEPTION_TSS_DESC_SIZE equ $ - ExceptionTssDescriptor
221
222ASM_PFX(gcPsd):
223 DB 'PSDSIG '
224 DW PSD_SIZE
225 DW 2
226 DW 1 << 2
227 DW CODE_SEL
228 DW DATA_SEL
229 DW DATA_SEL
230 DW DATA_SEL
231 DW 0
232 DQ 0
233 DQ 0
234 DQ 0
235 DD 0
236 DD NullSeg
237 DD GDT_SIZE
238 DD 0
239 times 24 DB 0
240 DD 0
241 DD 0
242PSD_SIZE equ $ - ASM_PFX(gcPsd)
243
244ASM_PFX(gcSmiGdtr):
245 DW GDT_SIZE - 1
246 DD NullSeg
247
248ASM_PFX(gcSmiIdtr):
249 DW 0
250 DD 0
251
252ASM_PFX(gTaskGateDescriptor):
253 DW 0 ; Reserved
254 DW EXCEPTION_TSS_SEL ; TSS Segment selector
255 DB 0 ; Reserved
256 DB 0x85 ; Task Gate, present, DPL = 0
257 DW 0 ; Reserved
258
259 SECTION .text
260;------------------------------------------------------------------------------
261; PageFaultIdtHandlerSmmProfile is the entry point page fault only
262;
263;
264; Stack:
265; +---------------------+
266; + EFlags +
267; +---------------------+
268; + CS +
269; +---------------------+
270; + EIP +
271; +---------------------+
272; + Error Code +
273; +---------------------+
274; + Vector Number +
275; +---------------------+
276; + EBP +
277; +---------------------+ <-- EBP
278;
279;
280;------------------------------------------------------------------------------
281global ASM_PFX(PageFaultIdtHandlerSmmProfile)
282ASM_PFX(PageFaultIdtHandlerSmmProfile):
283 push 0xe ; Page Fault
284
285 push ebp
286 mov ebp, esp
287
288 ;
289 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
290 ; is 16-byte aligned
291 ;
292 and esp, 0xfffffff0
293 sub esp, 12
294
295;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
296 push eax
297 push ecx
298 push edx
299 push ebx
300 lea ecx, [ebp + 6 * 4]
301 push ecx ; ESP
302 push dword [ebp] ; EBP
303 push esi
304 push edi
305
306;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
307 mov eax, ss
308 push eax
309 movzx eax, word [ebp + 4 * 4]
310 push eax
311 mov eax, ds
312 push eax
313 mov eax, es
314 push eax
315 mov eax, fs
316 push eax
317 mov eax, gs
318 push eax
319
320;; UINT32 Eip;
321 mov eax, [ebp + 3 * 4]
322 push eax
323
324;; UINT32 Gdtr[2], Idtr[2];
325 sub esp, 8
326 sidt [esp]
327 mov eax, [esp + 2]
328 xchg eax, [esp]
329 and eax, 0xFFFF
330 mov [esp+4], eax
331
332 sub esp, 8
333 sgdt [esp]
334 mov eax, [esp + 2]
335 xchg eax, [esp]
336 and eax, 0xFFFF
337 mov [esp+4], eax
338
339;; UINT32 Ldtr, Tr;
340 xor eax, eax
341 str ax
342 push eax
343 sldt ax
344 push eax
345
346;; UINT32 EFlags;
347 mov eax, [ebp + 5 * 4]
348 push eax
349
350;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
351 mov eax, cr4
352 or eax, 0x208
353 mov cr4, eax
354 push eax
355 mov eax, cr3
356 push eax
357 mov eax, cr2
358 push eax
359 xor eax, eax
360 push eax
361 mov eax, cr0
362 push eax
363
364;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
365 mov eax, dr7
366 push eax
367 mov eax, dr6
368 push eax
369 mov eax, dr3
370 push eax
371 mov eax, dr2
372 push eax
373 mov eax, dr1
374 push eax
375 mov eax, dr0
376 push eax
377
378;; FX_SAVE_STATE_IA32 FxSaveState;
379 sub esp, 512
380 mov edi, esp
381 fxsave [edi]
382
383; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
384 cld
385
386;; UINT32 ExceptionData;
387 push dword [ebp + 2 * 4]
388
389;; call into exception handler
390
391;; Prepare parameter and call
392 mov edx, esp
393 push edx
394 mov edx, dword [ebp + 1 * 4]
395 push edx
396
397 ;
398 ; Call External Exception Handler
399 ;
400 mov eax, ASM_PFX(SmiPFHandler)
401 call eax
402 add esp, 8
403
404;; UINT32 ExceptionData;
405 add esp, 4
406
407;; FX_SAVE_STATE_IA32 FxSaveState;
408 mov esi, esp
409 fxrstor [esi]
410 add esp, 512
411
412;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
413;; Skip restoration of DRx registers to support debuggers
414;; that set breakpoint in interrupt/exception context
415 add esp, 4 * 6
416
417;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
418 pop eax
419 mov cr0, eax
420 add esp, 4 ; not for Cr1
421 pop eax
422 mov cr2, eax
423 pop eax
424 mov cr3, eax
425 pop eax
426 mov cr4, eax
427
428;; UINT32 EFlags;
429 pop dword [ebp + 5 * 4]
430
431;; UINT32 Ldtr, Tr;
432;; UINT32 Gdtr[2], Idtr[2];
433;; Best not let anyone mess with these particular registers...
434 add esp, 24
435
436;; UINT32 Eip;
437 pop dword [ebp + 3 * 4]
438
439;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
440;; NOTE - modified segment registers could hang the debugger... We
441;; could attempt to insulate ourselves against this possibility,
442;; but that poses risks as well.
443;;
444 pop gs
445 pop fs
446 pop es
447 pop ds
448 pop dword [ebp + 4 * 4]
449 pop ss
450
451;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
452 pop edi
453 pop esi
454 add esp, 4 ; not for ebp
455 add esp, 4 ; not for esp
456 pop ebx
457 pop edx
458 pop ecx
459 pop eax
460
461 mov esp, ebp
462 pop ebp
463
464; Enable TF bit after page fault handler runs
465 bts dword [esp + 16], 8 ; EFLAGS
466
467 add esp, 8 ; skip INT# & ErrCode
468Return:
469 iretd
470;
471; Page Fault Exception Handler entry when SMM Stack Guard is enabled
472; Executiot starts here after a task switch
473;
474PFHandlerEntry:
475;
476; Get this processor's TSS
477;
478 sub esp, 8
479 sgdt [esp + 2]
480 mov eax, [esp + 4] ; GDT base
481 add esp, 8
482 mov ecx, [eax + TSS_SEL + 2]
483 shl ecx, 8
484 mov cl, [eax + TSS_SEL + 7]
485 ror ecx, 8 ; ecx = TSS base
486
487 mov ebp, esp
488
489 ;
490 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
491 ; is 16-byte aligned
492 ;
493 and esp, 0xfffffff0
494 sub esp, 12
495
496;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
497 push dword [ecx + IA32_TSS._EAX]
498 push dword [ecx + IA32_TSS._ECX]
499 push dword [ecx + IA32_TSS._EDX]
500 push dword [ecx + IA32_TSS._EBX]
501 push dword [ecx + IA32_TSS._ESP]
502 push dword [ecx + IA32_TSS._EBP]
503 push dword [ecx + IA32_TSS._ESI]
504 push dword [ecx + IA32_TSS._EDI]
505
506;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
507 movzx eax, word [ecx + IA32_TSS._SS]
508 push eax
509 movzx eax, word [ecx + IA32_TSS._CS]
510 push eax
511 movzx eax, word [ecx + IA32_TSS._DS]
512 push eax
513 movzx eax, word [ecx + IA32_TSS._ES]
514 push eax
515 movzx eax, word [ecx + IA32_TSS._FS]
516 push eax
517 movzx eax, word [ecx + IA32_TSS._GS]
518 push eax
519
520;; UINT32 Eip;
521 push dword [ecx + IA32_TSS.EIP]
522
523;; UINT32 Gdtr[2], Idtr[2];
524 sub esp, 8
525 sidt [esp]
526 mov eax, [esp + 2]
527 xchg eax, [esp]
528 and eax, 0xFFFF
529 mov [esp+4], eax
530
531 sub esp, 8
532 sgdt [esp]
533 mov eax, [esp + 2]
534 xchg eax, [esp]
535 and eax, 0xFFFF
536 mov [esp+4], eax
537
538;; UINT32 Ldtr, Tr;
539 mov eax, TSS_SEL
540 push eax
541 movzx eax, word [ecx + IA32_TSS.LDT]
542 push eax
543
544;; UINT32 EFlags;
545 push dword [ecx + IA32_TSS.EFLAGS]
546
547;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
548 mov eax, cr4
549 or eax, 0x208
550 mov cr4, eax
551 push eax
552 mov eax, cr3
553 push eax
554 mov eax, cr2
555 push eax
556 xor eax, eax
557 push eax
558 mov eax, cr0
559 push eax
560
561;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
562 mov eax, dr7
563 push eax
564 mov eax, dr6
565 push eax
566 mov eax, dr3
567 push eax
568 mov eax, dr2
569 push eax
570 mov eax, dr1
571 push eax
572 mov eax, dr0
573 push eax
574
575;; FX_SAVE_STATE_IA32 FxSaveState;
576;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
577;; when executing fxsave/fxrstor instruction
578 clts
579 sub esp, 512
580 mov edi, esp
581 fxsave [edi]
582
583; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
584 cld
585
586;; UINT32 ExceptionData;
587 push dword [ebp]
588
589;; call into exception handler
590 mov ebx, ecx
591 mov eax, ASM_PFX(SmiPFHandler)
592
593;; Prepare parameter and call
594 mov edx, esp
595 push edx
596 mov edx, 14
597 push edx
598
599 ;
600 ; Call External Exception Handler
601 ;
602 call eax
603 add esp, 8
604
605 mov ecx, ebx
606;; UINT32 ExceptionData;
607 add esp, 4
608
609;; FX_SAVE_STATE_IA32 FxSaveState;
610 mov esi, esp
611 fxrstor [esi]
612 add esp, 512
613
614;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
615;; Skip restoration of DRx registers to support debuggers
616;; that set breakpoints in interrupt/exception context
617 add esp, 4 * 6
618
619;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
620 pop eax
621 mov cr0, eax
622 add esp, 4 ; not for Cr1
623 pop eax
624 mov cr2, eax
625 pop eax
626 mov dword [ecx + IA32_TSS._CR3], eax
627 pop eax
628 mov cr4, eax
629
630;; UINT32 EFlags;
631 pop dword [ecx + IA32_TSS.EFLAGS]
632
633;; UINT32 Ldtr, Tr;
634;; UINT32 Gdtr[2], Idtr[2];
635;; Best not let anyone mess with these particular registers...
636 add esp, 24
637
638;; UINT32 Eip;
639 pop dword [ecx + IA32_TSS.EIP]
640
641;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
642;; NOTE - modified segment registers could hang the debugger... We
643;; could attempt to insulate ourselves against this possibility,
644;; but that poses risks as well.
645;;
646 pop eax
647o16 mov [ecx + IA32_TSS._GS], ax
648 pop eax
649o16 mov [ecx + IA32_TSS._FS], ax
650 pop eax
651o16 mov [ecx + IA32_TSS._ES], ax
652 pop eax
653o16 mov [ecx + IA32_TSS._DS], ax
654 pop eax
655o16 mov [ecx + IA32_TSS._CS], ax
656 pop eax
657o16 mov [ecx + IA32_TSS._SS], ax
658
659;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
660 pop dword [ecx + IA32_TSS._EDI]
661 pop dword [ecx + IA32_TSS._ESI]
662 add esp, 4 ; not for ebp
663 add esp, 4 ; not for esp
664 pop dword [ecx + IA32_TSS._EBX]
665 pop dword [ecx + IA32_TSS._EDX]
666 pop dword [ecx + IA32_TSS._ECX]
667 pop dword [ecx + IA32_TSS._EAX]
668
669 mov esp, ebp
670
671; Set single step DB# if SMM profile is enabled and page fault exception happens
672 cmp byte [dword ASM_PFX(mSetupDebugTrap)], 0
673 jz @Done2
674
675; Create return context for iretd in stub function
676 mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer
677 mov ebx, dword [ecx + IA32_TSS.EIP]
678 mov [eax - 0xc], ebx ; create EIP in old stack
679 movzx ebx, word [ecx + IA32_TSS._CS]
680 mov [eax - 0x8], ebx ; create CS in old stack
681 mov ebx, dword [ecx + IA32_TSS.EFLAGS]
682 bts ebx, 8
683 mov [eax - 0x4], ebx ; create eflags in old stack
684 mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer
685 sub eax, 0xc ; minus 12 byte
686 mov dword [ecx + IA32_TSS._ESP], eax ; Set new stack pointer
687; Replace the EIP of interrupted task with stub function
688 mov eax, ASM_PFX(PageFaultStubFunction)
689 mov dword [ecx + IA32_TSS.EIP], eax
690; Jump to the iretd so next page fault handler as a task will start again after iretd.
691@Done2:
692 add esp, 4 ; skip ErrCode
693
694 jmp Return
695
696global ASM_PFX(PageFaultStubFunction)
697ASM_PFX(PageFaultStubFunction):
698;
699; we need clean TS bit in CR0 to execute
700; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
701;
702 clts
703 iretd
704
Note: See TracBrowser for help on using the repository browser.

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