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