Home | History | Annotate | Download | only in X64
      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 ;   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   mXdSupported:BYTE
     33 EXTERNDEF   gSmiHandlerIdtr:FWORD
     34 
     35 MSR_IA32_MISC_ENABLE  EQU     1A0h
     36 MSR_EFER      EQU     0c0000080h
     37 MSR_EFER_XD   EQU     0800h
     38 
     39 ;
     40 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
     41 ;
     42 DSC_OFFSET    EQU     0fb00h
     43 DSC_GDTPTR    EQU     30h
     44 DSC_GDTSIZ    EQU     38h
     45 DSC_CS        EQU     14
     46 DSC_DS        EQU     16
     47 DSC_SS        EQU     18
     48 DSC_OTHERSEG  EQU     20
     49 ;
     50 ; Constants relating to CPU State Save Area
     51 ;
     52 SSM_DR6         EQU     0ffd0h
     53 SSM_DR7         EQU     0ffc8h
     54 
     55 PROTECT_MODE_CS EQU     08h
     56 PROTECT_MODE_DS EQU     20h
     57 LONG_MODE_CS    EQU     38h
     58 TSS_SEGMENT     EQU     40h
     59 GDT_SIZE        EQU     50h
     60 
     61     .code
     62 
     63 gcSmiHandlerTemplate    LABEL   BYTE
     64 
     65 _SmiEntryPoint:
     66     ;
     67     ; The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-
     68     ; bit addressing mode. And that coincidence has been used in the following
     69     ; "64-bit like" 16-bit code. Be aware that once RDI is referenced as a
     70     ; base address register, it is actually BX that is referenced.
     71     ;
     72     DB      0bbh                        ; mov bx, imm16
     73     DW      offset _GdtDesc - _SmiEntryPoint + 8000h  ; bx = GdtDesc offset
     74 ; fix GDT descriptor
     75     DB      2eh, 0a1h                   ; mov ax, cs:[offset16]
     76     DW      DSC_OFFSET + DSC_GDTSIZ
     77     DB      48h                         ; dec ax
     78     DB      2eh
     79     mov     [rdi], eax                  ; mov cs:[bx], ax
     80     DB      66h, 2eh, 0a1h              ; mov eax, cs:[offset16]
     81     DW      DSC_OFFSET + DSC_GDTPTR
     82     DB      2eh
     83     mov     [rdi + 2], ax               ; mov cs:[bx + 2], eax
     84     DB      66h, 2eh
     85     lgdt    fword ptr [rdi]             ; lgdt fword ptr cs:[bx]
     86 ; Patch ProtectedMode Segment
     87     DB      0b8h                        ; mov ax, imm16
     88     DW      PROTECT_MODE_CS             ; set AX for segment directly
     89     DB      2eh
     90     mov     [rdi - 2], eax              ; mov cs:[bx - 2], ax
     91 ; Patch ProtectedMode entry
     92     DB      66h, 0bfh                   ; mov edi, SMBASE
     93 gSmbase    DD    ?
     94     lea     ax, [edi + (@ProtectedMode - _SmiEntryPoint) + 8000h]
     95     DB      2eh
     96     mov     [rdi - 6], ax               ; mov cs:[bx - 6], eax
     97 ; Switch into @ProtectedMode
     98     mov     rbx, cr0
     99     DB      66h
    100     and     ebx, 9ffafff3h
    101     DB      66h
    102     or      ebx, 00000023h
    103 
    104     mov     cr0, rbx
    105     DB      66h, 0eah
    106     DD      ?
    107     DW      ?
    108 
    109 _GdtDesc    FWORD   ?
    110 @ProtectedMode:
    111     mov     ax, PROTECT_MODE_DS
    112     mov     ds, ax
    113     mov     es, ax
    114     mov     fs, ax
    115     mov     gs, ax
    116     mov     ss, ax
    117     DB      0bch                   ; mov esp, imm32
    118 gSmiStack   DD      ?
    119     jmp     ProtFlatMode
    120 
    121 ProtFlatMode:
    122     DB      0b8h                        ; mov eax, offset gSmiCr3
    123 gSmiCr3     DD      ?
    124     mov     cr3, rax
    125     mov     eax, 668h                   ; as cr4.PGE is not set here, refresh cr3
    126     mov     cr4, rax                    ; in PreModifyMtrrs() to flush TLB.
    127 ; Load TSS
    128     sub     esp, 8                      ; reserve room in stack
    129     sgdt    fword ptr [rsp]
    130     mov     eax, [rsp + 2]              ; eax = GDT base
    131     add     esp, 8
    132     mov     dl, 89h
    133     mov     [rax + TSS_SEGMENT + 5], dl ; clear busy flag
    134     mov     eax, TSS_SEGMENT
    135     ltr     ax
    136 
    137 ; enable NXE if supported
    138     DB      0b0h                        ; mov al, imm8
    139 mXdSupported     DB      1
    140     cmp     al, 0
    141     jz      @SkipXd
    142 ;
    143 ; Check XD disable bit
    144 ;
    145     mov     ecx, MSR_IA32_MISC_ENABLE
    146     rdmsr
    147     sub     esp, 4
    148     push    rdx                        ; save MSR_IA32_MISC_ENABLE[63-32]
    149     test    edx, BIT2                  ; MSR_IA32_MISC_ENABLE[34]
    150     jz      @f
    151     and     dx, 0FFFBh                 ; clear XD Disable bit if it is set
    152     wrmsr
    153 @@:
    154     mov     ecx, MSR_EFER
    155     rdmsr
    156     or      ax, MSR_EFER_XD            ; enable NXE
    157     wrmsr
    158     jmp     @XdDone
    159 @SkipXd:
    160     sub     esp, 8
    161 @XdDone:
    162 
    163 ; Switch into @LongMode
    164     push    LONG_MODE_CS                ; push cs hardcore here
    165     call    Base                       ; push return address for retf later
    166 Base:
    167     add     dword ptr [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
    168 
    169     mov     ecx, MSR_EFER
    170     rdmsr
    171     or      ah, 1                      ; enable LME
    172     wrmsr
    173     mov     rbx, cr0
    174     or      ebx, 080010023h            ; enable paging + WP + NE + MP + PE
    175     mov     cr0, rbx
    176     retf
    177 @LongMode:                              ; long mode (64-bit code) starts here
    178     mov     rax, offset gSmiHandlerIdtr
    179     lidt    fword ptr [rax]
    180     lea     ebx, [rdi + DSC_OFFSET]
    181     mov     ax, [rbx + DSC_DS]
    182     mov     ds, eax
    183     mov     ax, [rbx + DSC_OTHERSEG]
    184     mov     es, eax
    185     mov     fs, eax
    186     mov     gs, eax
    187     mov     ax, [rbx + DSC_SS]
    188     mov     ss, eax
    189 ;   jmp     _SmiHandler                 ; instruction is not needed
    190 
    191 _SmiHandler:
    192     mov     rbx, [rsp]                  ; rbx <- CpuIndex
    193 
    194     ;
    195     ; Save FP registers
    196     ;
    197     sub     rsp, 200h
    198     DB      48h                         ; FXSAVE64
    199     fxsave  [rsp]
    200 
    201     add     rsp, -20h
    202 
    203     mov     rcx, rbx
    204     mov     rax, CpuSmmDebugEntry
    205     call    rax
    206 
    207     mov     rcx, rbx
    208     mov     rax, SmiRendezvous          ; rax <- absolute addr of SmiRedezvous
    209     call    rax
    210 
    211     mov     rcx, rbx
    212     mov     rax, CpuSmmDebugExit
    213     call    rax
    214 
    215     add     rsp, 20h
    216 
    217     ;
    218     ; Restore FP registers
    219     ;
    220     DB      48h                         ; FXRSTOR64
    221     fxrstor [rsp]
    222 
    223     add     rsp, 200h
    224 
    225     mov     rax, offset ASM_PFX(mXdSupported)
    226     mov     al, [rax]
    227     cmp     al, 0
    228     jz      @f
    229     pop     rdx                       ; get saved MSR_IA32_MISC_ENABLE[63-32]
    230     test    edx, BIT2
    231     jz      @f
    232     mov     ecx, MSR_IA32_MISC_ENABLE
    233     rdmsr
    234     or      dx, BIT2                  ; set XD Disable bit if it was set before entering into SMM
    235     wrmsr
    236 
    237 @@:
    238     rsm
    239 
    240 gcSmiHandlerSize    DW      $ - _SmiEntryPoint
    241 
    242     END
    243