1;------------------------------------------------------------------------------ ; 2; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR> 3; SPDX-License-Identifier: BSD-2-Clause-Patent 4; 5; Module Name: 6; 7; SmiEntry.nasm 8; 9; Abstract: 10; 11; Code template of the SMI handler for a particular processor 12; 13;------------------------------------------------------------------------------- 14 15%include "StuffRsbNasm.inc" 16 17%define MSR_IA32_MISC_ENABLE 0x1A0 18%define MSR_EFER 0xc0000080 19%define MSR_EFER_XD 0x800 20 21; 22; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR 23; 24%define DSC_OFFSET 0xfb00 25%define DSC_GDTPTR 0x48 26%define DSC_GDTSIZ 0x50 27%define DSC_CS 0x14 28%define DSC_DS 0x16 29%define DSC_SS 0x18 30%define DSC_OTHERSEG 0x1a 31 32%define PROTECT_MODE_CS 0x8 33%define PROTECT_MODE_DS 0x20 34%define TSS_SEGMENT 0x40 35 36extern ASM_PFX(SmiRendezvous) 37extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard)) 38extern ASM_PFX(CpuSmmDebugEntry) 39extern ASM_PFX(CpuSmmDebugExit) 40 41global ASM_PFX(gcStmSmiHandlerTemplate) 42global ASM_PFX(gcStmSmiHandlerSize) 43global ASM_PFX(gcStmSmiHandlerOffset) 44global ASM_PFX(gStmSmiCr3) 45global ASM_PFX(gStmSmiStack) 46global ASM_PFX(gStmSmbase) 47global ASM_PFX(gStmXdSupported) 48extern ASM_PFX(gStmSmiHandlerIdtr) 49 50ASM_PFX(gStmSmiCr3) EQU StmSmiCr3Patch - 4 51ASM_PFX(gStmSmiStack) EQU StmSmiStackPatch - 4 52ASM_PFX(gStmSmbase) EQU StmSmbasePatch - 4 53ASM_PFX(gStmXdSupported) EQU StmXdSupportedPatch - 1 54 55 SECTION .text 56 57BITS 16 58ASM_PFX(gcStmSmiHandlerTemplate): 59_StmSmiEntryPoint: 60 mov bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000 61 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ] 62 dec ax 63 mov [cs:bx], ax 64 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR] 65 mov [cs:bx + 2], eax 66 mov ebp, eax ; ebp = GDT base 67o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx] 68 mov ax, PROTECT_MODE_CS 69 mov [cs:bx-0x2],ax 70o32 mov edi, strict dword 0 71StmSmbasePatch: 72 lea eax, [edi + (@32bit - _StmSmiEntryPoint) + 0x8000] 73 mov [cs:bx-0x6],eax 74 mov ebx, cr0 75 and ebx, 0x9ffafff3 76 or ebx, 0x23 77 mov cr0, ebx 78 jmp dword 0x0:0x0 79_StmGdtDesc: 80 DW 0 81 DD 0 82 83BITS 32 84@32bit: 85 mov ax, PROTECT_MODE_DS 86o16 mov ds, ax 87o16 mov es, ax 88o16 mov fs, ax 89o16 mov gs, ax 90o16 mov ss, ax 91 mov esp, strict dword 0 92StmSmiStackPatch: 93 mov eax, ASM_PFX(gStmSmiHandlerIdtr) 94 lidt [eax] 95 jmp ProtFlatMode 96 97ProtFlatMode: 98 mov eax, strict dword 0 99StmSmiCr3Patch: 100 mov cr3, eax 101; 102; Need to test for CR4 specific bit support 103; 104 mov eax, 1 105 cpuid ; use CPUID to determine if specific CR4 bits are supported 106 xor eax, eax ; Clear EAX 107 test edx, BIT2 ; Check for DE capabilities 108 jz .0 109 or eax, BIT3 110.0: 111 test edx, BIT6 ; Check for PAE capabilities 112 jz .1 113 or eax, BIT5 114.1: 115 test edx, BIT7 ; Check for MCE capabilities 116 jz .2 117 or eax, BIT6 118.2: 119 test edx, BIT24 ; Check for FXSR capabilities 120 jz .3 121 or eax, BIT9 122.3: 123 test edx, BIT25 ; Check for SSE capabilities 124 jz .4 125 or eax, BIT10 126.4: ; as cr4.PGE is not set here, refresh cr3 127 mov cr4, eax ; in PreModifyMtrrs() to flush TLB. 128 129 cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0 130 jz .6 131; Load TSS 132 mov byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag 133 mov eax, TSS_SEGMENT 134 ltr ax 135.6: 136 137; enable NXE if supported 138 mov al, strict byte 1 139StmXdSupportedPatch: 140 cmp al, 0 141 jz @SkipXd 142; 143; Check XD disable bit 144; 145 mov ecx, MSR_IA32_MISC_ENABLE 146 rdmsr 147 push edx ; save MSR_IA32_MISC_ENABLE[63-32] 148 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34] 149 jz .5 150 and dx, 0xFFFB ; clear XD Disable bit if it is set 151 wrmsr 152.5: 153 mov ecx, MSR_EFER 154 rdmsr 155 or ax, MSR_EFER_XD ; enable NXE 156 wrmsr 157 jmp @XdDone 158@SkipXd: 159 sub esp, 4 160@XdDone: 161 162 mov ebx, cr0 163 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE 164 mov cr0, ebx 165 lea ebx, [edi + DSC_OFFSET] 166 mov ax, [ebx + DSC_DS] 167 mov ds, eax 168 mov ax, [ebx + DSC_OTHERSEG] 169 mov es, eax 170 mov fs, eax 171 mov gs, eax 172 mov ax, [ebx + DSC_SS] 173 mov ss, eax 174 175CommonHandler: 176 mov ebx, [esp + 4] ; CPU Index 177 push ebx 178 mov eax, ASM_PFX(CpuSmmDebugEntry) 179 call eax 180 add esp, 4 181 182 push ebx 183 mov eax, ASM_PFX(SmiRendezvous) 184 call eax 185 add esp, 4 186 187 push ebx 188 mov eax, ASM_PFX(CpuSmmDebugExit) 189 call eax 190 add esp, 4 191 192 mov eax, ASM_PFX(gStmXdSupported) 193 mov al, [eax] 194 cmp al, 0 195 jz .7 196 pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32] 197 test edx, BIT2 198 jz .7 199 mov ecx, MSR_IA32_MISC_ENABLE 200 rdmsr 201 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM 202 wrmsr 203 204.7: 205 StuffRsb32 206 rsm 207 208 209_StmSmiHandler: 210; 211; Check XD disable bit 212; 213 xor esi, esi 214 mov eax, ASM_PFX(gStmXdSupported) 215 mov al, [eax] 216 cmp al, 0 217 jz @StmXdDone 218 mov ecx, MSR_IA32_MISC_ENABLE 219 rdmsr 220 mov esi, edx ; save MSR_IA32_MISC_ENABLE[63-32] 221 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34] 222 jz .5 223 and dx, 0xFFFB ; clear XD Disable bit if it is set 224 wrmsr 225.5: 226 mov ecx, MSR_EFER 227 rdmsr 228 or ax, MSR_EFER_XD ; enable NXE 229 wrmsr 230@StmXdDone: 231 push esi 232 233 ; below step is needed, because STM does not run above code. 234 ; we have to run below code to set IDT/CR0/CR4 235 mov eax, ASM_PFX(gStmSmiHandlerIdtr) 236 lidt [eax] 237 238 mov eax, cr0 239 or eax, 0x80010023 ; enable paging + WP + NE + MP + PE 240 mov cr0, eax 241; 242; Need to test for CR4 specific bit support 243; 244 mov eax, 1 245 cpuid ; use CPUID to determine if specific CR4 bits are supported 246 mov eax, cr4 ; init EAX 247 test edx, BIT2 ; Check for DE capabilities 248 jz .0 249 or eax, BIT3 250.0: 251 test edx, BIT6 ; Check for PAE capabilities 252 jz .1 253 or eax, BIT5 254.1: 255 test edx, BIT7 ; Check for MCE capabilities 256 jz .2 257 or eax, BIT6 258.2: 259 test edx, BIT24 ; Check for FXSR capabilities 260 jz .3 261 or eax, BIT9 262.3: 263 test edx, BIT25 ; Check for SSE capabilities 264 jz .4 265 or eax, BIT10 266.4: ; as cr4.PGE is not set here, refresh cr3 267 mov cr4, eax ; in PreModifyMtrrs() to flush TLB. 268 ; STM init finish 269 jmp CommonHandler 270 271ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint 272ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint 273 274global ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress) 275ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress): 276 ret 277