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(gPatch5LevelPagingSupport)
73 global ASM_PFX(gcSmiHandlerTemplate)
74 global ASM_PFX(gcSmiHandlerSize)
76 extern ASM_PFX(mCetSupported)
77 global ASM_PFX(mPatchCetSupported)
78 global ASM_PFX(mPatchCetPl0Ssp)
79 global ASM_PFX(mPatchCetInterruptSsp)
80 global ASM_PFX(mPatchCetInterruptSspTable)
86 ASM_PFX(gcSmiHandlerTemplate):
88 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
89 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
92 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
94 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
95 mov ax, PROTECT_MODE_CS
97 mov edi, strict dword 0 ; source operand will be patched
98 ASM_PFX(gPatchSmbase):
99 lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000]
112 mov ax, PROTECT_MODE_DS
118 mov esp, strict dword 0 ; source operand will be patched
119 ASM_PFX(gPatchSmiStack):
124 mov eax, strict dword 0 ; source operand will be patched
125 ASM_PFX(gPatchSmiCr3):
127 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
129 mov cl, strict byte 0 ; source operand will be patched
130 ASM_PFX(gPatch5LevelPagingSupport):
132 je SkipEnable5LevelPaging
134 ; Enable 5-Level Paging bit
136 bts eax, 12 ; Set LA57 bit (bit #12)
137 SkipEnable5LevelPaging:
139 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
141 sub esp, 8 ; reserve room in stack
143 mov eax, [rsp + 2] ; eax = GDT base
146 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
150 ; enable NXE if supported
151 mov al, strict byte 1 ; source operand may be patched
152 ASM_PFX(gPatchXdSupported):
156 ; Check XD disable bit
158 mov ecx, MSR_IA32_MISC_ENABLE
161 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
162 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
164 and dx, 0xFFFB ; clear XD Disable bit if it is set
169 or ax, MSR_EFER_XD ; enable NXE
176 ; Switch into @LongMode
177 push LONG_MODE_CS ; push cs hardcore here
178 call Base ; push return address for retf later
180 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
184 or ah, 1 ; enable LME
187 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
190 @LongMode: ; long mode (64-bit code) starts here
191 mov rax, strict qword 0 ; mov rax, ASM_PFX(gSmiHandlerIdtr)
192 SmiHandlerIdtrAbsAddr:
194 lea ebx, [rdi + DSC_OFFSET]
195 mov ax, [rbx + DSC_DS]
197 mov ax, [rbx + DSC_OTHERSEG]
201 mov ax, [rbx + DSC_SS]
204 mov rbx, [rsp + 0x8] ; rbx <- CpuIndex
206 ; enable CET if supported
207 mov al, strict byte 1 ; source operand may be patched
208 ASM_PFX(mPatchCetSupported):
212 mov ecx, MSR_IA32_S_CET
217 mov ecx, MSR_IA32_PL0_SSP
222 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
227 mov ecx, MSR_IA32_S_CET
228 mov eax, MSR_IA32_CET_SH_STK_EN
232 mov ecx, MSR_IA32_PL0_SSP
233 mov eax, strict dword 0 ; source operand will be patched
234 ASM_PFX(mPatchCetPl0Ssp):
238 btr ecx, 16 ; clear WP
240 mov [eax], eax ; reload SSP, and clear busyflag.
244 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
245 mov eax, strict dword 0 ; source operand will be patched
246 ASM_PFX(mPatchCetInterruptSspTable):
250 mov eax, strict dword 0 ; source operand will be patched
251 ASM_PFX(mPatchCetInterruptSsp):
254 mov [eax], eax ; reload SSP, and clear busyflag.
263 mov eax, 0x668 | CR4_CET
279 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugEntry)
280 CpuSmmDebugEntryAbsAddr:
284 mov rax, strict qword 0 ; call ASM_PFX(SmiRendezvous)
285 SmiRendezvousAbsAddr:
289 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugExit)
290 CpuSmmDebugExitAbsAddr:
296 ; Restore FP registers
302 mov rax, strict qword 0 ; mov rax, ASM_PFX(mCetSupported)
303 mCetSupportedAbsAddr:
309 mov cr4, rax ; disable CET
311 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
316 mov ecx, MSR_IA32_PL0_SSP
321 mov ecx, MSR_IA32_S_CET
327 mov rax, strict qword 0 ; lea rax, [ASM_PFX(mXdSupported)]
332 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
335 mov ecx, MSR_IA32_MISC_ENABLE
337 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
345 ASM_PFX(gcSmiHandlerSize) DW $ - _SmiEntryPoint
348 ; Retrieve the address and fill it into mov opcode.
350 ; It is called in the driver entry point first.
351 ; It is used to fix up the real address in mov opcode.
352 ; Then, after the code logic is copied to the different location,
353 ; the code can also run.
355 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
356 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
357 lea rax, [ASM_PFX(gSmiHandlerIdtr)]
358 lea rcx, [SmiHandlerIdtrAbsAddr]
359 mov qword [rcx - 8], rax
361 lea rax, [ASM_PFX(CpuSmmDebugEntry)]
362 lea rcx, [CpuSmmDebugEntryAbsAddr]
363 mov qword [rcx - 8], rax
365 lea rax, [ASM_PFX(SmiRendezvous)]
366 lea rcx, [SmiRendezvousAbsAddr]
367 mov qword [rcx - 8], rax
369 lea rax, [ASM_PFX(CpuSmmDebugExit)]
370 lea rcx, [CpuSmmDebugExitAbsAddr]
371 mov qword [rcx - 8], rax
373 lea rax, [ASM_PFX(mXdSupported)]
374 lea rcx, [mXdSupportedAbsAddr]
375 mov qword [rcx - 8], rax
377 lea rax, [ASM_PFX(mCetSupported)]
378 lea rcx, [mCetSupportedAbsAddr]
379 mov qword [rcx - 8], rax