]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmiEntry.nasm
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / Library / SmmCpuFeaturesLib / X64 / SmiEntry.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
4 ;
5 ; Module Name:
6 ;
7 ; SmiEntry.nasm
8 ;
9 ; Abstract:
10 ;
11 ; Code template of the SMI handler for a particular processor
12 ;
13 ;-------------------------------------------------------------------------------
14
15 %include "StuffRsbNasm.inc"
16
17 ;
18 ; Variables referenced by C code
19 ;
20
21 %define MSR_IA32_MISC_ENABLE 0x1A0
22 %define MSR_EFER 0xc0000080
23 %define MSR_EFER_XD 0x800
24
25 ;
26 ; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
27 ;
28 %define DSC_OFFSET 0xfb00
29 %define DSC_GDTPTR 0x48
30 %define DSC_GDTSIZ 0x50
31 %define DSC_CS 0x14
32 %define DSC_DS 0x16
33 %define DSC_SS 0x18
34 %define DSC_OTHERSEG 0x1a
35 ;
36 ; Constants relating to CPU State Save Area
37 ;
38 %define SSM_DR6 0xffd0
39 %define SSM_DR7 0xffc8
40
41 %define PROTECT_MODE_CS 0x8
42 %define PROTECT_MODE_DS 0x20
43 %define LONG_MODE_CS 0x38
44 %define TSS_SEGMENT 0x40
45 %define GDT_SIZE 0x50
46
47 extern ASM_PFX(SmiRendezvous)
48 extern ASM_PFX(gStmSmiHandlerIdtr)
49 extern ASM_PFX(CpuSmmDebugEntry)
50 extern ASM_PFX(CpuSmmDebugExit)
51
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)
59
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
64
65 DEFAULT REL
66 SECTION .text
67
68 BITS 16
69 ASM_PFX(gcStmSmiHandlerTemplate):
70 _StmSmiEntryPoint:
71 mov bx, _StmGdtDesc - _StmSmiEntryPoint + 0x8000
72 mov ax,[cs:DSC_OFFSET + DSC_GDTSIZ]
73 dec ax
74 mov [cs:bx], ax
75 mov eax, [cs:DSC_OFFSET + DSC_GDTPTR]
76 mov [cs:bx + 2], eax
77 o32 lgdt [cs:bx] ; lgdt fword ptr cs:[bx]
78 mov ax, PROTECT_MODE_CS
79 mov [cs:bx-0x2],ax
80 o32 mov edi, strict dword 0
81 StmSmbasePatch:
82 lea eax, [edi + (@ProtectedMode - _StmSmiEntryPoint) + 0x8000]
83 mov [cs:bx-0x6],eax
84 mov ebx, cr0
85 and ebx, 0x9ffafff3
86 or ebx, 0x23
87 mov cr0, ebx
88 jmp dword 0x0:0x0
89 _StmGdtDesc:
90 DW 0
91 DD 0
92
93 BITS 32
94 @ProtectedMode:
95 mov ax, PROTECT_MODE_DS
96 o16 mov ds, ax
97 o16 mov es, ax
98 o16 mov fs, ax
99 o16 mov gs, ax
100 o16 mov ss, ax
101 mov esp, strict dword 0
102 StmSmiStackPatch:
103 jmp ProtFlatMode
104
105 BITS 64
106 ProtFlatMode:
107 mov eax, strict dword 0
108 StmSmiCr3Patch:
109 mov cr3, rax
110 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
111 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
112 ; Load TSS
113 sub esp, 8 ; reserve room in stack
114 sgdt [rsp]
115 mov eax, [rsp + 2] ; eax = GDT base
116 add esp, 8
117 mov dl, 0x89
118 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
119 mov eax, TSS_SEGMENT
120 ltr ax
121
122 ; enable NXE if supported
123 mov al, strict byte 1
124 StmXdSupportedPatch:
125 cmp al, 0
126 jz @SkipXd
127 ;
128 ; Check XD disable bit
129 ;
130 mov ecx, MSR_IA32_MISC_ENABLE
131 rdmsr
132 sub esp, 4
133 push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
134 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
135 jz .0
136 and dx, 0xFFFB ; clear XD Disable bit if it is set
137 wrmsr
138 .0:
139 mov ecx, MSR_EFER
140 rdmsr
141 or ax, MSR_EFER_XD ; enable NXE
142 wrmsr
143 jmp @XdDone
144 @SkipXd:
145 sub esp, 8
146 @XdDone:
147
148 ; Switch into @LongMode
149 push LONG_MODE_CS ; push cs hardcore here
150 call Base ; push return address for retf later
151 Base:
152 add dword [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
153
154 mov ecx, MSR_EFER
155 rdmsr
156 or ah, 1 ; enable LME
157 wrmsr
158 mov rbx, cr0
159 or ebx, 0x80010023 ; enable paging + WP + NE + MP + PE
160 mov cr0, rbx
161 retf
162 @LongMode: ; long mode (64-bit code) starts here
163 mov rax, strict qword 0 ; mov rax, ASM_PFX(gStmSmiHandlerIdtr)
164 StmSmiEntrySmiHandlerIdtrAbsAddr:
165 lidt [rax]
166 lea ebx, [rdi + DSC_OFFSET]
167 mov ax, [rbx + DSC_DS]
168 mov ds, eax
169 mov ax, [rbx + DSC_OTHERSEG]
170 mov es, eax
171 mov fs, eax
172 mov gs, eax
173 mov ax, [rbx + DSC_SS]
174 mov ss, eax
175 mov rax, strict qword 0 ; mov rax, CommonHandler
176 StmSmiEntryCommonHandlerAbsAddr:
177 jmp rax
178 CommonHandler:
179 mov rbx, [rsp + 0x08] ; rbx <- CpuIndex
180
181 ;
182 ; Save FP registers
183 ;
184 sub rsp, 0x200
185 fxsave64 [rsp]
186
187 add rsp, -0x20
188
189 mov rcx, rbx
190 call ASM_PFX(CpuSmmDebugEntry)
191
192 mov rcx, rbx
193 call ASM_PFX(SmiRendezvous)
194
195 mov rcx, rbx
196 call ASM_PFX(CpuSmmDebugExit)
197
198 add rsp, 0x20
199
200 ;
201 ; Restore FP registers
202 ;
203 fxrstor64 [rsp]
204
205 add rsp, 0x200
206
207 lea rax, [ASM_PFX(gStmXdSupported)]
208 mov al, [rax]
209 cmp al, 0
210 jz .1
211 pop rdx ; get saved MSR_IA32_MISC_ENABLE[63-32]
212 test edx, BIT2
213 jz .1
214 mov ecx, MSR_IA32_MISC_ENABLE
215 rdmsr
216 or dx, BIT2 ; set XD Disable bit if it was set before entering into SMM
217 wrmsr
218
219 .1:
220 StuffRsb64
221 rsm
222
223 _StmSmiHandler:
224 ;
225 ; Check XD disable bit
226 ;
227 xor r8, r8
228 lea rax, [ASM_PFX(gStmXdSupported)]
229 mov al, [rax]
230 cmp al, 0
231 jz @StmXdDone
232 mov ecx, MSR_IA32_MISC_ENABLE
233 rdmsr
234 mov r8, rdx ; save MSR_IA32_MISC_ENABLE[63-32]
235 test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
236 jz .0
237 and dx, 0xFFFB ; clear XD Disable bit if it is set
238 wrmsr
239 .0:
240 mov ecx, MSR_EFER
241 rdmsr
242 or ax, MSR_EFER_XD ; enable NXE
243 wrmsr
244 @StmXdDone:
245 push r8
246
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:
251 lidt [rax]
252
253 mov rax, cr0
254 or eax, 0x80010023 ; enable paging + WP + NE + MP + PE
255 mov cr0, rax
256 mov rax, cr4
257 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
258 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
259 ; STM init finish
260 jmp CommonHandler
261
262 ASM_PFX(gcStmSmiHandlerSize) : DW $ - _StmSmiEntryPoint
263 ASM_PFX(gcStmSmiHandlerOffset) : DW _StmSmiHandler - _StmSmiEntryPoint
264
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
272
273 lea rax, [CommonHandler]
274 lea rcx, [StmSmiEntryCommonHandlerAbsAddr]
275 mov qword [rcx - 8], rax
276 ret