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(gcStmSmiHandlerTemplate) 23 ASM_GLOBAL ASM_PFX(gcStmSmiHandlerSize) 24 ASM_GLOBAL ASM_PFX(gcStmSmiHandlerOffset) 25 ASM_GLOBAL ASM_PFX(gStmSmiCr3) 26 ASM_GLOBAL ASM_PFX(gStmSmiStack) 27 ASM_GLOBAL ASM_PFX(gStmSmbase) 28 ASM_GLOBAL ASM_PFX(gStmXdSupported) 29 ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard)) 30 ASM_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 52 ASM_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 73 ASM_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 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(gStmSmiStack): .space 4 98 movl $ASM_PFX(gStmSmiHandlerIdtr), %eax 99 lidt (%eax) 100 jmp ProtFlatMode 101 102 ProtFlatMode: 103 .byte 0xb8 # mov eax, imm32 104 ASM_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 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(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 157 L13: 158 movl $MSR_EFER, %ecx 159 rdmsr 160 orw $MSR_EFER_XD,%ax # enable NXE 161 wrmsr 162 jmp XdDone 163 SkipXd: 164 subl $4, %esp 165 XdDone: 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 180 CommonHandler: 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 210 L16: 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 229 L14: 230 movl $MSR_EFER, %ecx 231 rdmsr 232 orw $MSR_EFER_XD,%ax # enable NXE 233 wrmsr 234 StmXdDone: 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 254 L28: 255 testl $BIT6, %edx # Check for PAE capabilities 256 jz L29 257 orl $BIT5, %eax 258 L29: 259 testl $BIT7, %edx # Check for MCE capabilities 260 jz L30 261 orl $BIT6, %eax 262 L30: 263 testl $BIT24, %edx # Check for FXSR capabilities 264 jz L31 265 orl $BIT9, %eax 266 L31: 267 testl $BIT25, %edx # Check for SSE capabilities 268 jz L32 269 orl $BIT10, %eax 270 L32: # 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 276 ASM_PFX(gcStmSmiHandlerSize) : .word . - _StmSmiEntryPoint 277 ASM_PFX(gcStmSmiHandlerOffset): .word _StmSmiHandler - _StmSmiEntryPoint 278 279