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 ;   SmiEntry.nasm
     14 ;
     15 ; Abstract:
     16 ;
     17 ;   Code template of the SMI handler for a particular processor
     18 ;
     19 ;-------------------------------------------------------------------------------
     20 
     21 ;
     22 ; Variables referrenced by C code
     23 ;
     24 
     25 %define MSR_IA32_MISC_ENABLE 0x1A0
     26 %define MSR_EFER      0xc0000080
     27 %define MSR_EFER_XD   0x800
     28 
     29 ;
     30 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
     31 ;
     32 %define DSC_OFFSET 0xfb00
     33 %define DSC_GDTPTR 0x30
     34 %define DSC_GDTSIZ 0x38
     35 %define DSC_CS 14
     36 %define DSC_DS 16
     37 %define DSC_SS 18
     38 %define DSC_OTHERSEG 20
     39 ;
     40 ; Constants relating to CPU State Save Area
     41 ;
     42 %define SSM_DR6 0xffd0
     43 %define SSM_DR7 0xffc8
     44 
     45 %define PROTECT_MODE_CS 0x8
     46 %define PROTECT_MODE_DS 0x20
     47 %define LONG_MODE_CS 0x38
     48 %define TSS_SEGMENT 0x40
     49 %define GDT_SIZE 0x50
     50 
     51 extern ASM_PFX(SmiRendezvous)
     52 extern ASM_PFX(gSmiHandlerIdtr)
     53 extern ASM_PFX(CpuSmmDebugEntry)
     54 extern ASM_PFX(CpuSmmDebugExit)
     55 
     56 global ASM_PFX(gSmbase)
     57 global ASM_PFX(mXdSupported)
     58 global ASM_PFX(gSmiStack)
     59 global ASM_PFX(gSmiCr3)
     60 global ASM_PFX(gcSmiHandlerTemplate)
     61 global ASM_PFX(gcSmiHandlerSize)
     62 
     63     DEFAULT REL
     64     SECTION .text
     65 
     66 BITS 16
     67 ASM_PFX(gcSmiHandlerTemplate):
     68 _SmiEntryPoint:
     69     mov     bx, _GdtDesc - _SmiEntryPoint + 0x8000
     70     mov     ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
     71     dec     ax
     72     mov     [cs:bx], ax
     73     mov     eax, [cs:DSC_OFFSET + DSC_GDTPTR]
     74     mov     [cs:bx + 2], eax
     75 o32 lgdt    [cs:bx]                       ; lgdt fword ptr cs:[bx]
     76     mov     ax, PROTECT_MODE_CS
     77     mov     [cs:bx-0x2],ax
     78     DB      0x66, 0xbf                   ; mov edi, SMBASE
     79 ASM_PFX(gSmbase): DD 0
     80     lea     eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000]
     81     mov     [cs:bx-0x6],eax
     82     mov     ebx, cr0
     83     and     ebx, 0x9ffafff3
     84     or      ebx, 0x23
     85     mov     cr0, ebx
     86     jmp     dword 0x0:0x0
     87 _GdtDesc:
     88     DW 0
     89     DD 0
     90 
     91 BITS 32
     92 @ProtectedMode:
     93     mov     ax, PROTECT_MODE_DS
     94 o16 mov     ds, ax
     95 o16 mov     es, ax
     96 o16 mov     fs, ax
     97 o16 mov     gs, ax
     98 o16 mov     ss, ax
     99     DB      0xbc                   ; mov esp, imm32
    100 ASM_PFX(gSmiStack): DD 0
    101     jmp     ProtFlatMode
    102 
    103 BITS 64
    104 ProtFlatMode:
    105     DB      0xb8                        ; mov eax, offset gSmiCr3
    106 ASM_PFX(gSmiCr3): DD 0
    107     mov     cr3, rax
    108     mov     eax, 0x668                   ; as cr4.PGE is not set here, refresh cr3
    109     mov     cr4, rax                    ; in PreModifyMtrrs() to flush TLB.
    110 ; Load TSS
    111     sub     esp, 8                      ; reserve room in stack
    112     sgdt    [rsp]
    113     mov     eax, [rsp + 2]              ; eax = GDT base
    114     add     esp, 8
    115     mov     dl, 0x89
    116     mov     [rax + TSS_SEGMENT + 5], dl ; clear busy flag
    117     mov     eax, TSS_SEGMENT
    118     ltr     ax
    119 
    120 ; enable NXE if supported
    121     DB      0xb0                        ; mov al, imm8
    122 ASM_PFX(mXdSupported):     DB      1
    123     cmp     al, 0
    124     jz      @SkipXd
    125 ;
    126 ; Check XD disable bit
    127 ;
    128     mov     ecx, MSR_IA32_MISC_ENABLE
    129     rdmsr
    130     sub     esp, 4
    131     push    rdx                        ; save MSR_IA32_MISC_ENABLE[63-32]
    132     test    edx, BIT2                  ; MSR_IA32_MISC_ENABLE[34]
    133     jz      .0
    134     and     dx, 0xFFFB                 ; clear XD Disable bit if it is set
    135     wrmsr
    136 .0:
    137     mov     ecx, MSR_EFER
    138     rdmsr
    139     or      ax, MSR_EFER_XD            ; enable NXE
    140     wrmsr
    141     jmp     @XdDone
    142 @SkipXd:
    143     sub     esp, 8
    144 @XdDone:
    145 
    146 ; Switch into @LongMode
    147     push    LONG_MODE_CS                ; push cs hardcore here
    148     call    Base                       ; push return address for retf later
    149 Base:
    150     add     dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
    151 
    152     mov     ecx, MSR_EFER
    153     rdmsr
    154     or      ah, 1                      ; enable LME
    155     wrmsr
    156     mov     rbx, cr0
    157     or      ebx, 0x80010023            ; enable paging + WP + NE + MP + PE
    158     mov     cr0, rbx
    159     retf
    160 @LongMode:                              ; long mode (64-bit code) starts here
    161     mov     rax, ASM_PFX(gSmiHandlerIdtr)
    162     lidt    [rax]
    163     lea     ebx, [rdi + DSC_OFFSET]
    164     mov     ax, [rbx + DSC_DS]
    165     mov     ds, eax
    166     mov     ax, [rbx + DSC_OTHERSEG]
    167     mov     es, eax
    168     mov     fs, eax
    169     mov     gs, eax
    170     mov     ax, [rbx + DSC_SS]
    171     mov     ss, eax
    172 ;   jmp     _SmiHandler                 ; instruction is not needed
    173 
    174 _SmiHandler:
    175     mov     rbx, [rsp + 0x8]             ; rcx <- CpuIndex
    176 
    177     ;
    178     ; Save FP registers
    179     ;
    180     sub     rsp, 0x200
    181     DB      0x48                         ; FXSAVE64
    182     fxsave  [rsp]
    183 
    184     add     rsp, -0x20
    185 
    186     mov     rcx, rbx
    187     mov     rax, CpuSmmDebugEntry
    188     call    rax
    189 
    190     mov     rcx, rbx
    191     mov     rax, SmiRendezvous          ; rax <- absolute addr of SmiRedezvous
    192     call    rax
    193 
    194     mov     rcx, rbx
    195     mov     rax, CpuSmmDebugExit
    196     call    rax
    197 
    198     add     rsp, 0x20
    199 
    200     ;
    201     ; Restore FP registers
    202     ;
    203     DB      0x48                         ; FXRSTOR64
    204     fxrstor [rsp]
    205 
    206     add     rsp, 0x200
    207 
    208     mov     rax, ASM_PFX(mXdSupported)
    209     mov     al, [rax]
    210     cmp     al, 0
    211     jz      .1
    212     pop     rdx                       ; get saved MSR_IA32_MISC_ENABLE[63-32]
    213     test    edx, BIT2
    214     jz      .1
    215     mov     ecx, MSR_IA32_MISC_ENABLE
    216     rdmsr
    217     or      dx, BIT2                  ; set XD Disable bit if it was set before entering into SMM
    218     wrmsr
    219 
    220 .1:
    221     rsm
    222 
    223 gcSmiHandlerSize    DW      $ - _SmiEntryPoint
    224 
    225