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 51 extern ASM_PFX(SmiRendezvous) 52 extern ASM_PFX(gSmiHandlerIdtr) 53 extern ASM_PFX(CpuSmmDebugEntry) 54 extern ASM_PFX(CpuSmmDebugExit) 55 56 global ASM_PFX(gSmbase) 57 global ASM_PFX(mXdSupported) 58 global ASM_PFX(gSmiStack) 59 global ASM_PFX(gSmiCr3) 60 global ASM_PFX(gcSmiHandlerTemplate) 61 global ASM_PFX(gcSmiHandlerSize) 62 63 DEFAULT REL 64 SECTION .text 65 66 BITS 16 67 ASM_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 75 o32 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 79 ASM_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 91 BITS 32 92 @ProtectedMode: 93 mov ax, PROTECT_MODE_DS 94 o16 mov ds, ax 95 o16 mov es, ax 96 o16 mov fs, ax 97 o16 mov gs, ax 98 o16 mov ss, ax 99 DB 0xbc ; mov esp, imm32 100 ASM_PFX(gSmiStack): DD 0 101 jmp ProtFlatMode 102 103 BITS 64 104 ProtFlatMode: 105 DB 0xb8 ; mov eax, offset gSmiCr3 106 ASM_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 122 ASM_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 149 Base: 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 223 gcSmiHandlerSize DW $ - _SmiEntryPoint 224 225