1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016 - 2018, 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"
18 ; Variables referenced by C code
21 %define MSR_IA32_MISC_ENABLE 0x1A0
22 %define MSR_EFER 0xc0000080
23 %define MSR_EFER_XD 0x800
26 ; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
28 %define DSC_OFFSET 0xfb00
29 %define DSC_GDTPTR 0x48
30 %define DSC_GDTSIZ 0x50
34 %define DSC_OTHERSEG 0x1a
36 ; Constants relating to CPU State Save Area
38 %define SSM_DR6 0xffd0
39 %define SSM_DR7 0xffc8
41 %define PROTECT_MODE_CS 0x8
42 %define PROTECT_MODE_DS 0x20
43 %define LONG_MODE_CS 0x38
44 %define TSS_SEGMENT 0x40
47 extern ASM_PFX(SmiRendezvous)
48 extern ASM_PFX(gStmSmiHandlerIdtr)
49 extern ASM_PFX(CpuSmmDebugEntry)
50 extern ASM_PFX(CpuSmmDebugExit)
52 global ASM_PFX(gStmSmbase)
53 global ASM_PFX(gStmXdSupported)
54 global ASM_PFX(gStmSmiStack)
55 global ASM_PFX(gStmSmiCr3)
56 global ASM_PFX(gcStmSmiHandlerTemplate)
57 global ASM_PFX(gcStmSmiHandlerSize)
58 global ASM_PFX(gcStmSmiHandlerOffset)
60 ASM_PFX(gStmSmbase) EQU StmSmbasePatch - 4
61 ASM_PFX(gStmSmiStack) EQU StmSmiStackPatch - 4
62 ASM_PFX(gStmSmiCr3) EQU StmSmiCr3Patch - 4
63 ASM_PFX(gStmXdSupported) EQU StmXdSupportedPatch - 1
69 ASM_PFX(gcStmSmiHandlerTemplate):
71 mov bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000
72 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
75 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
77 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
78 mov ax, PROTECT_MODE_CS
80 o32 mov edi, strict dword 0
82 lea eax, [edi + (@ProtectedMode - _StmSmiEntryPoint) + 0x8000]
95 mov ax, PROTECT_MODE_DS
101 mov esp, strict dword 0
107 mov eax, strict dword 0
110 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
111 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
113 sub esp, 8 ; reserve room in stack
115 mov eax, [rsp + 2] ; eax = GDT base
118 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
122 ; enable NXE if supported
123 mov al, strict byte 1
128 ; Check XD disable bit
130 mov ecx, MSR_IA32_MISC_ENABLE
133 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
134 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
136 and dx, 0xFFFB ; clear XD Disable bit if it is set
141 or ax, MSR_EFER_XD ; enable NXE
148 ; Switch into @LongMode
149 push LONG_MODE_CS ; push cs hardcore here
150 call Base ; push return address for retf later
152 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
156 or ah, 1 ; enable LME
159 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
162 @LongMode: ; long mode (64-bit code) starts here
163 mov rax, strict qword 0 ; mov rax, ASM_PFX(gStmSmiHandlerIdtr)
164 StmSmiEntrySmiHandlerIdtrAbsAddr:
166 lea ebx, [rdi + DSC_OFFSET]
167 mov ax, [rbx + DSC_DS]
169 mov ax, [rbx + DSC_OTHERSEG]
173 mov ax, [rbx + DSC_SS]
175 mov rax, strict qword 0 ; mov rax, CommonHandler
176 StmSmiEntryCommonHandlerAbsAddr:
179 mov rbx, [rsp + 0x08] ; rbx <- CpuIndex
190 call ASM_PFX(CpuSmmDebugEntry)
193 call ASM_PFX(SmiRendezvous)
196 call ASM_PFX(CpuSmmDebugExit)
201 ; Restore FP registers
207 lea rax, [ASM_PFX(gStmXdSupported)]
211 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
214 mov ecx, MSR_IA32_MISC_ENABLE
216 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
225 ; Check XD disable bit
228 lea rax, [ASM_PFX(gStmXdSupported)]
232 mov ecx, MSR_IA32_MISC_ENABLE
234 mov r8, rdx ; save MSR_IA32_MISC_ENABLE[63-32]
235 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
237 and dx, 0xFFFB ; clear XD Disable bit if it is set
242 or ax, MSR_EFER_XD ; enable NXE
247 ; below step is needed, because STM does not run above code.
248 ; we have to run below code to set IDT/CR0/CR4
249 mov rax, strict qword 0 ; mov rax, ASM_PFX(gStmSmiHandlerIdtr)
250 StmSmiHandlerIdtrAbsAddr:
254 or eax, 0x80010023 ; enable paging + WP + NE + MP + PE
257 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
258 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
262 ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint
263 ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint
265 global ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress)
266 ASM_PFX(SmmCpuFeaturesLibStmSmiEntryFixupAddress):
267 lea rax, [ASM_PFX(gStmSmiHandlerIdtr)]
268 lea rcx, [StmSmiEntrySmiHandlerIdtrAbsAddr]
269 mov qword [rcx - 8], rax
270 lea rcx, [StmSmiHandlerIdtrAbsAddr]
271 mov qword [rcx - 8], rax
273 lea rax, [CommonHandler]
274 lea rcx, [StmSmiEntryCommonHandlerAbsAddr]
275 mov qword [rcx - 8], rax