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