blob: 0c075582c3856cb107ec205fa5c978b43bb70085 [file] [log] [blame]
#------------------------------------------------------------------------------
#
# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
# Module Name:
#
# SmiEntry.S
#
# Abstract:
#
# Code template of the SMI handler for a particular processor
#
#------------------------------------------------------------------------------
ASM_GLOBAL ASM_PFX(gcSmiHandlerTemplate)
ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
ASM_GLOBAL ASM_PFX(gSmiCr3)
ASM_GLOBAL ASM_PFX(gSmiStack)
ASM_GLOBAL ASM_PFX(gSmbase)
ASM_GLOBAL ASM_PFX(mXdSupported)
ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
.equ MSR_EFER, 0xc0000080
.equ MSR_EFER_XD, 0x800
.equ DSC_OFFSET, 0xfb00
.equ DSC_GDTPTR, 0x30
.equ DSC_GDTSIZ, 0x38
.equ DSC_CS, 14
.equ DSC_DS, 16
.equ DSC_SS, 18
.equ DSC_OTHERSEG, 20
.equ PROTECT_MODE_CS, 0x08
.equ PROTECT_MODE_DS, 0x20
.equ TSS_SEGMENT, 0x40
.text
ASM_PFX(gcSmiHandlerTemplate):
_SmiEntryPoint:
.byte 0xbb # mov bx, imm16
.word _GdtDesc - _SmiEntryPoint + 0x8000
.byte 0x2e,0xa1 # mov ax, cs:[offset16]
.word DSC_OFFSET + DSC_GDTSIZ
decl %eax
movl %eax, %cs:(%edi) # mov cs:[bx], ax
.byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
.word DSC_OFFSET + DSC_GDTPTR
movw %ax, %cs:2(%edi)
movw %ax, %bp # ebp = GDT base
.byte 0x66
lgdt %cs:(%edi)
# Patch ProtectedMode Segment
.byte 0xb8 # mov ax, imm16
.word PROTECT_MODE_CS # set AX for segment directly
movl %eax, %cs:-2(%edi) # mov cs:[bx - 2], ax
# Patch ProtectedMode entry
.byte 0x66, 0xbf # mov edi, SMBASE
ASM_PFX(gSmbase): .space 4
.byte 0x67
lea ((Start32bit - _SmiEntryPoint) + 0x8000)(%edi), %ax
movw %ax, %cs:-6(%edi)
movl %cr0, %ebx
.byte 0x66
andl $0x9ffafff3, %ebx
.byte 0x66
orl $0x23, %ebx
movl %ebx, %cr0
.byte 0x66,0xea
.space 4
.space 2
_GdtDesc: .space 4
.space 2
Start32bit:
movw $PROTECT_MODE_DS, %ax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
movl %eax,%ss
.byte 0xbc # mov esp, imm32
ASM_PFX(gSmiStack): .space 4
movl $ASM_PFX(gSmiHandlerIdtr), %eax
lidt (%eax)
jmp ProtFlatMode
ProtFlatMode:
.byte 0xb8 # mov eax, imm32
ASM_PFX(gSmiCr3): .space 4
movl %eax, %cr3
#
# Need to test for CR4 specific bit support
#
movl $1, %eax
cpuid # use CPUID to determine if specific CR4 bits are supported
xorl %eax, %eax # Clear EAX
testl $BIT2, %edx # Check for DE capabilities
jz L8
orl $BIT3, %eax
L8:
testl $BIT6, %edx # Check for PAE capabilities
jz L9
orl $BIT5, %eax
L9:
testl $BIT7, %edx # Check for MCE capabilities
jz L10
orl $BIT6, %eax
L10:
testl $BIT24, %edx # Check for FXSR capabilities
jz L11
orl $BIT9, %eax
L11:
testl $BIT25, %edx # Check for SSE capabilities
jz L12
orl $BIT10, %eax
L12: # as cr4.PGE is not set here, refresh cr3
movl %eax, %cr4 # in PreModifyMtrrs() to flush TLB.
cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
jz L5
# Load TSS
movb $0x89, (TSS_SEGMENT + 5)(%ebp) # clear busy flag
movl $TSS_SEGMENT, %eax
ltrw %ax
L5:
# enable NXE if supported
.byte 0xb0 # mov al, imm8
ASM_PFX(mXdSupported): .byte 1
cmpb $0, %al
jz SkipNxe
#
# Check XD disable bit
#
movl $MSR_IA32_MISC_ENABLE, %ecx
rdmsr
pushl %edx # save MSR_IA32_MISC_ENABLE[63-32]
testl $BIT2, %edx # MSR_IA32_MISC_ENABLE[34]
jz L13
andw $0x0FFFB, %dx # clear XD Disable bit if it is set
wrmsr
L13:
movl $MSR_EFER, %ecx
rdmsr
orw $MSR_EFER_XD,%ax # enable NXE
wrmsr
SkipNxe:
subl $4, %esp
NxeDone:
movl %cr0, %ebx
orl $0x080010023, %ebx # enable paging + WP + NE + MP + PE
movl %ebx, %cr0
leal DSC_OFFSET(%edi),%ebx
movw DSC_DS(%ebx),%ax
movl %eax, %ds
movw DSC_OTHERSEG(%ebx),%ax
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movw DSC_SS(%ebx),%ax
movl %eax, %ss
# jmp _SmiHandler # instruction is not needed
_SmiHandler:
movl 4(%esp), %ebx
pushl %ebx
movl $ASM_PFX(CpuSmmDebugEntry), %eax
call *%eax
addl $4, %esp
pushl %ebx
movl $ASM_PFX(SmiRendezvous), %eax
call *%eax
addl $4, %esp
pushl %ebx
movl $ASM_PFX(CpuSmmDebugExit), %eax
call *%eax
addl $4, %esp
movl $ASM_PFX(mXdSupported), %eax
movb (%eax), %al
cmpb $0, %al
jz L16
popl %edx # get saved MSR_IA32_MISC_ENABLE[63-32]
testl $BIT2, %edx
jz L16
movl $MSR_IA32_MISC_ENABLE, %ecx
rdmsr
orw $BIT2, %dx # set XD Disable bit if it was set before entering into SMM
wrmsr
L16:
rsm
ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint