Home | History | Annotate | Download | only in X64
      1 ;------------------------------------------------------------------------------ ;
      2 ; Copyright (c) 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.nasm
     14 ;
     15 ; Abstract:
     16 ;
     17 ;   Exception handlers used in SM mode
     18 ;
     19 ;-------------------------------------------------------------------------------
     20 
     21 extern  ASM_PFX(SmiPFHandler)
     22 
     23 global  ASM_PFX(gcSmiIdtr)
     24 global  ASM_PFX(gcSmiGdtr)
     25 global  ASM_PFX(gcPsd)
     26 
     27     SECTION .data
     28 
     29 NullSeg: DQ 0                   ; reserved by architecture
     30 CodeSeg32:
     31             DW      -1                  ; LimitLow
     32             DW      0                   ; BaseLow
     33             DB      0                   ; BaseMid
     34             DB      0x9b
     35             DB      0xcf                ; LimitHigh
     36             DB      0                   ; BaseHigh
     37 ProtModeCodeSeg32:
     38             DW      -1                  ; LimitLow
     39             DW      0                   ; BaseLow
     40             DB      0                   ; BaseMid
     41             DB      0x9b
     42             DB      0xcf                ; LimitHigh
     43             DB      0                   ; BaseHigh
     44 ProtModeSsSeg32:
     45             DW      -1                  ; LimitLow
     46             DW      0                   ; BaseLow
     47             DB      0                   ; BaseMid
     48             DB      0x93
     49             DB      0xcf                ; LimitHigh
     50             DB      0                   ; BaseHigh
     51 DataSeg32:
     52             DW      -1                  ; LimitLow
     53             DW      0                   ; BaseLow
     54             DB      0                   ; BaseMid
     55             DB      0x93
     56             DB      0xcf                ; LimitHigh
     57             DB      0                   ; BaseHigh
     58 CodeSeg16:
     59             DW      -1
     60             DW      0
     61             DB      0
     62             DB      0x9b
     63             DB      0x8f
     64             DB      0
     65 DataSeg16:
     66             DW      -1
     67             DW      0
     68             DB      0
     69             DB      0x93
     70             DB      0x8f
     71             DB      0
     72 CodeSeg64:
     73             DW      -1                  ; LimitLow
     74             DW      0                   ; BaseLow
     75             DB      0                   ; BaseMid
     76             DB      0x9b
     77             DB      0xaf                ; LimitHigh
     78             DB      0                   ; BaseHigh
     79 ; TSS Segment for X64 specially
     80 TssSeg:
     81             DW      TSS_DESC_SIZE       ; LimitLow
     82             DW      0                   ; BaseLow
     83             DB      0                   ; BaseMid
     84             DB      0x89
     85             DB      0x80                ; LimitHigh
     86             DB      0                   ; BaseHigh
     87             DD      0                   ; BaseUpper
     88             DD      0                   ; Reserved
     89 GDT_SIZE equ $ -   NullSeg
     90 
     91 ; Create TSS Descriptor just after GDT
     92 TssDescriptor:
     93             DD      0                   ; Reserved
     94             DQ      0                   ; RSP0
     95             DQ      0                   ; RSP1
     96             DQ      0                   ; RSP2
     97             DD      0                   ; Reserved
     98             DD      0                   ; Reserved
     99             DQ      0                   ; IST1
    100             DQ      0                   ; IST2
    101             DQ      0                   ; IST3
    102             DQ      0                   ; IST4
    103             DQ      0                   ; IST5
    104             DQ      0                   ; IST6
    105             DQ      0                   ; IST7
    106             DD      0                   ; Reserved
    107             DD      0                   ; Reserved
    108             DW      0                   ; Reserved
    109             DW      0                   ; I/O Map Base Address
    110 TSS_DESC_SIZE equ $ -   TssDescriptor
    111 
    112 ;
    113 ; This structure serves as a template for all processors.
    114 ;
    115 ASM_PFX(gcPsd):
    116             DB      'PSDSIG  '
    117             DW      PSD_SIZE
    118             DW      2
    119             DW      1 << 2
    120             DW      CODE_SEL
    121             DW      DATA_SEL
    122             DW      DATA_SEL
    123             DW      DATA_SEL
    124             DW      0
    125             DQ      0
    126             DQ      0
    127             DQ      0                   ; fixed in InitializeMpServiceData()
    128             DQ        NullSeg
    129             DD      GDT_SIZE
    130             DD      0
    131             times   24 DB 0
    132             DQ      0
    133 PSD_SIZE  equ $ -   ASM_PFX(gcPsd)
    134 
    135 ;
    136 ; CODE & DATA segments for SMM runtime
    137 ;
    138 CODE_SEL    equ   CodeSeg64 -   NullSeg
    139 DATA_SEL    equ   DataSeg32 -   NullSeg
    140 CODE32_SEL  equ   CodeSeg32 -   NullSeg
    141 
    142 ASM_PFX(gcSmiGdtr):
    143     DW      GDT_SIZE - 1
    144     DQ        NullSeg
    145 
    146 ASM_PFX(gcSmiIdtr):
    147     DW      0
    148     DQ      0
    149 
    150     DEFAULT REL
    151     SECTION .text
    152 
    153 ;------------------------------------------------------------------------------
    154 ; _SmiExceptionEntryPoints is the collection of exception entrypoints followed
    155 ; by a common exception handler.
    156 ;
    157 ; Stack frame would be as follows as specified in IA32 manuals:
    158 ;
    159 ; +---------------------+ <-- 16-byte aligned ensured by processor
    160 ; +    Old SS           +
    161 ; +---------------------+
    162 ; +    Old RSP          +
    163 ; +---------------------+
    164 ; +    RFlags           +
    165 ; +---------------------+
    166 ; +    CS               +
    167 ; +---------------------+
    168 ; +    RIP              +
    169 ; +---------------------+
    170 ; +    Error Code       +
    171 ; +---------------------+
    172 ; +   Vector Number     +
    173 ; +---------------------+
    174 ; +    RBP              +
    175 ; +---------------------+ <-- RBP, 16-byte aligned
    176 ;
    177 ; RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
    178 ;------------------------------------------------------------------------------
    179 global ASM_PFX(PageFaultIdtHandlerSmmProfile)
    180 ASM_PFX(PageFaultIdtHandlerSmmProfile):
    181     push    0xe                         ; Page Fault
    182     test    spl, 8                      ; odd multiple of 8 => ErrCode present
    183     jnz     .0
    184     push    qword [rsp]                       ; duplicate INT# if no ErrCode
    185     mov     qword [rsp + 8], 0
    186 .0:
    187     push    rbp
    188     mov     rbp, rsp
    189 
    190     ;
    191     ; Since here the stack pointer is 16-byte aligned, so
    192     ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
    193     ; is 16-byte aligned
    194     ;
    195 
    196 ;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
    197 ;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
    198     push    r15
    199     push    r14
    200     push    r13
    201     push    r12
    202     push    r11
    203     push    r10
    204     push    r9
    205     push    r8
    206     push    rax
    207     push    rcx
    208     push    rdx
    209     push    rbx
    210     push    qword [rbp + 48]  ; RSP
    211     push    qword [rbp]       ; RBP
    212     push    rsi
    213     push    rdi
    214 
    215 ;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero
    216     movzx   rax, word [rbp + 56]
    217     push    rax                      ; for ss
    218     movzx   rax, word [rbp + 32]
    219     push    rax                      ; for cs
    220     mov     rax, ds
    221     push    rax
    222     mov     rax, es
    223     push    rax
    224     mov     rax, fs
    225     push    rax
    226     mov     rax, gs
    227     push    rax
    228 
    229 ;; UINT64  Rip;
    230     push    qword [rbp + 24]
    231 
    232 ;; UINT64  Gdtr[2], Idtr[2];
    233     sub     rsp, 16
    234     sidt    [rsp]
    235     sub     rsp, 16
    236     sgdt    [rsp]
    237 
    238 ;; UINT64  Ldtr, Tr;
    239     xor     rax, rax
    240     str     ax
    241     push    rax
    242     sldt    ax
    243     push    rax
    244 
    245 ;; UINT64  RFlags;
    246     push    qword [rbp + 40]
    247 
    248 ;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
    249     mov     rax, cr8
    250     push    rax
    251     mov     rax, cr4
    252     or      rax, 0x208
    253     mov     cr4, rax
    254     push    rax
    255     mov     rax, cr3
    256     push    rax
    257     mov     rax, cr2
    258     push    rax
    259     xor     rax, rax
    260     push    rax
    261     mov     rax, cr0
    262     push    rax
    263 
    264 ;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    265     mov     rax, dr7
    266     push    rax
    267     mov     rax, dr6
    268     push    rax
    269     mov     rax, dr3
    270     push    rax
    271     mov     rax, dr2
    272     push    rax
    273     mov     rax, dr1
    274     push    rax
    275     mov     rax, dr0
    276     push    rax
    277 
    278 ;; FX_SAVE_STATE_X64 FxSaveState;
    279 
    280     sub rsp, 512
    281     mov rdi, rsp
    282     db 0xf, 0xae, 00000111y ;fxsave [rdi]
    283 
    284 ; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
    285     cld
    286 
    287 ;; UINT32  ExceptionData;
    288     push    qword [rbp + 16]
    289 
    290 ;; call into exception handler
    291     mov     rcx, [rbp + 8]
    292     mov     rax, ASM_PFX(SmiPFHandler)
    293 
    294 ;; Prepare parameter and call
    295     mov     rdx, rsp
    296     ;
    297     ; Per X64 calling convention, allocate maximum parameter stack space
    298     ; and make sure RSP is 16-byte aligned
    299     ;
    300     sub     rsp, 4 * 8 + 8
    301     call    rax
    302     add     rsp, 4 * 8 + 8
    303     jmp     .1
    304 
    305 .1:
    306 ;; UINT64  ExceptionData;
    307     add     rsp, 8
    308 
    309 ;; FX_SAVE_STATE_X64 FxSaveState;
    310 
    311     mov rsi, rsp
    312     db 0xf, 0xae, 00001110y ; fxrstor [rsi]
    313     add rsp, 512
    314 
    315 ;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    316 ;; Skip restoration of DRx registers to support debuggers
    317 ;; that set breakpoints in interrupt/exception context
    318   add     rsp, 8 * 6
    319 
    320 ;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
    321     pop     rax
    322     mov     cr0, rax
    323     add     rsp, 8   ; not for Cr1
    324     pop     rax
    325     mov     cr2, rax
    326     pop     rax
    327     mov     cr3, rax
    328     pop     rax
    329     mov     cr4, rax
    330     pop     rax
    331     mov     cr8, rax
    332 
    333 ;; UINT64  RFlags;
    334     pop     qword [rbp + 40]
    335 
    336 ;; UINT64  Ldtr, Tr;
    337 ;; UINT64  Gdtr[2], Idtr[2];
    338 ;; Best not let anyone mess with these particular registers...
    339     add     rsp, 48
    340 
    341 ;; UINT64  Rip;
    342     pop     qword [rbp + 24]
    343 
    344 ;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;
    345     pop     rax
    346     ; mov     gs, rax ; not for gs
    347     pop     rax
    348     ; mov     fs, rax ; not for fs
    349     ; (X64 will not use fs and gs, so we do not restore it)
    350     pop     rax
    351     mov     es, rax
    352     pop     rax
    353     mov     ds, rax
    354     pop     qword [rbp + 32]  ; for cs
    355     pop     qword [rbp + 56]  ; for ss
    356 
    357 ;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
    358 ;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
    359     pop     rdi
    360     pop     rsi
    361     add     rsp, 8               ; not for rbp
    362     pop     qword [rbp + 48] ; for rsp
    363     pop     rbx
    364     pop     rdx
    365     pop     rcx
    366     pop     rax
    367     pop     r8
    368     pop     r9
    369     pop     r10
    370     pop     r11
    371     pop     r12
    372     pop     r13
    373     pop     r14
    374     pop     r15
    375 
    376     mov     rsp, rbp
    377 
    378 ; Enable TF bit after page fault handler runs
    379     bts     dword [rsp + 40], 8  ;RFLAGS
    380 
    381     pop     rbp
    382     add     rsp, 16           ; skip INT# & ErrCode
    383     iretq
    384 
    385