]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.S
UefiCpuPkg: Add PiSmmCpuDxeSmm module IA32 files
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / SmiException.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials
5 # are licensed and made available under the terms and conditions of the BSD License
6 # which accompanies this distribution. The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
8 #
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #
12 # Module Name:
13 #
14 # SmiException.S
15 #
16 # Abstract:
17 #
18 # Exception handlers used in SM mode
19 #
20 #------------------------------------------------------------------------------
21
22 ASM_GLOBAL ASM_PFX(SmiPFHandler)
23 ASM_GLOBAL ASM_PFX(PageFaultStubFunction)
24 ASM_GLOBAL ASM_PFX(gSmiMtrrs)
25 ASM_GLOBAL ASM_PFX(gcSmiIdtr)
26 ASM_GLOBAL ASM_PFX(gcSmiGdtr)
27 ASM_GLOBAL ASM_PFX(gcPsd)
28 ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
29
30 .data
31
32 NullSeg: .quad 0 # reserved by architecture
33 CodeSeg32:
34 .word -1 # LimitLow
35 .word 0 # BaseLow
36 .byte 0 # BaseMid
37 .byte 0x9b
38 .byte 0xcf # LimitHigh
39 .byte 0 # BaseHigh
40 ProtModeCodeSeg32:
41 .word -1 # LimitLow
42 .word 0 # BaseLow
43 .byte 0 # BaseMid
44 .byte 0x9b
45 .byte 0xcf # LimitHigh
46 .byte 0 # BaseHigh
47 ProtModeSsSeg32:
48 .word -1 # LimitLow
49 .word 0 # BaseLow
50 .byte 0 # BaseMid
51 .byte 0x93
52 .byte 0xcf # LimitHigh
53 .byte 0 # BaseHigh
54 DataSeg32:
55 .word -1 # LimitLow
56 .word 0 # BaseLow
57 .byte 0 # BaseMid
58 .byte 0x93
59 .byte 0xcf # LimitHigh
60 .byte 0 # BaseHigh
61 CodeSeg16:
62 .word -1
63 .word 0
64 .byte 0
65 .byte 0x9b
66 .byte 0x8f
67 .byte 0
68 DataSeg16:
69 .word -1
70 .word 0
71 .byte 0
72 .byte 0x93
73 .byte 0x8f
74 .byte 0
75 CodeSeg64:
76 .word -1 # LimitLow
77 .word 0 # BaseLow
78 .byte 0 # BaseMid
79 .byte 0x9b
80 .byte 0xaf # LimitHigh
81 .byte 0 # BaseHigh
82 .equ GDT_SIZE, .- NullSeg
83
84 TssSeg:
85 .word TSS_DESC_SIZE # LimitLow
86 .word 0 # BaseLow
87 .byte 0 # BaseMid
88 .byte 0x89
89 .byte 0x80 # LimitHigh
90 .byte 0 # BaseHigh
91 ExceptionTssSeg:
92 .word TSS_DESC_SIZE # LimitLow
93 .word 0 # BaseLow
94 .byte 0 # BaseMid
95 .byte 0x89
96 .byte 0x80 # LimitHigh
97 .byte 0 # BaseHigh
98
99 .equ CODE_SEL, CodeSeg32 - NullSeg
100 .equ DATA_SEL, DataSeg32 - NullSeg
101 .equ TSS_SEL, TssSeg - NullSeg
102 .equ EXCEPTION_TSS_SEL, ExceptionTssSeg - NullSeg
103
104 # IA32 TSS fields
105 .equ TSS_ESP0, 4
106 .equ TSS_SS0, 8
107 .equ TSS_ESP1, 12
108 .equ TSS_SS1, 16
109 .equ TSS_ESP2, 20
110 .equ TSS_SS2, 24
111 .equ TSS_CR3, 28
112 .equ TSS_EIP, 32
113 .equ TSS_EFLAGS, 36
114 .equ TSS_EAX, 40
115 .equ TSS_ECX, 44
116 .equ TSS_EDX, 48
117 .equ TSS_EBX, 52
118 .equ TSS_ESP, 56
119 .equ TSS_EBP, 60
120 .equ TSS_ESI, 64
121 .equ TSS_EDI, 68
122 .equ TSS_ES, 72
123 .equ TSS_CS, 76
124 .equ TSS_SS, 80
125 .equ TSS_DS, 84
126 .equ TSS_FS, 88
127 .equ TSS_GS, 92
128 .equ TSS_LDT, 96
129
130 # Create 2 TSS segments just after GDT
131 TssDescriptor:
132 .word 0 # PreviousTaskLink
133 .word 0 # Reserved
134 .long 0 # ESP0
135 .word 0 # SS0
136 .word 0 # Reserved
137 .long 0 # ESP1
138 .word 0 # SS1
139 .word 0 # Reserved
140 .long 0 # ESP2
141 .word 0 # SS2
142 .word 0 # Reserved
143 .long 0 # CR3
144 .long 0 # EIP
145 .long 0 # EFLAGS
146 .long 0 # EAX
147 .long 0 # ECX
148 .long 0 # EDX
149 .long 0 # EBX
150 .long 0 # ESP
151 .long 0 # EBP
152 .long 0 # ESI
153 .long 0 # EDI
154 .word 0 # ES
155 .word 0 # Reserved
156 .word 0 # CS
157 .word 0 # Reserved
158 .word 0 # SS
159 .word 0 # Reserved
160 .word 0 # DS
161 .word 0 # Reserved
162 .word 0 # FS
163 .word 0 # Reserved
164 .word 0 # GS
165 .word 0 # Reserved
166 .word 0 # LDT Selector
167 .word 0 # Reserved
168 .word 0 # T
169 .word 0 # I/O Map Base
170 .equ TSS_DESC_SIZE, . - TssDescriptor
171
172 ExceptionTssDescriptor:
173 .word 0 # PreviousTaskLink
174 .word 0 # Reserved
175 .long 0 # ESP0
176 .word 0 # SS0
177 .word 0 # Reserved
178 .long 0 # ESP1
179 .word 0 # SS1
180 .word 0 # Reserved
181 .long 0 # ESP2
182 .word 0 # SS2
183 .word 0 # Reserved
184 .long 0 # CR3
185 .long PFHandlerEntry # EIP
186 .long 00000002 # EFLAGS
187 .long 0 # EAX
188 .long 0 # ECX
189 .long 0 # EDX
190 .long 0 # EBX
191 .long 0 # ESP
192 .long 0 # EBP
193 .long 0 # ESI
194 .long 0 # EDI
195 .word DATA_SEL # ES
196 .word 0 # Reserved
197 .word CODE_SEL # CS
198 .word 0 # Reserved
199 .word DATA_SEL # SS
200 .word 0 # Reserved
201 .word DATA_SEL # DS
202 .word 0 # Reserved
203 .word DATA_SEL # FS
204 .word 0 # Reserved
205 .word DATA_SEL # GS
206 .word 0 # Reserved
207 .word 0 # LDT Selector
208 .word 0 # Reserved
209 .word 0 # T
210 .word 0 # I/O Map Base
211
212 ASM_PFX(gcPsd):
213 .ascii "PSDSIG "
214 .word PSD_SIZE
215 .word 2
216 .word 1 << 2
217 .word CODE_SEL
218 .word DATA_SEL
219 .word DATA_SEL
220 .word DATA_SEL
221 .word 0
222 .long 0
223 .long 0
224 .long 0
225 .long 0
226 .quad 0
227 .long NullSeg
228 .long 0
229 .long GDT_SIZE
230 .long 0
231 .space 24, 0
232 .long ASM_PFX(gSmiMtrrs)
233 .long 0
234 .equ PSD_SIZE, . - ASM_PFX(gcPsd)
235
236 ASM_PFX(gcSmiGdtr): .word GDT_SIZE - 1
237 .long NullSeg
238
239 ASM_PFX(gcSmiIdtr): .word IDT_SIZE - 1
240 .long _SmiIDT
241
242 _SmiIDT:
243 # The following segment repeats 32 times:
244 # No. 1
245 .word 0 # Offset 0:15
246 .word CODE_SEL
247 .byte 0 # Unused
248 .byte 0x8e # Interrupt Gate, Present
249 .word 0 # Offset 16:31
250 # No. 2
251 .word 0 # Offset 0:15
252 .word CODE_SEL
253 .byte 0 # Unused
254 .byte 0x8e # Interrupt Gate, Present
255 .word 0 # Offset 16:31
256 # No. 3
257 .word 0 # Offset 0:15
258 .word CODE_SEL
259 .byte 0 # Unused
260 .byte 0x8e # Interrupt Gate, Present
261 .word 0 # Offset 16:31
262 # No. 4
263 .word 0 # Offset 0:15
264 .word CODE_SEL
265 .byte 0 # Unused
266 .byte 0x8e # Interrupt Gate, Present
267 .word 0 # Offset 16:31
268 # No. 5
269 .word 0 # Offset 0:15
270 .word CODE_SEL
271 .byte 0 # Unused
272 .byte 0x8e # Interrupt Gate, Present
273 .word 0 # Offset 16:31
274 # No. 6
275 .word 0 # Offset 0:15
276 .word CODE_SEL
277 .byte 0 # Unused
278 .byte 0x8e # Interrupt Gate, Present
279 .word 0 # Offset 16:31
280 # No. 7
281 .word 0 # Offset 0:15
282 .word CODE_SEL
283 .byte 0 # Unused
284 .byte 0x8e # Interrupt Gate, Present
285 .word 0 # Offset 16:31
286 # No. 8
287 .word 0 # Offset 0:15
288 .word CODE_SEL
289 .byte 0 # Unused
290 .byte 0x8e # Interrupt Gate, Present
291 .word 0 # Offset 16:31
292 # No. 9
293 .word 0 # Offset 0:15
294 .word CODE_SEL
295 .byte 0 # Unused
296 .byte 0x8e # Interrupt Gate, Present
297 .word 0 # Offset 16:31
298 # No. 10
299 .word 0 # Offset 0:15
300 .word CODE_SEL
301 .byte 0 # Unused
302 .byte 0x8e # Interrupt Gate, Present
303 .word 0 # Offset 16:31
304 # No. 11
305 .word 0 # Offset 0:15
306 .word CODE_SEL
307 .byte 0 # Unused
308 .byte 0x8e # Interrupt Gate, Present
309 .word 0 # Offset 16:31
310 # No. 12
311 .word 0 # Offset 0:15
312 .word CODE_SEL
313 .byte 0 # Unused
314 .byte 0x8e # Interrupt Gate, Present
315 .word 0 # Offset 16:31
316 # No. 13
317 .word 0 # Offset 0:15
318 .word CODE_SEL
319 .byte 0 # Unused
320 .byte 0x8e # Interrupt Gate, Present
321 .word 0 # Offset 16:31
322 # No. 14
323 .word 0 # Offset 0:15
324 .word CODE_SEL
325 .byte 0 # Unused
326 .byte 0x8e # Interrupt Gate, Present
327 .word 0 # Offset 16:31
328 # No. 15
329 .word 0 # Offset 0:15
330 .word CODE_SEL
331 .byte 0 # Unused
332 .byte 0x8e # Interrupt Gate, Present
333 .word 0 # Offset 16:31
334 # No. 16
335 .word 0 # Offset 0:15
336 .word CODE_SEL
337 .byte 0 # Unused
338 .byte 0x8e # Interrupt Gate, Present
339 .word 0 # Offset 16:31
340 # No. 17
341 .word 0 # Offset 0:15
342 .word CODE_SEL
343 .byte 0 # Unused
344 .byte 0x8e # Interrupt Gate, Present
345 .word 0 # Offset 16:31
346 # No. 18
347 .word 0 # Offset 0:15
348 .word CODE_SEL
349 .byte 0 # Unused
350 .byte 0x8e # Interrupt Gate, Present
351 .word 0 # Offset 16:31
352 # No. 19
353 .word 0 # Offset 0:15
354 .word CODE_SEL
355 .byte 0 # Unused
356 .byte 0x8e # Interrupt Gate, Present
357 .word 0 # Offset 16:31
358 # No. 20
359 .word 0 # Offset 0:15
360 .word CODE_SEL
361 .byte 0 # Unused
362 .byte 0x8e # Interrupt Gate, Present
363 .word 0 # Offset 16:31
364 # No. 21
365 .word 0 # Offset 0:15
366 .word CODE_SEL
367 .byte 0 # Unused
368 .byte 0x8e # Interrupt Gate, Present
369 .word 0 # Offset 16:31
370 # No. 22
371 .word 0 # Offset 0:15
372 .word CODE_SEL
373 .byte 0 # Unused
374 .byte 0x8e # Interrupt Gate, Present
375 .word 0 # Offset 16:31
376 # No. 23
377 .word 0 # Offset 0:15
378 .word CODE_SEL
379 .byte 0 # Unused
380 .byte 0x8e # Interrupt Gate, Present
381 .word 0 # Offset 16:31
382 # No. 24
383 .word 0 # Offset 0:15
384 .word CODE_SEL
385 .byte 0 # Unused
386 .byte 0x8e # Interrupt Gate, Present
387 .word 0 # Offset 16:31
388 # No. 25
389 .word 0 # Offset 0:15
390 .word CODE_SEL
391 .byte 0 # Unused
392 .byte 0x8e # Interrupt Gate, Present
393 .word 0 # Offset 16:31
394 # No. 26
395 .word 0 # Offset 0:15
396 .word CODE_SEL
397 .byte 0 # Unused
398 .byte 0x8e # Interrupt Gate, Present
399 .word 0 # Offset 16:31
400 # No. 27
401 .word 0 # Offset 0:15
402 .word CODE_SEL
403 .byte 0 # Unused
404 .byte 0x8e # Interrupt Gate, Present
405 .word 0 # Offset 16:31
406 # No. 28
407 .word 0 # Offset 0:15
408 .word CODE_SEL
409 .byte 0 # Unused
410 .byte 0x8e # Interrupt Gate, Present
411 .word 0 # Offset 16:31
412 # No. 29
413 .word 0 # Offset 0:15
414 .word CODE_SEL
415 .byte 0 # Unused
416 .byte 0x8e # Interrupt Gate, Present
417 .word 0 # Offset 16:31
418 # No. 30
419 .word 0 # Offset 0:15
420 .word CODE_SEL
421 .byte 0 # Unused
422 .byte 0x8e # Interrupt Gate, Present
423 .word 0 # Offset 16:31
424 # No. 31
425 .word 0 # Offset 0:15
426 .word CODE_SEL
427 .byte 0 # Unused
428 .byte 0x8e # Interrupt Gate, Present
429 .word 0 # Offset 16:31
430 # No. 32
431 .word 0 # Offset 0:15
432 .word CODE_SEL
433 .byte 0 # Unused
434 .byte 0x8e # Interrupt Gate, Present
435 .word 0 # Offset 16:31
436
437 .equ IDT_SIZE, . - _SmiIDT
438
439 TaskGateDescriptor:
440 .word 0 # Reserved
441 .word EXCEPTION_TSS_SEL # TSS Segment selector
442 .byte 0 # Reserved
443 .byte 0x85 # Task Gate, present, DPL = 0
444 .word 0 # Reserved
445
446 .text
447
448 #------------------------------------------------------------------------------
449 # PageFaultIdtHandlerSmmProfile is the entry point for all exceptions
450 #
451 # Stack:
452 #+---------------------+
453 #+ EFlags +
454 #+---------------------+
455 #+ CS +
456 #+---------------------+
457 #+ EIP +
458 #+---------------------+
459 #+ Error Code +
460 #+---------------------+
461 #+ Vector Number +
462 #+---------------------+
463 #+ EBP +
464 #+---------------------+ <-- EBP
465 #
466 # RSP set to odd multiple of 8 means ErrCode PRESENT
467 #------------------------------------------------------------------------------
468 ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
469 ASM_PFX(PageFaultIdtHandlerSmmProfile):
470 pushl $0x0e # Page Fault
471 pushl %ebp
472 movl %esp, %ebp
473
474
475 #
476 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
477 # is 16-byte aligned
478 #
479 andl $0xfffffff0, %esp
480 subl $12, %esp
481
482 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
483 pushl %eax
484 pushl %ecx
485 pushl %edx
486 pushl %ebx
487 leal (6*4)(%ebp), %ecx
488 pushl %ecx # ESP
489 pushl (%ebp) # EBP
490 pushl %esi
491 pushl %edi
492
493 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
494 movl %ss, %eax
495 pushl %eax
496 movzwl (4*4)(%ebp), %eax
497 pushl %eax
498 movl %ds, %eax
499 pushl %eax
500 movl %es, %eax
501 pushl %eax
502 movl %fs, %eax
503 pushl %eax
504 movl %gs, %eax
505 pushl %eax
506
507 ## UINT32 Eip;
508 movl (3*4)(%ebp), %eax
509 pushl %eax
510
511 ## UINT32 Gdtr[2], Idtr[2];
512 subl $8, %esp
513 sidt (%esp)
514 movl 2(%esp), %eax
515 xchgl (%esp), %eax
516 andl $0xffff, %eax
517 movl %eax, 4(%esp)
518
519 subl $8, %esp
520 sgdt (%esp)
521 movl 2(%esp), %eax
522 xchgl (%esp), %eax
523 andl $0xffff, %eax
524 movl %eax, 4(%esp)
525
526 ## UINT32 Ldtr, Tr;
527 xorl %eax, %eax
528 strw %ax
529 pushl %eax
530 sldtw %ax
531 pushl %eax
532
533 ## UINT32 EFlags;
534 movl (5*4)(%ebp), %eax
535 pushl %eax
536
537 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
538 movl %cr4, %eax
539 orl $0x208, %eax
540 movl %eax, %cr4
541 pushl %eax
542 movl %cr3, %eax
543 pushl %eax
544 movl %cr2, %eax
545 pushl %eax
546 xorl %eax, %eax
547 pushl %eax
548 movl %cr0, %eax
549 pushl %eax
550
551 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
552 movl %dr7, %eax
553 pushl %eax
554 movl %dr6, %eax
555 pushl %eax
556 movl %dr3, %eax
557 pushl %eax
558 movl %dr2, %eax
559 pushl %eax
560 movl %dr1, %eax
561 pushl %eax
562 movl %dr0, %eax
563 pushl %eax
564
565 ## FX_SAVE_STATE_IA32 FxSaveState;
566 subl $512, %esp
567 movl %esp, %edi
568 .byte 0x0f, 0xae, 0x07 #fxsave [edi]
569
570 # UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
571 cld
572
573 ## UINT32 ExceptionData;
574 pushl (2*4)(%ebp)
575
576 ## call into exception handler
577
578 ## Prepare parameter and call
579 movl %esp, %edx
580 pushl %edx
581 movl (1*4)(%ebp), %edx
582 pushl %edx
583
584 #
585 # Call External Exception Handler
586 #
587 movl $ASM_PFX(SmiPFHandler), %eax
588 call *%eax
589 addl $8, %esp
590 jmp L4
591
592 L4:
593 ## UINT32 ExceptionData;
594 addl $4, %esp
595
596 ## FX_SAVE_STATE_IA32 FxSaveState;
597 movl %esp, %esi
598 .byte 0xf, 0xae, 0xe # fxrstor [esi]
599 addl $512, %esp
600
601 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
602 ## Skip restoration of DRx registers to support debuggers
603 ## that set breakpoints in interrupt/exception context
604 addl $4*6, %esp
605
606 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
607 popl %eax
608 movl %eax, %cr0
609 addl $4, %esp # not for Cr1
610 popl %eax
611 movl %eax, %cr2
612 popl %eax
613 movl %eax, %cr3
614 popl %eax
615 movl %eax, %cr4
616
617 ## UINT32 EFlags;
618 popl (5*4)(%ebp)
619
620 ## UINT32 Ldtr, Tr;
621 ## UINT32 Gdtr[2], Idtr[2];
622 ## Best not let anyone mess with these particular registers...
623 addl $24, %esp
624
625 ## UINT32 Eip;
626 popl (3*4)(%ebp)
627
628 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
629 ## NOTE - modified segment registers could hang the debugger... We
630 ## could attempt to insulate ourselves against this possibility,
631 ## but that poses risks as well.
632 ##
633 popl %gs
634 popl %fs
635 popl %es
636 popl %ds
637 popl (4*4)(%ebp)
638 popl %ss
639
640 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
641 popl %edi
642 popl %esi
643 addl $4, %esp # not for ebp
644 addl $4, %esp # not for esp
645 popl %ebx
646 popl %edx
647 popl %ecx
648 popl %eax
649
650 movl %ebp, %esp
651 popl %ebp
652
653 # Enable TF bit after page fault handler runs
654 btsl $8, 16(%esp) # EFLAGS
655
656 addl $8, %esp # skip INT# & ErrCode
657 Return:
658 iret
659 #
660 # Page Fault Exception Handler entry when SMM Stack Guard is enabled
661 # Executiot starts here after a task switch
662 #
663 PFHandlerEntry:
664 #
665 # Get this processor's TSS
666 #
667 subl $8, %esp
668 sgdt 2(%esp)
669 movl 4(%esp), %eax # GDT base
670 addl $8, %esp
671 movl (TSS_SEL+2)(%eax), %ecx
672 shll $8, %ecx
673 movb (TSS_SEL+7)(%eax), %cl
674 rorl $8, %ecx # ecx = TSS base
675
676 movl %esp, %ebp
677
678 #
679 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
680 # is 16-byte aligned
681 #
682 andl $0xfffffff0, %esp
683 subl $12, %esp
684
685 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
686 pushl TSS_EAX(%ecx)
687 pushl TSS_ECX(%ecx)
688 pushl TSS_EDX(%ecx)
689 pushl TSS_EBX(%ecx)
690 pushl TSS_ESP(%ecx)
691 pushl TSS_EBP(%ecx)
692 pushl TSS_ESI(%ecx)
693 pushl TSS_EDI(%ecx)
694
695 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
696 movzwl TSS_SS(%ecx), %eax
697 pushl %eax
698 movzwl TSS_CS(%ecx), %eax
699 pushl %eax
700 movzwl TSS_DS(%ecx), %eax
701 pushl %eax
702 movzwl TSS_ES(%ecx), %eax
703 pushl %eax
704 movzwl TSS_FS(%ecx), %eax
705 pushl %eax
706 movzwl TSS_GS(%ecx), %eax
707 pushl %eax
708
709 ## UINT32 Eip;
710 pushl TSS_EIP(%ecx)
711
712 ## UINT32 Gdtr[2], Idtr[2];
713 subl $8, %esp
714 sidt (%esp)
715 movl 2(%esp), %eax
716 xchgl (%esp), %eax
717 andl $0xFFFF, %eax
718 movl %eax, 4(%esp)
719
720 subl $8, %esp
721 sgdt (%esp)
722 movl 2(%esp), %eax
723 xchgl (%esp), %eax
724 andl $0xFFFF, %eax
725 movl %eax, 4(%esp)
726
727 ## UINT32 Ldtr, Tr;
728 movl $TSS_SEL, %eax
729 pushl %eax
730 movzwl TSS_LDT(%ecx), %eax
731 pushl %eax
732
733 ## UINT32 EFlags;
734 pushl TSS_EFLAGS(%ecx)
735
736 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
737 movl %cr4, %eax
738 orl $0x208, %eax
739 movl %eax, %cr4
740 pushl %eax
741 movl %cr3, %eax
742 pushl %eax
743 movl %cr2, %eax
744 pushl %eax
745 xorl %eax, %eax
746 pushl %eax
747 movl %cr0, %eax
748 pushl %eax
749
750 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
751 movl %dr7, %eax
752 pushl %eax
753 movl %dr6, %eax
754 pushl %eax
755 movl %dr3, %eax
756 pushl %eax
757 movl %dr2, %eax
758 pushl %eax
759 movl %dr1, %eax
760 pushl %eax
761 movl %dr0, %eax
762 pushl %eax
763
764 ## FX_SAVE_STATE_IA32 FxSaveState;
765 ## Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
766 ## when executing fxsave/fxrstor instruction
767 clts
768 subl $512, %esp
769 movl %esp, %edi
770 .byte 0x0f, 0xae, 0x07 #fxsave [edi]
771
772 # UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
773 cld
774
775 ## UINT32 ExceptionData;
776 pushl (%ebp)
777
778 ## call into exception handler
779 movl %ecx, %ebx
780 movl $ASM_PFX(SmiPFHandler), %eax
781
782 ## Prepare parameter and call
783 movl %esp, %edx
784 pushl %edx
785 movl $14, %edx
786 pushl %edx
787
788 #
789 # Call External Exception Handler
790 #
791 call *%eax
792 addl $8, %esp
793
794 movl %ebx, %ecx
795 ## UINT32 ExceptionData;
796 addl $4, %esp
797
798 ## FX_SAVE_STATE_IA32 FxSaveState;
799 movl %esp, %esi
800 .byte 0xf, 0xae, 0xe # fxrstor [esi]
801 addl $512, %esp
802
803 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
804 ## Skip restoration of DRx registers to support debuggers
805 ## that set breakpoints in interrupt/exception context
806 addl $4*6, %esp
807
808 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
809 popl %eax
810 movl %eax, %cr0
811 addl $4, %esp # not for Cr1
812 popl %eax
813 movl %eax, %cr2
814 popl %eax
815 movl %eax, TSS_CR3(%ecx)
816 popl %eax
817 movl %eax, %cr4
818
819 ## UINT32 EFlags;
820 popl TSS_EFLAGS(%ecx)
821
822 ## UINT32 Ldtr, Tr;
823 ## UINT32 Gdtr[2], Idtr[2];
824 ## Best not let anyone mess with these particular registers...
825 addl $24, %esp
826
827 ## UINT32 Eip;
828 popl TSS_EIP(%ecx)
829
830 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
831 ## NOTE - modified segment registers could hang the debugger... We
832 ## could attempt to insulate ourselves against this possibility,
833 ## but that poses risks as well.
834 ##
835 popl %eax
836 movw %ax, TSS_GS(%ecx)
837 popl %eax
838 movw %ax, TSS_FS(%ecx)
839 popl %eax
840 movw %ax, TSS_ES(%ecx)
841 popl %eax
842 movw %ax, TSS_DS(%ecx)
843 popl %eax
844 movw %ax, TSS_CS(%ecx)
845 popl %eax
846 movw %ax, TSS_SS(%ecx)
847
848 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
849 popl TSS_EDI(%ecx)
850 popl TSS_ESI(%ecx)
851 addl $4, %esp # not for ebp
852 addl $4, %esp # not for esp
853 popl TSS_EBX(%ecx)
854 popl TSS_EDX(%ecx)
855 popl TSS_ECX(%ecx)
856 popl TSS_EAX(%ecx)
857
858 movl %ebp, %esp
859
860 # Set single step DB# if SMM profile is enabled and page fault exception happens
861 cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
862 jz Done2
863 # Create return context for iret in stub function
864 movl TSS_ESP(%ecx), %eax # Get old stack pointer
865 movl TSS_EIP(%ecx), %ebx
866 movl %ebx, -0xc(%eax) # create EIP in old stack
867 movzwl TSS_CS(%ecx), %ebx
868 movl %ebx, -0x8(%eax) # create CS in old stack
869 movl TSS_EFLAGS(%ecx), %ebx
870 btsl $8,%ebx
871 movl %ebx, -0x4(%eax) # create eflags in old stack
872 movl TSS_ESP(%ecx), %eax # Get old stack pointer
873 subl $12, %eax # minus 12 byte
874 movl %eax, TSS_ESP(%ecx) # Set new stack pointer
875
876 # Replace the EIP of interrupted task with stub function
877 movl $ASM_PFX(PageFaultStubFunction), %eax
878 movl %eax, TSS_EIP(%ecx)
879 # Jump to the iret so next page fault handler as a task will start again after iret.
880
881 Done2:
882
883 addl $4, %esp # skip ErrCode
884
885 jmp Return
886
887 ASM_PFX(PageFaultStubFunction):
888 #
889 # we need clean TS bit in CR0 to execute
890 # x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
891 #
892 clts
893 iret
894
895 ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard)
896 ASM_PFX(InitializeIDTSmmStackGuard):
897 pushl %ebx
898 #
899 # If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT
900 # is a Task Gate Descriptor so that when a Page Fault Exception occurs,
901 # the processors can use a known good stack in case stack ran out.
902 #
903 leal _SmiIDT + 14 * 8, %ebx
904 leal TaskGateDescriptor, %edx
905 movl (%edx), %eax
906 movl %eax, (%ebx)
907 movl 4(%edx), %eax
908 movl %eax, 4(%ebx)
909
910 popl %ebx
911 ret