1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
3 ; This program and the accompanying materials
4 ; are licensed and made available under the terms and conditions of the BSD License
5 ; which accompanies this distribution. The full text of the license may be found at
6 ; http://opensource.org/licenses/bsd-license.php.
8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 ; Code template of the SMI handler for a particular processor
19 ;-------------------------------------------------------------------------------
21 %include "StuffRsbNasm.inc"
25 ; Variables referrenced by C code
28 %define MSR_IA32_S_CET 0x6A2
29 %define MSR_IA32_CET_SH_STK_EN 0x1
30 %define MSR_IA32_CET_WR_SHSTK_EN 0x2
31 %define MSR_IA32_CET_ENDBR_EN 0x4
32 %define MSR_IA32_CET_LEG_IW_EN 0x8
33 %define MSR_IA32_CET_NO_TRACK_EN 0x10
34 %define MSR_IA32_CET_SUPPRESS_DIS 0x20
35 %define MSR_IA32_CET_SUPPRESS 0x400
36 %define MSR_IA32_CET_TRACKER 0x800
37 %define MSR_IA32_PL0_SSP 0x6A4
38 %define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR 0x6A8
40 %define CR4_CET 0x800000
42 %define MSR_IA32_MISC_ENABLE 0x1A0
43 %define MSR_EFER 0xc0000080
44 %define MSR_EFER_XD 0x800
47 ; Constants relating to PROCESSOR_SMM_DESCRIPTOR
49 %define DSC_OFFSET 0xfb00
50 %define DSC_GDTPTR 0x30
51 %define DSC_GDTSIZ 0x38
55 %define DSC_OTHERSEG 20
57 ; Constants relating to CPU State Save Area
59 %define SSM_DR6 0xffd0
60 %define SSM_DR7 0xffc8
62 %define PROTECT_MODE_CS 0x8
63 %define PROTECT_MODE_DS 0x20
64 %define LONG_MODE_CS 0x38
65 %define TSS_SEGMENT 0x40
68 extern ASM_PFX(SmiRendezvous)
69 extern ASM_PFX(gSmiHandlerIdtr)
70 extern ASM_PFX(CpuSmmDebugEntry)
71 extern ASM_PFX(CpuSmmDebugExit)
73 global ASM_PFX(gPatchSmbase)
74 extern ASM_PFX(mXdSupported)
75 global ASM_PFX(gPatchXdSupported)
76 global ASM_PFX(gPatchSmiStack)
77 global ASM_PFX(gPatchSmiCr3)
78 global ASM_PFX(gcSmiHandlerTemplate)
79 global ASM_PFX(gcSmiHandlerSize)
81 extern ASM_PFX(mCetSupported)
82 global ASM_PFX(mPatchCetSupported)
83 global ASM_PFX(mPatchCetPl0Ssp)
84 global ASM_PFX(mPatchCetInterruptSsp)
85 global ASM_PFX(mPatchCetInterruptSspTable)
91 ASM_PFX(gcSmiHandlerTemplate):
93 mov bx, _GdtDesc - _SmiEntryPoint + 0x8000
94 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
97 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
99 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
100 mov ax, PROTECT_MODE_CS
102 mov edi, strict dword 0 ; source operand will be patched
103 ASM_PFX(gPatchSmbase):
104 lea eax, [edi + (@ProtectedMode - _SmiEntryPoint) + 0x8000]
117 mov ax, PROTECT_MODE_DS
123 mov esp, strict dword 0 ; source operand will be patched
124 ASM_PFX(gPatchSmiStack):
129 mov eax, strict dword 0 ; source operand will be patched
130 ASM_PFX(gPatchSmiCr3):
132 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
133 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
135 sub esp, 8 ; reserve room in stack
137 mov eax, [rsp + 2] ; eax = GDT base
140 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
144 ; enable NXE if supported
145 mov al, strict byte 1 ; source operand may be patched
146 ASM_PFX(gPatchXdSupported):
150 ; Check XD disable bit
152 mov ecx, MSR_IA32_MISC_ENABLE
155 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
156 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
158 and dx, 0xFFFB ; clear XD Disable bit if it is set
163 or ax, MSR_EFER_XD ; enable NXE
170 ; Switch into @LongMode
171 push LONG_MODE_CS ; push cs hardcore here
172 call Base ; push return address for retf later
174 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
178 or ah, 1 ; enable LME
181 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
184 @LongMode: ; long mode (64-bit code) starts here
185 mov rax, strict qword 0 ; mov rax, ASM_PFX(gSmiHandlerIdtr)
186 SmiHandlerIdtrAbsAddr:
188 lea ebx, [rdi + DSC_OFFSET]
189 mov ax, [rbx + DSC_DS]
191 mov ax, [rbx + DSC_OTHERSEG]
195 mov ax, [rbx + DSC_SS]
198 mov rbx, [rsp + 0x8] ; rbx <- CpuIndex
200 ; enable CET if supported
201 mov al, strict byte 1 ; source operand may be patched
202 ASM_PFX(mPatchCetSupported):
206 mov ecx, MSR_IA32_S_CET
211 mov ecx, MSR_IA32_PL0_SSP
216 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
221 mov ecx, MSR_IA32_S_CET
222 mov eax, MSR_IA32_CET_SH_STK_EN
226 mov ecx, MSR_IA32_PL0_SSP
227 mov eax, strict dword 0 ; source operand will be patched
228 ASM_PFX(mPatchCetPl0Ssp):
232 btr ecx, 16 ; clear WP
234 mov [eax], eax ; reload SSP, and clear busyflag.
238 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
239 mov eax, strict dword 0 ; source operand will be patched
240 ASM_PFX(mPatchCetInterruptSspTable):
244 mov eax, strict dword 0 ; source operand will be patched
245 ASM_PFX(mPatchCetInterruptSsp):
248 mov [eax], eax ; reload SSP, and clear busyflag.
257 mov eax, 0x668 | CR4_CET
273 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugEntry)
274 CpuSmmDebugEntryAbsAddr:
278 mov rax, strict qword 0 ; call ASM_PFX(SmiRendezvous)
279 SmiRendezvousAbsAddr:
283 mov rax, strict qword 0 ; call ASM_PFX(CpuSmmDebugExit)
284 CpuSmmDebugExitAbsAddr:
290 ; Restore FP registers
296 mov rax, strict qword 0 ; mov rax, ASM_PFX(mCetSupported)
297 mCetSupportedAbsAddr:
303 mov cr4, rax ; disable CET
305 mov ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
310 mov ecx, MSR_IA32_PL0_SSP
315 mov ecx, MSR_IA32_S_CET
321 mov rax, strict qword 0 ; lea rax, [ASM_PFX(mXdSupported)]
326 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
329 mov ecx, MSR_IA32_MISC_ENABLE
331 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
339 ASM_PFX(gcSmiHandlerSize) DW $ - _SmiEntryPoint
342 ; Retrieve the address and fill it into mov opcode.
344 ; It is called in the driver entry point first.
345 ; It is used to fix up the real address in mov opcode.
346 ; Then, after the code logic is copied to the different location,
347 ; the code can also run.
349 global ASM_PFX(PiSmmCpuSmiEntryFixupAddress)
350 ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
351 lea rax, [ASM_PFX(gSmiHandlerIdtr)]
352 lea rcx, [SmiHandlerIdtrAbsAddr]
353 mov qword [rcx - 8], rax
355 lea rax, [ASM_PFX(CpuSmmDebugEntry)]
356 lea rcx, [CpuSmmDebugEntryAbsAddr]
357 mov qword [rcx - 8], rax
359 lea rax, [ASM_PFX(SmiRendezvous)]
360 lea rcx, [SmiRendezvousAbsAddr]
361 mov qword [rcx - 8], rax
363 lea rax, [ASM_PFX(CpuSmmDebugExit)]
364 lea rcx, [CpuSmmDebugExitAbsAddr]
365 mov qword [rcx - 8], rax
367 lea rax, [ASM_PFX(mXdSupported)]
368 lea rcx, [mXdSupportedAbsAddr]
369 mov qword [rcx - 8], rax
371 lea rax, [ASM_PFX(mCetSupported)]
372 lea rcx, [mCetSupportedAbsAddr]
373 mov qword [rcx - 8], rax