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 %define MSR_IA32_MISC_ENABLE 0x1A0 22 %define MSR_EFER 0xc0000080 23 %define MSR_EFER_XD 0x800 24 25 ; 26 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR 27 ; 28 %define DSC_OFFSET 0xfb00 29 %define DSC_GDTPTR 0x30 30 %define DSC_GDTSIZ 0x38 31 %define DSC_CS 14 32 %define DSC_DS 16 33 %define DSC_SS 18 34 %define DSC_OTHERSEG 20 35 36 %define PROTECT_MODE_CS 0x8 37 %define PROTECT_MODE_DS 0x20 38 %define TSS_SEGMENT 0x40 39 40 extern ASM_PFX(SmiRendezvous) 41 extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard)) 42 extern ASM_PFX(CpuSmmDebugEntry) 43 extern ASM_PFX(CpuSmmDebugExit) 44 45 global ASM_PFX(gcSmiHandlerTemplate) 46 global ASM_PFX(gcSmiHandlerSize) 47 global ASM_PFX(gSmiCr3) 48 global ASM_PFX(gSmiStack) 49 global ASM_PFX(gSmbase) 50 global ASM_PFX(mXdSupported) 51 extern ASM_PFX(gSmiHandlerIdtr) 52 53 SECTION .text 54 55 BITS 16 56 ASM_PFX(gcSmiHandlerTemplate): 57 _SmiEntryPoint: 58 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000 59 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ] 60 dec ax 61 mov [cs:bx], ax 62 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR] 63 mov [cs:bx + 2], eax 64 mov ebp, eax ; ebp = GDT base 65 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx] 66 mov ax, PROTECT_MODE_CS 67 mov [cs:bx-0x2],ax 68 DB 0x66, 0xbf ; mov edi, SMBASE 69 ASM_PFX(gSmbase): DD 0 70 lea eax, [edi + (@32bit - _SmiEntryPoint) + 0x8000] 71 mov [cs:bx-0x6],eax 72 mov ebx, cr0 73 and ebx, 0x9ffafff3 74 or ebx, 0x23 75 mov cr0, ebx 76 jmp dword 0x0:0x0 77 _GdtDesc: 78 DW 0 79 DD 0 80 81 BITS 32 82 @32bit: 83 mov ax, PROTECT_MODE_DS 84 o16 mov ds, ax 85 o16 mov es, ax 86 o16 mov fs, ax 87 o16 mov gs, ax 88 o16 mov ss, ax 89 DB 0xbc ; mov esp, imm32 90 ASM_PFX(gSmiStack): DD 0 91 mov eax, ASM_PFX(gSmiHandlerIdtr) 92 lidt [eax] 93 jmp ProtFlatMode 94 95 ProtFlatMode: 96 DB 0xb8 ; mov eax, imm32 97 ASM_PFX(gSmiCr3): DD 0 98 mov cr3, eax 99 ; 100 ; Need to test for CR4 specific bit support 101 ; 102 mov eax, 1 103 cpuid ; use CPUID to determine if specific CR4 bits are supported 104 xor eax, eax ; Clear EAX 105 test edx, BIT2 ; Check for DE capabilities 106 jz .0 107 or eax, BIT3 108 .0: 109 test edx, BIT6 ; Check for PAE capabilities 110 jz .1 111 or eax, BIT5 112 .1: 113 test edx, BIT7 ; Check for MCE capabilities 114 jz .2 115 or eax, BIT6 116 .2: 117 test edx, BIT24 ; Check for FXSR capabilities 118 jz .3 119 or eax, BIT9 120 .3: 121 test edx, BIT25 ; Check for SSE capabilities 122 jz .4 123 or eax, BIT10 124 .4: ; as cr4.PGE is not set here, refresh cr3 125 mov cr4, eax ; in PreModifyMtrrs() to flush TLB. 126 127 cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0 128 jz .6 129 ; Load TSS 130 mov byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag 131 mov eax, TSS_SEGMENT 132 ltr ax 133 .6: 134 135 ; enable NXE if supported 136 DB 0b0h ; mov al, imm8 137 ASM_PFX(mXdSupported): DB 1 138 cmp al, 0 139 jz @SkipXd 140 ; 141 ; Check XD disable bit 142 ; 143 mov ecx, MSR_IA32_MISC_ENABLE 144 rdmsr 145 push edx ; save MSR_IA32_MISC_ENABLE[63-32] 146 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34] 147 jz .5 148 and dx, 0xFFFB ; clear XD Disable bit if it is set 149 wrmsr 150 .5: 151 mov ecx, MSR_EFER 152 rdmsr 153 or ax, MSR_EFER_XD ; enable NXE 154 wrmsr 155 jmp @XdDone 156 @SkipXd: 157 sub esp, 4 158 @XdDone: 159 160 mov ebx, cr0 161 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE 162 mov cr0, ebx 163 lea ebx, [edi + DSC_OFFSET] 164 mov ax, [ebx + DSC_DS] 165 mov ds, eax 166 mov ax, [ebx + DSC_OTHERSEG] 167 mov es, eax 168 mov fs, eax 169 mov gs, eax 170 mov ax, [ebx + DSC_SS] 171 mov ss, eax 172 173 ; jmp _SmiHandler ; instruction is not needed 174 175 global ASM_PFX(SmiHandler) 176 ASM_PFX(SmiHandler): 177 mov ebx, [esp + 4] ; CPU Index 178 push ebx 179 mov eax, ASM_PFX(CpuSmmDebugEntry) 180 call eax 181 add esp, 4 182 183 push ebx 184 mov eax, ASM_PFX(SmiRendezvous) 185 call eax 186 add esp, 4 187 188 push ebx 189 mov eax, ASM_PFX(CpuSmmDebugExit) 190 call eax 191 add esp, 4 192 193 mov eax, ASM_PFX(mXdSupported) 194 mov al, [eax] 195 cmp al, 0 196 jz .7 197 pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32] 198 test edx, BIT2 199 jz .7 200 mov ecx, MSR_IA32_MISC_ENABLE 201 rdmsr 202 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM 203 wrmsr 204 205 .7: 206 rsm 207 208 ASM_PFX(gcSmiHandlerSize): DW $ - _SmiEntryPoint 209 210