]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiEntry.nasm
CommitLineData
9a36d4dc 1;------------------------------------------------------------------------------ ;\r
3eb69b08 2; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
9a36d4dc
LG
3; This program and the accompanying materials\r
4; are licensed and made available under the terms and conditions of the BSD License\r
5; which accompanies this distribution. The full text of the license may be found at\r
6; http://opensource.org/licenses/bsd-license.php.\r
7;\r
8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10;\r
11; Module Name:\r
12;\r
13; SmiEntry.nasm\r
14;\r
15; Abstract:\r
16;\r
17; Code template of the SMI handler for a particular processor\r
18;\r
19;-------------------------------------------------------------------------------\r
20\r
ada4a003 21%include "StuffRsbNasm.inc"\r
3eb69b08 22%include "Nasm.inc"\r
02f7fd15 23\r
9a36d4dc
LG
24;\r
25; Variables referrenced by C code\r
26;\r
27\r
3eb69b08
JY
28%define MSR_IA32_S_CET 0x6A2\r
29%define MSR_IA32_CET_SH_STK_EN 0x1\r
30%define MSR_IA32_CET_WR_SHSTK_EN 0x2\r
31%define MSR_IA32_CET_ENDBR_EN 0x4\r
32%define MSR_IA32_CET_LEG_IW_EN 0x8\r
33%define MSR_IA32_CET_NO_TRACK_EN 0x10\r
34%define MSR_IA32_CET_SUPPRESS_DIS 0x20\r
35%define MSR_IA32_CET_SUPPRESS 0x400\r
36%define MSR_IA32_CET_TRACKER 0x800\r
37%define MSR_IA32_PL0_SSP 0x6A4\r
38%define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR 0x6A8\r
39\r
40%define CR4_CET 0x800000\r
41\r
717fb604
JY
42%define MSR_IA32_MISC_ENABLE 0x1A0\r
43%define MSR_EFER 0xc0000080\r
44%define MSR_EFER_XD 0x800\r
45\r
9a36d4dc
LG
46;\r
47; Constants relating to PROCESSOR_SMM_DESCRIPTOR\r
48;\r
49%define DSC_OFFSET 0xfb00\r
50%define DSC_GDTPTR 0x30\r
51%define DSC_GDTSIZ 0x38\r
52%define DSC_CS 14\r
53%define DSC_DS 16\r
54%define DSC_SS 18\r
55%define DSC_OTHERSEG 20\r
56;\r
57; Constants relating to CPU State Save Area\r
58;\r
59%define SSM_DR6 0xffd0\r
60%define SSM_DR7 0xffc8\r
61\r
62%define PROTECT_MODE_CS 0x8\r
63%define PROTECT_MODE_DS 0x20\r
64%define LONG_MODE_CS 0x38\r
65%define TSS_SEGMENT 0x40\r
66%define GDT_SIZE 0x50\r
67\r
68extern ASM_PFX(SmiRendezvous)\r
69extern ASM_PFX(gSmiHandlerIdtr)\r
70extern ASM_PFX(CpuSmmDebugEntry)\r
71extern ASM_PFX(CpuSmmDebugExit)\r
72\r
5a1bfda4 73global ASM_PFX(gPatchSmbase)\r
3c5ce64f
LE
74extern ASM_PFX(mXdSupported)\r
75global ASM_PFX(gPatchXdSupported)\r
fc504fde 76global ASM_PFX(gPatchSmiStack)\r
c455687f 77global ASM_PFX(gPatchSmiCr3)\r
9a36d4dc
LG
78global ASM_PFX(gcSmiHandlerTemplate)\r
79global ASM_PFX(gcSmiHandlerSize)\r
80\r
3eb69b08
JY
81extern ASM_PFX(mCetSupported)\r
82global ASM_PFX(mPatchCetSupported)\r
83global ASM_PFX(mPatchCetPl0Ssp)\r
84global ASM_PFX(mPatchCetInterruptSsp)\r
85global ASM_PFX(mPatchCetInterruptSspTable)\r
86\r
9a36d4dc
LG
87 DEFAULT REL\r
88 SECTION .text\r
89\r
90BITS 16\r
91ASM_PFX(gcSmiHandlerTemplate):\r
92_SmiEntryPoint:\r
93 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000\r
94 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]\r
95 dec ax\r
96 mov [cs:bx], ax\r
97 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]\r
98 mov [cs:bx + 2], eax\r
99o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]\r
100 mov ax, PROTECT_MODE_CS\r
717fb604 101 mov [cs:bx-0x2],ax\r
5a1bfda4
LE
102 mov edi, strict dword 0 ; source operand will be patched\r
103ASM_PFX(gPatchSmbase):\r
9a36d4dc
LG
104 lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000]\r
105 mov [cs:bx-0x6],eax\r
106 mov ebx, cr0\r
107 and ebx, 0x9ffafff3\r
108 or ebx, 0x23\r
109 mov cr0, ebx\r
110 jmp dword 0x0:0x0\r
717fb604 111_GdtDesc:\r
9a36d4dc
LG
112 DW 0\r
113 DD 0\r
114\r
115BITS 32\r
116@ProtectedMode:\r
117 mov ax, PROTECT_MODE_DS\r
118o16 mov ds, ax\r
119o16 mov es, ax\r
120o16 mov fs, ax\r
121o16 mov gs, ax\r
122o16 mov ss, ax\r
fc504fde
LE
123 mov esp, strict dword 0 ; source operand will be patched\r
124ASM_PFX(gPatchSmiStack):\r
9a36d4dc
LG
125 jmp ProtFlatMode\r
126\r
127BITS 64\r
128ProtFlatMode:\r
c455687f
LE
129 mov eax, strict dword 0 ; source operand will be patched\r
130ASM_PFX(gPatchSmiCr3):\r
9a36d4dc
LG
131 mov cr3, rax\r
132 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3\r
133 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.\r
134; Load TSS\r
135 sub esp, 8 ; reserve room in stack\r
136 sgdt [rsp]\r
137 mov eax, [rsp + 2] ; eax = GDT base\r
138 add esp, 8\r
139 mov dl, 0x89\r
140 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag\r
141 mov eax, TSS_SEGMENT\r
142 ltr ax\r
143\r
717fb604 144; enable NXE if supported\r
3c5ce64f
LE
145 mov al, strict byte 1 ; source operand may be patched\r
146ASM_PFX(gPatchXdSupported):\r
717fb604
JY
147 cmp al, 0\r
148 jz @SkipXd\r
149;\r
150; Check XD disable bit\r
151;\r
152 mov ecx, MSR_IA32_MISC_ENABLE\r
153 rdmsr\r
154 sub esp, 4\r
155 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]\r
156 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]\r
157 jz .0\r
158 and dx, 0xFFFB ; clear XD Disable bit if it is set\r
159 wrmsr\r
160.0:\r
161 mov ecx, MSR_EFER\r
162 rdmsr\r
163 or ax, MSR_EFER_XD ; enable NXE\r
164 wrmsr\r
165 jmp @XdDone\r
166@SkipXd:\r
167 sub esp, 8\r
168@XdDone:\r
169\r
9a36d4dc
LG
170; Switch into @LongMode\r
171 push LONG_MODE_CS ; push cs hardcore here\r
717fb604 172 call Base ; push return address for retf later\r
9a36d4dc
LG
173Base:\r
174 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg\r
717fb604
JY
175\r
176 mov ecx, MSR_EFER\r
9a36d4dc 177 rdmsr\r
717fb604 178 or ah, 1 ; enable LME\r
9a36d4dc
LG
179 wrmsr\r
180 mov rbx, cr0\r
717fb604 181 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE\r
9a36d4dc
LG
182 mov cr0, rbx\r
183 retf\r
184@LongMode: ; long mode (64-bit code) starts here\r
e21e355e
LG
185 mov rax, strict qword 0 ; mov rax, ASM_PFX(gSmiHandlerIdtr)\r
186SmiHandlerIdtrAbsAddr:\r
9a36d4dc
LG
187 lidt [rax]\r
188 lea ebx, [rdi + DSC_OFFSET]\r
189 mov ax, [rbx + DSC_DS]\r
190 mov ds, eax\r
191 mov ax, [rbx + DSC_OTHERSEG]\r
192 mov es, eax\r
193 mov fs, eax\r
194 mov gs, eax\r
195 mov ax, [rbx + DSC_SS]\r
196 mov ss, eax\r
9a36d4dc 197\r
3eb69b08
JY
198 mov rbx, [rsp + 0x8] ; rbx <- CpuIndex\r
199\r
200; enable CET if supported\r
201 mov al, strict byte 1 ; source operand may be patched\r
202ASM_PFX(mPatchCetSupported):\r
203 cmp al, 0\r
204 jz CetDone\r
205\r
206 mov ecx, MSR_IA32_S_CET\r
207 rdmsr\r
208 push rdx\r
209 push rax\r
210\r
211 mov ecx, MSR_IA32_PL0_SSP\r
212 rdmsr\r
213 push rdx\r
214 push rax\r
215\r
216 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR\r
217 rdmsr\r
218 push rdx\r
219 push rax\r
220\r
221 mov ecx, MSR_IA32_S_CET\r
222 mov eax, MSR_IA32_CET_SH_STK_EN\r
223 xor edx, edx\r
224 wrmsr\r
225\r
226 mov ecx, MSR_IA32_PL0_SSP\r
227 mov eax, strict dword 0 ; source operand will be patched\r
228ASM_PFX(mPatchCetPl0Ssp):\r
229 xor edx, edx\r
230 wrmsr\r
231 mov rcx, cr0\r
232 btr ecx, 16 ; clear WP\r
233 mov cr0, rcx\r
234 mov [eax], eax ; reload SSP, and clear busyflag.\r
235 xor ecx, ecx\r
236 mov [eax + 4], ecx\r
237\r
238 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR\r
239 mov eax, strict dword 0 ; source operand will be patched\r
240ASM_PFX(mPatchCetInterruptSspTable):\r
241 xor edx, edx\r
242 wrmsr\r
243\r
244 mov eax, strict dword 0 ; source operand will be patched\r
245ASM_PFX(mPatchCetInterruptSsp):\r
246 cmp eax, 0\r
247 jz CetInterruptDone\r
248 mov [eax], eax ; reload SSP, and clear busyflag.\r
249 xor ecx, ecx\r
250 mov [eax + 4], ecx\r
251CetInterruptDone:\r
252\r
253 mov rcx, cr0\r
254 bts ecx, 16 ; set WP\r
255 mov cr0, rcx\r
256\r
257 mov eax, 0x668 | CR4_CET\r
258 mov cr4, rax\r
259\r
260 SETSSBSY\r
261\r
262CetDone:\r
9a36d4dc
LG
263\r
264 ;\r
265 ; Save FP registers\r
266 ;\r
717fb604 267 sub rsp, 0x200\r
d22c995a 268 fxsave64 [rsp]\r
9a36d4dc
LG
269\r
270 add rsp, -0x20\r
271\r
272 mov rcx, rbx\r
a3649281
LG
273 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugEntry)\r
274CpuSmmDebugEntryAbsAddr:\r
275 call rax\r
717fb604 276\r
9a36d4dc 277 mov rcx, rbx\r
a3649281
LG
278 mov rax, strict qword 0 ; call ASM_PFX(SmiRendezvous)\r
279SmiRendezvousAbsAddr:\r
280 call rax\r
717fb604 281\r
9a36d4dc 282 mov rcx, rbx\r
a3649281
LG
283 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugExit)\r
284CpuSmmDebugExitAbsAddr:\r
285 call rax\r
717fb604 286\r
9a36d4dc
LG
287 add rsp, 0x20\r
288\r
289 ;\r
290 ; Restore FP registers\r
291 ;\r
d22c995a 292 fxrstor64 [rsp]\r
9a36d4dc 293\r
717fb604
JY
294 add rsp, 0x200\r
295\r
3eb69b08
JY
296 mov rax, strict qword 0 ; mov rax, ASM_PFX(mCetSupported)\r
297mCetSupportedAbsAddr:\r
298 mov al, [rax]\r
299 cmp al, 0\r
300 jz CetDone2\r
301\r
302 mov eax, 0x668\r
303 mov cr4, rax ; disable CET\r
304\r
305 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR\r
306 pop rax\r
307 pop rdx\r
308 wrmsr\r
309\r
310 mov ecx, MSR_IA32_PL0_SSP\r
311 pop rax\r
312 pop rdx\r
313 wrmsr\r
314\r
315 mov ecx, MSR_IA32_S_CET\r
316 pop rax\r
317 pop rdx\r
318 wrmsr\r
319CetDone2:\r
320\r
a3649281
LG
321 mov rax, strict qword 0 ; lea rax, [ASM_PFX(mXdSupported)]\r
322mXdSupportedAbsAddr:\r
717fb604
JY
323 mov al, [rax]\r
324 cmp al, 0\r
325 jz .1\r
326 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]\r
327 test edx, BIT2\r
328 jz .1\r
329 mov ecx, MSR_IA32_MISC_ENABLE\r
330 rdmsr\r
331 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM\r
332 wrmsr\r
333\r
334.1:\r
3eb69b08 335\r
02f7fd15 336 StuffRsb64\r
9a36d4dc
LG
337 rsm\r
338\r
8764ed57 339ASM_PFX(gcSmiHandlerSize) DW $ - _SmiEntryPoint\r
9a36d4dc 340\r
a3649281
LG
341;\r
342; Retrieve the address and fill it into mov opcode.\r
343;\r
344; It is called in the driver entry point first.\r
345; It is used to fix up the real address in mov opcode.\r
346; Then, after the code logic is copied to the different location,\r
347; the code can also run.\r
348;\r
e21e355e
LG
349global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)\r
350ASM_PFX(PiSmmCpuSmiEntryFixupAddress):\r
351 lea rax, [ASM_PFX(gSmiHandlerIdtr)]\r
352 lea rcx, [SmiHandlerIdtrAbsAddr]\r
353 mov qword [rcx - 8], rax\r
354\r
a3649281
LG
355 lea rax, [ASM_PFX(CpuSmmDebugEntry)]\r
356 lea rcx, [CpuSmmDebugEntryAbsAddr]\r
357 mov qword [rcx - 8], rax\r
358\r
359 lea rax, [ASM_PFX(SmiRendezvous)]\r
360 lea rcx, [SmiRendezvousAbsAddr]\r
361 mov qword [rcx - 8], rax\r
362\r
363 lea rax, [ASM_PFX(CpuSmmDebugExit)]\r
364 lea rcx, [CpuSmmDebugExitAbsAddr]\r
365 mov qword [rcx - 8], rax\r
366\r
367 lea rax, [ASM_PFX(mXdSupported)]\r
368 lea rcx, [mXdSupportedAbsAddr]\r
e21e355e 369 mov qword [rcx - 8], rax\r
3eb69b08
JY
370\r
371 lea rax, [ASM_PFX(mCetSupported)]\r
372 lea rcx, [mCetSupportedAbsAddr]\r
373 mov qword [rcx - 8], rax\r
e21e355e 374 ret\r