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(gcSmiHandlerTemplate)
     23 ASM_GLOBAL  ASM_PFX(gcSmiHandlerSize)
     24 ASM_GLOBAL  ASM_PFX(gSmiCr3)
     25 ASM_GLOBAL  ASM_PFX(gSmiStack)
     26 ASM_GLOBAL  ASM_PFX(gSmbase)
     27 ASM_GLOBAL  ASM_PFX(mXdSupported)
     28 ASM_GLOBAL  ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
     29 ASM_GLOBAL  ASM_PFX(gSmiHandlerIdtr)
     30 
     31 .equ            MSR_IA32_MISC_ENABLE, 0x1A0
     32 .equ            MSR_EFER, 0xc0000080
     33 .equ            MSR_EFER_XD, 0x800
     34 
     35 #
     36 # Constants relating to PROCESSOR_SMM_DESCRIPTOR
     37 #
     38 .equ            DSC_OFFSET, 0xfb00
     39 .equ            DSC_GDTPTR, 0x30
     40 .equ            DSC_GDTSIZ, 0x38
     41 .equ            DSC_CS, 14
     42 .equ            DSC_DS, 16
     43 .equ            DSC_SS, 18
     44 .equ            DSC_OTHERSEG, 20
     45 
     46 .equ            PROTECT_MODE_CS, 0x08
     47 .equ            PROTECT_MODE_DS, 0x20
     48 .equ            TSS_SEGMENT,     0x40
     49 
     50     .text
     51 
     52 ASM_PFX(gcSmiHandlerTemplate):
     53 
     54 _SmiEntryPoint:
     55     .byte 0xbb                          # mov bx, imm16
     56     .word _GdtDesc - _SmiEntryPoint + 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(gSmbase): .space 4
     74     .byte 0x67
     75     lea     ((Start32bit - _SmiEntryPoint) + 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 _GdtDesc:   .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(gSmiStack): .space 4
     98     movl    $ASM_PFX(gSmiHandlerIdtr), %eax
     99     lidt    (%eax)
    100     jmp     ProtFlatMode
    101 
    102 ProtFlatMode:
    103     .byte   0xb8                           # mov eax, imm32
    104 ASM_PFX(gSmiCr3): .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(mXdSupported): .byte 1
    145     cmpb    $0, %al
    146     jz      SkipNxe
    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 SkipNxe:
    163     subl    $4, %esp
    164 NxeDone:
    165 
    166     movl    %cr0, %ebx
    167     orl     $0x080010023, %ebx             # enable paging + WP + NE + MP + PE
    168     movl    %ebx, %cr0
    169     leal    DSC_OFFSET(%edi),%ebx
    170     movw    DSC_DS(%ebx),%ax
    171     movl    %eax, %ds
    172     movw    DSC_OTHERSEG(%ebx),%ax
    173     movl    %eax, %es
    174     movl    %eax, %fs
    175     movl    %eax, %gs
    176     movw    DSC_SS(%ebx),%ax
    177     movl    %eax, %ss
    178 
    179 #   jmp     _SmiHandler                 # instruction is not needed
    180 
    181 _SmiHandler:
    182     movl    4(%esp), %ebx
    183 
    184     pushl   %ebx
    185     movl    $ASM_PFX(CpuSmmDebugEntry), %eax
    186     call    *%eax
    187     addl    $4, %esp
    188 
    189     pushl   %ebx
    190     movl    $ASM_PFX(SmiRendezvous), %eax
    191     call    *%eax
    192     addl    $4, %esp
    193 
    194     pushl   %ebx
    195     movl    $ASM_PFX(CpuSmmDebugExit), %eax
    196     call    *%eax
    197     addl    $4, %esp
    198 
    199     movl    $ASM_PFX(mXdSupported), %eax
    200     movb    (%eax), %al
    201     cmpb    $0, %al
    202     jz      L16
    203     popl    %edx                        # get saved MSR_IA32_MISC_ENABLE[63-32]
    204     testl   $BIT2, %edx
    205     jz      L16
    206     movl    $MSR_IA32_MISC_ENABLE, %ecx
    207     rdmsr
    208     orw     $BIT2, %dx                  # set XD Disable bit if it was set before entering into SMM
    209     wrmsr
    210 
    211 L16:
    212     rsm
    213 
    214 ASM_PFX(gcSmiHandlerSize):    .word      . - _SmiEntryPoint
    215