Home | History | Annotate | Download | only in Ia32
      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 -1    # LimitLow
     86             .word      0                   # BaseLow
     87             .byte      0                   # BaseMid
     88             .byte      0x89
     89             .byte      0x00                # LimitHigh
     90             .byte      0                   # BaseHigh
     91 ExceptionTssSeg:
     92             .word      TSS_DESC_SIZE - 1   # LimitLow
     93             .word      0                   # BaseLow
     94             .byte      0                   # BaseMid
     95             .byte      0x89
     96             .byte      0x00                # 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
    912