Home | History | Annotate | Download | only in X64
      1 ;------------------------------------------------------------------------------ ;
      2 ; Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
      3 ; This program and the accompanying materials
      4 ; are licensed and made available under the terms and conditions of the BSD License
      5 ; which accompanies this distribution.  The full text of the license may be found at
      6 ; http://opensource.org/licenses/bsd-license.php.
      7 ;
      8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
      9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     10 ;
     11 ; Module Name:
     12 ;
     13 ;   SmiEntry.asm
     14 ;
     15 ; Abstract:
     16 ;
     17 ;   Code template of the SMI handler for a particular processor
     18 ;
     19 ;-------------------------------------------------------------------------------
     20 
     21 ;
     22 ; Variables referenced by C code
     23 ;
     24 EXTERNDEF   SmiRendezvous:PROC
     25 EXTERNDEF   CpuSmmDebugEntry:PROC
     26 EXTERNDEF   CpuSmmDebugExit:PROC
     27 EXTERNDEF   gcSmiHandlerTemplate:BYTE
     28 EXTERNDEF   gcSmiHandlerSize:WORD
     29 EXTERNDEF   gSmiCr3:DWORD
     30 EXTERNDEF   gSmiStack:DWORD
     31 EXTERNDEF   gSmbase:DWORD
     32 EXTERNDEF   gSmiHandlerIdtr:FWORD
     33 
     34 
     35 ;
     36 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
     37 ;
     38 DSC_OFFSET    EQU     0fb00h
     39 DSC_GDTPTR    EQU     30h
     40 DSC_GDTSIZ    EQU     38h
     41 DSC_CS        EQU     14
     42 DSC_DS        EQU     16
     43 DSC_SS        EQU     18
     44 DSC_OTHERSEG  EQU     20
     45 ;
     46 ; Constants relating to CPU State Save Area
     47 ;
     48 SSM_DR6         EQU     0ffd0h
     49 SSM_DR7         EQU     0ffc8h
     50 
     51 PROTECT_MODE_CS EQU     08h
     52 PROTECT_MODE_DS EQU     20h
     53 LONG_MODE_CS    EQU     38h
     54 TSS_SEGMENT     EQU     40h
     55 GDT_SIZE        EQU     50h
     56 
     57     .code
     58 
     59 gcSmiHandlerTemplate    LABEL   BYTE
     60 
     61 _SmiEntryPoint:
     62     ;
     63     ; The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-
     64     ; bit addressing mode. And that coincidence has been used in the following
     65     ; "64-bit like" 16-bit code. Be aware that once RDI is referenced as a
     66     ; base address register, it is actually BX that is referenced.
     67     ;
     68     DB      0bbh                        ; mov bx, imm16
     69     DW      offset _GdtDesc - _SmiEntryPoint + 8000h  ; bx = GdtDesc offset
     70 ; fix GDT descriptor
     71     DB      2eh, 0a1h                   ; mov ax, cs:[offset16]
     72     DW      DSC_OFFSET + DSC_GDTSIZ
     73     DB      48h                         ; dec ax
     74     DB      2eh
     75     mov     [rdi], eax                  ; mov cs:[bx], ax
     76     DB      66h, 2eh, 0a1h              ; mov eax, cs:[offset16]
     77     DW      DSC_OFFSET + DSC_GDTPTR
     78     DB      2eh
     79     mov     [rdi + 2], ax               ; mov cs:[bx + 2], eax
     80     DB      66h, 2eh
     81     lgdt    fword ptr [rdi]             ; lgdt fword ptr cs:[bx]
     82 ; Patch ProtectedMode Segment
     83     DB      0b8h                        ; mov ax, imm16
     84     DW      PROTECT_MODE_CS             ; set AX for segment directly
     85     DB      2eh
     86     mov     [rdi - 2], eax              ; mov cs:[bx - 2], ax
     87 ; Patch ProtectedMode entry
     88     DB      66h, 0bfh                   ; mov edi, SMBASE
     89 gSmbase    DD    ?
     90     lea     ax, [edi + (@ProtectedMode - _SmiEntryPoint) + 8000h]
     91     DB      2eh
     92     mov     [rdi - 6], ax               ; mov cs:[bx - 6], eax
     93 ; Switch into @ProtectedMode
     94     mov     rbx, cr0
     95     DB      66h
     96     and     ebx, 9ffafff3h
     97     DB      66h
     98     or      ebx, 00000023h
     99 
    100     mov     cr0, rbx
    101     DB      66h, 0eah
    102     DD      ?
    103     DW      ?
    104 
    105 _GdtDesc    FWORD   ?
    106 @ProtectedMode:
    107     mov     ax, PROTECT_MODE_DS
    108     mov     ds, ax
    109     mov     es, ax
    110     mov     fs, ax
    111     mov     gs, ax
    112     mov     ss, ax
    113     DB      0bch                   ; mov esp, imm32
    114 gSmiStack   DD      ?
    115     jmp     ProtFlatMode
    116 
    117 ProtFlatMode:
    118     DB      0b8h                        ; mov eax, offset gSmiCr3
    119 gSmiCr3     DD      ?
    120     mov     cr3, rax
    121     mov     eax, 668h                   ; as cr4.PGE is not set here, refresh cr3
    122     mov     cr4, rax                    ; in PreModifyMtrrs() to flush TLB.
    123 ; Load TSS
    124     sub     esp, 8                      ; reserve room in stack
    125     sgdt    fword ptr [rsp]
    126     mov     eax, [rsp + 2]              ; eax = GDT base
    127     add     esp, 8
    128     mov     dl, 89h
    129     mov     [rax + TSS_SEGMENT + 5], dl ; clear busy flag
    130     mov     eax, TSS_SEGMENT
    131     ltr     ax
    132 
    133 ; Switch into @LongMode
    134     push    LONG_MODE_CS                ; push cs hardcore here
    135     call    Base                       ; push return address for retf later
    136 Base:
    137     add     dword ptr [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
    138     mov     ecx, 0c0000080h
    139     rdmsr
    140     or      ah, 1
    141     wrmsr
    142     mov     rbx, cr0
    143     or      ebx, 080010000h            ; enable paging + WP
    144     mov     cr0, rbx
    145     retf
    146 @LongMode:                              ; long mode (64-bit code) starts here
    147     mov     rax, offset gSmiHandlerIdtr
    148     lidt    fword ptr [rax]
    149     lea     ebx, [rdi + DSC_OFFSET]
    150     mov     ax, [rbx + DSC_DS]
    151     mov     ds, eax
    152     mov     ax, [rbx + DSC_OTHERSEG]
    153     mov     es, eax
    154     mov     fs, eax
    155     mov     gs, eax
    156     mov     ax, [rbx + DSC_SS]
    157     mov     ss, eax
    158 ;   jmp     _SmiHandler                 ; instruction is not needed
    159 
    160 _SmiHandler:
    161     mov     rbx, [rsp]                  ; rbx <- CpuIndex
    162 
    163     ;
    164     ; Save FP registers
    165     ;
    166     sub     rsp, 208h
    167     DB      48h                         ; FXSAVE64
    168     fxsave  [rsp]
    169 
    170     add     rsp, -20h
    171 
    172     mov     rcx, rbx
    173     mov     rax, CpuSmmDebugEntry
    174     call    rax
    175     
    176     mov     rcx, rbx
    177     mov     rax, SmiRendezvous          ; rax <- absolute addr of SmiRedezvous
    178     call    rax
    179     
    180     mov     rcx, rbx
    181     mov     rax, CpuSmmDebugExit
    182     call    rax
    183     
    184     add     rsp, 20h
    185 
    186     ;
    187     ; Restore FP registers
    188     ;
    189     DB      48h                         ; FXRSTOR64
    190     fxrstor [rsp]
    191 
    192     rsm
    193 
    194 gcSmiHandlerSize    DW      $ - _SmiEntryPoint
    195 
    196     END
    197