1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
11 ; Code template of the SMI handler for a particular processor
13 ;-------------------------------------------------------------------------------
15 %include "StuffRsbNasm.inc"
19 ; Variables referrenced by C code
22 %define MSR_IA32_S_CET 0x6A2
23 %define MSR_IA32_CET_SH_STK_EN 0x1
24 %define MSR_IA32_CET_WR_SHSTK_EN 0x2
25 %define MSR_IA32_CET_ENDBR_EN 0x4
26 %define MSR_IA32_CET_LEG_IW_EN 0x8
27 %define MSR_IA32_CET_NO_TRACK_EN 0x10
28 %define MSR_IA32_CET_SUPPRESS_DIS 0x20
29 %define MSR_IA32_CET_SUPPRESS 0x400
30 %define MSR_IA32_CET_TRACKER 0x800
31 %define MSR_IA32_PL0_SSP 0x6A4
32 %define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR 0x6A8
34 %define CR4_CET 0x800000
36 %define MSR_IA32_MISC_ENABLE 0x1A0
37 %define MSR_EFER 0xc0000080
38 %define MSR_EFER_XD 0x800
41 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
43 %define DSC_OFFSET 0xfb00
44 %define DSC_GDTPTR 0x30
45 %define DSC_GDTSIZ 0x38
49 %define DSC_OTHERSEG 20
51 ; Constants relating to CPU State Save Area
53 %define SSM_DR6 0xffd0
54 %define SSM_DR7 0xffc8
56 %define PROTECT_MODE_CS 0x8
57 %define PROTECT_MODE_DS 0x20
58 %define LONG_MODE_CS 0x38
59 %define TSS_SEGMENT 0x40
62 extern ASM_PFX(SmiRendezvous)
63 extern ASM_PFX(gSmiHandlerIdtr)
64 extern ASM_PFX(CpuSmmDebugEntry)
65 extern ASM_PFX(CpuSmmDebugExit)
67 global ASM_PFX(gPatchSmbase)
68 extern ASM_PFX(mXdSupported)
69 global ASM_PFX(gPatchXdSupported)
70 global ASM_PFX(gPatchSmiStack)
71 global ASM_PFX(gPatchSmiCr3)
72 global ASM_PFX(gcSmiHandlerTemplate)
73 global ASM_PFX(gcSmiHandlerSize)
75 extern ASM_PFX(mCetSupported)
76 global ASM_PFX(mPatchCetSupported)
77 global ASM_PFX(mPatchCetPl0Ssp)
78 global ASM_PFX(mPatchCetInterruptSsp)
79 global ASM_PFX(mPatchCetInterruptSspTable)
85 ASM_PFX(gcSmiHandlerTemplate):
87 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
88 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
91 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
93 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
94 mov ax, PROTECT_MODE_CS
96 mov edi, strict dword 0 ; source operand will be patched
97 ASM_PFX(gPatchSmbase):
98 lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000]
111 mov ax, PROTECT_MODE_DS
117 mov esp, strict dword 0 ; source operand will be patched
118 ASM_PFX(gPatchSmiStack):
123 mov eax, strict dword 0 ; source operand will be patched
124 ASM_PFX(gPatchSmiCr3):
126 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
127 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
129 sub esp, 8 ; reserve room in stack
131 mov eax, [rsp + 2] ; eax = GDT base
134 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
138 ; enable NXE if supported
139 mov al, strict byte 1 ; source operand may be patched
140 ASM_PFX(gPatchXdSupported):
144 ; Check XD disable bit
146 mov ecx, MSR_IA32_MISC_ENABLE
149 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
150 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
152 and dx, 0xFFFB ; clear XD Disable bit if it is set
157 or ax, MSR_EFER_XD ; enable NXE
164 ; Switch into @LongMode
165 push LONG_MODE_CS ; push cs hardcore here
166 call Base ; push return address for retf later
168 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
172 or ah, 1 ; enable LME
175 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
178 @LongMode: ; long mode (64-bit code) starts here
179 mov rax, strict qword 0 ; mov rax, ASM_PFX(gSmiHandlerIdtr)
180 SmiHandlerIdtrAbsAddr:
182 lea ebx, [rdi + DSC_OFFSET]
183 mov ax, [rbx + DSC_DS]
185 mov ax, [rbx + DSC_OTHERSEG]
189 mov ax, [rbx + DSC_SS]
192 mov rbx, [rsp + 0x8] ; rbx <- CpuIndex
194 ; enable CET if supported
195 mov al, strict byte 1 ; source operand may be patched
196 ASM_PFX(mPatchCetSupported):
200 mov ecx, MSR_IA32_S_CET
205 mov ecx, MSR_IA32_PL0_SSP
210 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
215 mov ecx, MSR_IA32_S_CET
216 mov eax, MSR_IA32_CET_SH_STK_EN
220 mov ecx, MSR_IA32_PL0_SSP
221 mov eax, strict dword 0 ; source operand will be patched
222 ASM_PFX(mPatchCetPl0Ssp):
226 btr ecx, 16 ; clear WP
228 mov [eax], eax ; reload SSP, and clear busyflag.
232 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
233 mov eax, strict dword 0 ; source operand will be patched
234 ASM_PFX(mPatchCetInterruptSspTable):
238 mov eax, strict dword 0 ; source operand will be patched
239 ASM_PFX(mPatchCetInterruptSsp):
242 mov [eax], eax ; reload SSP, and clear busyflag.
251 mov eax, 0x668 | CR4_CET
267 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugEntry)
268 CpuSmmDebugEntryAbsAddr:
272 mov rax, strict qword 0 ; call ASM_PFX(SmiRendezvous)
273 SmiRendezvousAbsAddr:
277 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugExit)
278 CpuSmmDebugExitAbsAddr:
284 ; Restore FP registers
290 mov rax, strict qword 0 ; mov rax, ASM_PFX(mCetSupported)
291 mCetSupportedAbsAddr:
297 mov cr4, rax ; disable CET
299 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
304 mov ecx, MSR_IA32_PL0_SSP
309 mov ecx, MSR_IA32_S_CET
315 mov rax, strict qword 0 ; lea rax, [ASM_PFX(mXdSupported)]
320 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
323 mov ecx, MSR_IA32_MISC_ENABLE
325 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
333 ASM_PFX(gcSmiHandlerSize) DW $ - _SmiEntryPoint
336 ; Retrieve the address and fill it into mov opcode.
338 ; It is called in the driver entry point first.
339 ; It is used to fix up the real address in mov opcode.
340 ; Then, after the code logic is copied to the different location,
341 ; the code can also run.
343 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
344 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
345 lea rax, [ASM_PFX(gSmiHandlerIdtr)]
346 lea rcx, [SmiHandlerIdtrAbsAddr]
347 mov qword [rcx - 8], rax
349 lea rax, [ASM_PFX(CpuSmmDebugEntry)]
350 lea rcx, [CpuSmmDebugEntryAbsAddr]
351 mov qword [rcx - 8], rax
353 lea rax, [ASM_PFX(SmiRendezvous)]
354 lea rcx, [SmiRendezvousAbsAddr]
355 mov qword [rcx - 8], rax
357 lea rax, [ASM_PFX(CpuSmmDebugExit)]
358 lea rcx, [CpuSmmDebugExitAbsAddr]
359 mov qword [rcx - 8], rax
361 lea rax, [ASM_PFX(mXdSupported)]
362 lea rcx, [mXdSupportedAbsAddr]
363 mov qword [rcx - 8], rax
365 lea rax, [ASM_PFX(mCetSupported)]
366 lea rcx, [mCetSupportedAbsAddr]
367 mov qword [rcx - 8], rax