1;------------------------------------------------------------------------------ ; 2; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> 3; This program and the accompanying materials 4; are licensed and made available under the terms and conditions of the BSD License 5; which accompanies this distribution. The full text of the license may be found at 6; http://opensource.org/licenses/bsd-license.php. 7; 8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 10; 11; Module Name: 12; 13; SmiEntry.nasm 14; 15; Abstract: 16; 17; Code template of the SMI handler for a particular processor 18; 19;------------------------------------------------------------------------------- 20 21; 22; Variables referrenced by C code 23; 24 25%define MSR_IA32_MISC_ENABLE 0x1A0 26%define MSR_EFER 0xc0000080 27%define MSR_EFER_XD 0x800 28 29; 30; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR 31; 32%define DSC_OFFSET 0xfb00 33%define DSC_GDTPTR 0x48 34%define DSC_GDTSIZ 0x50 35%define DSC_CS 0x14 36%define DSC_DS 0x16 37%define DSC_SS 0x18 38%define DSC_OTHERSEG 0x1a 39; 40; Constants relating to CPU State Save Area 41; 42%define SSM_DR6 0xffd0 43%define SSM_DR7 0xffc8 44 45%define PROTECT_MODE_CS 0x8 46%define PROTECT_MODE_DS 0x20 47%define LONG_MODE_CS 0x38 48%define TSS_SEGMENT 0x40 49%define GDT_SIZE 0x50 50 51extern ASM_PFX(SmiRendezvous) 52extern ASM_PFX(gStmSmiHandlerIdtr) 53extern ASM_PFX(CpuSmmDebugEntry) 54extern ASM_PFX(CpuSmmDebugExit) 55 56global ASM_PFX(gStmSmbase) 57global ASM_PFX(gStmXdSupported) 58global ASM_PFX(gStmSmiStack) 59global ASM_PFX(gStmSmiCr3) 60global ASM_PFX(gcStmSmiHandlerTemplate) 61global ASM_PFX(gcStmSmiHandlerSize) 62global ASM_PFX(gcStmSmiHandlerOffset) 63 64 DEFAULT REL 65 SECTION .text 66 67BITS 16 68ASM_PFX(gcStmSmiHandlerTemplate): 69_StmSmiEntryPoint: 70 mov bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000 71 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ] 72 dec ax 73 mov [cs:bx], ax 74 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR] 75 mov [cs:bx + 2], eax 76o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx] 77 mov ax, PROTECT_MODE_CS 78 mov [cs:bx-0x2],ax 79 DB 0x66, 0xbf ; mov edi, SMBASE 80ASM_PFX(gStmSmbase): DD 0 81 lea eax, [edi + (@ProtectedMode - _StmSmiEntryPoint) + 0x8000] 82 mov [cs:bx-0x6],eax 83 mov ebx, cr0 84 and ebx, 0x9ffafff3 85 or ebx, 0x23 86 mov cr0, ebx 87 jmp dword 0x0:0x0 88_StmGdtDesc: 89 DW 0 90 DD 0 91 92BITS 32 93@ProtectedMode: 94 mov ax, PROTECT_MODE_DS 95o16 mov ds, ax 96o16 mov es, ax 97o16 mov fs, ax 98o16 mov gs, ax 99o16 mov ss, ax 100 DB 0xbc ; mov esp, imm32 101ASM_PFX(gStmSmiStack): DD 0 102 jmp ProtFlatMode 103 104BITS 64 105ProtFlatMode: 106 DB 0xb8 ; mov eax, offset gStmSmiCr3 107ASM_PFX(gStmSmiCr3): DD 0 108 mov cr3, rax 109 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3 110 mov cr4, rax ; in PreModifyMtrrs() to flush TLB. 111; Load TSS 112 sub esp, 8 ; reserve room in stack 113 sgdt [rsp] 114 mov eax, [rsp + 2] ; eax = GDT base 115 add esp, 8 116 mov dl, 0x89 117 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag 118 mov eax, TSS_SEGMENT 119 ltr ax 120 121; enable NXE if supported 122 DB 0xb0 ; mov al, imm8 123ASM_PFX(gStmXdSupported): DB 1 124 cmp al, 0 125 jz @SkipXd 126; 127; Check XD disable bit 128; 129 mov ecx, MSR_IA32_MISC_ENABLE 130 rdmsr 131 sub esp, 4 132 push rdx ; save MSR_IA32_MISC_ENABLE[63-32] 133 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34] 134 jz .0 135 and dx, 0xFFFB ; clear XD Disable bit if it is set 136 wrmsr 137.0: 138 mov ecx, MSR_EFER 139 rdmsr 140 or ax, MSR_EFER_XD ; enable NXE 141 wrmsr 142 jmp @XdDone 143@SkipXd: 144 sub esp, 8 145@XdDone: 146 147; Switch into @LongMode 148 push LONG_MODE_CS ; push cs hardcore here 149 call Base ; push return address for retf later 150Base: 151 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg 152 153 mov ecx, MSR_EFER 154 rdmsr 155 or ah, 1 ; enable LME 156 wrmsr 157 mov rbx, cr0 158 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE 159 mov cr0, rbx 160 retf 161@LongMode: ; long mode (64-bit code) starts here 162 mov rax, ASM_PFX(gStmSmiHandlerIdtr) 163 lidt [rax] 164 lea ebx, [rdi + DSC_OFFSET] 165 mov ax, [rbx + DSC_DS] 166 mov ds, eax 167 mov ax, [rbx + DSC_OTHERSEG] 168 mov es, eax 169 mov fs, eax 170 mov gs, eax 171 mov ax, [rbx + DSC_SS] 172 mov ss, eax 173 174CommonHandler: 175 mov rbx, [rsp + 0x08] ; rbx <- CpuIndex 176 177 ; 178 ; Save FP registers 179 ; 180 sub rsp, 0x200 181 DB 0x48 ; FXSAVE64 182 fxsave [rsp] 183 184 add rsp, -0x20 185 186 mov rcx, rbx 187 mov rax, CpuSmmDebugEntry 188 call rax 189 190 mov rcx, rbx 191 mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous 192 call rax 193 194 mov rcx, rbx 195 mov rax, CpuSmmDebugExit 196 call rax 197 198 add rsp, 0x20 199 200 ; 201 ; Restore FP registers 202 ; 203 DB 0x48 ; FXRSTOR64 204 fxrstor [rsp] 205 206 add rsp, 0x200 207 208 mov rax, ASM_PFX(gStmXdSupported) 209 mov al, [rax] 210 cmp al, 0 211 jz .1 212 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32] 213 test edx, BIT2 214 jz .1 215 mov ecx, MSR_IA32_MISC_ENABLE 216 rdmsr 217 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM 218 wrmsr 219 220.1: 221 rsm 222 223_StmSmiHandler: 224; 225; Check XD disable bit 226; 227 xor r8, r8 228 mov rax, ASM_PFX(gStmXdSupported) 229 mov al, [rax] 230 cmp al, 0 231 jz @StmXdDone 232 mov ecx, MSR_IA32_MISC_ENABLE 233 rdmsr 234 mov r8, rdx ; save MSR_IA32_MISC_ENABLE[63-32] 235 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34] 236 jz .0 237 and dx, 0xFFFB ; clear XD Disable bit if it is set 238 wrmsr 239.0: 240 mov ecx, MSR_EFER 241 rdmsr 242 or ax, MSR_EFER_XD ; enable NXE 243 wrmsr 244@StmXdDone: 245 push r8 246 247 ; below step is needed, because STM does not run above code. 248 ; we have to run below code to set IDT/CR0/CR4 249 250 mov rax, ASM_PFX(gStmSmiHandlerIdtr) 251 lidt [rax] 252 253 mov rax, cr0 254 or eax, 0x80010023 ; enable paging + WP + NE + MP + PE 255 mov cr0, rax 256 mov rax, cr4 257 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3 258 mov cr4, rax ; in PreModifyMtrrs() to flush TLB. 259 ; STM init finish 260 jmp CommonHandler 261 262ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint 263ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint 264