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 PROCESSOR_SMM_DESCRIPTOR 31; 32%define DSC_OFFSET 0xfb00 33%define DSC_GDTPTR 0x30 34%define DSC_GDTSIZ 0x38 35%define DSC_CS 14 36%define DSC_DS 16 37%define DSC_SS 18 38%define DSC_OTHERSEG 20 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(gSmiHandlerIdtr) 53extern ASM_PFX(CpuSmmDebugEntry) 54extern ASM_PFX(CpuSmmDebugExit) 55 56global ASM_PFX(gSmbase) 57global ASM_PFX(mXdSupported) 58global ASM_PFX(gSmiStack) 59global ASM_PFX(gSmiCr3) 60global ASM_PFX(gcSmiHandlerTemplate) 61global ASM_PFX(gcSmiHandlerSize) 62 63 DEFAULT REL 64 SECTION .text 65 66BITS 16 67ASM_PFX(gcSmiHandlerTemplate): 68_SmiEntryPoint: 69 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000 70 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ] 71 dec ax 72 mov [cs:bx], ax 73 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR] 74 mov [cs:bx + 2], eax 75o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx] 76 mov ax, PROTECT_MODE_CS 77 mov [cs:bx-0x2],ax 78 DB 0x66, 0xbf ; mov edi, SMBASE 79ASM_PFX(gSmbase): DD 0 80 lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000] 81 mov [cs:bx-0x6],eax 82 mov ebx, cr0 83 and ebx, 0x9ffafff3 84 or ebx, 0x23 85 mov cr0, ebx 86 jmp dword 0x0:0x0 87_GdtDesc: 88 DW 0 89 DD 0 90 91BITS 32 92@ProtectedMode: 93 mov ax, PROTECT_MODE_DS 94o16 mov ds, ax 95o16 mov es, ax 96o16 mov fs, ax 97o16 mov gs, ax 98o16 mov ss, ax 99 DB 0xbc ; mov esp, imm32 100ASM_PFX(gSmiStack): DD 0 101 jmp ProtFlatMode 102 103BITS 64 104ProtFlatMode: 105 DB 0xb8 ; mov eax, offset gSmiCr3 106ASM_PFX(gSmiCr3): DD 0 107 mov cr3, rax 108 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3 109 mov cr4, rax ; in PreModifyMtrrs() to flush TLB. 110; Load TSS 111 sub esp, 8 ; reserve room in stack 112 sgdt [rsp] 113 mov eax, [rsp + 2] ; eax = GDT base 114 add esp, 8 115 mov dl, 0x89 116 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag 117 mov eax, TSS_SEGMENT 118 ltr ax 119 120; enable NXE if supported 121 DB 0xb0 ; mov al, imm8 122ASM_PFX(mXdSupported): DB 1 123 cmp al, 0 124 jz @SkipXd 125; 126; Check XD disable bit 127; 128 mov ecx, MSR_IA32_MISC_ENABLE 129 rdmsr 130 sub esp, 4 131 push rdx ; save MSR_IA32_MISC_ENABLE[63-32] 132 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34] 133 jz .0 134 and dx, 0xFFFB ; clear XD Disable bit if it is set 135 wrmsr 136.0: 137 mov ecx, MSR_EFER 138 rdmsr 139 or ax, MSR_EFER_XD ; enable NXE 140 wrmsr 141 jmp @XdDone 142@SkipXd: 143 sub esp, 8 144@XdDone: 145 146; Switch into @LongMode 147 push LONG_MODE_CS ; push cs hardcore here 148 call Base ; push return address for retf later 149Base: 150 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg 151 152 mov ecx, MSR_EFER 153 rdmsr 154 or ah, 1 ; enable LME 155 wrmsr 156 mov rbx, cr0 157 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE 158 mov cr0, rbx 159 retf 160@LongMode: ; long mode (64-bit code) starts here 161 mov rax, ASM_PFX(gSmiHandlerIdtr) 162 lidt [rax] 163 lea ebx, [rdi + DSC_OFFSET] 164 mov ax, [rbx + DSC_DS] 165 mov ds, eax 166 mov ax, [rbx + DSC_OTHERSEG] 167 mov es, eax 168 mov fs, eax 169 mov gs, eax 170 mov ax, [rbx + DSC_SS] 171 mov ss, eax 172; jmp _SmiHandler ; instruction is not needed 173 174_SmiHandler: 175 mov rbx, [rsp + 0x8] ; rcx <- 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(mXdSupported) 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 223gcSmiHandlerSize DW $ - _SmiEntryPoint 224 225