Home | History | Annotate | Download | only in Ia32
      1 #------------------------------------------------------------------------------
      2 #
      3 # Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
      4 # This program and the accompanying materials
      5 # are licensed and made available under the terms and conditions of the BSD License
      6 # which accompanies this distribution.  The full text of the license may be found at
      7 # http://opensource.org/licenses/bsd-license.php.
      8 #
      9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 #
     12 # Module Name:
     13 #
     14 #   SmiEntry.S
     15 #
     16 # Abstract:
     17 #
     18 #   Code template of the SMI handler for a particular processor
     19 #
     20 #------------------------------------------------------------------------------
     21 
     22 ASM_GLOBAL  ASM_PFX(gcStmSmiHandlerTemplate)
     23 ASM_GLOBAL  ASM_PFX(gcStmSmiHandlerSize)
     24 ASM_GLOBAL  ASM_PFX(gcStmSmiHandlerOffset)
     25 ASM_GLOBAL  ASM_PFX(gStmSmiCr3)
     26 ASM_GLOBAL  ASM_PFX(gStmSmiStack)
     27 ASM_GLOBAL  ASM_PFX(gStmSmbase)
     28 ASM_GLOBAL  ASM_PFX(gStmXdSupported)
     29 ASM_GLOBAL  ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
     30 ASM_GLOBAL  ASM_PFX(gStmSmiHandlerIdtr)
     31 
     32 .equ            MSR_IA32_MISC_ENABLE, 0x1A0
     33 .equ            MSR_EFER, 0xc0000080
     34 .equ            MSR_EFER_XD, 0x800
     35 
     36 #
     37 # Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
     38 #
     39 .equ            DSC_OFFSET, 0xfb00
     40 .equ            DSC_GDTPTR, 0x48
     41 .equ            DSC_GDTSIZ, 0x50
     42 .equ            DSC_CS, 0x14
     43 .equ            DSC_DS, 0x16
     44 .equ            DSC_SS, 0x18
     45 .equ            DSC_OTHERSEG, 0x1A
     46 
     47 .equ            PROTECT_MODE_CS, 0x08
     48 .equ            PROTECT_MODE_DS, 0x20
     49 .equ            TSS_SEGMENT,     0x40
     50 
     51     .text
     52 ASM_PFX(gcStmSmiHandlerTemplate):
     53 
     54 _StmSmiEntryPoint:
     55     .byte 0xbb                          # mov bx, imm16
     56     .word _StmGdtDesc - _StmSmiEntryPoint + 0x8000
     57     .byte 0x2e,0xa1                     # mov ax, cs:[offset16]
     58     .word DSC_OFFSET + DSC_GDTSIZ
     59     decl    %eax
     60     movl    %eax, %cs:(%edi)            # mov cs:[bx], ax
     61     .byte 0x66,0x2e,0xa1                # mov eax, cs:[offset16]
     62     .word   DSC_OFFSET + DSC_GDTPTR
     63     movw    %ax, %cs:2(%edi)
     64     movw    %ax, %bp                    # ebp = GDT base
     65     .byte 0x66
     66     lgdt    %cs:(%edi)
     67 # Patch ProtectedMode Segment
     68     .byte   0xb8                        # mov ax, imm16
     69     .word   PROTECT_MODE_CS             # set AX for segment directly
     70     movl    %eax, %cs:-2(%edi)          # mov cs:[bx - 2], ax
     71 # Patch ProtectedMode entry
     72     .byte 0x66, 0xbf                    # mov edi, SMBASE
     73 ASM_PFX(gStmSmbase): .space 4
     74     .byte 0x67
     75     lea     ((Start32bit - _StmSmiEntryPoint) + 0x8000)(%edi), %ax
     76     movw     %ax, %cs:-6(%edi)
     77     movl    %cr0, %ebx
     78     .byte 0x66
     79     andl    $0x9ffafff3, %ebx
     80     .byte 0x66
     81     orl     $0x23, %ebx
     82     movl    %ebx, %cr0
     83     .byte 0x66,0xea
     84     .space  4
     85     .space  2
     86 _StmGdtDesc:   .space 4
     87             .space 2
     88 
     89 Start32bit:
     90     movw    $PROTECT_MODE_DS, %ax
     91     movl    %eax,%ds
     92     movl    %eax,%es
     93     movl    %eax,%fs
     94     movl    %eax,%gs
     95     movl    %eax,%ss
     96     .byte   0xbc                          # mov esp, imm32
     97 ASM_PFX(gStmSmiStack): .space 4
     98     movl    $ASM_PFX(gStmSmiHandlerIdtr), %eax
     99     lidt    (%eax)
    100     jmp     ProtFlatMode
    101 
    102 ProtFlatMode:
    103     .byte   0xb8                           # mov eax, imm32
    104 ASM_PFX(gStmSmiCr3): .space 4
    105     movl    %eax, %cr3
    106 #
    107 # Need to test for CR4 specific bit support
    108 #
    109     movl    $1, %eax
    110     cpuid                                  # use CPUID to determine if specific CR4 bits are supported
    111     xorl    %eax, %eax                     # Clear EAX
    112     testl   $BIT2, %edx                    # Check for DE capabilities
    113     jz      L8
    114     orl     $BIT3, %eax
    115 L8:
    116     testl   $BIT6, %edx                    # Check for PAE capabilities
    117     jz      L9
    118     orl     $BIT5, %eax
    119 L9:
    120     testl   $BIT7, %edx                    # Check for MCE capabilities
    121     jz      L10
    122     orl     $BIT6, %eax
    123 L10:
    124     testl   $BIT24, %edx                   # Check for FXSR capabilities
    125     jz      L11
    126     orl     $BIT9, %eax
    127 L11:
    128     testl   $BIT25, %edx                   # Check for SSE capabilities
    129     jz      L12
    130     orl     $BIT10, %eax
    131 L12:                                       # as cr4.PGE is not set here, refresh cr3
    132     movl    %eax, %cr4                     # in PreModifyMtrrs() to flush TLB.
    133 
    134     cmpb    $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
    135     jz      L5
    136 # Load TSS
    137     movb    $0x89, (TSS_SEGMENT + 5)(%ebp) # clear busy flag
    138     movl    $TSS_SEGMENT, %eax
    139     ltrw    %ax
    140 L5:
    141 
    142 # enable NXE if supported
    143     .byte   0xb0                           # mov al, imm8
    144 ASM_PFX(gStmXdSupported): .byte 1
    145     cmpb    $0, %al
    146     jz      SkipXd
    147 #
    148 # Check XD disable bit
    149 #
    150     movl    $MSR_IA32_MISC_ENABLE, %ecx
    151     rdmsr
    152     pushl   %edx                           # save MSR_IA32_MISC_ENABLE[63-32]
    153     testl   $BIT2, %edx                    # MSR_IA32_MISC_ENABLE[34]
    154     jz      L13
    155     andw    $0x0FFFB, %dx                  # clear XD Disable bit if it is set
    156     wrmsr
    157 L13:
    158     movl    $MSR_EFER, %ecx
    159     rdmsr
    160     orw     $MSR_EFER_XD,%ax               # enable NXE
    161     wrmsr
    162     jmp     XdDone
    163 SkipXd:
    164     subl    $4, %esp
    165 XdDone:
    166 
    167     movl    %cr0, %ebx
    168     orl     $0x080010023, %ebx             # enable paging + WP + NE + MP + PE
    169     movl    %ebx, %cr0
    170     leal    DSC_OFFSET(%edi),%ebx
    171     movw    DSC_DS(%ebx),%ax
    172     movl    %eax, %ds
    173     movw    DSC_OTHERSEG(%ebx),%ax
    174     movl    %eax, %es
    175     movl    %eax, %fs
    176     movl    %eax, %gs
    177     movw    DSC_SS(%ebx),%ax
    178     movl    %eax, %ss
    179 
    180 CommonHandler:
    181     movl    4(%esp), %ebx
    182 
    183     pushl   %ebx
    184     movl    $ASM_PFX(CpuSmmDebugEntry), %eax
    185     call    *%eax
    186     addl    $4, %esp
    187 
    188     pushl   %ebx
    189     movl    $ASM_PFX(SmiRendezvous), %eax
    190     call    *%eax
    191     addl    $4, %esp
    192 
    193     pushl   %ebx
    194     movl    $ASM_PFX(CpuSmmDebugExit), %eax
    195     call    *%eax
    196     addl    $4, %esp
    197 
    198     movl    $ASM_PFX(gStmXdSupported), %eax
    199     movb    (%eax), %al
    200     cmpb    $0, %al
    201     jz      L16
    202     popl    %edx                        # get saved MSR_IA32_MISC_ENABLE[63-32]
    203     testl   $BIT2, %edx
    204     jz      L16
    205     movl    $MSR_IA32_MISC_ENABLE, %ecx
    206     rdmsr
    207     orw     $BIT2, %dx                  # set XD Disable bit if it was set before entering into SMM
    208     wrmsr
    209 
    210 L16:
    211     rsm
    212 
    213 _StmSmiHandler:
    214 #
    215 # Check XD disable bit
    216 #
    217     xorl    %esi, %esi
    218     movl    $ASM_PFX(gStmXdSupported), %eax
    219     movb    (%eax), %al
    220     cmpb    $0, %al
    221     jz      StmXdDone
    222     movl    $MSR_IA32_MISC_ENABLE, %ecx
    223     rdmsr
    224     movl    %edx, %esi                     # save MSR_IA32_MISC_ENABLE[63-32]
    225     testl   $BIT2, %edx                    # MSR_IA32_MISC_ENABLE[34]
    226     jz      L14
    227     andw    $0x0FFFB, %dx                  # clear XD Disable bit if it is set
    228     wrmsr
    229 L14:
    230     movl    $MSR_EFER, %ecx
    231     rdmsr
    232     orw     $MSR_EFER_XD,%ax               # enable NXE
    233     wrmsr
    234 StmXdDone:
    235     push    %esi
    236 
    237     # below step is needed, because STM does not run above code.
    238     # we have to run below code to set IDT/CR0/CR4
    239     movl    $ASM_PFX(gStmSmiHandlerIdtr), %eax
    240     lidt    (%eax)
    241 
    242     movl    %cr0, %eax
    243     orl     $0x80010023, %eax           # enable paging + WP + NE + MP + PE
    244     movl    %eax, %cr0
    245 #
    246 # Need to test for CR4 specific bit support
    247 #
    248     movl    $1, %eax
    249     cpuid                               # use CPUID to determine if specific CR4 bits are supported
    250     movl    %cr4, %eax                  # init EAX
    251     testl   $BIT2, %edx                 # Check for DE capabilities
    252     jz      L28
    253     orl     $BIT3, %eax
    254 L28:
    255     testl   $BIT6, %edx                 # Check for PAE capabilities
    256     jz      L29
    257     orl     $BIT5, %eax
    258 L29:
    259     testl   $BIT7, %edx                 # Check for MCE capabilities
    260     jz      L30
    261     orl     $BIT6, %eax
    262 L30:
    263     testl   $BIT24, %edx                # Check for FXSR capabilities
    264     jz      L31
    265     orl     $BIT9, %eax
    266 L31:
    267     testl   $BIT25, %edx                # Check for SSE capabilities
    268     jz      L32
    269     orl     $BIT10, %eax
    270 L32:                                    # as cr4.PGE is not set here, refresh cr3
    271     movl    %eax, %cr4                  # in PreModifyMtrrs() to flush TLB.
    272     # STM init finish
    273     jmp     CommonHandler
    274 
    275 
    276 ASM_PFX(gcStmSmiHandlerSize)  :  .word      . - _StmSmiEntryPoint
    277 ASM_PFX(gcStmSmiHandlerOffset):  .word      _StmSmiHandler - _StmSmiEntryPoint
    278 
    279