]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg PiSmmCpuDxeSmm: Convert Ia32/SmiException.asm to NASM
authorLiming Gao <liming.gao@intel.com>
Tue, 14 Jun 2016 08:29:11 +0000 (16:29 +0800)
committerLiming Gao <liming.gao@intel.com>
Tue, 28 Jun 2016 01:52:15 +0000 (09:52 +0800)
Manually convert Ia32/SmiException.asm to Ia32/SmiException.nasm

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Liming Gao <liming.gao@intel.com>
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm [new file with mode: 0644]

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm
new file mode 100644 (file)
index 0000000..f9f3986
--- /dev/null
@@ -0,0 +1,737 @@
+;------------------------------------------------------------------------------ ;\r
+; Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution.  The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php.\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+; Module Name:\r
+;\r
+;   SmiException.nasm\r
+;\r
+; Abstract:\r
+;\r
+;   Exception handlers used in SM mode\r
+;\r
+;-------------------------------------------------------------------------------\r
+\r
+extern  ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))\r
+extern  ASM_PFX(gSmiMtrrs)\r
+extern  ASM_PFX(SmiPFHandler)\r
+\r
+global  ASM_PFX(gcSmiIdtr)\r
+global  ASM_PFX(gcSmiGdtr)\r
+global  ASM_PFX(gcPsd)\r
+\r
+    SECTION .data\r
+\r
+NullSeg: DQ 0                   ; reserved by architecture\r
+CodeSeg32:\r
+            DW      -1                  ; LimitLow\r
+            DW      0                   ; BaseLow\r
+            DB      0                   ; BaseMid\r
+            DB      0x9b\r
+            DB      0xcf                ; LimitHigh\r
+            DB      0                   ; BaseHigh\r
+ProtModeCodeSeg32:\r
+            DW      -1                  ; LimitLow\r
+            DW      0                   ; BaseLow\r
+            DB      0                   ; BaseMid\r
+            DB      0x9b\r
+            DB      0xcf                ; LimitHigh\r
+            DB      0                   ; BaseHigh\r
+ProtModeSsSeg32:\r
+            DW      -1                  ; LimitLow\r
+            DW      0                   ; BaseLow\r
+            DB      0                   ; BaseMid\r
+            DB      0x93\r
+            DB      0xcf                ; LimitHigh\r
+            DB      0                   ; BaseHigh\r
+DataSeg32:\r
+            DW      -1                  ; LimitLow\r
+            DW      0                   ; BaseLow\r
+            DB      0                   ; BaseMid\r
+            DB      0x93\r
+            DB      0xcf                ; LimitHigh\r
+            DB      0                   ; BaseHigh\r
+CodeSeg16:\r
+            DW      -1\r
+            DW      0\r
+            DB      0\r
+            DB      0x9b\r
+            DB      0x8f\r
+            DB      0\r
+DataSeg16:\r
+            DW      -1\r
+            DW      0\r
+            DB      0\r
+            DB      0x93\r
+            DB      0x8f\r
+            DB      0\r
+CodeSeg64:\r
+            DW      -1                  ; LimitLow\r
+            DW      0                   ; BaseLow\r
+            DB      0                   ; BaseMid\r
+            DB      0x9b\r
+            DB      0xaf                ; LimitHigh\r
+            DB      0                   ; BaseHigh\r
+GDT_SIZE equ $ - NullSeg\r
+\r
+TssSeg:\r
+            DW      TSS_DESC_SIZE       ; LimitLow\r
+            DW      0                   ; BaseLow\r
+            DB      0                   ; BaseMid\r
+            DB      0x89\r
+            DB      0x80                ; LimitHigh\r
+            DB      0                   ; BaseHigh\r
+ExceptionTssSeg:\r
+            DW      TSS_DESC_SIZE       ; LimitLow\r
+            DW      0                   ; BaseLow\r
+            DB      0                   ; BaseMid\r
+            DB      0x89\r
+            DB      0x80                ; LimitHigh\r
+            DB      0                   ; BaseHigh\r
+\r
+CODE_SEL          equ CodeSeg32 - NullSeg\r
+DATA_SEL          equ DataSeg32 - NullSeg\r
+TSS_SEL           equ TssSeg - NullSeg\r
+EXCEPTION_TSS_SEL equ ExceptionTssSeg - NullSeg\r
+\r
+struc IA32_TSS\r
+                    resw 1\r
+                    resw 1\r
+  .ESP0: resd 1\r
+  .SS0:  resw 1\r
+                    resw 1\r
+  .ESP1: resd 1\r
+  .SS1:  resw 1\r
+                    resw 1\r
+  .ESP2: resd 1\r
+  .SS2:  resw 1\r
+                    resw 1\r
+  ._CR3: resd 1\r
+  .EIP:  resd 1\r
+  .EFLAGS: resd 1\r
+  ._EAX: resd 1\r
+  ._ECX: resd 1\r
+  ._EDX: resd 1\r
+  ._EBX: resd 1\r
+  ._ESP: resd 1\r
+  ._EBP: resd 1\r
+  ._ESI: resd 1\r
+  ._EDI: resd 1\r
+  ._ES:  resw 1\r
+                    resw 1\r
+  ._CS: resw 1\r
+                    resw 1\r
+  ._SS: resw 1\r
+                    resw 1\r
+  ._DS: resw 1\r
+                    resw 1\r
+  ._FS: resw 1\r
+                    resw 1\r
+  ._GS: resw 1\r
+                    resw 1\r
+  .LDT: resw 1\r
+                    resw 1\r
+                    resw 1\r
+                    resw 1\r
+endstruc\r
+\r
+; Create 2 TSS segments just after GDT\r
+TssDescriptor:\r
+            DW      0                   ; PreviousTaskLink\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; ESP0\r
+            DW      0                   ; SS0\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; ESP1\r
+            DW      0                   ; SS1\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; ESP2\r
+            DW      0                   ; SS2\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; CR3\r
+            DD      0                   ; EIP\r
+            DD      0                   ; EFLAGS\r
+            DD      0                   ; EAX\r
+            DD      0                   ; ECX\r
+            DD      0                   ; EDX\r
+            DD      0                   ; EBX\r
+            DD      0                   ; ESP\r
+            DD      0                   ; EBP\r
+            DD      0                   ; ESI\r
+            DD      0                   ; EDI\r
+            DW      0                   ; ES\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; CS\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; SS\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; DS\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; FS\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; GS\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; LDT Selector\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; T\r
+            DW      0                   ; I/O Map Base\r
+TSS_DESC_SIZE equ $ - TssDescriptor\r
+\r
+ExceptionTssDescriptor:\r
+            DW      0                   ; PreviousTaskLink\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; ESP0\r
+            DW      0                   ; SS0\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; ESP1\r
+            DW      0                   ; SS1\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; ESP2\r
+            DW      0                   ; SS2\r
+            DW      0                   ; Reserved\r
+            DD      0                   ; CR3\r
+            DD      PFHandlerEntry ; EIP\r
+            DD      00000002            ; EFLAGS\r
+            DD      0                   ; EAX\r
+            DD      0                   ; ECX\r
+            DD      0                   ; EDX\r
+            DD      0                   ; EBX\r
+            DD      0                   ; ESP\r
+            DD      0                   ; EBP\r
+            DD      0                   ; ESI\r
+            DD      0                   ; EDI\r
+            DW      DATA_SEL            ; ES\r
+            DW      0                   ; Reserved\r
+            DW      CODE_SEL            ; CS\r
+            DW      0                   ; Reserved\r
+            DW      DATA_SEL            ; SS\r
+            DW      0                   ; Reserved\r
+            DW      DATA_SEL            ; DS\r
+            DW      0                   ; Reserved\r
+            DW      DATA_SEL            ; FS\r
+            DW      0                   ; Reserved\r
+            DW      DATA_SEL            ; GS\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; LDT Selector\r
+            DW      0                   ; Reserved\r
+            DW      0                   ; T\r
+            DW      0                   ; I/O Map Base\r
+\r
+ASM_PFX(gcPsd):\r
+            DB      'PSDSIG  '\r
+            DW      PSD_SIZE\r
+            DW      2\r
+            DW      1 << 2\r
+            DW      CODE_SEL\r
+            DW      DATA_SEL\r
+            DW      DATA_SEL\r
+            DW      DATA_SEL\r
+            DW      0\r
+            DQ      0\r
+            DQ      0\r
+            DQ      0\r
+            DD      0\r
+            DD      NullSeg\r
+            DD      GDT_SIZE\r
+            DD      0\r
+            times   24 DB 0\r
+            DD      0\r
+            DD      ASM_PFX(gSmiMtrrs)\r
+PSD_SIZE  equ $ - ASM_PFX(gcPsd)\r
+\r
+ASM_PFX(gcSmiGdtr):\r
+    DW      GDT_SIZE - 1\r
+    DD      NullSeg\r
+\r
+ASM_PFX(gcSmiIdtr):\r
+    DW      IDT_SIZE - 1\r
+    DD      _SmiIDT\r
+\r
+_SmiIDT:\r
+%rep 32\r
+    DW      0                           ; Offset 0:15\r
+    DW      CODE_SEL                    ; Segment selector\r
+    DB      0                           ; Unused\r
+    DB      0x8e                         ; Interrupt Gate, Present\r
+    DW      0                           ; Offset 16:31\r
+%endrep\r
+\r
+IDT_SIZE equ $ - _SmiIDT\r
+\r
+TaskGateDescriptor:\r
+    DW      0                           ; Reserved\r
+    DW      EXCEPTION_TSS_SEL           ; TSS Segment selector\r
+    DB      0                           ; Reserved\r
+    DB      0x85                         ; Task Gate, present, DPL = 0\r
+    DW      0                           ; Reserved\r
+\r
+    SECTION .text\r
+;------------------------------------------------------------------------------\r
+; PageFaultIdtHandlerSmmProfile is the entry point page fault only\r
+;\r
+;\r
+; Stack:\r
+; +---------------------+\r
+; +    EFlags           +\r
+; +---------------------+\r
+; +    CS               +\r
+; +---------------------+\r
+; +    EIP              +\r
+; +---------------------+\r
+; +    Error Code       +\r
+; +---------------------+\r
+; +    Vector Number    +\r
+; +---------------------+\r
+; +    EBP              +\r
+; +---------------------+ <-- EBP\r
+;\r
+;\r
+;------------------------------------------------------------------------------\r
+global ASM_PFX(PageFaultIdtHandlerSmmProfile)\r
+ASM_PFX(PageFaultIdtHandlerSmmProfile):\r
+    push    0xe                         ; Page Fault\r
+\r
+    push    ebp\r
+    mov     ebp, esp\r
+\r
+    ;\r
+    ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+    ; is 16-byte aligned\r
+    ;\r
+    and     esp, 0xfffffff0\r
+    sub     esp, 12\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    push    eax\r
+    push    ecx\r
+    push    edx\r
+    push    ebx\r
+    lea     ecx, [ebp + 6 * 4]\r
+    push    ecx                          ; ESP\r
+    push    dword [ebp]              ; EBP\r
+    push    esi\r
+    push    edi\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+    mov     eax, ss\r
+    push    eax\r
+    movzx   eax, word [ebp + 4 * 4]\r
+    push    eax\r
+    mov     eax, ds\r
+    push    eax\r
+    mov     eax, es\r
+    push    eax\r
+    mov     eax, fs\r
+    push    eax\r
+    mov     eax, gs\r
+    push    eax\r
+\r
+;; UINT32  Eip;\r
+    mov     eax, [ebp + 3 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+    sub     esp, 8\r
+    sidt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0xFFFF\r
+    mov     [esp+4], eax\r
+\r
+    sub     esp, 8\r
+    sgdt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0xFFFF\r
+    mov     [esp+4], eax\r
+\r
+;; UINT32  Ldtr, Tr;\r
+    xor     eax, eax\r
+    str     ax\r
+    push    eax\r
+    sldt    ax\r
+    push    eax\r
+\r
+;; UINT32  EFlags;\r
+    mov     eax, [ebp + 5 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    mov     eax, cr4\r
+    or      eax, 0x208\r
+    mov     cr4, eax\r
+    push    eax\r
+    mov     eax, cr3\r
+    push    eax\r
+    mov     eax, cr2\r
+    push    eax\r
+    xor     eax, eax\r
+    push    eax\r
+    mov     eax, cr0\r
+    push    eax\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    mov     eax, dr7\r
+    push    eax\r
+    mov     eax, dr6\r
+    push    eax\r
+    mov     eax, dr3\r
+    push    eax\r
+    mov     eax, dr2\r
+    push    eax\r
+    mov     eax, dr1\r
+    push    eax\r
+    mov     eax, dr0\r
+    push    eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    sub     esp, 512\r
+    mov     edi, esp\r
+    db      0xf, 0xae, 0x7 ;fxsave [edi]\r
+\r
+; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
+    cld\r
+\r
+;; UINT32  ExceptionData;\r
+    push    dword [ebp + 2 * 4]\r
+\r
+;; call into exception handler\r
+\r
+;; Prepare parameter and call\r
+    mov     edx, esp\r
+    push    edx\r
+    mov     edx, dword [ebp + 1 * 4]\r
+    push    edx\r
+\r
+    ;\r
+    ; Call External Exception Handler\r
+    ;\r
+    mov     eax, ASM_PFX(SmiPFHandler)\r
+    call    eax\r
+    add     esp, 8\r
+\r
+;; UINT32  ExceptionData;\r
+    add     esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    mov     esi, esp\r
+    db      0xf, 0xae, 0xe ; fxrstor [esi]\r
+    add     esp, 512\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+;; Skip restoration of DRx registers to support debuggers\r
+;; that set breakpoint in interrupt/exception context\r
+    add     esp, 4 * 6\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    pop     eax\r
+    mov     cr0, eax\r
+    add     esp, 4    ; not for Cr1\r
+    pop     eax\r
+    mov     cr2, eax\r
+    pop     eax\r
+    mov     cr3, eax\r
+    pop     eax\r
+    mov     cr4, eax\r
+\r
+;; UINT32  EFlags;\r
+    pop     dword [ebp + 5 * 4]\r
+\r
+;; UINT32  Ldtr, Tr;\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+    add     esp, 24\r
+\r
+;; UINT32  Eip;\r
+    pop     dword [ebp + 3 * 4]\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger...  We\r
+;;        could attempt to insulate ourselves against this possibility,\r
+;;        but that poses risks as well.\r
+;;\r
+    pop     gs\r
+    pop     fs\r
+    pop     es\r
+    pop     ds\r
+    pop     dword [ebp + 4 * 4]\r
+    pop     ss\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    pop     edi\r
+    pop     esi\r
+    add     esp, 4   ; not for ebp\r
+    add     esp, 4   ; not for esp\r
+    pop     ebx\r
+    pop     edx\r
+    pop     ecx\r
+    pop     eax\r
+\r
+    mov     esp, ebp\r
+    pop     ebp\r
+\r
+; Enable TF bit after page fault handler runs\r
+    bts     dword [esp + 16], 8  ; EFLAGS\r
+\r
+    add     esp, 8                      ; skip INT# & ErrCode\r
+Return:\r
+    iretd\r
+;\r
+; Page Fault Exception Handler entry when SMM Stack Guard is enabled\r
+; Executiot starts here after a task switch\r
+;\r
+PFHandlerEntry:\r
+;\r
+; Get this processor's TSS\r
+;\r
+    sub     esp, 8\r
+    sgdt    [esp + 2]\r
+    mov     eax, [esp + 4]              ; GDT base\r
+    add     esp, 8\r
+    mov     ecx, [eax + TSS_SEL + 2]\r
+    shl     ecx, 8\r
+    mov     cl, [eax + TSS_SEL + 7]\r
+    ror     ecx, 8                      ; ecx = TSS base\r
+\r
+    mov     ebp, esp\r
+\r
+    ;\r
+    ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+    ; is 16-byte aligned\r
+    ;\r
+    and     esp, 0xfffffff0\r
+    sub     esp, 12\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    push    dword [ecx + IA32_TSS._EAX]\r
+    push    dword [ecx + IA32_TSS._ECX]\r
+    push    dword [ecx + IA32_TSS._EDX]\r
+    push    dword [ecx + IA32_TSS._EBX]\r
+    push    dword [ecx + IA32_TSS._ESP]\r
+    push    dword [ecx + IA32_TSS._EBP]\r
+    push    dword [ecx + IA32_TSS._ESI]\r
+    push    dword [ecx + IA32_TSS._EDI]\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+    movzx   eax, word [ecx + IA32_TSS._SS]\r
+    push    eax\r
+    movzx   eax, word [ecx + IA32_TSS._CS]\r
+    push    eax\r
+    movzx   eax, word [ecx + IA32_TSS._DS]\r
+    push    eax\r
+    movzx   eax, word [ecx + IA32_TSS._ES]\r
+    push    eax\r
+    movzx   eax, word [ecx + IA32_TSS._FS]\r
+    push    eax\r
+    movzx   eax, word [ecx + IA32_TSS._GS]\r
+    push    eax\r
+\r
+;; UINT32  Eip;\r
+    push    dword [ecx + IA32_TSS.EIP]\r
+\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+    sub     esp, 8\r
+    sidt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0xFFFF\r
+    mov     [esp+4], eax\r
+\r
+    sub     esp, 8\r
+    sgdt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0xFFFF\r
+    mov     [esp+4], eax\r
+\r
+;; UINT32  Ldtr, Tr;\r
+    mov     eax, TSS_SEL\r
+    push    eax\r
+    movzx   eax, word [ecx + IA32_TSS.LDT]\r
+    push    eax\r
+\r
+;; UINT32  EFlags;\r
+    push    dword [ecx + IA32_TSS.EFLAGS]\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    mov     eax, cr4\r
+    or      eax, 0x208\r
+    mov     cr4, eax\r
+    push    eax\r
+    mov     eax, cr3\r
+    push    eax\r
+    mov     eax, cr2\r
+    push    eax\r
+    xor     eax, eax\r
+    push    eax\r
+    mov     eax, cr0\r
+    push    eax\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    mov     eax, dr7\r
+    push    eax\r
+    mov     eax, dr6\r
+    push    eax\r
+    mov     eax, dr3\r
+    push    eax\r
+    mov     eax, dr2\r
+    push    eax\r
+    mov     eax, dr1\r
+    push    eax\r
+    mov     eax, dr0\r
+    push    eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)\r
+;; when executing fxsave/fxrstor instruction\r
+    clts\r
+    sub     esp, 512\r
+    mov     edi, esp\r
+    db      0xf, 0xae, 0x7 ;fxsave [edi]\r
+\r
+; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
+    cld\r
+\r
+;; UINT32  ExceptionData;\r
+    push    dword [ebp]\r
+\r
+;; call into exception handler\r
+    mov     ebx, ecx\r
+    mov     eax, ASM_PFX(SmiPFHandler)\r
+\r
+;; Prepare parameter and call\r
+    mov     edx, esp\r
+    push    edx\r
+    mov     edx, 14\r
+    push    edx\r
+\r
+    ;\r
+    ; Call External Exception Handler\r
+    ;\r
+    call    eax\r
+    add     esp, 8\r
+\r
+    mov     ecx, ebx\r
+;; UINT32  ExceptionData;\r
+    add     esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    mov     esi, esp\r
+    db      0xf, 0xae, 0xe ; fxrstor [esi]\r
+    add     esp, 512\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+;; Skip restoration of DRx registers to support debuggers\r
+;; that set breakpoints in interrupt/exception context\r
+    add     esp, 4 * 6\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    pop     eax\r
+    mov     cr0, eax\r
+    add     esp, 4    ; not for Cr1\r
+    pop     eax\r
+    mov     cr2, eax\r
+    pop     eax\r
+    mov     dword [ecx + IA32_TSS._CR3], eax\r
+    pop     eax\r
+    mov     cr4, eax\r
+\r
+;; UINT32  EFlags;\r
+    pop     dword [ecx + IA32_TSS.EFLAGS]\r
+\r
+;; UINT32  Ldtr, Tr;\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+    add     esp, 24\r
+\r
+;; UINT32  Eip;\r
+    pop     dword [ecx + IA32_TSS.EIP]\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger...  We\r
+;;        could attempt to insulate ourselves against this possibility,\r
+;;        but that poses risks as well.\r
+;;\r
+    pop     eax\r
+o16 mov     [ecx + IA32_TSS._GS], ax\r
+    pop     eax\r
+o16 mov     [ecx + IA32_TSS._FS], ax\r
+    pop     eax\r
+o16 mov     [ecx + IA32_TSS._ES], ax\r
+    pop     eax\r
+o16 mov     [ecx + IA32_TSS._DS], ax\r
+    pop     eax\r
+o16 mov     [ecx + IA32_TSS._CS], ax\r
+    pop     eax\r
+o16 mov     [ecx + IA32_TSS._SS], ax\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    pop     dword [ecx + IA32_TSS._EDI]\r
+    pop     dword [ecx + IA32_TSS._ESI]\r
+    add     esp, 4   ; not for ebp\r
+    add     esp, 4   ; not for esp\r
+    pop     dword [ecx + IA32_TSS._EBX]\r
+    pop     dword [ecx + IA32_TSS._EDX]\r
+    pop     dword [ecx + IA32_TSS._ECX]\r
+    pop     dword [ecx + IA32_TSS._EAX]\r
+\r
+    mov     esp, ebp\r
+\r
+; Set single step DB# if SMM profile is enabled and page fault exception happens\r
+    cmp     byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))], 0\r
+    jz      @Done2\r
+\r
+; Create return context for iretd in stub function\r
+    mov    eax, dword [ecx + IA32_TSS._ESP]        ; Get old stack pointer\r
+    mov    ebx, dword [ecx + IA32_TSS.EIP]\r
+    mov    [eax - 0xc], ebx                      ; create EIP in old stack\r
+    movzx  ebx, word [ecx + IA32_TSS._CS]\r
+    mov    [eax - 0x8], ebx                      ; create CS in old stack\r
+    mov    ebx, dword [ecx + IA32_TSS.EFLAGS]\r
+    bts    ebx, 8\r
+    mov    [eax - 0x4], ebx                      ; create eflags in old stack\r
+    mov    eax, dword [ecx + IA32_TSS._ESP]        ; Get old stack pointer\r
+    sub    eax, 0xc                              ; minus 12 byte\r
+    mov    dword [ecx + IA32_TSS._ESP], eax        ; Set new stack pointer\r
+; Replace the EIP of interrupted task with stub function\r
+    mov    eax, ASM_PFX(PageFaultStubFunction)\r
+    mov    dword [ecx + IA32_TSS.EIP], eax\r
+; Jump to the iretd so next page fault handler as a task will start again after iretd.\r
+@Done2:\r
+    add     esp, 4                      ; skip ErrCode\r
+\r
+    jmp     Return\r
+\r
+global ASM_PFX(PageFaultStubFunction)\r
+ASM_PFX(PageFaultStubFunction):\r
+;\r
+; we need clean TS bit in CR0 to execute\r
+; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.\r
+;\r
+    clts\r
+    iretd\r
+\r
+global ASM_PFX(InitializeIDTSmmStackGuard)\r
+ASM_PFX(InitializeIDTSmmStackGuard):\r
+    push    ebx\r
+;\r
+; If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT\r
+; is a Task Gate Descriptor so that when a Page Fault Exception occurrs,\r
+; the processors can use a known good stack in case stack is ran out.\r
+;\r
+    lea     ebx, [_SmiIDT + 14 * 8]\r
+    lea     edx, [TaskGateDescriptor]\r
+    mov     eax, [edx]\r
+    mov     [ebx], eax\r
+    mov     eax, [edx + 4]\r
+    mov     [ebx + 4], eax\r
+    pop     ebx\r
+    ret\r
+\r
+    END\r