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