Home | History | Annotate | Download | only in Ia32
      1 ;------------------------------------------------------------------------------ ;
      2 ; Copyright (c) 2009 - 2016, 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   gcSmiIdtr:FWORD
     27 EXTERNDEF   gcSmiGdtr:FWORD
     28 EXTERNDEF   gTaskGateDescriptor:QWORD
     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      0
    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      0
    256     DD      0
    257 
    258 gTaskGateDescriptor LABEL QWORD
    259     DW      0                           ; Reserved
    260     DW      EXCEPTION_TSS_SEL           ; TSS Segment selector
    261     DB      0                           ; Reserved
    262     DB      85h                         ; Task Gate, present, DPL = 0
    263     DW      0                           ; Reserved
    264 
    265 
    266     .code
    267 ;------------------------------------------------------------------------------
    268 ; PageFaultIdtHandlerSmmProfile is the entry point page fault only
    269 ;
    270 ;
    271 ; Stack:
    272 ; +---------------------+
    273 ; +    EFlags           +
    274 ; +---------------------+
    275 ; +    CS               +
    276 ; +---------------------+
    277 ; +    EIP              +
    278 ; +---------------------+
    279 ; +    Error Code       +
    280 ; +---------------------+
    281 ; +    Vector Number    +
    282 ; +---------------------+
    283 ; +    EBP              +
    284 ; +---------------------+ <-- EBP
    285 ;
    286 ;
    287 ;------------------------------------------------------------------------------
    288 PageFaultIdtHandlerSmmProfile PROC
    289     push    0eh                         ; Page Fault
    290 
    291     push    ebp
    292     mov     ebp, esp
    293 
    294 
    295     ;
    296     ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
    297     ; is 16-byte aligned
    298     ;
    299     and     esp, 0fffffff0h
    300     sub     esp, 12
    301 
    302 ;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
    303     push    eax
    304     push    ecx
    305     push    edx
    306     push    ebx
    307     lea     ecx, [ebp + 6 * 4]
    308     push    ecx                          ; ESP
    309     push    dword ptr [ebp]              ; EBP
    310     push    esi
    311     push    edi
    312 
    313 ;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
    314     mov     eax, ss
    315     push    eax
    316     movzx   eax, word ptr [ebp + 4 * 4]
    317     push    eax
    318     mov     eax, ds
    319     push    eax
    320     mov     eax, es
    321     push    eax
    322     mov     eax, fs
    323     push    eax
    324     mov     eax, gs
    325     push    eax
    326 
    327 ;; UINT32  Eip;
    328     mov     eax, [ebp + 3 * 4]
    329     push    eax
    330 
    331 ;; UINT32  Gdtr[2], Idtr[2];
    332     sub     esp, 8
    333     sidt    [esp]
    334     mov     eax, [esp + 2]
    335     xchg    eax, [esp]
    336     and     eax, 0FFFFh
    337     mov     [esp+4], eax
    338 
    339     sub     esp, 8
    340     sgdt    [esp]
    341     mov     eax, [esp + 2]
    342     xchg    eax, [esp]
    343     and     eax, 0FFFFh
    344     mov     [esp+4], eax
    345 
    346 ;; UINT32  Ldtr, Tr;
    347     xor     eax, eax
    348     str     ax
    349     push    eax
    350     sldt    ax
    351     push    eax
    352 
    353 ;; UINT32  EFlags;
    354     mov     eax, [ebp + 5 * 4]
    355     push    eax
    356 
    357 ;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
    358     mov     eax, cr4
    359     or      eax, 208h
    360     mov     cr4, eax
    361     push    eax
    362     mov     eax, cr3
    363     push    eax
    364     mov     eax, cr2
    365     push    eax
    366     xor     eax, eax
    367     push    eax
    368     mov     eax, cr0
    369     push    eax
    370 
    371 ;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    372     mov     eax, dr7
    373     push    eax
    374     mov     eax, dr6
    375     push    eax
    376     mov     eax, dr3
    377     push    eax
    378     mov     eax, dr2
    379     push    eax
    380     mov     eax, dr1
    381     push    eax
    382     mov     eax, dr0
    383     push    eax
    384 
    385 ;; FX_SAVE_STATE_IA32 FxSaveState;
    386     sub     esp, 512
    387     mov     edi, esp
    388     db      0fh, 0aeh, 07h ;fxsave [edi]
    389 
    390 ; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
    391     cld
    392 
    393 ;; UINT32  ExceptionData;
    394     push    dword ptr [ebp + 2 * 4]
    395 
    396 ;; call into exception handler
    397 
    398 ;; Prepare parameter and call
    399     mov     edx, esp
    400     push    edx
    401     mov     edx, dword ptr [ebp + 1 * 4]
    402     push    edx
    403 
    404     ;
    405     ; Call External Exception Handler
    406     ;
    407     mov     eax, SmiPFHandler
    408     call    eax
    409     add     esp, 8
    410 
    411 ;; UINT32  ExceptionData;
    412     add     esp, 4
    413 
    414 ;; FX_SAVE_STATE_IA32 FxSaveState;
    415     mov     esi, esp
    416     db      0fh, 0aeh, 0eh ; fxrstor [esi]
    417     add     esp, 512
    418 
    419 ;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    420 ;; Skip restoration of DRx registers to support debuggers
    421 ;; that set breakpoint in interrupt/exception context
    422     add     esp, 4 * 6
    423 
    424 ;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
    425     pop     eax
    426     mov     cr0, eax
    427     add     esp, 4    ; not for Cr1
    428     pop     eax
    429     mov     cr2, eax
    430     pop     eax
    431     mov     cr3, eax
    432     pop     eax
    433     mov     cr4, eax
    434 
    435 ;; UINT32  EFlags;
    436     pop     dword ptr [ebp + 5 * 4]
    437 
    438 ;; UINT32  Ldtr, Tr;
    439 ;; UINT32  Gdtr[2], Idtr[2];
    440 ;; Best not let anyone mess with these particular registers...
    441     add     esp, 24
    442 
    443 ;; UINT32  Eip;
    444     pop     dword ptr [ebp + 3 * 4]
    445 
    446 ;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
    447 ;; NOTE - modified segment registers could hang the debugger...  We
    448 ;;        could attempt to insulate ourselves against this possibility,
    449 ;;        but that poses risks as well.
    450 ;;
    451     pop     gs
    452     pop     fs
    453     pop     es
    454     pop     ds
    455     pop     dword ptr [ebp + 4 * 4]
    456     pop     ss
    457 
    458 ;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
    459     pop     edi
    460     pop     esi
    461     add     esp, 4   ; not for ebp
    462     add     esp, 4   ; not for esp
    463     pop     ebx
    464     pop     edx
    465     pop     ecx
    466     pop     eax
    467 
    468     mov     esp, ebp
    469     pop     ebp
    470 
    471 ; Enable TF bit after page fault handler runs
    472     bts     dword ptr [esp + 16], 8  ; EFLAGS
    473 
    474     add     esp, 8                      ; skip INT# & ErrCode
    475 Return:
    476     iretd
    477 ;
    478 ; Page Fault Exception Handler entry when SMM Stack Guard is enabled
    479 ; Executiot starts here after a task switch
    480 ;
    481 PFHandlerEntry::
    482 ;
    483 ; Get this processor's TSS
    484 ;
    485     sub     esp, 8
    486     sgdt    [esp + 2]
    487     mov     eax, [esp + 4]              ; GDT base
    488     add     esp, 8
    489     mov     ecx, [eax + TSS_SEL + 2]
    490     shl     ecx, 8
    491     mov     cl, [eax + TSS_SEL + 7]
    492     ror     ecx, 8                      ; ecx = TSS base
    493 
    494     mov     ebp, esp
    495 
    496     ;
    497     ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
    498     ; is 16-byte aligned
    499     ;
    500     and     esp, 0fffffff0h
    501     sub     esp, 12
    502 
    503 ;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
    504     push    (IA32_TSS ptr [ecx])._EAX
    505     push    (IA32_TSS ptr [ecx])._ECX
    506     push    (IA32_TSS ptr [ecx])._EDX
    507     push    (IA32_TSS ptr [ecx])._EBX
    508     push    (IA32_TSS ptr [ecx])._ESP
    509     push    (IA32_TSS ptr [ecx])._EBP
    510     push    (IA32_TSS ptr [ecx])._ESI
    511     push    (IA32_TSS ptr [ecx])._EDI
    512 
    513 ;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
    514     movzx   eax, (IA32_TSS ptr [ecx])._SS
    515     push    eax
    516     movzx   eax, (IA32_TSS ptr [ecx])._CS
    517     push    eax
    518     movzx   eax, (IA32_TSS ptr [ecx])._DS
    519     push    eax
    520     movzx   eax, (IA32_TSS ptr [ecx])._ES
    521     push    eax
    522     movzx   eax, (IA32_TSS ptr [ecx])._FS
    523     push    eax
    524     movzx   eax, (IA32_TSS ptr [ecx])._GS
    525     push    eax
    526 
    527 ;; UINT32  Eip;
    528     push    (IA32_TSS ptr [ecx]).EIP
    529 
    530 ;; UINT32  Gdtr[2], Idtr[2];
    531     sub     esp, 8
    532     sidt    [esp]
    533     mov     eax, [esp + 2]
    534     xchg    eax, [esp]
    535     and     eax, 0FFFFh
    536     mov     [esp+4], eax
    537 
    538     sub     esp, 8
    539     sgdt    [esp]
    540     mov     eax, [esp + 2]
    541     xchg    eax, [esp]
    542     and     eax, 0FFFFh
    543     mov     [esp+4], eax
    544 
    545 ;; UINT32  Ldtr, Tr;
    546     mov     eax, TSS_SEL
    547     push    eax
    548     movzx   eax, (IA32_TSS ptr [ecx]).LDT
    549     push    eax
    550 
    551 ;; UINT32  EFlags;
    552     push    (IA32_TSS ptr [ecx]).EFLAGS
    553 
    554 ;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
    555     mov     eax, cr4
    556     or      eax, 208h
    557     mov     cr4, eax
    558     push    eax
    559     mov     eax, cr3
    560     push    eax
    561     mov     eax, cr2
    562     push    eax
    563     xor     eax, eax
    564     push    eax
    565     mov     eax, cr0
    566     push    eax
    567 
    568 ;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    569     mov     eax, dr7
    570     push    eax
    571     mov     eax, dr6
    572     push    eax
    573     mov     eax, dr3
    574     push    eax
    575     mov     eax, dr2
    576     push    eax
    577     mov     eax, dr1
    578     push    eax
    579     mov     eax, dr0
    580     push    eax
    581 
    582 ;; FX_SAVE_STATE_IA32 FxSaveState;
    583 ;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
    584 ;; when executing fxsave/fxrstor instruction
    585     clts
    586     sub     esp, 512
    587     mov     edi, esp
    588     db      0fh, 0aeh, 07h ;fxsave [edi]
    589 
    590 ; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
    591     cld
    592 
    593 ;; UINT32  ExceptionData;
    594     push    dword ptr [ebp]
    595 
    596 ;; call into exception handler
    597     mov     ebx, ecx
    598     mov     eax, SmiPFHandler
    599 
    600 ;; Prepare parameter and call
    601     mov     edx, esp
    602     push    edx
    603     mov     edx, 14
    604     push    edx
    605 
    606     ;
    607     ; Call External Exception Handler
    608     ;
    609     call    eax
    610     add     esp, 8
    611 
    612     mov     ecx, ebx
    613 ;; UINT32  ExceptionData;
    614     add     esp, 4
    615 
    616 ;; FX_SAVE_STATE_IA32 FxSaveState;
    617     mov     esi, esp
    618     db      0fh, 0aeh, 0eh ; fxrstor [esi]
    619     add     esp, 512
    620 
    621 ;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    622 ;; Skip restoration of DRx registers to support debuggers
    623 ;; that set breakpoints in interrupt/exception context
    624     add     esp, 4 * 6
    625 
    626 ;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
    627     pop     eax
    628     mov     cr0, eax
    629     add     esp, 4    ; not for Cr1
    630     pop     eax
    631     mov     cr2, eax
    632     pop     eax
    633     mov     (IA32_TSS ptr [ecx])._CR3, eax
    634     pop     eax
    635     mov     cr4, eax
    636 
    637 ;; UINT32  EFlags;
    638     pop     (IA32_TSS ptr [ecx]).EFLAGS
    639 
    640 ;; UINT32  Ldtr, Tr;
    641 ;; UINT32  Gdtr[2], Idtr[2];
    642 ;; Best not let anyone mess with these particular registers...
    643     add     esp, 24
    644 
    645 ;; UINT32  Eip;
    646     pop     (IA32_TSS ptr [ecx]).EIP
    647 
    648 ;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
    649 ;; NOTE - modified segment registers could hang the debugger...  We
    650 ;;        could attempt to insulate ourselves against this possibility,
    651 ;;        but that poses risks as well.
    652 ;;
    653     pop     eax
    654     mov     (IA32_TSS ptr [ecx])._GS, ax
    655     pop     eax
    656     mov     (IA32_TSS ptr [ecx])._FS, ax
    657     pop     eax
    658     mov     (IA32_TSS ptr [ecx])._ES, ax
    659     pop     eax
    660     mov     (IA32_TSS ptr [ecx])._DS, ax
    661     pop     eax
    662     mov     (IA32_TSS ptr [ecx])._CS, ax
    663     pop     eax
    664     mov     (IA32_TSS ptr [ecx])._SS, ax
    665 
    666 ;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
    667     pop     (IA32_TSS ptr [ecx])._EDI
    668     pop     (IA32_TSS ptr [ecx])._ESI
    669     add     esp, 4   ; not for ebp
    670     add     esp, 4   ; not for esp
    671     pop     (IA32_TSS ptr [ecx])._EBX
    672     pop     (IA32_TSS ptr [ecx])._EDX
    673     pop     (IA32_TSS ptr [ecx])._ECX
    674     pop     (IA32_TSS ptr [ecx])._EAX
    675 
    676     mov     esp, ebp
    677 
    678 ; Set single step DB# if SMM profile is enabled and page fault exception happens
    679     cmp     FeaturePcdGet (PcdCpuSmmProfileEnable), 0
    680     jz      @Done2
    681 
    682 ; Create return context for iretd in stub function
    683     mov    eax, (IA32_TSS ptr [ecx])._ESP        ; Get old stack pointer
    684     mov    ebx, (IA32_TSS ptr [ecx]).EIP
    685     mov    [eax - 0ch], ebx                      ; create EIP in old stack
    686     movzx  ebx, (IA32_TSS ptr [ecx])._CS
    687     mov    [eax - 08h], ebx                      ; create CS in old stack
    688     mov    ebx, (IA32_TSS ptr [ecx]).EFLAGS
    689     bts    ebx, 8
    690     mov    [eax - 04h], ebx                      ; create eflags in old stack
    691     mov    eax, (IA32_TSS ptr [ecx])._ESP        ; Get old stack pointer
    692     sub    eax, 0ch                              ; minus 12 byte
    693     mov    (IA32_TSS ptr [ecx])._ESP, eax        ; Set new stack pointer
    694 ; Replace the EIP of interrupted task with stub function
    695     mov    eax, PageFaultStubFunction
    696     mov    (IA32_TSS ptr [ecx]).EIP, eax
    697 ; Jump to the iretd so next page fault handler as a task will start again after iretd.
    698 @Done2:
    699     add     esp, 4                      ; skip ErrCode
    700 
    701     jmp     Return
    702 PageFaultIdtHandlerSmmProfile ENDP
    703 
    704 PageFaultStubFunction   PROC
    705 ;
    706 ; we need clean TS bit in CR0 to execute
    707 ; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
    708 ;
    709     clts
    710     iretd
    711 PageFaultStubFunction   ENDP
    712 
    713     END
    714