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