summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32')
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.S278
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.asm285
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.nasm271
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.S174
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.asm170
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.nasm176
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c83
7 files changed, 1437 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
+
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.asm b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.asm
new file mode 100644
index 0000000000..94888d5aec
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.asm
@@ -0,0 +1,285 @@
+;------------------------------------------------------------------------------ ;
+; 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.asm
+;
+; Abstract:
+;
+; Code template of the SMI handler for a particular processor
+;
+;-------------------------------------------------------------------------------
+
+ .686p
+ .model flat,C
+ .xmm
+
+MSR_IA32_MISC_ENABLE EQU 1A0h
+MSR_EFER EQU 0c0000080h
+MSR_EFER_XD EQU 0800h
+
+;
+; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
+;
+DSC_OFFSET EQU 0fb00h
+DSC_GDTPTR EQU 48h
+DSC_GDTSIZ EQU 50h
+DSC_CS EQU 14h
+DSC_DS EQU 16h
+DSC_SS EQU 18h
+DSC_OTHERSEG EQU 1Ah
+
+PROTECT_MODE_CS EQU 08h
+PROTECT_MODE_DS EQU 20h
+TSS_SEGMENT EQU 40h
+
+SmiRendezvous PROTO C
+CpuSmmDebugEntry PROTO C
+CpuSmmDebugExit PROTO C
+
+EXTERNDEF gcStmSmiHandlerTemplate:BYTE
+EXTERNDEF gcStmSmiHandlerSize:WORD
+EXTERNDEF gcStmSmiHandlerOffset:WORD
+EXTERNDEF gStmSmiCr3:DWORD
+EXTERNDEF gStmSmiStack:DWORD
+EXTERNDEF gStmSmbase:DWORD
+EXTERNDEF gStmXdSupported:BYTE
+EXTERNDEF FeaturePcdGet (PcdCpuSmmStackGuard):BYTE
+EXTERNDEF gStmSmiHandlerIdtr:FWORD
+
+ .code
+
+gcStmSmiHandlerTemplate LABEL BYTE
+
+_StmSmiEntryPoint:
+ DB 0bbh ; mov bx, imm16
+ DW offset _StmGdtDesc - _StmSmiEntryPoint + 8000h
+ DB 2eh, 0a1h ; mov ax, cs:[offset16]
+ DW DSC_OFFSET + DSC_GDTSIZ
+ dec eax
+ mov cs:[edi], eax ; mov cs:[bx], ax
+ DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]
+ DW DSC_OFFSET + DSC_GDTPTR
+ mov cs:[edi + 2], ax ; mov cs:[bx + 2], eax
+ mov bp, ax ; ebp = GDT base
+ DB 66h
+ lgdt fword ptr cs:[edi] ; lgdt fword ptr cs:[bx]
+; Patch ProtectedMode Segment
+ DB 0b8h ; mov ax, imm16
+ DW PROTECT_MODE_CS ; set AX for segment directly
+ mov cs:[edi - 2], eax ; mov cs:[bx - 2], ax
+; Patch ProtectedMode entry
+ DB 66h, 0bfh ; mov edi, SMBASE
+gStmSmbase DD ?
+ DB 67h
+ lea ax, [edi + (@32bit - _StmSmiEntryPoint) + 8000h]
+ mov cs:[edi - 6], ax ; mov cs:[bx - 6], eax
+ mov ebx, cr0
+ DB 66h
+ and ebx, 9ffafff3h
+ DB 66h
+ or ebx, 23h
+ mov cr0, ebx
+ DB 66h, 0eah
+ DD ?
+ DW ?
+_StmGdtDesc FWORD ?
+
+@32bit:
+ mov ax, PROTECT_MODE_DS
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ DB 0bch ; mov esp, imm32
+gStmSmiStack DD ?
+ mov eax, offset gStmSmiHandlerIdtr
+ lidt fword ptr [eax]
+ jmp ProtFlatMode
+
+ProtFlatMode:
+ DB 0b8h ; mov eax, imm32
+gStmSmiCr3 DD ?
+ mov cr3, eax
+;
+; Need to test for CR4 specific bit support
+;
+ mov eax, 1
+ cpuid ; use CPUID to determine if specific CR4 bits are supported
+ xor eax, eax ; Clear EAX
+ test edx, BIT2 ; Check for DE capabilities
+ jz @f
+ or eax, BIT3
+@@:
+ test edx, BIT6 ; Check for PAE capabilities
+ jz @f
+ or eax, BIT5
+@@:
+ test edx, BIT7 ; Check for MCE capabilities
+ jz @f
+ or eax, BIT6
+@@:
+ test edx, BIT24 ; Check for FXSR capabilities
+ jz @f
+ or eax, BIT9
+@@:
+ test edx, BIT25 ; Check for SSE capabilities
+ jz @f
+ or eax, BIT10
+@@: ; as cr4.PGE is not set here, refresh cr3
+ mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
+
+ cmp FeaturePcdGet (PcdCpuSmmStackGuard), 0
+ jz @F
+; Load TSS
+ mov byte ptr [ebp + TSS_SEGMENT + 5], 89h ; clear busy flag
+ mov eax, TSS_SEGMENT
+ ltr ax
+@@:
+
+; enable NXE if supported
+ DB 0b0h ; mov al, imm8
+gStmXdSupported DB 1
+ cmp al, 0
+ jz @SkipXd
+;
+; Check XD disable bit
+;
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ push edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz @f
+ and dx, 0FFFBh ; clear XD Disable bit if it is set
+ wrmsr
+@@:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; enable NXE
+ wrmsr
+ jmp @XdDone
+@SkipXd:
+ sub esp, 4
+@XdDone:
+
+ mov ebx, cr0
+ or ebx, 080010023h ; enable paging + WP + NE + MP + PE
+ mov cr0, ebx
+ lea ebx, [edi + DSC_OFFSET]
+ mov ax, [ebx + DSC_DS]
+ mov ds, eax
+ mov ax, [ebx + DSC_OTHERSEG]
+ mov es, eax
+ mov fs, eax
+ mov gs, eax
+ mov ax, [ebx + DSC_SS]
+ mov ss, eax
+
+CommonHandler:
+ mov ebx, [esp + 4] ; CPU Index
+ push ebx
+ mov eax, CpuSmmDebugEntry
+ call eax
+ add esp, 4
+
+ push ebx
+ mov eax, SmiRendezvous
+ call eax
+ add esp, 4
+
+ push ebx
+ mov eax, CpuSmmDebugExit
+ call eax
+ add esp, 4
+
+ mov eax, gStmXdSupported
+ mov al, [eax]
+ cmp al, 0
+ jz @f
+ pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2
+ jz @f
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
+ wrmsr
+
+@@:
+ rsm
+
+_StmSmiHandler:
+;
+; Check XD disable bit
+;
+ xor esi, esi
+ mov eax, gStmXdSupported
+ mov al, [eax]
+ cmp al, 0
+ jz @StmXdDone
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz @f
+ and dx, 0FFFBh ; clear XD Disable bit if it is set
+ wrmsr
+@@:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; 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
+ mov eax, offset gStmSmiHandlerIdtr
+ lidt fword ptr [eax]
+
+
+ mov eax, cr0
+ or eax, 80010023h ; enable paging + WP + NE + MP + PE
+ mov cr0, eax
+;
+; Need to test for CR4 specific bit support
+;
+ mov eax, 1
+ cpuid ; use CPUID to determine if specific CR4 bits are supported
+ mov eax, cr4 ; init EAX
+ test edx, BIT2 ; Check for DE capabilities
+ jz @f
+ or eax, BIT3
+@@:
+ test edx, BIT6 ; Check for PAE capabilities
+ jz @f
+ or eax, BIT5
+@@:
+ test edx, BIT7 ; Check for MCE capabilities
+ jz @f
+ or eax, BIT6
+@@:
+ test edx, BIT24 ; Check for FXSR capabilities
+ jz @f
+ or eax, BIT9
+@@:
+ test edx, BIT25 ; Check for SSE capabilities
+ jz @f
+ or eax, BIT10
+@@: ; as cr4.PGE is not set here, refresh cr3
+ mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
+ ; STM init finish
+ jmp CommonHandler
+
+gcStmSmiHandlerSize DW $ - _StmSmiEntryPoint
+gcStmSmiHandlerOffset DW _StmSmiHandler - _StmSmiEntryPoint
+
+ END
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.nasm b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.nasm
new file mode 100644
index 0000000000..b1c84a494f
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiEntry.nasm
@@ -0,0 +1,271 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 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.nasm
+;
+; Abstract:
+;
+; Code template of the SMI handler for a particular processor
+;
+;-------------------------------------------------------------------------------
+
+%define MSR_IA32_MISC_ENABLE 0x1A0
+%define MSR_EFER 0xc0000080
+%define MSR_EFER_XD 0x800
+
+;
+; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
+;
+%define DSC_OFFSET 0xfb00
+%define DSC_GDTPTR 0x48
+%define DSC_GDTSIZ 0x50
+%define DSC_CS 0x14
+%define DSC_DS 0x16
+%define DSC_SS 0x18
+%define DSC_OTHERSEG 0x1a
+
+%define PROTECT_MODE_CS 0x8
+%define PROTECT_MODE_DS 0x20
+%define TSS_SEGMENT 0x40
+
+extern ASM_PFX(SmiRendezvous)
+extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
+extern ASM_PFX(CpuSmmDebugEntry)
+extern ASM_PFX(CpuSmmDebugExit)
+
+global ASM_PFX(gcStmSmiHandlerTemplate)
+global ASM_PFX(gcStmSmiHandlerSize)
+global ASM_PFX(gcStmSmiHandlerOffset)
+global ASM_PFX(gStmSmiCr3)
+global ASM_PFX(gStmSmiStack)
+global ASM_PFX(gStmSmbase)
+global ASM_PFX(gStmXdSupported)
+extern ASM_PFX(gStmSmiHandlerIdtr)
+
+ SECTION .text
+
+BITS 16
+ASM_PFX(gcStmSmiHandlerTemplate):
+_StmSmiEntryPoint:
+ mov bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000
+ mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
+ dec ax
+ mov [cs:bx], ax
+ mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
+ mov [cs:bx + 2], eax
+ mov ebp, eax ; ebp = GDT base
+o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
+ mov ax, PROTECT_MODE_CS
+ mov [cs:bx-0x2],ax
+ DB 0x66, 0xbf ; mov edi, SMBASE
+ASM_PFX(gStmSmbase): DD 0
+ lea eax, [edi + (@32bit - _StmSmiEntryPoint) + 0x8000]
+ mov [cs:bx-0x6],eax
+ mov ebx, cr0
+ and ebx, 0x9ffafff3
+ or ebx, 0x23
+ mov cr0, ebx
+ jmp dword 0x0:0x0
+_StmGdtDesc:
+ DW 0
+ DD 0
+
+BITS 32
+@32bit:
+ mov ax, PROTECT_MODE_DS
+o16 mov ds, ax
+o16 mov es, ax
+o16 mov fs, ax
+o16 mov gs, ax
+o16 mov ss, ax
+ DB 0xbc ; mov esp, imm32
+ASM_PFX(gStmSmiStack): DD 0
+ mov eax, ASM_PFX(gStmSmiHandlerIdtr)
+ lidt [eax]
+ jmp ProtFlatMode
+
+ProtFlatMode:
+ DB 0xb8 ; mov eax, imm32
+ASM_PFX(gStmSmiCr3): DD 0
+ mov cr3, eax
+;
+; Need to test for CR4 specific bit support
+;
+ mov eax, 1
+ cpuid ; use CPUID to determine if specific CR4 bits are supported
+ xor eax, eax ; Clear EAX
+ test edx, BIT2 ; Check for DE capabilities
+ jz .0
+ or eax, BIT3
+.0:
+ test edx, BIT6 ; Check for PAE capabilities
+ jz .1
+ or eax, BIT5
+.1:
+ test edx, BIT7 ; Check for MCE capabilities
+ jz .2
+ or eax, BIT6
+.2:
+ test edx, BIT24 ; Check for FXSR capabilities
+ jz .3
+ or eax, BIT9
+.3:
+ test edx, BIT25 ; Check for SSE capabilities
+ jz .4
+ or eax, BIT10
+.4: ; as cr4.PGE is not set here, refresh cr3
+ mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
+
+ cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
+ jz .6
+; Load TSS
+ mov byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag
+ mov eax, TSS_SEGMENT
+ ltr ax
+.6:
+
+; enable NXE if supported
+ DB 0b0h ; mov al, imm8
+ASM_PFX(gStmXdSupported): DB 1
+ cmp al, 0
+ jz @SkipXd
+;
+; Check XD disable bit
+;
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ push edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz .5
+ and dx, 0xFFFB ; clear XD Disable bit if it is set
+ wrmsr
+.5:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; enable NXE
+ wrmsr
+ jmp @XdDone
+@SkipXd:
+ sub esp, 4
+@XdDone:
+
+ mov ebx, cr0
+ or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
+ mov cr0, ebx
+ lea ebx, [edi + DSC_OFFSET]
+ mov ax, [ebx + DSC_DS]
+ mov ds, eax
+ mov ax, [ebx + DSC_OTHERSEG]
+ mov es, eax
+ mov fs, eax
+ mov gs, eax
+ mov ax, [ebx + DSC_SS]
+ mov ss, eax
+
+CommonHandler:
+ mov ebx, [esp + 4] ; CPU Index
+ push ebx
+ mov eax, ASM_PFX(CpuSmmDebugEntry)
+ call eax
+ add esp, 4
+
+ push ebx
+ mov eax, ASM_PFX(SmiRendezvous)
+ call eax
+ add esp, 4
+
+ push ebx
+ mov eax, ASM_PFX(CpuSmmDebugExit)
+ call eax
+ add esp, 4
+
+ mov eax, ASM_PFX(gStmXdSupported)
+ mov al, [eax]
+ cmp al, 0
+ jz .7
+ pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2
+ jz .7
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
+ wrmsr
+
+.7:
+ rsm
+
+
+_StmSmiHandler:
+;
+; Check XD disable bit
+;
+ xor esi, esi
+ mov eax, ASM_PFX(gStmXdSupported)
+ mov al, [eax]
+ cmp al, 0
+ jz @StmXdDone
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz .5
+ and dx, 0xFFFB ; clear XD Disable bit if it is set
+ wrmsr
+.5:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; 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
+ mov eax, ASM_PFX(gStmSmiHandlerIdtr)
+ lidt [eax]
+
+ mov eax, cr0
+ or eax, 0x80010023 ; enable paging + WP + NE + MP + PE
+ mov cr0, eax
+;
+; Need to test for CR4 specific bit support
+;
+ mov eax, 1
+ cpuid ; use CPUID to determine if specific CR4 bits are supported
+ mov eax, cr4 ; init EAX
+ test edx, BIT2 ; Check for DE capabilities
+ jz .0
+ or eax, BIT3
+.0:
+ test edx, BIT6 ; Check for PAE capabilities
+ jz .1
+ or eax, BIT5
+.1:
+ test edx, BIT7 ; Check for MCE capabilities
+ jz .2
+ or eax, BIT6
+.2:
+ test edx, BIT24 ; Check for FXSR capabilities
+ jz .3
+ or eax, BIT9
+.3:
+ test edx, BIT25 ; Check for SSE capabilities
+ jz .4
+ or eax, BIT10
+.4: ; as cr4.PGE is not set here, refresh cr3
+ mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
+ ; STM init finish
+ jmp CommonHandler
+
+ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint
+ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint
+
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.S b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.S
new file mode 100644
index 0000000000..7d0057af80
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.S
@@ -0,0 +1,174 @@
+#------------------------------------------------------------------------------
+#
+# 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:
+#
+# SmiException.S
+#
+# Abstract:
+#
+# Exception handlers used in SM mode
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(gcStmPsd)
+
+ASM_GLOBAL ASM_PFX(SmmStmExceptionHandler)
+ASM_GLOBAL ASM_PFX(SmmStmSetup)
+ASM_GLOBAL ASM_PFX(SmmStmTeardown)
+
+.equ MSR_IA32_MISC_ENABLE, 0x1A0
+.equ MSR_EFER, 0xc0000080
+.equ MSR_EFER_XD, 0x800
+
+.equ CODE_SEL, 0x08
+.equ DATA_SEL, 0x20
+.equ TSS_SEL, 0x40
+
+ .data
+
+ASM_PFX(gcStmPsd):
+ .ascii "TXTPSSIG"
+ .word PSD_SIZE
+ .word 1 # Version
+ .long 0 # LocalApicId
+ .byte 0x5 # Cr4Pse;Cr4Pae;Intel64Mode;ExecutionDisableOutsideSmrr
+ .byte 0 # BIOS to STM
+ .byte 0 # STM to BIOS
+ .byte 0
+ .word CODE_SEL
+ .word DATA_SEL
+ .word DATA_SEL
+ .word DATA_SEL
+ .word TSS_SEL
+ .word 0
+ .quad 0 # SmmCr3
+ .long ASM_PFX(_OnStmSetup)
+ .long 0
+ .long ASM_PFX(_OnStmTeardown)
+ .long 0
+ .quad 0 # SmmSmiHandlerRip - SMM guest entrypoint
+ .quad 0 # SmmSmiHandlerRsp
+ .quad 0
+ .long 0
+ .long 0x80010100 # RequiredStmSmmRevId
+ .long ASM_PFX(_OnException)
+ .long 0
+ .quad 0 # ExceptionStack
+ .word DATA_SEL
+ .word 0x1F # ExceptionFilter
+ .long 0
+ .quad 0
+ .quad 0 # BiosHwResourceRequirementsPtr
+ .quad 0 # AcpiRsdp
+ .byte 0 # PhysicalAddressBits
+.equ PSD_SIZE, . - ASM_PFX(gcStmPsd)
+
+ .text
+
+#------------------------------------------------------------------------------
+# SMM Exception handlers
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(_OnException)
+ASM_PFX(_OnException):
+ movl %esp, %ecx
+ pushl %ecx
+ call ASM_PFX(SmmStmExceptionHandler)
+ addl $4, %esp
+
+ movl %eax, %ebx
+ movl $4, %eax
+ .byte 0xf, 0x1, 0xc1 # VMCALL
+ jmp .
+
+ASM_GLOBAL ASM_PFX(_OnStmSetup)
+ASM_PFX(_OnStmSetup):
+#
+# Check XD disable bit
+#
+ xorl %esi, %esi
+ movl $ASM_PFX(gStmXdSupported), %eax
+ movb (%eax), %al
+ cmpb $0, %al
+ jz StmXdDone1
+ 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 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
+StmXdDone1:
+ push %esi
+
+ call ASM_PFX(SmmStmSetup)
+
+ movl $ASM_PFX(gStmXdSupported), %eax
+ movb (%eax), %al
+ cmpb $0, %al
+ jz L14
+ popl %edx # get saved MSR_IA32_MISC_ENABLE[63-32]
+ testl $BIT2, %edx
+ jz L14
+ movl $MSR_IA32_MISC_ENABLE, %ecx
+ rdmsr
+ orw $BIT2, %dx # set XD Disable bit if it was set before entering into SMM
+ wrmsr
+L14:
+
+ rsm
+
+ASM_GLOBAL ASM_PFX(_OnStmTeardown)
+ASM_PFX(_OnStmTeardown):
+#
+# Check XD disable bit
+#
+ xorl %esi, %esi
+ movl $ASM_PFX(gStmXdSupported), %eax
+ movb (%eax), %al
+ cmpb $0, %al
+ jz StmXdDone2
+ 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 L15
+ andw $0x0FFFB, %dx # clear XD Disable bit if it is set
+ wrmsr
+L15:
+ movl $MSR_EFER, %ecx
+ rdmsr
+ orw $MSR_EFER_XD,%ax # enable NXE
+ wrmsr
+StmXdDone2:
+ push %esi
+
+ call ASM_PFX(SmmStmTeardown)
+
+ 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
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.asm b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.asm
new file mode 100644
index 0000000000..7c04ad91f2
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.asm
@@ -0,0 +1,170 @@
+;------------------------------------------------------------------------------ ;
+; 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:
+;
+; SmiException.asm
+;
+; Abstract:
+;
+; Exception handlers used in SM mode
+;
+;-------------------------------------------------------------------------------
+
+ .686p
+ .model flat,C
+
+EXTERNDEF gcStmPsd:BYTE
+
+EXTERNDEF SmmStmExceptionHandler:PROC
+EXTERNDEF SmmStmSetup:PROC
+EXTERNDEF SmmStmTeardown:PROC
+
+CODE_SEL = 08h
+DATA_SEL = 20h
+TSS_SEL = 40h
+
+ .data
+
+gcStmPsd LABEL BYTE
+ DB 'TXTPSSIG'
+ DW PSD_SIZE
+ DW 1 ; Version
+ DD 0 ; LocalApicId
+ DB 05h ; Cr4Pse;Cr4Pae;Intel64Mode;ExecutionDisableOutsideSmrr
+ DB 0 ; BIOS to STM
+ DB 0 ; STM to BIOS
+ DB 0
+ DW CODE_SEL
+ DW DATA_SEL
+ DW DATA_SEL
+ DW DATA_SEL
+ DW TSS_SEL
+ DW 0
+ DQ 0 ; SmmCr3
+ DQ _OnStmSetup
+ DQ _OnStmTeardown
+ DQ 0 ; SmmSmiHandlerRip - SMM guest entrypoint
+ DQ 0 ; SmmSmiHandlerRsp
+ DQ 0
+ DD 0
+ DD 80010100h ; RequiredStmSmmRevId
+ DQ _OnException
+ DQ 0 ; ExceptionStack
+ DW DATA_SEL
+ DW 01Fh ; ExceptionFilter
+ DD 0
+ DQ 0
+ DQ 0 ; BiosHwResourceRequirementsPtr
+ DQ 0 ; AcpiRsdp
+ DB 0 ; PhysicalAddressBits
+PSD_SIZE = $ - offset gcStmPsd
+
+ .code
+;------------------------------------------------------------------------------
+; SMM Exception handlers
+;------------------------------------------------------------------------------
+_OnException PROC
+ mov ecx, esp
+ push ecx
+ call SmmStmExceptionHandler
+ add esp, 4
+
+ mov ebx, eax
+ mov eax, 4
+ DB 0fh, 01h, 0c1h ; VMCALL
+ jmp $
+_OnException ENDP
+
+_OnStmSetup PROC
+;
+; Check XD disable bit
+;
+ xor esi, esi
+ mov eax, gStmXdSupported
+ mov al, [eax]
+ cmp al, 0
+ jz @StmXdDone1
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz @f
+ and dx, 0FFFBh ; clear XD Disable bit if it is set
+ wrmsr
+@@:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; enable NXE
+ wrmsr
+@StmXdDone1:
+ push esi
+
+ call SmmStmSetup
+
+ mov eax, gStmXdSupported
+ mov al, [eax]
+ cmp al, 0
+ jz @f
+ pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2
+ jz @f
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
+ wrmsr
+@@:
+
+ rsm
+_OnStmSetup ENDP
+
+_OnStmTeardown PROC
+;
+; Check XD disable bit
+;
+ xor esi, esi
+ mov eax, gStmXdSupported
+ mov al, [eax]
+ cmp al, 0
+ jz @StmXdDone2
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz @f
+ and dx, 0FFFBh ; clear XD Disable bit if it is set
+ wrmsr
+@@:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; enable NXE
+ wrmsr
+@StmXdDone2:
+ push esi
+
+ call SmmStmTeardown
+
+ mov eax, gStmXdSupported
+ mov al, [eax]
+ cmp al, 0
+ jz @f
+ pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2
+ jz @f
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
+ wrmsr
+@@:
+
+ rsm
+_OnStmTeardown ENDP
+
+ END
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.nasm b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.nasm
new file mode 100644
index 0000000000..0ce8501ba9
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmiException.nasm
@@ -0,0 +1,176 @@
+;------------------------------------------------------------------------------ ;
+; 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:
+;
+; SmiException.nasm
+;
+; Abstract:
+;
+; Exception handlers used in SM mode
+;
+;-------------------------------------------------------------------------------
+
+global ASM_PFX(gcStmPsd)
+
+extern ASM_PFX(SmmStmExceptionHandler)
+extern ASM_PFX(SmmStmSetup)
+extern ASM_PFX(SmmStmTeardown)
+extern ASM_PFX(gStmXdSupported)
+extern ASM_PFX(gStmSmiHandlerIdtr)
+
+%define MSR_IA32_MISC_ENABLE 0x1A0
+%define MSR_EFER 0xc0000080
+%define MSR_EFER_XD 0x800
+
+CODE_SEL equ 0x08
+DATA_SEL equ 0x20
+TSS_SEL equ 0x40
+
+ SECTION .data
+
+ASM_PFX(gcStmPsd):
+ DB 'TXTPSSIG'
+ DW PSD_SIZE
+ DW 1 ; Version
+ DD 0 ; LocalApicId
+ DB 0x05 ; Cr4Pse;Cr4Pae;Intel64Mode;ExecutionDisableOutsideSmrr
+ DB 0 ; BIOS to STM
+ DB 0 ; STM to BIOS
+ DB 0
+ DW CODE_SEL
+ DW DATA_SEL
+ DW DATA_SEL
+ DW DATA_SEL
+ DW TSS_SEL
+ DW 0
+ DQ 0 ; SmmCr3
+ DD ASM_PFX(OnStmSetup)
+ DD 0
+ DD ASM_PFX(OnStmTeardown)
+ DD 0
+ DQ 0 ; SmmSmiHandlerRip - SMM guest entrypoint
+ DQ 0 ; SmmSmiHandlerRsp
+ DQ 0
+ DD 0
+ DD 0x80010100 ; RequiredStmSmmRevId
+ DD ASM_PFX(OnException)
+ DD 0
+ DQ 0 ; ExceptionStack
+ DW DATA_SEL
+ DW 0x01F ; ExceptionFilter
+ DD 0
+ DD 0
+ DD 0
+ DQ 0 ; BiosHwResourceRequirementsPtr
+ DQ 0 ; AcpiRsdp
+ DB 0 ; PhysicalAddressBits
+PSD_SIZE equ $ - ASM_PFX(gcStmPsd)
+
+ SECTION .text
+;------------------------------------------------------------------------------
+; SMM Exception handlers
+;------------------------------------------------------------------------------
+global ASM_PFX(OnException)
+ASM_PFX(OnException):
+ mov ecx, esp
+ push ecx
+ call ASM_PFX(SmmStmExceptionHandler)
+ add esp, 4
+
+ mov ebx, eax
+ mov eax, 4
+ DB 0x0f, 0x01, 0x0c1 ; VMCALL
+ jmp $
+
+global ASM_PFX(OnStmSetup)
+ASM_PFX(OnStmSetup):
+;
+; Check XD disable bit
+;
+ xor esi, esi
+ mov eax, ASM_PFX(gStmXdSupported)
+ mov al, [eax]
+ cmp al, 0
+ jz @StmXdDone1
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz .51
+ and dx, 0xFFFB ; clear XD Disable bit if it is set
+ wrmsr
+.51:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; enable NXE
+ wrmsr
+@StmXdDone1:
+ push esi
+
+ call ASM_PFX(SmmStmSetup)
+
+ mov eax, ASM_PFX(gStmXdSupported)
+ mov al, [eax]
+ cmp al, 0
+ jz .71
+ pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2
+ jz .71
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
+ wrmsr
+
+.71:
+ rsm
+
+global ASM_PFX(OnStmTeardown)
+ASM_PFX(OnStmTeardown):
+;
+; Check XD disable bit
+;
+ xor esi, esi
+ mov eax, ASM_PFX(gStmXdSupported)
+ mov al, [eax]
+ cmp al, 0
+ jz @StmXdDone2
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
+ jz .52
+ and dx, 0xFFFB ; clear XD Disable bit if it is set
+ wrmsr
+.52:
+ mov ecx, MSR_EFER
+ rdmsr
+ or ax, MSR_EFER_XD ; enable NXE
+ wrmsr
+@StmXdDone2:
+ push esi
+
+ call ASM_PFX(SmmStmTeardown)
+
+ mov eax, ASM_PFX(gStmXdSupported)
+ mov al, [eax]
+ cmp al, 0
+ jz .72
+ pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
+ test edx, BIT2
+ jz .72
+ mov ecx, MSR_IA32_MISC_ENABLE
+ rdmsr
+ or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
+ wrmsr
+
+.72:
+ rsm
+
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c
new file mode 100644
index 0000000000..0154c7c0f8
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c
@@ -0,0 +1,83 @@
+/** @file
+ SMM STM support functions
+
+ Copyright (c) 2015 - 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.
+
+**/
+
+#include <PiSmm.h>
+#include <Library/DebugLib.h>
+
+#include "SmmStm.h"
+
+///
+/// Page Table Entry
+///
+#define IA32_PG_P BIT0
+#define IA32_PG_RW BIT1
+#define IA32_PG_PS BIT7
+
+/**
+
+ Create 4G page table for STM.
+ 4M Non-PAE page table in IA32 version.
+
+ @param PageTableBase The page table base in MSEG
+
+**/
+VOID
+StmGen4GPageTable (
+ IN UINTN PageTableBase
+ )
+{
+ UINTN Index;
+ UINT32 *Pte;
+ UINT32 Address;
+
+ Pte = (UINT32*)(UINTN)PageTableBase;
+
+ Address = 0;
+ for (Index = 0; Index < SIZE_4KB / sizeof (*Pte); Index++) {
+ *Pte = Address | IA32_PG_PS | IA32_PG_RW | IA32_PG_P;
+ Pte++;
+ Address += SIZE_4MB;
+ }
+}
+
+/**
+ This is SMM exception handle.
+ Consumed by STM when exception happen.
+
+ @param Context STM protection exception stack frame
+
+ @return the EBX value for STM reference.
+ EBX = 0: resume SMM guest using register state found on exception stack.
+ EBX = 1 to 0x0F: EBX contains a BIOS error code which the STM must record in the
+ TXT.ERRORCODE register and subsequently reset the system via
+ TXT.CMD.SYS_RESET. The value of the TXT.ERRORCODE register is calculated as
+ follows: TXT.ERRORCODE = (EBX & 0x0F) | STM_CRASH_BIOS_PANIC
+ EBX = 0x10 to 0xFFFFFFFF - reserved, do not use.
+
+**/
+UINT32
+EFIAPI
+SmmStmExceptionHandler (
+ IN OUT STM_PROTECTION_EXCEPTION_STACK_FRAME Context
+ )
+{
+ // TBD - SmmStmExceptionHandler, record information
+ DEBUG ((DEBUG_ERROR, "SmmStmExceptionHandler ...\n"));
+ //
+ // Skip this instruction and continue;
+ //
+ Context.Ia32StackFrame->Rip += Context.Ia32StackFrame->VmcsExitInstructionLength;
+
+ return 0;
+}