summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S')
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S278
1 files changed, 278 insertions, 0 deletions
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S
new file mode 100644
index 0000000000..4c0f8c8933
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S
@@ -0,0 +1,278 @@
+#------------------------------------------------------------------------------
+#
+# 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(gcStmSmiHandlerTemplate)
+ASM_GLOBAL ASM_PFX(gcStmSmiHandlerSize)
+ASM_GLOBAL ASM_PFX(gcStmSmiHandlerOffset)
+ASM_GLOBAL ASM_PFX(gStmSmiCr3)
+ASM_GLOBAL ASM_PFX(gStmSmiStack)
+ASM_GLOBAL ASM_PFX(gStmSmbase)
+ASM_GLOBAL ASM_PFX(gStmXdSupported)
+ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
+ASM_GLOBAL ASM_PFX(gStmSmiHandlerIdtr)
+
+.equ MSR_IA32_MISC_ENABLE, 0x1A0
+.equ MSR_EFER, 0xc0000080
+.equ MSR_EFER_XD, 0x800
+
+#
+# Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
+#
+.equ DSC_OFFSET, 0xfb00
+.equ DSC_GDTPTR, 0x48
+.equ DSC_GDTSIZ, 0x50
+.equ DSC_CS, 0x14
+.equ DSC_DS, 0x16
+.equ DSC_SS, 0x18
+.equ DSC_OTHERSEG, 0x1A
+
+.equ PROTECT_MODE_CS, 0x08
+.equ PROTECT_MODE_DS, 0x20
+.equ TSS_SEGMENT, 0x40
+
+ .text
+ASM_PFX(gcStmSmiHandlerTemplate):
+
+_StmSmiEntryPoint:
+ .byte 0xbb # mov bx, imm16
+ .word _StmGdtDesc - _StmSmiEntryPoint + 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(gStmSmbase): .space 4
+ .byte 0x67
+ lea ((Start32bit - _StmSmiEntryPoint) + 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
+_StmGdtDesc: .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(gStmSmiStack): .space 4
+ movl $ASM_PFX(gStmSmiHandlerIdtr), %eax
+ lidt (%eax)
+ jmp ProtFlatMode
+
+ProtFlatMode:
+ .byte 0xb8 # mov eax, imm32
+ASM_PFX(gStmSmiCr3): .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(gStmXdSupported): .byte 1
+ cmpb $0, %al
+ jz SkipXd
+#
+# 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
+ jmp XdDone
+SkipXd:
+ subl $4, %esp
+XdDone:
+
+ 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
+
+CommonHandler:
+ 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(gStmXdSupported), %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
+
+_StmSmiHandler:
+#
+# Check XD disable bit
+#
+ xorl %esi, %esi
+ movl $ASM_PFX(gStmXdSupported), %eax
+ movb (%eax), %al
+ cmpb $0, %al
+ jz StmXdDone
+ movl $MSR_IA32_MISC_ENABLE, %ecx
+ rdmsr
+ movl %edx, %esi # save MSR_IA32_MISC_ENABLE[63-32]
+ testl $BIT2, %edx # MSR_IA32_MISC_ENABLE[34]
+ jz L14
+ andw $0x0FFFB, %dx # clear XD Disable bit if it is set
+ wrmsr
+L14:
+ movl $MSR_EFER, %ecx
+ rdmsr
+ orw $MSR_EFER_XD,%ax # enable NXE
+ wrmsr
+StmXdDone:
+ push %esi
+
+ # below step is needed, because STM does not run above code.
+ # we have to run below code to set IDT/CR0/CR4
+ movl $ASM_PFX(gStmSmiHandlerIdtr), %eax
+ lidt (%eax)
+
+ movl %cr0, %eax
+ orl $0x80010023, %eax # enable paging + WP + NE + MP + PE
+ movl %eax, %cr0
+#
+# Need to test for CR4 specific bit support
+#
+ movl $1, %eax
+ cpuid # use CPUID to determine if specific CR4 bits are supported
+ movl %cr4, %eax # init EAX
+ testl $BIT2, %edx # Check for DE capabilities
+ jz L28
+ orl $BIT3, %eax
+L28:
+ testl $BIT6, %edx # Check for PAE capabilities
+ jz L29
+ orl $BIT5, %eax
+L29:
+ testl $BIT7, %edx # Check for MCE capabilities
+ jz L30
+ orl $BIT6, %eax
+L30:
+ testl $BIT24, %edx # Check for FXSR capabilities
+ jz L31
+ orl $BIT9, %eax
+L31:
+ testl $BIT25, %edx # Check for SSE capabilities
+ jz L32
+ orl $BIT10, %eax
+L32: # as cr4.PGE is not set here, refresh cr3
+ movl %eax, %cr4 # in PreModifyMtrrs() to flush TLB.
+ # STM init finish
+ jmp CommonHandler
+
+
+ASM_PFX(gcStmSmiHandlerSize) : .word . - _StmSmiEntryPoint
+ASM_PFX(gcStmSmiHandlerOffset): .word _StmSmiHandler - _StmSmiEntryPoint
+