VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm@ 105381

Last change on this file since 105381 was 99404, checked in by vboxsync, 2 years ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-asm
File size: 10.3 KB
Line 
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
63extern ASM_PFX(SmiRendezvous)
64extern ASM_PFX(gSmiHandlerIdtr)
65extern ASM_PFX(CpuSmmDebugEntry)
66extern ASM_PFX(CpuSmmDebugExit)
67
68global ASM_PFX(gPatchSmbase)
69extern ASM_PFX(mXdSupported)
70global ASM_PFX(gPatchXdSupported)
71global ASM_PFX(gPatchMsrIa32MiscEnableSupported)
72global ASM_PFX(gPatchSmiStack)
73global ASM_PFX(gPatchSmiCr3)
74global ASM_PFX(gPatch5LevelPagingNeeded)
75global ASM_PFX(gcSmiHandlerTemplate)
76global ASM_PFX(gcSmiHandlerSize)
77
78extern ASM_PFX(mCetSupported)
79global ASM_PFX(mPatchCetSupported)
80global ASM_PFX(mPatchCetPl0Ssp)
81global ASM_PFX(mPatchCetInterruptSsp)
82global ASM_PFX(mPatchCetInterruptSspTable)
83
84 DEFAULT REL
85 SECTION .text
86
87BITS 16
88ASM_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
96o32 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
100ASM_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
112BITS 32
113@ProtectedMode:
114 mov ax, PROTECT_MODE_DS
115o16 mov ds, ax
116o16 mov es, ax
117o16 mov fs, ax
118o16 mov gs, ax
119o16 mov ss, ax
120 mov esp, strict dword 0 ; source operand will be patched
121ASM_PFX(gPatchSmiStack):
122 jmp ProtFlatMode
123
124BITS 64
125ProtFlatMode:
126 mov eax, strict dword 0 ; source operand will be patched
127ASM_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
132ASM_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)
139SkipEnable5LevelPaging:
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
154ASM_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
160ASM_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;
173MsrIa32MiscEnableSupported:
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
182EnableNxe:
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
195Base:
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)
208SmiHandlerIdtrAbsAddr:
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
224ASM_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
250ASM_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
262ASM_PFX(mPatchCetInterruptSspTable):
263 xor edx, edx
264 wrmsr
265
266 mov eax, strict dword 0 ; source operand will be patched
267ASM_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
273CetInterruptDone:
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
284CetDone:
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)
296CpuSmmDebugEntryAbsAddr:
297 call rax
298
299 mov rcx, rbx
300 mov rax, strict qword 0 ; call ASM_PFX(SmiRendezvous)
301SmiRendezvousAbsAddr:
302 call rax
303
304 mov rcx, rbx
305 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugExit)
306CpuSmmDebugExitAbsAddr:
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)
319mCetSupportedAbsAddr:
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
341CetDone2:
342
343 mov rax, strict qword 0 ; lea rax, [ASM_PFX(mXdSupported)]
344mXdSupportedAbsAddr:
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
361ASM_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;
371global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
372ASM_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
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette