1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016 - 2018, 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"
24 ; Variables referrenced by C code
27 %define MSR_IA32_MISC_ENABLE 0x1A0
28 %define MSR_EFER 0xc0000080
29 %define MSR_EFER_XD 0x800
32 ; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
34 %define DSC_OFFSET 0xfb00
35 %define DSC_GDTPTR 0x48
36 %define DSC_GDTSIZ 0x50
40 %define DSC_OTHERSEG 0x1a
42 ; Constants relating to CPU State Save Area
44 %define SSM_DR6 0xffd0
45 %define SSM_DR7 0xffc8
47 %define PROTECT_MODE_CS 0x8
48 %define PROTECT_MODE_DS 0x20
49 %define LONG_MODE_CS 0x38
50 %define TSS_SEGMENT 0x40
53 extern ASM_PFX(SmiRendezvous)
54 extern ASM_PFX(gStmSmiHandlerIdtr)
55 extern ASM_PFX(CpuSmmDebugEntry)
56 extern ASM_PFX(CpuSmmDebugExit)
58 global ASM_PFX(gStmSmbase)
59 global ASM_PFX(gStmXdSupported)
60 global ASM_PFX(gStmSmiStack)
61 global ASM_PFX(gStmSmiCr3)
62 global ASM_PFX(gcStmSmiHandlerTemplate)
63 global ASM_PFX(gcStmSmiHandlerSize)
64 global ASM_PFX(gcStmSmiHandlerOffset)
66 ASM_PFX(gStmSmbase) EQU StmSmbasePatch - 4
67 ASM_PFX(gStmSmiStack) EQU StmSmiStackPatch - 4
68 ASM_PFX(gStmSmiCr3) EQU StmSmiCr3Patch - 4
69 ASM_PFX(gStmXdSupported) EQU StmXdSupportedPatch - 1
75 ASM_PFX(gcStmSmiHandlerTemplate):
77 mov bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000
78 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
81 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
83 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
84 mov ax, PROTECT_MODE_CS
86 o32 mov edi, strict dword 0
88 lea eax, [edi + (@ProtectedMode - _StmSmiEntryPoint) + 0x8000]
101 mov ax, PROTECT_MODE_DS
107 mov esp, strict dword 0
113 mov eax, strict dword 0
116 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
117 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
119 sub esp, 8 ; reserve room in stack
121 mov eax, [rsp + 2] ; eax = GDT base
124 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
128 ; enable NXE if supported
129 mov al, strict byte 1
134 ; Check XD disable bit
136 mov ecx, MSR_IA32_MISC_ENABLE
139 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
140 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
142 and dx, 0xFFFB ; clear XD Disable bit if it is set
147 or ax, MSR_EFER_XD ; enable NXE
154 ; Switch into @LongMode
155 push LONG_MODE_CS ; push cs hardcore here
156 call Base ; push return address for retf later
158 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
162 or ah, 1 ; enable LME
165 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
168 @LongMode: ; long mode (64-bit code) starts here
169 mov rax, strict qword 0 ; mov rax, ASM_PFX(gStmSmiHandlerIdtr)
170 StmSmiEntrySmiHandlerIdtrAbsAddr:
172 lea ebx, [rdi + DSC_OFFSET]
173 mov ax, [rbx + DSC_DS]
175 mov ax, [rbx + DSC_OTHERSEG]
179 mov ax, [rbx + DSC_SS]
181 mov rax, strict qword 0 ; mov rax, CommonHandler
182 StmSmiEntryCommonHandlerAbsAddr:
185 mov rbx, [rsp + 0x08] ; rbx <- CpuIndex
196 call ASM_PFX(CpuSmmDebugEntry)
199 call ASM_PFX(SmiRendezvous)
202 call ASM_PFX(CpuSmmDebugExit)
207 ; Restore FP registers
213 lea rax, [ASM_PFX(gStmXdSupported)]
217 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
220 mov ecx, MSR_IA32_MISC_ENABLE
222 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
231 ; Check XD disable bit
234 lea rax, [ASM_PFX(gStmXdSupported)]
238 mov ecx, MSR_IA32_MISC_ENABLE
240 mov r8, rdx ; save MSR_IA32_MISC_ENABLE[63-32]
241 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
243 and dx, 0xFFFB ; clear XD Disable bit if it is set
248 or ax, MSR_EFER_XD ; enable NXE
253 ; below step is needed, because STM does not run above code.
254 ; we have to run below code to set IDT/CR0/CR4
255 mov rax, strict qword 0 ; mov rax, ASM_PFX(gStmSmiHandlerIdtr)
256 StmSmiHandlerIdtrAbsAddr:
260 or eax, 0x80010023 ; enable paging + WP + NE + MP + PE
263 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
264 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
268 ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint
269 ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint
271 global ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress)
272 ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress):
273 lea rax, [ASM_PFX(gStmSmiHandlerIdtr)]
274 lea rcx, [StmSmiEntrySmiHandlerIdtrAbsAddr]
275 mov qword [rcx - 8], rax
276 lea rcx, [StmSmiHandlerIdtrAbsAddr]
277 mov qword [rcx - 8], rax
279 lea rax, [CommonHandler]
280 lea rcx, [StmSmiEntryCommonHandlerAbsAddr]
281 mov qword [rcx - 8], rax