]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / Ia32 / SmiEntry.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016 - 2019, 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 %include "StuffRsbNasm.inc"
22 %include "Nasm.inc"
23
24 %define MSR_IA32_S_CET 0x6A2
25 %define MSR_IA32_CET_SH_STK_EN 0x1
26 %define MSR_IA32_CET_WR_SHSTK_EN 0x2
27 %define MSR_IA32_CET_ENDBR_EN 0x4
28 %define MSR_IA32_CET_LEG_IW_EN 0x8
29 %define MSR_IA32_CET_NO_TRACK_EN 0x10
30 %define MSR_IA32_CET_SUPPRESS_DIS 0x20
31 %define MSR_IA32_CET_SUPPRESS 0x400
32 %define MSR_IA32_CET_TRACKER 0x800
33 %define MSR_IA32_PL0_SSP 0x6A4
34
35 %define CR4_CET 0x800000
36
37 %define MSR_IA32_MISC_ENABLE 0x1A0
38 %define MSR_EFER 0xc0000080
39 %define MSR_EFER_XD 0x800
40
41 ;
42 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
43 ;
44 %define DSC_OFFSET 0xfb00
45 %define DSC_GDTPTR 0x30
46 %define DSC_GDTSIZ 0x38
47 %define DSC_CS 14
48 %define DSC_DS 16
49 %define DSC_SS 18
50 %define DSC_OTHERSEG 20
51
52 %define PROTECT_MODE_CS 0x8
53 %define PROTECT_MODE_DS 0x20
54 %define TSS_SEGMENT 0x40
55
56 extern ASM_PFX(SmiRendezvous)
57 extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
58 extern ASM_PFX(CpuSmmDebugEntry)
59 extern ASM_PFX(CpuSmmDebugExit)
60
61 global ASM_PFX(gcSmiHandlerTemplate)
62 global ASM_PFX(gcSmiHandlerSize)
63 global ASM_PFX(gPatchSmiCr3)
64 global ASM_PFX(gPatchSmiStack)
65 global ASM_PFX(gPatchSmbase)
66 extern ASM_PFX(mXdSupported)
67 global ASM_PFX(gPatchXdSupported)
68 extern ASM_PFX(gSmiHandlerIdtr)
69
70 extern ASM_PFX(mCetSupported)
71 global ASM_PFX(mPatchCetSupported)
72 global ASM_PFX(mPatchCetPl0Ssp)
73 global ASM_PFX(mPatchCetInterruptSsp)
74
75 SECTION .text
76
77 BITS 16
78 ASM_PFX(gcSmiHandlerTemplate):
79 _SmiEntryPoint:
80 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
81 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
82 dec ax
83 mov [cs:bx], ax
84 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
85 mov [cs:bx + 2], eax
86 mov ebp, eax ; ebp = GDT base
87 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
88 mov ax, PROTECT_MODE_CS
89 mov [cs:bx-0x2],ax
90 mov edi, strict dword 0 ; source operand will be patched
91 ASM_PFX(gPatchSmbase):
92 lea eax, [edi + (@32bit - _SmiEntryPoint) + 0x8000]
93 mov [cs:bx-0x6],eax
94 mov ebx, cr0
95 and ebx, 0x9ffafff3
96 or ebx, 0x23
97 mov cr0, ebx
98 jmp dword 0x0:0x0
99 _GdtDesc:
100 DW 0
101 DD 0
102
103 BITS 32
104 @32bit:
105 mov ax, PROTECT_MODE_DS
106 o16 mov ds, ax
107 o16 mov es, ax
108 o16 mov fs, ax
109 o16 mov gs, ax
110 o16 mov ss, ax
111 mov esp, strict dword 0 ; source operand will be patched
112 ASM_PFX(gPatchSmiStack):
113 mov eax, ASM_PFX(gSmiHandlerIdtr)
114 lidt [eax]
115 jmp ProtFlatMode
116
117 ProtFlatMode:
118 mov eax, strict dword 0 ; source operand will be patched
119 ASM_PFX(gPatchSmiCr3):
120 mov cr3, eax
121 ;
122 ; Need to test for CR4 specific bit support
123 ;
124 mov eax, 1
125 cpuid ; use CPUID to determine if specific CR4 bits are supported
126 xor eax, eax ; Clear EAX
127 test edx, BIT2 ; Check for DE capabilities
128 jz .0
129 or eax, BIT3
130 .0:
131 test edx, BIT6 ; Check for PAE capabilities
132 jz .1
133 or eax, BIT5
134 .1:
135 test edx, BIT7 ; Check for MCE capabilities
136 jz .2
137 or eax, BIT6
138 .2:
139 test edx, BIT24 ; Check for FXSR capabilities
140 jz .3
141 or eax, BIT9
142 .3:
143 test edx, BIT25 ; Check for SSE capabilities
144 jz .4
145 or eax, BIT10
146 .4: ; as cr4.PGE is not set here, refresh cr3
147 mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
148
149 cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
150 jz .6
151 ; Load TSS
152 mov byte [ebp + TSS_SEGMENT + 5], 0x89 ; clear busy flag
153 mov eax, TSS_SEGMENT
154 ltr ax
155 .6:
156
157 ; enable NXE if supported
158 mov al, strict byte 1 ; source operand may be patched
159 ASM_PFX(gPatchXdSupported):
160 cmp al, 0
161 jz @SkipXd
162 ;
163 ; Check XD disable bit
164 ;
165 mov ecx, MSR_IA32_MISC_ENABLE
166 rdmsr
167 push edx ; save MSR_IA32_MISC_ENABLE[63-32]
168 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
169 jz .5
170 and dx, 0xFFFB ; clear XD Disable bit if it is set
171 wrmsr
172 .5:
173 mov ecx, MSR_EFER
174 rdmsr
175 or ax, MSR_EFER_XD ; enable NXE
176 wrmsr
177 jmp @XdDone
178 @SkipXd:
179 sub esp, 4
180 @XdDone:
181
182 mov ebx, cr0
183 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
184 mov cr0, ebx
185 lea ebx, [edi + DSC_OFFSET]
186 mov ax, [ebx + DSC_DS]
187 mov ds, eax
188 mov ax, [ebx + DSC_OTHERSEG]
189 mov es, eax
190 mov fs, eax
191 mov gs, eax
192 mov ax, [ebx + DSC_SS]
193 mov ss, eax
194
195 mov ebx, [esp + 4] ; ebx <- CpuIndex
196
197 ; enable CET if supported
198 mov al, strict byte 1 ; source operand may be patched
199 ASM_PFX(mPatchCetSupported):
200 cmp al, 0
201 jz CetDone
202
203 mov ecx, MSR_IA32_S_CET
204 rdmsr
205 push edx
206 push eax
207
208 mov ecx, MSR_IA32_PL0_SSP
209 rdmsr
210 push edx
211 push eax
212
213 mov ecx, MSR_IA32_S_CET
214 mov eax, MSR_IA32_CET_SH_STK_EN
215 xor edx, edx
216 wrmsr
217
218 mov ecx, MSR_IA32_PL0_SSP
219 mov eax, strict dword 0 ; source operand will be patched
220 ASM_PFX(mPatchCetPl0Ssp):
221 xor edx, edx
222 wrmsr
223 mov ecx, cr0
224 btr ecx, 16 ; clear WP
225 mov cr0, ecx
226 mov [eax], eax ; reload SSP, and clear busyflag.
227 xor ecx, ecx
228 mov [eax + 4], ecx
229
230 mov eax, strict dword 0 ; source operand will be patched
231 ASM_PFX(mPatchCetInterruptSsp):
232 cmp eax, 0
233 jz CetInterruptDone
234 mov [eax], eax ; reload SSP, and clear busyflag.
235 xor ecx, ecx
236 mov [eax + 4], ecx
237 CetInterruptDone:
238
239 mov ecx, cr0
240 bts ecx, 16 ; set WP
241 mov cr0, ecx
242
243 mov eax, 0x668 | CR4_CET
244 mov cr4, eax
245
246 SETSSBSY
247
248 CetDone:
249
250 push ebx
251 mov eax, ASM_PFX(CpuSmmDebugEntry)
252 call eax
253 add esp, 4
254
255 push ebx
256 mov eax, ASM_PFX(SmiRendezvous)
257 call eax
258 add esp, 4
259
260 push ebx
261 mov eax, ASM_PFX(CpuSmmDebugExit)
262 call eax
263 add esp, 4
264
265 mov eax, ASM_PFX(mCetSupported)
266 mov al, [eax]
267 cmp al, 0
268 jz CetDone2
269
270 mov eax, 0x668
271 mov cr4, eax ; disable CET
272
273 mov ecx, MSR_IA32_PL0_SSP
274 pop eax
275 pop edx
276 wrmsr
277
278 mov ecx, MSR_IA32_S_CET
279 pop eax
280 pop edx
281 wrmsr
282 CetDone2:
283
284 mov eax, ASM_PFX(mXdSupported)
285 mov al, [eax]
286 cmp al, 0
287 jz .7
288 pop edx ; get saved MSR_IA32_MISC_ENABLE[63-32]
289 test edx, BIT2
290 jz .7
291 mov ecx, MSR_IA32_MISC_ENABLE
292 rdmsr
293 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
294 wrmsr
295
296 .7:
297
298 StuffRsb32
299 rsm
300
301 ASM_PFX(gcSmiHandlerSize): DW $ - _SmiEntryPoint
302
303 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
304 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
305 ret