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