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 22ASM_GLOBAL ASM_PFX(gcStmSmiHandlerTemplate) 23ASM_GLOBAL ASM_PFX(gcStmSmiHandlerSize) 24ASM_GLOBAL ASM_PFX(gcStmSmiHandlerOffset) 25ASM_GLOBAL ASM_PFX(gStmSmiCr3) 26ASM_GLOBAL ASM_PFX(gStmSmiStack) 27ASM_GLOBAL ASM_PFX(gStmSmbase) 28ASM_GLOBAL ASM_PFX(gStmXdSupported) 29ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard)) 30ASM_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 52ASM_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 73ASM_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 89Start32bit: 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 97ASM_PFX(gStmSmiStack): .space 4 98 movl $ASM_PFX(gStmSmiHandlerIdtr), %eax 99 lidt (%eax) 100 jmp ProtFlatMode 101 102ProtFlatMode: 103 .byte 0xb8 # mov eax, imm32 104ASM_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 115L8: 116 testl $BIT6, %edx # Check for PAE capabilities 117 jz L9 118 orl $BIT5, %eax 119L9: 120 testl $BIT7, %edx # Check for MCE capabilities 121 jz L10 122 orl $BIT6, %eax 123L10: 124 testl $BIT24, %edx # Check for FXSR capabilities 125 jz L11 126 orl $BIT9, %eax 127L11: 128 testl $BIT25, %edx # Check for SSE capabilities 129 jz L12 130 orl $BIT10, %eax 131L12: # 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 140L5: 141 142# enable NXE if supported 143 .byte 0xb0 # mov al, imm8 144ASM_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 157L13: 158 movl $MSR_EFER, %ecx 159 rdmsr 160 orw $MSR_EFER_XD,%ax # enable NXE 161 wrmsr 162 jmp XdDone 163SkipXd: 164 subl $4, %esp 165XdDone: 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 180CommonHandler: 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 210L16: 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 229L14: 230 movl $MSR_EFER, %ecx 231 rdmsr 232 orw $MSR_EFER_XD,%ax # enable NXE 233 wrmsr 234StmXdDone: 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 254L28: 255 testl $BIT6, %edx # Check for PAE capabilities 256 jz L29 257 orl $BIT5, %eax 258L29: 259 testl $BIT7, %edx # Check for MCE capabilities 260 jz L30 261 orl $BIT6, %eax 262L30: 263 testl $BIT24, %edx # Check for FXSR capabilities 264 jz L31 265 orl $BIT9, %eax 266L31: 267 testl $BIT25, %edx # Check for SSE capabilities 268 jz L32 269 orl $BIT10, %eax 270L32: # 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 276ASM_PFX(gcStmSmiHandlerSize) : .word . - _StmSmiEntryPoint 277ASM_PFX(gcStmSmiHandlerOffset): .word _StmSmiHandler - _StmSmiEntryPoint 278 279