Home | History | Annotate | Download | only in Ia32
      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 %define MSR_IA32_MISC_ENABLE 0x1A0
     22 %define MSR_EFER      0xc0000080
     23 %define MSR_EFER_XD   0x800
     24 
     25 ;
     26 ; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
     27 ;
     28 %define DSC_OFFSET 0xfb00
     29 %define DSC_GDTPTR 0x48
     30 %define DSC_GDTSIZ 0x50
     31 %define DSC_CS 0x14
     32 %define DSC_DS 0x16
     33 %define DSC_SS 0x18
     34 %define DSC_OTHERSEG 0x1a
     35 
     36 %define PROTECT_MODE_CS 0x8
     37 %define PROTECT_MODE_DS 0x20
     38 %define TSS_SEGMENT 0x40
     39 
     40 extern ASM_PFX(SmiRendezvous)
     41 extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
     42 extern ASM_PFX(CpuSmmDebugEntry)
     43 extern ASM_PFX(CpuSmmDebugExit)
     44 
     45 global ASM_PFX(gcStmSmiHandlerTemplate)
     46 global ASM_PFX(gcStmSmiHandlerSize)
     47 global ASM_PFX(gcStmSmiHandlerOffset)
     48 global ASM_PFX(gStmSmiCr3)
     49 global ASM_PFX(gStmSmiStack)
     50 global ASM_PFX(gStmSmbase)
     51 global ASM_PFX(gStmXdSupported)
     52 extern ASM_PFX(gStmSmiHandlerIdtr)
     53 
     54     SECTION .text
     55 
     56 BITS 16
     57 ASM_PFX(gcStmSmiHandlerTemplate):
     58 _StmSmiEntryPoint:
     59     mov     bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000
     60     mov     ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
     61     dec     ax
     62     mov     [cs:bx], ax
     63     mov     eax, [cs:DSC_OFFSET + DSC_GDTPTR]
     64     mov     [cs:bx + 2], eax
     65     mov     ebp, eax                      ; ebp = GDT base
     66 o32 lgdt    [cs:bx]                       ; lgdt fword ptr cs:[bx]
     67     mov     ax, PROTECT_MODE_CS
     68     mov     [cs:bx-0x2],ax
     69     DB      0x66, 0xbf                   ; mov edi, SMBASE
     70 ASM_PFX(gStmSmbase): DD 0
     71     lea     eax, [edi + (@32bit - _StmSmiEntryPoint) + 0x8000]
     72     mov     [cs:bx-0x6],eax
     73     mov     ebx, cr0
     74     and     ebx, 0x9ffafff3
     75     or      ebx, 0x23
     76     mov     cr0, ebx
     77     jmp     dword 0x0:0x0
     78 _StmGdtDesc:
     79     DW 0
     80     DD 0
     81 
     82 BITS 32
     83 @32bit:
     84     mov     ax, PROTECT_MODE_DS
     85 o16 mov     ds, ax
     86 o16 mov     es, ax
     87 o16 mov     fs, ax
     88 o16 mov     gs, ax
     89 o16 mov     ss, ax
     90     DB      0xbc                   ; mov esp, imm32
     91 ASM_PFX(gStmSmiStack): DD 0
     92     mov     eax, ASM_PFX(gStmSmiHandlerIdtr)
     93     lidt    [eax]
     94     jmp     ProtFlatMode
     95 
     96 ProtFlatMode:
     97     DB      0xb8                        ; mov eax, imm32
     98 ASM_PFX(gStmSmiCr3): DD 0
     99     mov     cr3, eax
    100 ;
    101 ; Need to test for CR4 specific bit support
    102 ;
    103     mov     eax, 1
    104     cpuid                               ; use CPUID to determine if specific CR4 bits are supported
    105     xor     eax, eax                    ; Clear EAX
    106     test    edx, BIT2                   ; Check for DE capabilities
    107     jz      .0
    108     or      eax, BIT3
    109 .0:
    110     test    edx, BIT6                   ; Check for PAE capabilities
    111     jz      .1
    112     or      eax, BIT5
    113 .1:
    114     test    edx, BIT7                   ; Check for MCE capabilities
    115     jz      .2
    116     or      eax, BIT6
    117 .2:
    118     test    edx, BIT24                  ; Check for FXSR capabilities
    119     jz      .3
    120     or      eax, BIT9
    121 .3:
    122     test    edx, BIT25                  ; Check for SSE capabilities
    123     jz      .4
    124     or      eax, BIT10
    125 .4:                                     ; as cr4.PGE is not set here, refresh cr3
    126     mov     cr4, eax                    ; in PreModifyMtrrs() to flush TLB.
    127 
    128     cmp     byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
    129     jz      .6
    130 ; Load TSS
    131     mov     byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag
    132     mov     eax, TSS_SEGMENT
    133     ltr     ax
    134 .6:
    135 
    136 ; enable NXE if supported
    137     DB      0b0h                        ; mov al, imm8
    138 ASM_PFX(gStmXdSupported):     DB      1
    139     cmp     al, 0
    140     jz      @SkipXd
    141 ;
    142 ; Check XD disable bit
    143 ;
    144     mov     ecx, MSR_IA32_MISC_ENABLE
    145     rdmsr
    146     push    edx                        ; save MSR_IA32_MISC_ENABLE[63-32]
    147     test    edx, BIT2                  ; MSR_IA32_MISC_ENABLE[34]
    148     jz      .5
    149     and     dx, 0xFFFB                 ; clear XD Disable bit if it is set
    150     wrmsr
    151 .5:
    152     mov     ecx, MSR_EFER
    153     rdmsr
    154     or      ax, MSR_EFER_XD             ; enable NXE
    155     wrmsr
    156     jmp     @XdDone
    157 @SkipXd:
    158     sub     esp, 4
    159 @XdDone:
    160 
    161     mov     ebx, cr0
    162     or      ebx, 0x80010023             ; enable paging + WP + NE + MP + PE
    163     mov     cr0, ebx
    164     lea     ebx, [edi + DSC_OFFSET]
    165     mov     ax, [ebx + DSC_DS]
    166     mov     ds, eax
    167     mov     ax, [ebx + DSC_OTHERSEG]
    168     mov     es, eax
    169     mov     fs, eax
    170     mov     gs, eax
    171     mov     ax, [ebx + DSC_SS]
    172     mov     ss, eax
    173 
    174 CommonHandler:
    175     mov     ebx, [esp + 4]                  ; CPU Index
    176     push    ebx
    177     mov     eax, ASM_PFX(CpuSmmDebugEntry)
    178     call    eax
    179     add     esp, 4
    180 
    181     push    ebx
    182     mov     eax, ASM_PFX(SmiRendezvous)
    183     call    eax
    184     add     esp, 4
    185 
    186     push    ebx
    187     mov     eax, ASM_PFX(CpuSmmDebugExit)
    188     call    eax
    189     add     esp, 4
    190 
    191     mov     eax, ASM_PFX(gStmXdSupported)
    192     mov     al, [eax]
    193     cmp     al, 0
    194     jz      .7
    195     pop     edx                       ; get saved MSR_IA32_MISC_ENABLE[63-32]
    196     test    edx, BIT2
    197     jz      .7
    198     mov     ecx, MSR_IA32_MISC_ENABLE
    199     rdmsr
    200     or      dx, BIT2                  ; set XD Disable bit if it was set before entering into SMM
    201     wrmsr
    202 
    203 .7:
    204     rsm
    205 
    206 
    207 _StmSmiHandler:
    208 ;
    209 ; Check XD disable bit
    210 ;
    211     xor     esi, esi
    212     mov     eax, ASM_PFX(gStmXdSupported)
    213     mov     al, [eax]
    214     cmp     al, 0
    215     jz      @StmXdDone
    216     mov     ecx, MSR_IA32_MISC_ENABLE
    217     rdmsr
    218     mov     esi, edx                   ; save MSR_IA32_MISC_ENABLE[63-32]
    219     test    edx, BIT2                  ; MSR_IA32_MISC_ENABLE[34]
    220     jz      .5
    221     and     dx, 0xFFFB                 ; clear XD Disable bit if it is set
    222     wrmsr
    223 .5:
    224     mov     ecx, MSR_EFER
    225     rdmsr
    226     or      ax, MSR_EFER_XD             ; enable NXE
    227     wrmsr
    228 @StmXdDone:
    229     push    esi
    230 
    231     ; below step is needed, because STM does not run above code.
    232     ; we have to run below code to set IDT/CR0/CR4
    233     mov     eax, ASM_PFX(gStmSmiHandlerIdtr)
    234     lidt    [eax]
    235 
    236     mov     eax, cr0
    237     or      eax, 0x80010023             ; enable paging + WP + NE + MP + PE
    238     mov     cr0, eax
    239 ;
    240 ; Need to test for CR4 specific bit support
    241 ;
    242     mov     eax, 1
    243     cpuid                               ; use CPUID to determine if specific CR4 bits are supported
    244     mov     eax, cr4                    ; init EAX
    245     test    edx, BIT2                   ; Check for DE capabilities
    246     jz      .0
    247     or      eax, BIT3
    248 .0:
    249     test    edx, BIT6                   ; Check for PAE capabilities
    250     jz      .1
    251     or      eax, BIT5
    252 .1:
    253     test    edx, BIT7                   ; Check for MCE capabilities
    254     jz      .2
    255     or      eax, BIT6
    256 .2:
    257     test    edx, BIT24                  ; Check for FXSR capabilities
    258     jz      .3
    259     or      eax, BIT9
    260 .3:
    261     test    edx, BIT25                  ; Check for SSE capabilities
    262     jz      .4
    263     or      eax, BIT10
    264 .4:                                     ; as cr4.PGE is not set here, refresh cr3
    265     mov     cr4, eax                    ; in PreModifyMtrrs() to flush TLB.
    266     ; STM init finish
    267     jmp     CommonHandler
    268 
    269 ASM_PFX(gcStmSmiHandlerSize)   : DW        $ - _StmSmiEntryPoint
    270 ASM_PFX(gcStmSmiHandlerOffset) : DW        _StmSmiHandler - _StmSmiEntryPoint
    271 
    272