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